Project

General

Profile

Download (99.2 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
	interfaces_bring_up($interface);
477
	mwexec("/sbin/ifconfig {$bridgeif} addm {$interface}");
478
}
479

    
480
function interfaces_lagg_configure() 
481
{
482
        global $config, $g;
483
		if($g['booting']) 
484
			echo "Configuring LAGG interfaces...";
485
        $i = 0;
486
		if (is_array($config['laggs']['lagg']) && count($config['laggs']['lagg'])) {
487
			foreach ($config['laggs']['lagg'] as $lagg) {
488
				if(empty($lagg['laggif']))
489
					$lagg['laggif'] = "lagg{$i}";
490
				/* XXX: Maybe we should report any errors?! */
491
				interface_lagg_configure($lagg);
492
				$i++;
493
			}
494
		}
495
		if($g['booting']) 
496
			echo "done.\n";
497
}
498

    
499
function interface_lagg_configure(&$lagg) {
500
        global $config, $g;
501

    
502
        if (!is_array($lagg))
503
		return -1;
504

    
505
	$members = explode(',', $lagg['members']);
506
	if (!count($members))
507
		return -1;
508
	
509
	$checklist = get_interface_list();
510

    
511
	if ($g['booting'] || !(empty($lagg['laggif']))) {
512
		pfSense_interface_destroy($lagg['laggif']);
513
		pfSense_interface_create($lagg['laggif']);
514
                $laggif = $lagg['laggif'];
515
        } else
516
		$laggif = pfSense_interface_create("lagg");
517

    
518
	/* Calculate smaller mtu and enforce it */
519
        $smallermtu = 0;
520
        foreach ($members as $member) {
521
                $mtu = get_interface_mtu($member);
522
		if ($smallermtu == 0 && !empty($mtu))
523
			$smallermtu = $mtu;
524
                else if (!empty($mtu) && $mtu < $smallermtu)
525
                        $smallermtu = $mtu;
526
        }
527

    
528
	/* Just in case anything is not working well */
529
        if ($smallermtu == 0)
530
                $smallermtu = 1500;
531

    
532
	foreach ($members as $member) {
533
		if (!array_key_exists($member, $checklist))
534
			continue;
535
		/* make sure the parent interface is up */
536
		pfSense_interface_mtu($member, $smallermtu);
537
		interfaces_bring_up($member);
538
		mwexec("/sbin/ifconfig {$laggif} laggport {$member}");
539
	}
540
	
541
	mwexec("/sbin/ifconfig {$laggif} laggproto {$lagg['proto']}");
542

    
543
	interfaces_bring_up($laggif);
544

    
545
	return $laggif;
546
}
547

    
548
function interfaces_gre_configure() {
549
        global $config;
550

    
551
        $i = 0;
552
        if (is_array($config['gres']['gre']) && count($config['gres']['gre'])) {
553
                foreach ($config['gres']['gre'] as $gre) {
554
                        if(empty($gre['greif']))
555
                                $gre['greif'] = "gre{$i}";
556
                        /* XXX: Maybe we should report any errors?! */
557
                        interface_gre_configure($gre);
558
                        $i++;
559
                }
560
        }
561
}
562

    
563
function interface_gre_configure(&$gre) {
564
        global $config, $g;
565

    
566
	if (!is_array($gre))
567
		return -1;
568

    
569
	$realif = get_real_interface($gre['if']);
570
	$realifip = get_interface_ip($gre['if']);
571

    
572
	/* make sure the parent interface is up */
573
	interfaces_bring_up($realif);
574

    
575
	if ($g['booting'] || !(empty($gre['greif']))) {
576
		pfSense_interface_destroy($gre['greif']);
577
		pfSense_interface_create($gre['greif']);
578
		$greif = $gre['greif'];
579
	} else
580
		$greif = pfSense_interface_create("gre");
581

    
582
	/* Do not change the order here for more see gre(4) NOTES section. */
583
	mwexec("/sbin/ifconfig {$greif} tunnel {$realifip} {$gre['remote-addr']}");
584
	mwexec("/sbin/ifconfig {$greif} {$gre['tunnel-local-addr']} {$gre['tunnel-remote-addr']} netmask " . gen_subnet_mask($gre['tunnel-remote-net']));
585
	if (isset($gre['link0']) && $gre['link0'])
586
		pfSense_interface_flags($greif, IFF_LINK0);
587
	if (isset($gre['link1']) && $gre['link1'])
588
		pfSense_interface_flags($greif, IFF_LINK1);
589
	if (isset($gre['link2']) && $gre['link2'])
590
		pfSense_interface_flags($greif, IFF_LINK2);
591

    
592
	if($greif)
593
		interfaces_bring_up($greif);
594
	else 
595
		log_error("Could not bring greif up -- variable not defined.");
596

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

    
601
	return $greif;
602
}
603

    
604
function interfaces_gif_configure() {
605
	global $config;
606
	$i = 0;
607
	if (is_array($config['gifs']['gif']) && count($config['gifs']['gif'])) {
608
		foreach ($config['gifs']['gif'] as $gif) {
609
			if(empty($gif['gifif']))
610
				$gre['gifif'] = "gif{$i}";
611
			/* XXX: Maybe we should report any errors?! */
612
			interface_gif_configure($gif);
613
			$i++;
614
		}
615
	}
616
}
617

    
618
function interface_gif_configure(&$gif) {
619
	global $config, $g;
620

    
621
	if (!is_array($gif))
622
		return -1;
623

    
624
	$realif = get_real_interface($gif['if']);
625
	$realifip = get_interface_ip($gif['if']);
626

    
627
	/* make sure the parent interface is up */
628
	if($realif)
629
		interfaces_bring_up($realif);
630
	else 
631
		log_error("could not bring realif up -- variable not defined -- interface_gif_configure()");
632

    
633
	if ($g['booting'] || !(empty($gif['gifif']))) {
634
		pfSense_interface_destroy($gif['gifif']);
635
		pfSense_interface_create($gif['gifif']);
636
		$gifif = $gif['gifif'];
637
	} else
638
		$gifif = pfSense_interface_create("gif");
639

    
640
	/* Do not change the order here for more see gif(4) NOTES section. */
641
	mwexec("/sbin/ifconfig {$gifif} tunnel {$realifip} {$gif['remote-addr']}");
642
	mwexec("/sbin/ifconfig {$gifif} {$gif['tunnel-local-addr']} {$gif['tunnel-remote-addr']} netmask " . gen_subnet_mask($gif['tunnel-remote-net']));
643
	if (isset($gif['link0']) && $gif['link0'])
644
		pfSense_interface_flags($gifif, IFF_LINK0);
645
	if (isset($gif['link1']) && $gif['link1'])
646
		pfSense_interface_flags($gifif, IFF_LINK1);
647
	if($gifif)
648
		interfaces_bring_up($gifif);
649
	else
650
		log_error("could not bring gifif up -- variable not defined");
651

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

    
656
	return $gifif;
657
}
658

    
659
function interfaces_configure() {
660
	global $config, $g;
661

    
662
	/* Set up our loopback interface */
663
	interfaces_loopback_configure();
664

    
665
	/* set up LAGG virtual interfaces */
666
	interfaces_lagg_configure();
667

    
668
	/* set up VLAN virtual interfaces */
669
	interfaces_vlan_configure();
670

    
671
	interfaces_qinq_configure();
672

    
673
	$iflist = get_configured_interface_with_descr();
674
	$delayed_list = array();
675
	$bridge_list = array();
676
	
677
	/* This is needed to speedup interfaces on bootup. */
678
	$reload = false;
679
	if ($g['booting'])
680
		$reload = true;
681

    
682
	foreach($iflist as $if => $ifname) {
683
		$realif = $config['interfaces'][$if]['if'];
684
		if(is_array($config['interfaces'][$if]['pppoe']) && isset($config['interfaces'][$if]['pppoe']['pppoe-reset-type']))
685
			setup_pppoe_reset_file($if, true);
686
		else 
687
			setup_pppoe_reset_file($if, false);
688
		if (strstr($realif, "bridge")) 
689
			$bridge_list[$if] = $ifname;
690
		else if (strstr($realif, "gre"))
691
			$delayed_list[$if] = $ifname;
692
		else if (strstr($realif, "gif"))
693
			$delayed_list[$if] = $ifname;
694
		else {
695
			if ($g['booting'])
696
				echo "Configuring {$ifname} interface...";
697
			if($g['debug'])
698
				log_error("Configuring {$ifname}");
699
			interface_configure($if, $reload);
700
			if ($g['booting']) 
701
				echo "done.\n";
702
		}
703
	}
704

    
705
	/* create the unconfigured wireless clones */
706
	interfaces_create_wireless_clones();
707

    
708
	/* set up GRE virtual interfaces */
709
	interfaces_gre_configure();
710

    
711
	/* set up GIF virtual interfaces */
712
	interfaces_gif_configure();
713
	
714
	foreach ($delayed_list as $if => $ifname) {
715
		if ($g['booting'])
716
			echo "Configuring {$ifname} interface...";
717
        	if ($g['debug'])
718
        		log_error("Configuring {$ifname}");
719

    
720
		interface_configure($if, $reload);
721

    
722
		if ($g['booting'])
723
			echo "done.\n";
724
	}
725

    
726
	/* set up BRIDGe virtual interfaces */
727
	interfaces_bridge_configure();
728

    
729
	foreach ($bridge_list as $if => $ifname) {
730
		if ($g['booting'])
731
			echo "Configuring {$ifname} interface...";
732
		if($g['debug'])
733
			log_error("Configuring {$ifname}");
734

    
735
		interface_configure($if, $reload);
736

    
737
		if ($g['booting'])
738
			echo "done.\n";
739
	}
740

    
741
	/* bring up vip interfaces */
742
	interfaces_vips_configure();
743

    
744
	/* configure interface groups */
745
	interfaces_group_setup();
746

    
747
	if (!$g['booting']) {
748
		/* reconfigure static routes (kernel may have deleted them) */
749
		system_routing_configure();
750

    
751
		/* reload IPsec tunnels */
752
		vpn_ipsec_configure();
753

    
754
		/* reload dhcpd (interface enabled/disabled status may have changed) */
755
		services_dhcpd_configure();
756

    
757
		/* restart dnsmasq */
758
		services_dnsmasq_configure();
759

    
760
		/* reload captive portal */
761
		captiveportal_configure();
762

    
763
		/* set the reload filter dity flag */
764
		filter_configure();
765
	}
766

    
767
	return 0;
768
}
769

    
770
function interface_reconfigure($interface = "wan") {
771
	interface_bring_down($interface);
772
	interface_configure($interface, true);
773
}
774

    
775
function interface_vip_bring_down(&$vip) {
776
	switch ($vip['mode']) {
777
	case "proxyarp":
778
		interface_proxyarp_configure();
779
		break;
780
	case "ipalias":
781
		$vipif = get_real_interface($vip['interface']);
782
		if(does_interface_exist($vipif))
783
			pfSense_interface_deladdress($vipif, $vip['subnet']);
784
		break;
785
	case "carp":
786
		$vipif = "vip" . $vip['vhid'];
787
		if(does_interface_exist($vipif)) 
788
			pfSense_interface_destroy($vipif);
789
		break;
790
	case "carpdev-dhcp":
791
		$vipif = "vip" . $vip['vhid'];
792
		if(does_interface_exist($vipif)) 
793
			pfSense_interface_destroy($vipif);
794
		break;
795
	}
796
}
797

    
798
function interface_bring_down($interface = "wan", $destroy = false) {
799
	global $config, $g;
800

    
801
	if (!isset($config['interfaces'][$interface]))
802
		return; 
803

    
804
	$ifcfg = $config['interfaces'][$interface];
805

    
806
	$realif = get_real_interface($interface);
807

    
808
	switch ($ifcfg['ipaddr']) {
809
	case "ppp":
810
	case "pppoe":
811
	case "pptp":
812
	case "l2tp":
813
		killbypid("{$g['varrun_path']}/{$ifcfg['ipaddr']}_{$interface}.pid");
814
		sleep(2);
815
		unlink_if_exists("{$g['varetc_path']}/mpd_{$interface}.conf");
816
		break;
817
	case "carpdev-dhcp":
818
		/* 
819
		 * NB: When carpdev gets enabled it would be better to be handled as all
820
		 *	   other interfaces! 
821
		 */
822
	case "dhcp":
823
		$pid = find_dhclient_process($realif);
824
		if($pid)
825
			mwexec("kill {$pid}");
826
		sleep(1);
827
		unlink_if_exists("{$g['varetc_path']}/dhclient_{$interface}.conf");
828
		if(does_interface_exist("$realif")) {
829
			mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete", true);
830
			pfSense_interface_flags($realif, -IFF_UP);
831
			mwexec("/usr/sbin/arp -d -i {$realif} -a");
832
		}
833
		break;
834
	default:
835
		if(does_interface_exist("$realif")) {
836
			mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete", true);
837
			pfSense_interface_flags($realif, -IFF_UP);
838
			mwexec("/usr/sbin/arp -d -i {$realif} -a");
839
		}
840
		break;
841
	}
842

    
843
	/* remove interface up file if it exists */
844
	unlink_if_exists("{$g['tmp_path']}/{$realif}up");
845
	unlink_if_exists("{$g['vardb_path']}/{$interface}ip");
846
	unlink_if_exists("{$g['tmp_path']}/{$realif}_router");
847
	
848
	/* hostapd and wpa_supplicant do not need to be running when the interface is down.
849
	 * They will also use 100% CPU if running after the wireless clone gets deleted. */
850
	if (is_array($ifcfg['wireless'])) {
851
		mwexec(kill_hostapd($realif));
852
		mwexec(kill_wpasupplicant($realif));
853
	}
854

    
855
	if ($destroy == true) {
856
		if (preg_match("/^tun|^ovpn|^gif|^gre|^lagg|^bridge|vlan/i", $realif))
857
			pfSense_interface_destroy($realif);
858
	}	
859

    
860
	return;
861
}
862

    
863
function interfaces_ptpid_used($ptpid) {
864
	global $config;
865

    
866
	if (is_array($config['ppps']['ppp']))
867
		foreach ($config['ppps']['ppp'] as & $settings)
868
			if ($ptpid == $settings['ptpid'])
869
				return true;
870

    
871
	return false;
872
}
873

    
874
function interfaces_ptpid_next() {
875

    
876
	$ptpid = 0;
877
	while(interfaces_ptpid_used($ptpid))
878
		$ptpid++;
879

    
880
	return $ptpid;
881
}
882

    
883
function getMPDCRONSettings($pppif_) {
884
	global $config;
885
	if (is_array($config['cron']['item'])) {
886
		for ($i = 0; $i < count($config['cron']['item']); $i++) {
887
			$item = $config['cron']['item'][$i];
888
			if (strpos($item['command'], $pppif_) !== false) {
889
				return array("ID" => $i, "ITEM" => $item);
890
			}
891
		}
892
	}
893
	return NULL;
894
}
895

    
896
function handle_pppoe_reset($post_array) {
897
	global $config, $g;
898

    
899
	$cron_cmd_file = "{$g['varetc_path']}/pppoe_restart_";
900

    
901
	$pppif = $post_array['type'].$post_array['ptpid'];
902
	if (!is_array($config['cron']['item'])) 
903
		$config['cron']['item'] = array(); 
904
	$itemhash = getMPDCRONSettings($cron_cmd_file.$pppif);
905
	$item = $itemhash['ITEM'];
906
	
907
	// reset cron items if necessary and return
908
	if (empty($post_array['pppoe-reset-type'])) {
909
		if (isset($item))
910
			unset($config['cron']['item'][$itemhash['ID']]);
911
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
912
		return;
913
	}
914

    
915
	if (empty($item)) 
916
		$item = array();
917
	if (isset($post_array['pppoe-reset-type']) && $post_array['pppoe-reset-type'] == "custom") {
918
		$item['minute'] = $post_array['pppoe_resetminute'];
919
		$item['hour'] = $post_array['pppoe_resethour'];
920
		if (isset($post_array['pppoe_resetdate']) && $post_array['pppoe_resetdate'] <> "") {
921
			$date = explode("/", $post_array['pppoe_resetdate']);
922
			$item['mday'] = $date[1];
923
			$item['month'] = $date[0];
924
		} else {
925
			$item['mday'] = "*";
926
			$item['month'] = "*";
927
		}
928
		$item['wday'] = "*";
929
		$item['who'] = "root";
930
		$item['command'] = $cron_cmd_file.$pppif;
931
	} else if (isset($post_array['pppoe-reset-type']) && $post_array['pppoe-reset-type'] == "preset") {
932
		switch ($post_array['pppoe_pr_preset_val']) {
933
			case "monthly":
934
				$item['minute'] = "0";
935
				$item['hour'] = "0";
936
				$item['mday'] = "1";
937
				$item['month'] = "*";
938
				$item['wday'] = "*";
939
				$item['who'] = "root";
940
				$item['command'] = $cron_cmd_file.$pppif;
941
				break;
942
	        case "weekly":
943
				$item['minute'] = "0";
944
				$item['hour'] = "0";
945
				$item['mday'] = "*";
946
				$item['month'] = "*";
947
				$item['wday'] = "0";
948
				$item['who'] = "root";
949
				$item['command'] = $cron_cmd_file.$pppif;
950
				break;
951
			case "daily":
952
				$item['minute'] = "0";
953
				$item['hour'] = "0";
954
				$item['mday'] = "*";
955
				$item['month'] = "*";
956
				$item['wday'] = "*";
957
				$item['who'] = "root";
958
				$item['command'] = $cron_cmd_file.$pppif;
959
				break;
960
			case "hourly":
961
				$item['minute'] = "0";
962
				$item['hour'] = "*";
963
				$item['mday'] = "*";
964
				$item['month'] = "*";
965
				$item['wday'] = "*";
966
				$item['who'] = "root";
967
				$item['command'] = $cron_cmd_file.$pppif;
968
				break;
969
		} // end switch
970
	} else {
971
		/* test whether a cron item exists and unset() it if necessary */
972
		$itemhash = getMPDCRONSettings($cron_cmd_file.$pppif);
973
		$item = $itemhash['ITEM'];
974
		if (isset($item))
975
			unset($config['cron']['item'][$itemhash['ID']]); 
976
	}// end if
977
	if (isset($itemhash['ID'])) 
978
		$config['cron']['item'][$itemhash['ID']] = $item;
979
	else 
980
		$config['cron']['item'][] = $item;
981
}
982

    
983
/*	This function can configure PPPoE, MLPPP (PPPoE), PPtP.
984
*	It writes the mpd config file to /var/etc every time the link is opened.
985
*/
986

    
987
function interface_ppps_configure($interface) {
988
	global $config, $g;
989
	
990
	// mpd5 requires a /var/spool/lock directory for PPP modem links.
991
	if(!is_dir("/var/spool/lock")) {
992
		exec("/bin/mkdir -p /var/spool/lock");
993
		exec("/bin/chmod a+rw /var/spool/lock/.");
994
	}
995
	// mpd5 modem chat script expected in the same directory as the mpd_xxx.conf files	
996
	if (!file_exists("{$g['varetc_path']}/mpd.script"))
997
		mwexec("/bin/ln -s /usr/local/sbin/mpd.script {$g['varetc_path']}/.");
998
		
999
	$ifcfg = &$config['interfaces'][$interface];
1000
	if (is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) {
1001
		foreach ($config['ppps']['ppp'] as $pppid => $ppp) {
1002
			if ($ifcfg['ptpid'] == $ppp['ptpid'])
1003
				break;
1004
		}
1005
	}
1006
	if (!$ppp || $ifcfg['ptpid'] != $ppp['ptpid']){
1007
		log_error("Can't find PPP config with ptpid {$ifcfg['ptpid']} in interface_ppps_configure().");
1008
		return 0;
1009
	}
1010
	if (!isset($ifcfg['enable'])) {
1011
		log_error("{$interface} is not enabled.");
1012
		return 0;
1013
	}
1014
	$pppif = $ifcfg['if'];
1015
	if ($ppp['type'] == "ppp")
1016
		$type = "modem";
1017
	else
1018
		$type = $ppp['type'];
1019
	$upper_type = strtoupper($ppp['type']);	
1020
	
1021
	if($g['booting']) {
1022
		echo " configuring {$upper_type} on {$pppif} interface...\n";
1023
		// Do not re-configure the interface if we are booting and it's already been started
1024
		if(file_exists("{$g['varrun_path']}/{$ppp['type']}_{$interface}.pid"))
1025
			return 0;
1026
	}
1027
	
1028
	$ports = explode(',',$ppp['ports']);
1029
	$localips = explode(',',$ppp['localip']);
1030
	$gateways = explode(',',$ppp['gateway']);
1031
	$subnets = explode(',',$ppp['subnet']);
1032
	
1033
	/* We bring up the parent interface first because if DHCP is configured on the parent we need
1034
	to obtain an address first so we can write it in the mpd .conf file for PPtP and L2tP configs
1035
	*/
1036
	foreach($ports as $pid => $port){
1037
		switch ($ppp['type']) {
1038
			case "pppoe": 
1039
				/* Bring the parent interface up */
1040
				interfaces_bring_up($port);
1041
				break;
1042
			case "pptp":
1043
			case "l2tp":
1044
				/* configure interface */
1045
				if ($localips[$pid] == "dhcp") {
1046
					// configure DHCP on the $port interface
1047
					interface_dhcp_configure($port);
1048
					// Wait for the IP address before proceeding.
1049
					for ($count = 0; $count < 30; $count++) {
1050
						$localips[$pid] = find_interface_ip($port);
1051
						if(is_ipaddr($localips[$pid]))						
1052
							break;
1053
						sleep(1);
1054
					}
1055
					log_error("Could not get PPtP/L2tP Local IP address for {$port} using DHCP in interfaces_ppps_configure");
1056
					return 0;
1057
				} else {
1058
					// Manually configure interface IP/subnet
1059
					mwexec("/sbin/ifconfig " . escapeshellarg($port) . " " .
1060
						escapeshellarg($localips[$pid] . "/" . $subnets[$pid]) . " up");
1061
				}
1062
				/* configure the gateway (remote IP ) */
1063
				if (!is_ipaddr($gateways[$pid]) && is_hostname($gateways[$pid])) {
1064
					// do a DNS lookup for the gateway IP and store it in $gateways[$pid]
1065
					for ($count = 0; $count < 30; $count++) {
1066
						$gateways[$pid] = gethostbyname($gateways[$pid]);
1067
						if(is_ipaddr($gateways[$pid]))						
1068
							break;
1069
						sleep(1);
1070
					}
1071
					log_error("Could not get a PPtP/L2tP Remote IP address for {$port} using DNS in interfaces_ppps_configure");
1072
					return 0;
1073
				}
1074
				if (0) // Logic for this? 
1075
					log_error("Could not bring up interface {$port} for {$interface} {$ppp['type']} link in interface_ppps_configure().");
1076
				break;
1077
			case "ppp":
1078
				if (!file_exists("{$port}")) {
1079
					log_error("Device {$port} does not exist. PPP link cannot start without the modem device.");
1080
					return 1;
1081
				}
1082
				break;
1083
			default:
1084
				break;
1085
		}
1086
	}
1087

    
1088
	/* generate mpd.conf */
1089
	$fd = fopen("{$g['varetc_path']}/mpd_{$interface}.conf", "w");
1090
	if (!$fd) {
1091
		log_error("Error: cannot open mpd_{$interface}.conf in interface_ppps_configure().\n");
1092
		return 1;
1093
	}
1094
	
1095
	if (is_array($ports) && count($ports) > 1)
1096
		$multilink = "enable";
1097
	else
1098
		$multilink = "disable";
1099
	
1100
	if ($type == "modem"){
1101
		if (is_ipaddr($ppp['localip']))
1102
			$localip = $ppp['localip'];
1103
		else
1104
			$localip = '0.0.0.0';
1105

    
1106
		if (is_ipaddr($ppp['gateway']))
1107
			$gateway = $ppp['gateway'];
1108
		else
1109
			$gateway = "10.6.6.{$pppid}";
1110
		$ranges = "{$localip}/0 {$gateway}/0";
1111
		
1112
		if (empty($ppp['apnum']))	
1113
			$ppp['apnum'] = 1;
1114
	}
1115
	else
1116
		$ranges = "0.0.0.0/0 0.0.0.0/0";
1117

    
1118
	if (isset($ppp['ondemand'])) 
1119
		$ondemand = "enable";
1120
	else
1121
		$ondemand = "disable";
1122
	if (!isset($ppp['idletimeout']))
1123
		$ppp['idletimeout'] = 0;
1124

    
1125
	if (empty($ppp['username']) && $type == "modem"){
1126
		$ppp['username'] = "user";
1127
		$ppp['password'] = "none";
1128
	}
1129
	if (empty($ppp['password']) && $type == "modem")
1130
		$passwd = "none";
1131
	else
1132
		$passwd = base64_decode($ppp['password']);
1133

    
1134
	$bandwidths = explode(',',$ppp['bandwidth']);
1135
	$mtus = explode(',',$ppp['mtu']);
1136
	$mrus = explode(',',$ppp['mru']);
1137

    
1138
	if (isset($ppp['mrru']))
1139
		$mrrus = explode(',',$ppp['mrru']);
1140

    
1141
	// Construct the mpd.conf file
1142
	$mpdconf = <<<EOD
1143
startup:
1144
	# configure the console
1145
	set console close
1146
	# configure the web server
1147
	set web close
1148

    
1149
default:
1150
{$ppp['type']}client:
1151
	create bundle static {$interface}
1152
	set iface name {$pppif}
1153

    
1154
EOD;
1155
	$setdefaultgw = false;
1156
	$founddefaultgw = false;
1157
	if (is_array($config['gateways']['gateway_item'])) {
1158
		foreach($config['gateways']['gateway_item'] as $gateway) {
1159
			if($interface == $gateway['interface'] && isset($gateway['defaultgw'])) {
1160
				$setdefaultgw = true;
1161
				break;
1162
			} else if (isset($gateway['defaultgw']) && !empty($gateway['interface'])) {
1163
				$founddefaultgw = true;
1164
				break;
1165
			}
1166
		}
1167
	}
1168
	
1169
	if (($interface == "wan" && $founddefaultgw == false) || $setdefaultgw == true){
1170
		$setdefaultgw = true;
1171
		$mpdconf .= <<<EOD
1172
	set iface route default
1173

    
1174
EOD;
1175
	}
1176
	$mpdconf .= <<<EOD
1177
	set iface {$ondemand} on-demand
1178
	set iface idle {$ppp['idletimeout']}
1179

    
1180
EOD;
1181

    
1182
	if (isset($ppp['ondemand']))
1183
		$mpdconf .= <<<EOD
1184
	set iface addrs 10.10.1.1 10.10.1.2
1185

    
1186
EOD;
1187
	
1188
	if (isset($ppp['tcpmssfix']))
1189
		$tcpmss = "disable";
1190
	else
1191
		$tcpmss = "enable";
1192
		$mpdconf .= <<<EOD
1193
	set iface {$tcpmss} tcpmssfix
1194

    
1195
EOD;
1196

    
1197
	$mpdconf .= <<<EOD
1198
	set iface up-script /usr/local/sbin/ppp-linkup
1199
	set iface down-script /usr/local/sbin/ppp-linkdown
1200
	set ipcp ranges {$ranges}
1201

    
1202
EOD;
1203
	if (isset($ppp['vjcomp']))
1204
		$mpdconf .= <<<EOD
1205
	set ipcp no vjcomp
1206

    
1207
EOD;
1208

    
1209
	if (isset($config['system']['dnsallowoverride']) && $setdefaultgw == true)
1210
		$mpdconf .= <<<EOD
1211
	set ipcp enable req-pri-dns
1212
	set ipcp enable req-sec-dns
1213

    
1214
EOD;
1215

    
1216
/*
1217
	if (!isset($ifcfg['dnsnosec']) && isset($config['system']['dnsallowoverride']))
1218
			$mpdconf .= <<<EOD
1219
	set ipcp enable req-sec-dns
1220

    
1221
EOD;
1222
*/	
1223
	foreach($ports as $pid => $port){
1224
		$mpdconf .= <<<EOD
1225

    
1226
	create link static {$interface}_link{$pid} {$type}
1227
	set link action bundle {$interface}
1228
	set link {$multilink} multilink
1229
	set link keep-alive 10 60
1230
	set link max-redial 0
1231

    
1232
EOD;
1233
		if (isset($ppp['shortseq']))
1234
			$mpdconf .= <<<EOD
1235
	set link no shortseq
1236

    
1237
EOD;
1238

    
1239
		if (isset($ppp['acfcomp']))
1240
			$mpdconf .= <<<EOD
1241
	set link no acfcomp
1242

    
1243
EOD;
1244

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

    
1249
EOD;
1250

    
1251
		$mpdconf .= <<<EOD
1252
	set link disable chap pap
1253
	set link accept chap pap eap
1254
	set link disable incoming
1255

    
1256
EOD;
1257

    
1258

    
1259
		if (!empty($bandwidths[$pid]))
1260
			$mpdconf .= <<<EOD
1261
	set link bandwidth {$bandwidths[$pid]}
1262

    
1263
EOD;
1264

    
1265
		if (empty($mtus[$pid]))
1266
			$mtus[$pid] = "1492";
1267
			$mpdconf .= <<<EOD
1268
	set link mtu {$mtus[$pid]}
1269

    
1270
EOD;
1271

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

    
1276
EOD;
1277

    
1278
		$mpdconf .= <<<EOD
1279
	set auth authname "{$ppp['username']}"
1280
	set auth password {$passwd}
1281

    
1282
EOD;
1283
		if ($type == "modem") {
1284
			$mpdconf .= <<<EOD
1285
	set modem device {$ppp['ports']}
1286
	set modem script DialPeer
1287
	set modem idle-script Ringback
1288
	set modem watch -cd
1289
	set modem var \$DialPrefix "DT"
1290
	set modem var \$Telephone "{$ppp['phone']}"
1291

    
1292
EOD;
1293
		}
1294
		if (isset($ppp['connect-timeout']) && $type == "modem") {
1295
			$mpdconf .= <<<EOD
1296
	set modem var \$ConnectTimeout "{$ppp['connect-timeout']}"
1297

    
1298
EOD;
1299
		}
1300
		if (isset($ppp['initstr']) && $type == "modem") {
1301
			$initstr = base64_decode($ppp['initstr']);
1302
			$mpdconf .= <<<EOD
1303
	set modem var \$InitString "{$initstr}"
1304

    
1305
EOD;
1306
		}
1307
		if (isset($ppp['simpin']) && $type == "modem") {
1308
			$mpdconf .= <<<EOD
1309
	set modem var \$SimPin "{$ppp['simpin']}"
1310
	set modem var \$PinWait "{$ppp['pin-wait']}"
1311

    
1312
EOD;
1313
		}
1314
		if (isset($ppp['apn']) && $type == "modem") {
1315
			$mpdconf .= <<<EOD
1316
	set modem var \$APN "{$ppp['apn']}"
1317
	set modem var \$APNum "{$ppp['apnum']}"
1318

    
1319
EOD;
1320
		}
1321
		if (isset($ppp['provider']) && $type == "pppoe") {
1322
			$mpdconf .= <<<EOD
1323
	set pppoe service "{$ppp['provider']}"
1324

    
1325
EOD;
1326
		}
1327
		if ($type == "pppoe")
1328
			$mpdconf .= <<<EOD
1329
	set pppoe iface {$port}
1330

    
1331
EOD;
1332

    
1333
		if ($type == "pptp" || $type == "l2tp") {
1334
			$mpdconf .= <<<EOD
1335
	set bundle no noretry
1336
	set pptp self {$localips[$pid]}
1337
	set pptp peer {$gateways[$pid]}
1338
	set pptp disable windowing
1339

    
1340
EOD;
1341
		}
1342
		$mpdconf .= "\topen\r\n";
1343
	} //end foreach($port)
1344

    
1345
	// Write out mpd_ppp.conf
1346
	fwrite($fd, $mpdconf);
1347
	fclose($fd);
1348

    
1349
	// Create the uptime log if requested and if it doesn't exist already, or delete it if it is no longer requested.
1350
	if (isset($ppp['uptime'])) {
1351
		if (!file_exists("/conf/{$pppif}.log")) {
1352
			conf_mount_rw();
1353
			mwexec("echo /dev/null > /conf/{$pppif}.log");
1354
			conf_mount_ro();
1355
		}
1356
	} else {
1357
		if (file_exists("/conf/{$pppif}.log")) {
1358
			conf_mount_rw();
1359
			mwexec("rm -f /conf/{$pppif}.log");
1360
			conf_mount_ro();
1361
		}
1362
	}
1363
		
1364
	/* fire up mpd */
1365
	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");
1366

    
1367
	// Check for PPPoE periodic reset request 
1368
	if ($type == "pppoe")
1369
		if (isset($ppp['pppoe-reset-type']))
1370
			setup_pppoe_reset_file($ppp['if'], $interface);
1371
		else
1372
			setup_pppoe_reset_file($ppp['if']);
1373

    
1374
	/* sleep until wan is up - or 30 seconds, whichever comes first */
1375
	for ($count = 0; $count < 12; $count++) {
1376
		if(file_exists("{$g['tmp_path']}/{$pppif}up")) {
1377
			break;
1378
		}
1379
		sleep(1);
1380
	}
1381

    
1382
	return 0;
1383
}
1384

    
1385
function interfaces_carp_setup() {
1386
	global $g, $config;
1387

    
1388
	$balanacing = "";
1389
	$pfsyncinterface = "";
1390
	$pfsyncenabled = "";
1391
	if(isset($config['system']['developerspew'])) {
1392
		$mt = microtime();
1393
		echo "interfaces_carp_setup() being called $mt\n";
1394
	}
1395

    
1396
	// Prepare CmdCHAIN that will be used to execute commands.
1397
	$cmdchain = new CmdCHAIN();	
1398

    
1399
	if ($g['booting']) {
1400
		echo "Configuring CARP settings...";
1401
		mute_kernel_msgs();
1402
	}
1403

    
1404
	/* suck in configuration items */
1405
	if($config['installedpackages']['carpsettings']) {
1406
		if($config['installedpackages']['carpsettings']['config']) {
1407
			foreach($config['installedpackages']['carpsettings']['config'] as $carp) {
1408
				$pfsyncenabled = $carp['pfsyncenabled'];
1409
				$balanacing = $carp['balancing'];
1410
				$pfsyncinterface = $carp['pfsyncinterface'];
1411
				$pfsyncpeerip = $carp['pfsyncpeerip'];
1412
			}
1413
		}
1414
	} else {
1415
		unset($pfsyncinterface);
1416
		unset($balanacing);
1417
		unset($pfsyncenabled);
1418
	}
1419

    
1420
	$cmdchain->add("Allow CARP", "/sbin/sysctl net.inet.carp.allow=1", true);			
1421
	if($balanacing) {
1422
		$cmdchain->add("Enable CARP ARP-balancing", "/sbin/sysctl net.inet.carp.arpbalance=1", true);
1423
		$cmdchain->add("Disallow CARP preemption", "/sbin/sysctl net.inet.carp.preempt=0", true);
1424
	} else
1425
		$cmdchain->add("Enable CARP preemption", "/sbin/sysctl net.inet.carp.preempt=1", true);		
1426

    
1427
	$cmdchain->add("Enable CARP logging", "/sbin/sysctl net.inet.carp.log=2", true);
1428
	if (!empty($pfsyncinterface))
1429
		$carp_sync_int = get_real_interface($pfsyncinterface);
1430

    
1431
	if($g['booting']) {
1432
		/*    install rules to alllow pfsync to sync up during boot
1433
		 *    carp interfaces will remain down until the bootup sequence finishes
1434
		 */
1435
		$fd = fopen("{$g['tmp_path']}/rules.boot", "w");
1436
		if ($fd) {
1437
			fwrite($fd, "pass quick proto carp all keep state\n");
1438
			fwrite($fd, "pass quick proto pfsync all\n");
1439
			fwrite($fd, "pass out quick from any to any keep state\n");
1440
			fclose($fd);
1441
			mwexec("/sbin/pfctl -f {$g['tmp_path']}/rules.boot");
1442
		} else
1443
			log_error("Could not create rules.boot file!");
1444
	}
1445

    
1446
	/* setup pfsync interface */
1447
	if($carp_sync_int and $pfsyncenabled) {
1448
		if (is_ipaddr($pfsyncpeerip))
1449
			$cmdchain->add("Bring up pfsync0 syncpeer", "/sbin/ifconfig pfsync0 syncdev {$carp_sync_int} syncpeer {$pfsyncpeerip} up", false);						
1450
		else
1451
			$cmdchain->add("Bring up pfsync0 syncdev", "/sbin/ifconfig pfsync0 syncdev {$carp_sync_int} up", false);			
1452
	} else
1453
		$cmdchain->add("Bring up pfsync0", "/sbin/ifconfig pfsync0 syncdev lo0 up", false);						
1454

    
1455
	if($config['virtualip']['vip'])
1456
		$cmdchain->add("Allow CARP.", "/sbin/sysctl net.inet.carp.allow=1", true);				
1457
	else
1458
		$cmdchain->add("Disallow CARP.", "/sbin/sysctl net.inet.carp.allow=0", true);		
1459
	
1460
	if($g['debug'])
1461
		$cmdchain->setdebug(); // optional for verbose logging
1462

    
1463
	$cmdchain->execute();
1464
	$cmdchain->clear();
1465

    
1466
	if ($g['booting']) {
1467
		unmute_kernel_msgs();
1468
		echo "done.\n";
1469
	}
1470
}
1471

    
1472
function interface_proxyarp_configure() {
1473
	global $config, $g;
1474
	if(isset($config['system']['developerspew'])) {
1475
		$mt = microtime();
1476
		echo "interface_proxyarp_configure() being called $mt\n";
1477
	}
1478

    
1479
	/* kill any running choparp */
1480
	killbyname("choparp");
1481

    
1482
	if (isset($config['virtualip']) && is_array($config['virtualip']['vip'])) {
1483
		$paa = array();
1484

    
1485
		/* group by interface */
1486
		foreach ($config['virtualip']['vip'] as $vipent) {
1487
			if ($vipent['mode'] === "proxyarp") {
1488
				if ($vipent['interface'])
1489
					$proxyif = $vipent['interface'];
1490
				else
1491
					$proxyif = "wan";
1492

    
1493
				if (!is_array($paa[$if]))
1494
					$paa[$proxyif] = array();
1495

    
1496
				$paa[$proxyif][] = $vipent;
1497
			}
1498
	}
1499

    
1500
	if (count($paa))
1501
		foreach ($paa as $paif => $paents) {
1502
			$paaifip = get_interface_ip($paif);
1503
			if (!(is_ipaddr($paaifip)))
1504
				continue;
1505
			$args = get_real_interface($paif) . " auto";
1506
			foreach ($paents as $paent) {
1507

    
1508
				if (isset($paent['subnet']))
1509
					$args .= " " . escapeshellarg("{$paent['subnet']}/{$paent['subnet_bits']}");
1510
				else if (isset($paent['range']))
1511
					$args .= " " . escapeshellarg($paent['range']['from'] . "-" .
1512
					$paent['range']['to']);
1513
			}
1514
			mwexec_bg("/usr/local/sbin/choparp " . $args);
1515
		}
1516
	}
1517

    
1518
}
1519

    
1520
function interfaces_vips_configure($interface = "") {
1521
	global $g, $config;
1522
	if(isset($config['system']['developerspew'])) {
1523
		$mt = microtime();
1524
		echo "interfaces_vips_configure() being called $mt\n";
1525
	}
1526
	$paa = array();
1527
	if(is_array($config['virtualip']['vip'])) {
1528
		$carp_setuped = false;
1529
		$anyproxyarp = false;
1530
		foreach ($config['virtualip']['vip'] as $vip) {
1531
			switch ($vip['mode']) {
1532
			case "proxyarp":
1533
				/* nothing it is handled on interface_proxyarp_configure() */
1534
				if ($interface <> "" && $vip['interface'] <> $interface)
1535
					continue;
1536
				$anyproxyarp = true;
1537
				break;
1538
			case "ipalias":
1539
				if ($interface <> "" && $vip['interface'] <> $interface)
1540
					continue;
1541
				interface_ipalias_configure(&$vip);
1542
				break;
1543
			case "carp":
1544
				if ($interface <> "" && $vip['interface'] <> $interface)
1545
					continue;
1546
				if ($carp_setuped == false) {
1547
					interfaces_carp_setup();
1548
					$carp_setuped = true;
1549
				}
1550
				interface_carp_configure($vip);
1551
				break;
1552
			case "carpdev-dhcp":
1553
				if ($interface <> "" && $vip['interface'] <> $interface)
1554
					continue;
1555
				interface_carpdev_configure($vip);
1556
				break;
1557
			}
1558
		}
1559
		
1560
		if ($anyproxyarp == true)
1561
			interface_proxyarp_configure();
1562
	}
1563
}
1564

    
1565
function interface_ipalias_configure(&$vip) {
1566

    
1567
	if ($vip['mode'] == "ipalias") {
1568
		$if = get_real_interface($vip['interface']);
1569
		mwexec("/sbin/ifconfig " . escapeshellarg($if) . " " . $vip['subnet'] . "/" . escapeshellarg($vip['subnet_bits']) . " alias");
1570
	}
1571
}
1572

    
1573
function interface_reload_carps($cif) {
1574
	global $config;
1575

    
1576
	$carpifs = link_ip_to_carp_interface(find_interface_ip($cif));
1577
	if (empty($carpifs))
1578
		return;
1579

    
1580
	$carps = explode(" ", $carpifs);
1581
	if(is_array($config['virtualip']['vip'])) {
1582
		$viparr = &$config['virtualip']['vip'];
1583
		foreach ($viparr as $vip) {
1584
			if (in_array($vip['carpif'], $carps)) {
1585
				switch ($vip['mode']) {
1586
					case "carp":
1587
					interface_vip_bring_down($vip);
1588
					sleep(1);
1589
					interface_carp_configure($vip);
1590
					break;
1591
					case "carpdev-dhcp":
1592
					interface_vip_bring_down($vip);
1593
					sleep(1);
1594
					interface_carpdev_configure($vip);
1595
					break;
1596
				}
1597
			}
1598
		}
1599
	}
1600
}
1601

    
1602
function interface_carp_configure(&$vip) {
1603
	global $config, $g;
1604
	if(isset($config['system']['developerspew'])) {
1605
		$mt = microtime();
1606
		echo "interface_carp_configure() being called $mt\n";
1607
	}
1608

    
1609
	if ($vip['mode'] != "carp")
1610
		return;
1611

    
1612
	$vip_password = $vip['password'];
1613
	$vip_password = escapeshellarg(addslashes(str_replace(" ", "", $vip_password)));
1614
	if ($vip['password'] != "")
1615
		$password = " pass {$vip_password}";
1616

    
1617
	// set the vip interface to the vhid
1618
	$vipif = "vip{$vip['vhid']}";
1619

    
1620
	$interface = interface_translate_type_to_real($vip['interface']);
1621
	/*
1622
	 * ensure the interface containing the VIP really exists
1623
 	 * prevents a panic if the interface is missing or invalid
1624
	 */
1625
	$realif = get_real_interface($vip['interface']);
1626
	if (!does_interface_exist($realif)) {
1627
		file_notice("CARP", "Interface specified for the virtual IP address {$vip['subnet']} does not exist. Skipping this VIP.", "Firewall: Virtual IP", "");
1628
		return;
1629
	}
1630

    
1631
	/* ensure CARP IP really exists prior to loading up */
1632
	/* XXX: this can be bound to only the interface choosen in the carp creation. Not yet since upgrade is needed! */
1633
	$found = false;
1634
	$iflist = get_configured_interface_list();
1635
	foreach($iflist as $if) {
1636
		$ww_subnet_ip = get_interface_ip($if);
1637
		$ww_subnet_bits = get_interface_subnet($if);
1638
		if (ip_in_subnet($vip['subnet'], gen_subnet($ww_subnet_ip, $ww_subnet_bits) . "/" . $ww_subnet_bits)) {
1639
			$found = true;
1640
			break;
1641
		}
1642
	}
1643
	if($found == false) {
1644
		file_notice("CARP", "Sorry but we could not find a matching real interface subnet for the virtual IP address {$vip['subnet']}.", "Firewall: Virtual IP", "");
1645
		return;
1646
	}
1647

    
1648
	/* invalidate interface cache */
1649
	get_interface_arr(true);
1650

    
1651
	/* create the carp interface and setup */
1652
	if (does_interface_exist($vipif)) {
1653
		pfSense_interface_flags($vipif, -IFF_UP);
1654
	} else {
1655
		$carpif = pfSense_interface_create("carp");
1656
		pfSense_interface_rename($carpif, $vipif);
1657
		pfSense_ngctl_name("{$carpif}:", $vipif);
1658
	}
1659

    
1660
	/* invalidate interface cache */
1661
	get_interface_arr(true);
1662

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

    
1666
	interfaces_bring_up($vipif);
1667
	
1668
	return $vipif;
1669
}
1670

    
1671
function interface_carpdev_configure(&$vip) {
1672
	global $g;
1673

    
1674
	if ($vip['mode'] != "carpdev-dhcp")
1675
		return;
1676

    
1677
	$vip_password = $vip['password'];
1678
	$vip_password = str_replace(" ", "", $vip_password);
1679
	if($vip['password'] != "")
1680
		$password = " pass \"" . $vip_password . "\"";
1681

    
1682
	log_error("Found carpdev interface {$vip['interface']} on top of interface {$interface}");
1683
	if (empty($vip['interface']))
1684
		return;
1685

    
1686
	$vipif = "vip" . $vip['vhid'];
1687
	$realif = interface_translate_type_to_real($vip['interface']);
1688
	interfaces_bring_up($realif);
1689
	/*
1690
	 * ensure the interface containing the VIP really exists
1691
	 * prevents a panic if the interface is missing or invalid
1692
	 */
1693
	if (!does_interface_exist($realif)) {
1694
		file_notice("CARP", "Interface specified for the virtual IP address {$vip['subnet']} does not exist. Skipping this VIP.", "Firewall: Virtual IP", "");
1695
		return;
1696
	}
1697

    
1698
	if (does_interface_exist($vipif)) {
1699
		interface_bring_down($vipif);
1700
	} else {
1701
		$carpdevif = exec("/sbin/ifconfig carp create");
1702
		mwexec("/sbin/ifconfig {$carpdevif} name {$vipif}");
1703
		pfSense_ngctl_name("{$carpdevif}:", $vipif);
1704
	}
1705

    
1706
	mwexec("/sbin/ifconfig {$vipif} carpdev {$realif} vhid {$vip['vhid']} advskew {$vip['advskew']} {$password}");
1707
	interfaces_bring_up($vipif);
1708

    
1709
	/*
1710
	 * XXX: BIG HACK but carpdev needs ip services active
1711
	 *      before even starting something as dhclient.
1712
	 *      I do not know if this is a feature or a bug
1713
	 *      but better than track it make it work ;) .
1714
	 */
1715
	//$fakeiptouse = "10.254.254." . ($carp_instances_counter+1);
1716
	//$cmdchain->add("CarpDEV hack", "/sbin/ifconfig {$carpint} inet {$fakeiptouse}", false);
1717

    
1718
	/* generate dhclient_wan.conf */
1719
	$fd = fopen("{$g['varetc_path']}/dhclient_{$vipif}.conf", "w");
1720
	if ($fd) {
1721
		$dhclientconf = "";
1722

    
1723
		$dhclientconf .= <<<EOD
1724
interface "{$vipif}" {
1725
timeout 60;
1726
retry 1;
1727
select-timeout 0;
1728
initial-interval 1;
1729
script "/sbin/dhclient-script";
1730
}
1731

    
1732
EOD;
1733

    
1734
		fwrite($fd, $dhclientconf);
1735
		fclose($fd);
1736

    
1737
		/* fire up dhclient */
1738
		mwexec("/sbin/dhclient -c {$g['varetc_path']}/dhclient_{$vipif}.conf {$vipif} > {$g['tmp_path']}/{$vipif}_output > {$g['tmp_path']}/{$vipif}_error_output", false);
1739
	} else {
1740
		log_error("Error: cannot open dhclient_{$vipif}.conf in interfaces_carpdev_configure() for writing.\n");
1741
		mwexec("/sbin/dhclient -b {$vipif}");
1742
	}
1743

    
1744
	return $vipif;
1745
}
1746

    
1747
function interface_wireless_clone($realif, $wlcfg) {
1748
	global $config, $g;
1749
	/*   Check to see if interface has been cloned as of yet.  
1750
	 *   If it has not been cloned then go ahead and clone it.
1751
	 */
1752
	$needs_clone = false;
1753
	if(is_array($wlcfg['wireless']))
1754
		$wlcfg_mode = $wlcfg['wireless']['mode'];
1755
	else
1756
		$wlcfg_mode = $wlcfg['mode'];
1757
	switch($wlcfg_mode) {
1758
		 case "hostap":
1759
			$mode = "wlanmode hostap";
1760
			break;
1761
		 case "adhoc":
1762
			$mode = "wlanmode adhoc";
1763
			break;
1764
		 default:
1765
			$mode = "";
1766
			break;
1767
	}
1768
	$baseif = interface_get_wireless_base($wlcfg['if']);
1769
	if(does_interface_exist($realif)) {
1770
		exec("/sbin/ifconfig {$realif}", $output, $ret);
1771
		$ifconfig_str = implode($output);
1772
		if(($wlcfg_mode == "hostap") && (! preg_match("/hostap/si", $ifconfig_str))) {
1773
			log_error("Interface {$realif} changed to hostap mode");
1774
			$needs_clone = true;
1775
		}
1776
		if(($wlcfg_mode == "adhoc") && (! preg_match("/adhoc/si", $ifconfig_str))) {
1777
			log_error("Interface {$realif} changed to adhoc mode");
1778
			$needs_clone = true;
1779
		}
1780
		if(($wlcfg_mode == "bss") && (preg_match("/hostap|adhoc/si", $ifconfig_str))) {
1781
			log_error("Interface {$realif} changed to infrastructure mode");
1782
			$needs_clone = true;
1783
		}
1784
	} else {
1785
		$needs_clone = true;
1786
	}
1787

    
1788
	if($needs_clone == true) {
1789
		/* remove previous instance if it exists */
1790
		if(does_interface_exist($realif))
1791
			pfSense_interface_destroy($realif);
1792

    
1793
		log_error("Cloning new wireless interface {$realif}");
1794
		// Create the new wlan interface. FreeBSD returns the new interface name.
1795
		// example:  wlan2
1796
		exec("/sbin/ifconfig wlan create wlandev {$baseif} {$mode} bssid 2>&1", $out, $ret);
1797
		if($ret <> 0) {
1798
			log_error("Failed to clone interface {$baseif} with error code {$ret}, output {$out[0]}");
1799
			return false;
1800
		}
1801
		$newif = trim($out[0]);
1802
		// Rename the interface to {$parentnic}_wlan{$number}#: EX: ath0_wlan0
1803
		pfSense_interface_rename($newif, $realif);
1804
		// FIXME: not sure what ngctl is for. Doesn't work.
1805
		// mwexec("/usr/sbin/ngctl name {$newif}: {$realif}", false);
1806
	}
1807
	return true;
1808
}
1809

    
1810
function interface_sync_wireless_clones(&$ifcfg, $sync_changes = false) {
1811
	global $config, $g;
1812

    
1813
	$shared_settings = array('standard', 'turbo', 'protmode', 'txpower', 'channel', 'distance', 'regdomain', 'regcountry', 'reglocation');
1814

    
1815
	if(!is_interface_wireless($ifcfg['if']))
1816
		return;
1817

    
1818
	$baseif = interface_get_wireless_base($ifcfg['if']);
1819

    
1820
	$iflist = get_configured_interface_list(false, true);
1821
	foreach ($iflist as $if) {
1822
		if ($baseif == interface_get_wireless_base($config['interfaces'][$if]['if']) && $ifcfg['if'] != $config['interfaces'][$if]['if']) {
1823
			if (isset($config['interfaces'][$if]['wireless']['standard']) || $sync_changes) {
1824
				foreach ($shared_settings as $setting) {
1825
					if ($sync_changes) {
1826
						$config['interfaces'][$if]['wireless'][$setting] = $ifcfg['wireless'][$setting];
1827
					} else {
1828
						$ifcfg['wireless'][$setting] = $config['interfaces'][$if]['wireless'][$setting];
1829
					}
1830
				}
1831
				if (!$sync_changes)
1832
					break;
1833
			}
1834
		}
1835
	}
1836

    
1837
	if (interface_is_wireless_clone($ifcfg['if'])) {
1838
		foreach ($config['wireless']['clone'] as &$clone) {
1839
			if ($clone['cloneif'] == $ifcfg['if']) {
1840
				if ($sync_changes) {
1841
					$clone['mode'] = $ifcfg['wireless']['mode'];
1842
				} else {
1843
					$ifcfg['wireless']['mode'] = $clone['mode'];
1844
				}
1845
				break;
1846
			}
1847
		}
1848
		unset($clone);
1849
	}
1850
}
1851

    
1852
function interface_wireless_configure($if, &$wl, &$wlcfg) {
1853
	global $config, $g;
1854

    
1855
	/*    open up a shell script that will be used to output the commands.
1856
	 *    since wireless is changing a lot, these series of commands are fragile
1857
     *    and will sometimes need to be verified by a operator by executing the command
1858
     *    and returning the output of the command to the developers for inspection.  please
1859
     *    do not change this routine from a shell script to individul exec commands.  -sullrich
1860
	 */
1861

    
1862
	// Remove script file
1863
	unlink_if_exists("{$g['tmp_path']}/{$if}_setup.sh");
1864

    
1865
	// Clone wireless nic if needed.
1866
	interface_wireless_clone($if, $wl);
1867

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

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

    
1875
	/* set values for /path/program */
1876
	$hostapd = "/usr/sbin/hostapd";
1877
	$wpa_supplicant = "/usr/sbin/wpa_supplicant";
1878
	$ifconfig = "/sbin/ifconfig";
1879
	$killall = "/usr/bin/killall";
1880

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

    
1883
	$wlcmd = array();
1884
	/* Make sure it's up */
1885
	$wlcmd[] = "up";
1886
	/* Set a/b/g standard */
1887
	$standard = str_replace(" Turbo", "", $wlcfg['standard']);
1888
	$wlcmd[] = "mode " . escapeshellarg($standard);
1889

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

    
1895
	/* Set ssid */
1896
	if($wlcfg['ssid'])
1897
		$wlcmd[] = "ssid " .escapeshellarg($wlcfg['ssid']);
1898

    
1899
	/* Set 802.11g protection mode */
1900
	$wlcmd[] = "protmode " . escapeshellarg($wlcfg['protmode']);
1901

    
1902
	/* set wireless channel value */
1903
	if(isset($wlcfg['channel'])) {
1904
		if($wlcfg['channel'] == "0") {
1905
			$wlcmd[] = "channel any";
1906
		} else {
1907
			$wlcmd[] = "channel " . escapeshellarg($wlcfg['channel']);
1908
		}
1909
	}
1910

    
1911
	/* set Distance value */
1912
	if($wlcfg['distance'])
1913
		$distance = escapeshellarg($wlcfg['distance']);
1914

    
1915
	/* Set wireless hostap mode */
1916
	if ($wlcfg['mode'] == "hostap") {
1917
		$wlcmd[] = "mediaopt hostap";
1918
	} else {
1919
		$wlcmd[] = "-mediaopt hostap";
1920
	}
1921

    
1922
	/* Set wireless adhoc mode */
1923
	if ($wlcfg['mode'] == "adhoc") {
1924
		$wlcmd[] = "mediaopt adhoc";
1925
	} else {
1926
		$wlcmd[] = "-mediaopt adhoc";
1927
	}
1928

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

    
1931
	/* handle hide ssid option */
1932
	if(isset($wlcfg['hidessid']['enable'])) {
1933
		$wlcmd[] = "hidessid";
1934
	} else {
1935
		$wlcmd[] = "-hidessid";
1936
	}
1937

    
1938
	/* handle pureg (802.11g) only option */
1939
	if(isset($wlcfg['pureg']['enable'])) {
1940
		$wlcmd[] = "mode 11g pureg";
1941
	} else {
1942
		$wlcmd[] = "-pureg";
1943
	}
1944

    
1945
	/* handle puren (802.11n) only option */
1946
	if(isset($wlcfg['puren']['enable'])) {
1947
		$wlcmd[] = "puren";
1948
	} else {
1949
		$wlcmd[] = "-puren";
1950
	}
1951

    
1952
	/* enable apbridge option */
1953
	if(isset($wlcfg['apbridge']['enable'])) {
1954
		$wlcmd[] = "apbridge";
1955
	} else {
1956
		$wlcmd[] = "-apbridge";
1957
	}
1958

    
1959
	/* handle turbo option */
1960
	if(isset($wlcfg['turbo']['enable'])) {
1961
		$wlcmd[] = "mediaopt turbo";
1962
	} else {
1963
		$wlcmd[] = "-mediaopt turbo";
1964
	}
1965

    
1966
	/* handle txpower setting */
1967
	/* if($wlcfg['txpower'] <> "")
1968
		$wlcmd[] = "txpower " . escapeshellarg($wlcfg['txpower']);
1969
	*/
1970
	/* handle wme option */
1971
	if(isset($wlcfg['wme']['enable'])) {
1972
		$wlcmd[] = "wme";
1973
	} else {
1974
		$wlcmd[] = "-wme";
1975
	}
1976

    
1977
	/* set up wep if enabled */
1978
	$wepset = "";
1979
	if (isset($wlcfg['wep']['enable']) && is_array($wlcfg['wep']['key'])) {
1980
		switch($wlcfg['wpa']['auth_algs']) {
1981
			case "1":
1982
				$wepset .= "authmode open wepmode on ";
1983
				break;
1984
			case "2":
1985
				$wepset .= "authmode shared wepmode on ";
1986
				break;
1987
			case "3":
1988
				$wepset .= "authmode mixed wepmode on ";
1989
		}
1990
		$i = 1;
1991
		foreach ($wlcfg['wep']['key'] as $wepkey) {
1992
			$wepset .= "wepkey " . escapeshellarg("{$i}:{$wepkey['value']}") . " ";
1993
			if (isset($wepkey['txkey'])) {
1994
				$wlcmd[] = "weptxkey {$i} ";
1995
			}
1996
			$i++;
1997
		}
1998
		$wlcmd[] = $wepset;
1999
	} else {
2000
		$wlcmd[] = "authmode open wepmode off ";
2001
	}
2002

    
2003
	mwexec(kill_hostapd("{$if}"));
2004
	mwexec(kill_wpasupplicant("{$if}"));
2005

    
2006
	/* generate wpa_supplicant/hostap config if wpa is enabled */
2007
	conf_mount_rw();
2008

    
2009
	switch ($wlcfg['mode']) {
2010
		case 'bss':
2011
			if (isset($wlcfg['wpa']['enable'])) {
2012
				$wpa .= <<<EOD
2013
ctrl_interface={$g['varrun_path']}/wpa_supplicant
2014
ctrl_interface_group=0
2015
ap_scan=1
2016
#fast_reauth=1
2017
network={
2018
ssid="{$wlcfg['ssid']}"
2019
scan_ssid=1
2020
priority=5
2021
key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
2022
psk="{$wlcfg['wpa']['passphrase']}"
2023
pairwise={$wlcfg['wpa']['wpa_pairwise']}
2024
group={$wlcfg['wpa']['wpa_pairwise']}
2025
}
2026
EOD;
2027

    
2028
				$fd = fopen("{$g['varetc_path']}/wpa_supplicant_{$if}.conf", "w");
2029
				fwrite($fd, "{$wpa}");
2030
				fclose($fd);
2031
			}
2032
			break;
2033
		case 'hostap':
2034
			if($wlcfg['wpa']['passphrase']) 
2035
				$wpa_passphrase = "wpa_passphrase={$wlcfg['wpa']['passphrase']}\n";
2036
			else 
2037
				$wpa_passphrase = "";
2038
			if (isset($wlcfg['wpa']['enable'])) {
2039
				$wpa .= <<<EOD
2040
interface={$if}
2041
driver=bsd
2042
logger_syslog=-1
2043
logger_syslog_level=0
2044
logger_stdout=-1
2045
logger_stdout_level=0
2046
dump_file={$g['tmp_path']}/hostapd_{$if}.dump
2047
ctrl_interface={$g['varrun_path']}/hostapd
2048
ctrl_interface_group=wheel
2049
#accept_mac_file={$g['tmp_path']}/hostapd_{$if}.accept
2050
#deny_mac_file={$g['tmp_path']}/hostapd_{$if}.deny
2051
#macaddr_acl={$wlcfg['wpa']['macaddr_acl']}
2052
ssid={$wlcfg['ssid']}
2053
debug={$wlcfg['wpa']['debug_mode']}
2054
auth_algs={$wlcfg['wpa']['auth_algs']}
2055
wpa={$wlcfg['wpa']['wpa_mode']}
2056
wpa_key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
2057
wpa_pairwise={$wlcfg['wpa']['wpa_pairwise']}
2058
wpa_group_rekey={$wlcfg['wpa']['wpa_group_rekey']}
2059
wpa_gmk_rekey={$wlcfg['wpa']['wpa_gmk_rekey']}
2060
wpa_strict_rekey={$wlcfg['wpa']['wpa_strict_rekey']}
2061
{$wpa_passphrase}
2062
#Enable the next lines for preauth when roaming. Interface = wired or wireless interface talking to the AP you want to roam from/to
2063
#rsn_preauth=1
2064
#rsn_preauth_interfaces=eth0
2065

    
2066
EOD;
2067

    
2068
				if($wlcfg['auth_server_addr'] && $wlcfg['auth_server_shared_secret']) {
2069
					$auth_server_port = "1812";
2070
					if($wlcfg['auth_server_port']) 
2071
						$auth_server_port = $wlcfg['auth_server_port'];
2072
					$wpa .= <<<EOD
2073

    
2074
ieee8021x=1
2075
auth_server_addr={$wlcfg['auth_server_addr']}
2076
auth_server_port={$auth_server_port}
2077
auth_server_shared_secret={$wlcfg['auth_server_shared_secret']}
2078

    
2079
EOD;
2080
				} else {
2081
					$wpa .= "ieee8021x={$wlcfg['wpa']['ieee8021x']}\n";
2082
				}
2083

    
2084
				$fd = fopen("{$g['varetc_path']}/hostapd_{$if}.conf", "w");
2085
				fwrite($fd, "{$wpa}");
2086
				fclose($fd);
2087

    
2088
			}
2089
			break;
2090
	}
2091

    
2092
	/*
2093
	 *    all variables are set, lets start up everything
2094
	 */
2095

    
2096
	$baseif = interface_get_wireless_base($if);
2097

    
2098
	/* set ack timers according to users preference (if he/she has any) */
2099
	if($distance) {
2100
		fwrite($fd_set, "# Enable ATH distance settings\n");
2101
		fwrite($fd_set, "/sbin/athctrl.sh -i {$baseif} -d {$distance}\n");
2102
	}
2103

    
2104
	if (isset($wlcfg['wpa']['enable'])) {
2105
		if ($wlcfg['mode'] == "bss") {
2106
			fwrite($fd_set, "{$wpa_supplicant} -B -i {$if} -c {$g['varetc_path']}/wpa_supplicant_{$if}.conf\n");
2107
		}
2108
		if ($wlcfg['mode'] == "hostap") {
2109
			fwrite($fd_set, "{$hostapd} -B {$g['varetc_path']}/hostapd_{$if}.conf\n");
2110
		}
2111
	}
2112

    
2113
	fclose($fd_set);
2114
	conf_mount_ro();
2115

    
2116
	/* Making sure regulatory settings have actually changed
2117
	 * before applying, because changing them requires bringing
2118
	 * down all wireless networks on the interface. */
2119
	exec("{$ifconfig} " . escapeshellarg($if), $output);
2120
	$ifconfig_str = implode($output);
2121
	unset($output);
2122
	$reg_changing = false;
2123

    
2124
	if ($wlcfg['regdomain'] && !preg_match("/\sregdomain\s+{$wlcfg['regdomain']}\s/si", $ifconfig_str))
2125
		$reg_changing = true;
2126
	else if ($wlcfg['regcountry'] && !preg_match("/\scountry\s+{$wlcfg['regcountry']}\s/si", $ifconfig_str))
2127
		$reg_changing = true;
2128
	/* anywhere needs a special case, since it is not included in the ifconfig output.
2129
	 * Do not combine this if with the one inside. */
2130
	else if ($wlcfg['reglocation'] == 'anywhere') {
2131
		if (preg_match("/\s(indoor|outdoor)\s/si", $ifconfig_str))
2132
			$reg_changing = true;
2133
	} else if ($wlcfg['reglocation'] && !preg_match("/\s{$wlcfg['reglocation']}\s/si", $ifconfig_str))
2134
		$reg_changing = true;
2135

    
2136
	/* special case for the debug country code */
2137
	if ($wlcfg['regcountry'] == 'DEBUG' && preg_match("/\sregdomain\s+DEBUG\s/si", $ifconfig_str))
2138
		$reg_changing = false;
2139

    
2140
	if ($reg_changing) {
2141
		/* set regulatory domain */
2142
		if($wlcfg['regdomain'])
2143
			$wlregcmd[] = "regdomain " . escapeshellarg($wlcfg['regdomain']);
2144

    
2145
		/* set country */
2146
		if($wlcfg['regcountry'])
2147
			$wlregcmd[] = "country " . escapeshellarg($wlcfg['regcountry']);
2148

    
2149
		/* set location */
2150
		if($wlcfg['reglocation'])
2151
			$wlregcmd[] = escapeshellarg($wlcfg['reglocation']);
2152

    
2153
		$wlregcmd_args = implode(" ", $wlregcmd);
2154

    
2155
		/* build a complete list of the wireless clones for this interface */
2156
		$clone_list = array();
2157
		if (does_interface_exist(interface_get_wireless_clone($baseif)))
2158
			$clone_list[] = interface_get_wireless_clone($baseif);
2159
		if (is_array($config['wireless']['clone'])) {
2160
			foreach ($config['wireless']['clone'] as $clone) {
2161
				if ($clone['if'] == $baseif)
2162
					$clone_list[] = $clone['cloneif'];
2163
			}
2164
		}
2165

    
2166
		/* find which clones are up and bring them down */
2167
		$clones_up = array();
2168
		foreach ($clone_list as $clone_if) {
2169
			$clone_status = pfSense_get_interface_addresses($clone_if);
2170
			if ($clone_status['status'] == 'up') {
2171
				$clones_up[] = $clone_if;
2172
				mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " down");
2173
			}
2174
		}
2175

    
2176
		/* apply the regulatory settings */
2177
		mwexec("{$ifconfig} " . escapeshellarg($if) . " {$wlregcmd_args}");
2178

    
2179
		/* bring the clones back up that were previously up */
2180
		foreach ($clones_up as $clone_if) {
2181
			mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " up");
2182
		}
2183
	}
2184

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

    
2189
	/* configure wireless */
2190
	$wlcmd_args = implode(" ", $wlcmd);
2191
	mwexec("/sbin/ifconfig {$if} $wlcmd_args", false);
2192

    
2193
	
2194
	sleep(1);
2195
	/* execute hostapd and wpa_supplicant if required in shell */
2196
	mwexec("/bin/sh {$g['tmp_path']}/{$if}_setup.sh");
2197

    
2198
	return 0;
2199

    
2200
}
2201

    
2202
function kill_hostapd($interface) {
2203
	return "/bin/pkill -f \"hostapd .*{$interface}\"\n";
2204
}
2205

    
2206
function kill_wpasupplicant($interface) {
2207
	return "/bin/pkill -f \"wpa_supplicant .*{$interface}\"\n";
2208
}
2209

    
2210
function find_dhclient_process($interface) {
2211
	if($interface) {
2212
		$pid = `/bin/pgrep -xf "dhclient: {$interface}"`;
2213
	}
2214
	return $pid;
2215
}
2216

    
2217
function interface_configure($interface = "wan", $reloadall = false) {
2218
	global $config, $g;
2219
	global $interface_sn_arr_cache, $interface_ip_arr_cache;
2220

    
2221
	$wancfg = $config['interfaces'][$interface];
2222

    
2223
	$realif = get_real_interface($interface);
2224

    
2225
	if (!$g['booting']) {
2226
		/* remove all IPv4 addresses */
2227
		while (mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " -alias", true) == 0);
2228
			interface_bring_down($interface);
2229
	}
2230

    
2231
	/* wireless configuration? */
2232
	if (is_array($wancfg['wireless']))
2233
		interface_wireless_configure($realif, $wancfg, $wancfg['wireless']);
2234

    
2235
	if ($wancfg['spoofmac']) {
2236
		mwexec("/sbin/ifconfig " . escapeshellarg($realif) .
2237
			" link " . escapeshellarg($wancfg['spoofmac']));
2238

    
2239
                /*
2240
                 * All vlans need to spoof their parent mac address, too.  see
2241
                 * ticket #1514: http://cvstrac.pfsense.com/tktview?tn=1514,33
2242
                 */
2243
                if (is_array($config['vlans']['vlan'])) {
2244
                        foreach ($config['vlans']['vlan'] as $vlan) {
2245
                                if ($vlan['if'] == $realif)
2246
                                        mwexec("/sbin/ifconfig " . escapeshellarg($vlan['vlanif']) .
2247
                                                " link " . escapeshellarg($wancfg['spoofmac']));
2248
                        }
2249
                }
2250
	}  else {
2251
		$mac = get_interface_mac(get_real_interface($wancfg['if']));
2252
		if($mac == "ff:ff:ff:ff:ff:ff") {
2253
			/*   this is not a valid mac address.  generate a
2254
			 *   temporary mac address so the machine can get online.
2255
			 */
2256
			echo "Generating new MAC address.";
2257
			$random_mac = generate_random_mac_address();
2258
			mwexec("/sbin/ifconfig " . escapeshellarg(get_real_interface($wancfg['if'])) .
2259
				" link " . escapeshellarg($random_mac));
2260
			$wancfg['spoofmac'] = $random_mac;
2261
			write_config();
2262
			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");
2263
		}
2264
	}
2265

    
2266
	/* media */
2267
	if ($wancfg['media'] || $wancfg['mediaopt']) {
2268
		$cmd = "/sbin/ifconfig " . escapeshellarg(get_real_interface($wancfg['if']));
2269
		if ($wancfg['media'])
2270
			$cmd .= " media " . escapeshellarg($wancfg['media']);
2271
		if ($wancfg['mediaopt'])
2272
			$cmd .= " mediaopt " . escapeshellarg($wancfg['mediaopt']);
2273
		mwexec($cmd);
2274
	}
2275
	if (!empty($wancfg['mtu']))
2276
		pfSense_interface_mtu($realif, $wancfg['mtu']);
2277

    
2278
	/* invalidate interface/ip/sn cache */
2279
	get_interface_arr(true);
2280
	unset($interface_ip_arr_cache[$realif]);
2281
	unset($interface_sn_arr_cache[$realif]);
2282

    
2283
	switch ($wancfg['ipaddr']) {
2284

    
2285
		case 'carpdev-dhcp':
2286
			interface_carpdev_dhcp_configure($interface);
2287
			break;
2288
		case 'dhcp':
2289
			interface_dhcp_configure($interface);
2290
			break;
2291
		case 'pppoe':
2292
			interface_ppps_configure($interface);
2293
			break;
2294
		case 'pptp':
2295
			interface_ppps_configure($interface);
2296
			break;
2297
		case 'ppp':
2298
			interface_ppps_configure($interface);
2299
			break;
2300
		default:
2301
			if ($wancfg['ipaddr'] <> "" && $wancfg['subnet'] <> "") {
2302
				pfSense_interface_setaddress($realif, "{$wancfg['ipaddr']}/{$wancfg['subnet']}");
2303
			} else if (substr($realif, 0, 3) == "gre") {
2304
				if (is_array($config['gres']['gre'])) {
2305
					foreach ($config['gres']['gre'] as $gre)
2306
						if ($gre['greif'] == $realif)
2307
							interface_gre_configure($gre);
2308
				}
2309
			} else if (substr($realif, 0, 3) == "gif") {
2310
				 if (is_array($config['gifs']['gif'])) {
2311
					foreach ($config['gifs']['gif'] as $gif)
2312
						if($gif['gifif'] == $interface)
2313
							interface_gif_configure($gif);
2314
				}
2315
			} else if (substr($realif, 0, 4) == "ovpn") {
2316
				/* XXX: Should be done anything?! */
2317
			}
2318

    
2319
			if (is_ipaddr($wancfg['gateway']))
2320
				file_put_contents("{$g['tmp_path']}/{$realif}_router", $wancfg['gateway']);
2321
			break;
2322
	}
2323

    
2324
	if(does_interface_exist($wancfg['if']))
2325
		interfaces_bring_up($wancfg['if']);
2326
 	
2327
	if (!$g['booting'])
2328
		interface_reload_carps($realif);
2329
	
2330
	if (!$g['booting']) {
2331
		if (link_interface_to_gre($interface)) {
2332
			foreach ($config['gres']['gre'] as $gre)
2333
				if ($gre['if'] == $interface)
2334
					interface_gre_configure($gre);
2335
		}
2336
		if (link_interface_to_gif($interface)) {
2337
                	foreach ($config['gifs']['gif'] as $gif)
2338
				if ($gif['if'] == $interface)
2339
                        		interface_gif_configure($gif);
2340
        	}
2341
		if (link_interface_to_bridge($interface)) {
2342
			foreach ($config['bridges']['bridged'] as $bridge)
2343
				if (stristr($bridge['members'], "{$interface}"))
2344
					interface_bridge_add_member($bridge['bridgeif'], $realif);
2345
		}
2346

    
2347
		link_interface_to_vips($interface, "update");
2348

    
2349
		if ($interface == "lan")
2350
			/* make new hosts file */
2351
			system_hosts_generate();
2352

    
2353
		if ($reloadall == true) {
2354

    
2355
			/* reconfigure static routes (kernel may have deleted them) */
2356
			system_routing_configure();
2357

    
2358
			/* reload ipsec tunnels */
2359
			vpn_ipsec_configure();
2360

    
2361
			/* update dyndns */
2362
			services_dyndns_configure($interface);
2363

    
2364
			/* force DNS update */
2365
			services_dnsupdate_process($interface);
2366

    
2367
			/* restart dnsmasq */
2368
			services_dnsmasq_configure();
2369

    
2370
			/* reload captive portal */
2371
			captiveportal_configure();
2372

    
2373
			/* set the reload filter dity flag */
2374
			filter_configure();
2375
		}
2376
	}
2377

    
2378
	return 0;
2379
}
2380

    
2381
function interface_carpdev_dhcp_configure($interface = "wan") {
2382
	global $config, $g;
2383

    
2384
	$wancfg = $config['interfaces'][$interface];
2385
	$wanif = $wancfg['if'];
2386
	/* bring wan interface up before starting dhclient */
2387
	if($wanif)
2388
		interfaces_bring_up($wanif);
2389
	else 
2390
		log_error("Could not bring wanif up in terface_carpdev_dhcp_configure()");
2391

    
2392
	return 0;
2393
}
2394

    
2395
function interface_dhcp_configure($interface = "wan") {
2396
	global $config, $g;
2397

    
2398
	$wancfg = $config['interfaces'][$interface];
2399

    
2400
	/* generate dhclient_wan.conf */
2401
	$fd = fopen("{$g['varetc_path']}/dhclient_{$interface}.conf", "w");
2402
	if (!$fd) {
2403
		printf("Error: cannot open dhclient_{$interface}.conf in interfaces_wan_dhcp_configure() for writing.\n");
2404
		return 1;
2405
	}
2406

    
2407
	if ($wancfg['dhcphostname']) {
2408
		$dhclientconf_hostname = "send dhcp-client-identifier \"{$wancfg['dhcphostname']}\";\n";
2409
		$dhclientconf_hostname .= "\tsend host-name \"{$wancfg['dhcphostname']}\";\n";
2410
	} else {
2411
		$dhclientconf_hostname = "";
2412
	}
2413

    
2414
	$wanif = get_real_interface($interface);
2415
	if (isset($wancfg['ptpid']))
2416
		$wanif = get_real_interface($interface, true);
2417
	if (stristr($wanif,',')) {
2418
		log_error("Invalid interface \"{$wanif}\" in interface_dhcp_configure()");
2419
		return 0;
2420
	}
2421
 	$dhclientconf = "";
2422
	
2423
	$dhclientconf .= <<<EOD
2424
interface "{$wanif}" {
2425
timeout 60;
2426
retry 1;
2427
select-timeout 0;
2428
initial-interval 1;
2429
	{$dhclientconf_hostname}
2430
	script "/sbin/dhclient-script";
2431
}
2432

    
2433
EOD;
2434

    
2435
if(is_ipaddr($wancfg['alias-address'])) {
2436
	$subnetmask = gen_subnet_mask($wancfg['alias-subnet']);
2437
	$dhclientconf .= <<<EOD
2438
alias {
2439
	interface  "{$wanif}";
2440
	fixed-address {$wancfg['alias-address']};
2441
	option subnet-mask {$subnetmask};
2442
}
2443

    
2444
EOD;
2445
}
2446
	fwrite($fd, $dhclientconf);
2447
	fclose($fd);
2448

    
2449
	/* bring wan interface up before starting dhclient */
2450
	if($wanif)
2451
		interfaces_bring_up($wanif);
2452
	else 
2453
		log_error("Could not bring up {$wanif} interface in interface_dhcp_configure()");
2454

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

    
2458
	return 0;
2459
}
2460

    
2461
function interface_pppoe_configure($interface = "wan") {
2462
	global $config, $g;
2463

    
2464
	if (!is_array($config['interfaces'][$interface]))
2465
                return;
2466

    
2467
	$wancfg =& $config['interfaces'][$interface];
2468

    
2469
	/* generate mpd.conf */
2470
	$fd = fopen("{$g['varetc_path']}/mpd_{$interface}.conf", "w");
2471
	if (!$fd) {
2472
		printf("Error: cannot open mpd_{$interface}.conf in interface_pppoe_configure().\n");
2473
		return 1;
2474
	}
2475

    
2476
	$idle = 0;
2477

    
2478
	if (isset($wancfg['ondemand'])) {
2479
		$ondemand = "enable";
2480
		if ($wancfg['timeout'])
2481
			$idle = $wancfg['timeout'];
2482
	} else {
2483
		$ondemand = "disable";
2484
	}
2485

    
2486
	$mpdconf = <<<EOD
2487
startup:
2488
        # configure the web server
2489
	set console close
2490
        set web close
2491

    
2492
default:
2493
pppoeclient:
2494

    
2495
EOD;
2496

    
2497
	if ($interface == "wan")
2498
		$realif = "pppoe0";
2499
	else {
2500
		// Here code assumes only that strings of form "opt#" will be passed.
2501
		$pppoeidx = substr($interface, 3);
2502
		$realif = "pppoe{$pppoeidx}";
2503
	}
2504
	
2505
	$mpdconf .= <<<EOD
2506
	create bundle static {$interface}
2507
	set iface name {$realif}
2508

    
2509
EOD;
2510
	$setdefaultgw = false;
2511
	$founddefaultgw = false;
2512
	if (is_array($config['gateways']['gateway_item'])) {
2513
		foreach($config['gateways']['gateway_item'] as $gateway) {
2514
			if($interface == $gateway['interface'] && isset($gateway['defaultgw'])) {
2515
				$setdefaultgw = true;
2516
				break;
2517
			} else if (isset($gateway['defaultgw']) && !empty($gateway['interface'])) {
2518
				$founddefaultgw = true;
2519
				break;
2520
			}
2521
		}
2522
	}
2523
	if (($interface == "wan" && $founddefaultgw == false) || $setdefaultgw == true)
2524
		$mpdconf .= <<<EOD
2525
	set iface route default
2526

    
2527
EOD;
2528
	
2529
	$mpdconf .= <<<EOD
2530
	set iface {$ondemand} on-demand
2531
	set iface idle {$idle}
2532
	set iface enable tcpmssfix
2533
	set iface up-script /usr/local/sbin/ppp-linkup
2534
	set iface down-script /usr/local/sbin/ppp-linkdown
2535

    
2536
EOD;
2537

    
2538
	if (isset($wancfg['ondemand'])) {
2539
		if (isset($wancfg['local-ip']) && isset($wancfg['remote-ip'])) {
2540
			$mpdconf .= <<<EOD
2541
	set iface addrs {$wancfg['local-ip']} {$wancfg['remote-ip']}
2542

    
2543
EOD;
2544
		} else {
2545
			$mpdconf .= <<<EOD
2546
	set iface addrs 192.0.2.112 192.0.2.113
2547

    
2548
EOD;
2549
		}
2550
	}
2551

    
2552
	if (isset($config['system']['dnsallowoverride'])) {
2553
		$mpdconf .= <<<EOD
2554
	set ipcp enable req-pri-dns
2555

    
2556
EOD;
2557
	}
2558

    
2559
	if (!isset($wancfg['dnsnosec']) && isset($config['system']['dnsallowoverride'])) {
2560
			$mpdconf .= <<<EOD
2561
	set ipcp enable req-sec-dns
2562

    
2563
EOD;
2564
	}
2565
	
2566
	$mpdconf .= <<<EOD
2567
	set ipcp no vjcomp
2568
	set ipcp ranges 0.0.0.0/0 0.0.0.0/0
2569
	create link static {$interface}L1 pppoe
2570
	set link disable incoming
2571
	set link action bundle {$interface}
2572
	set auth authname "{$wancfg['pppoe_username']}"
2573
	set auth password "{$wancfg['pppoe_password']}"
2574
	set link keep-alive 10 60
2575
	set link max-redial 0
2576
	set link no acfcomp protocomp
2577
	set link disable pap chap
2578
	set link accept chap
2579
	set pppoe iface {$wancfg['if']}
2580
	set pppoe service "{$wancfg['provider']}"
2581

    
2582
EOD;
2583
	if (empty($wancfg['mtu']))
2584
		$mpdmtu = "1492";
2585
	else 
2586
		$mpdmtu = "{$wancfg['mtu']}";
2587

    
2588
	$mpdconf .= <<<EOD
2589
	set link mtu {$mpdmtu}
2590
	open
2591

    
2592
EOD;
2593

    
2594
	fwrite($fd, $mpdconf);
2595
	fclose($fd);
2596

    
2597
	if(file_exists("{$g['varrun_path']}/pppoe_{$interface}.pid") and $g['booting']) {
2598
		/* if we are booting and mpd has already been started then don't start again. */
2599
	} else {
2600
		/* Bring the parent interface up */
2601
		if($wancfg['if'])
2602
			interfaces_bring_up($wancfg['if']);
2603
		else 
2604
			log_error("Could not bring wancfg['if'] up in interface_pppoe_configure()");
2605

    
2606
		/* fire up mpd */
2607
		mwexec("/usr/local/sbin/mpd5 -b -k -d {$g['varetc_path']} -f mpd_{$interface}.conf -p {$g['varrun_path']}/pppoe_{$interface}.pid -s {$interface} pppoeclient");
2608
	}
2609

    
2610
	/* sleep until wan is up - or 30 seconds, whichever comes first */
2611
	for ($count = 0; $count < 30; $count++) {
2612
		if(file_exists("{$g['tmp_path']}/{$realif}up")) {
2613
			break;
2614
		}
2615
		sleep(1);
2616
	}
2617

    
2618
	unlink_if_exists("{$g['tmp_path']}/{$realif}up");
2619

    
2620
	return 0;
2621
}
2622

    
2623
function interface_pptp_configure($interface) {
2624
	global $config, $g;
2625

    
2626
	if (!is_array($config['interfaces'][$interface]))
2627
                return;
2628

    
2629
	$wancfg =& $config['interfaces'][$interface];
2630

    
2631
	/* generate mpd.conf */
2632
	$fd = fopen("{$g['varetc_path']}/mpd_{$interface}.conf", "w");
2633
	if (!$fd) {
2634
		printf("Error: cannot open mpd_{$interface}.conf in interface_pptp_configure().\n");
2635
		return 1;
2636
	}
2637

    
2638
	$idle = 0;
2639

    
2640
	if (isset($wancfg['ondemand'])) {
2641
		$ondemand = "enable";
2642
		if ($wancfg['timeout'])
2643
			$idle = $wancfg['timeout'];
2644
	} else {
2645
		$ondemand = "disable";
2646
	}
2647

    
2648
	$mpdconf = <<<EOD
2649
startup:
2650
        # configure the web server
2651
        set console close
2652
        set web close
2653

    
2654
default:
2655
pptpclient:
2656

    
2657
EOD;
2658

    
2659
        if ($interface == "wan")
2660
                $realif = "pptp0";
2661
        else {
2662
                // Here code assumes only that strings of form "opt#" will be passed.
2663
                $pptpidx = substr($interface, 3);
2664
                $realif = "pptp{$pptpidx}";
2665
        }
2666

    
2667
        $mpdconf .= <<<EOD
2668
	create bundle static {$interface}
2669
	set iface name {$realif}
2670

    
2671
EOD;
2672
	$setdefaultgw = false;
2673
        $founddefaultgw = false;
2674
        if (is_array($config['gateways']['gateway_item'])) {
2675
                foreach($config['gateways']['gateway_item'] as $gateway) {
2676
                        if($interface == $gateway['interface'] && isset($gateway['defaultgw'])) {
2677
                                $setdefaultgw = true;
2678
                                break;
2679
                        } else if (isset($gateway['defaultgw'])) {
2680
                                $founddefaultgw = true;
2681
                                break;
2682
                        }
2683
		}
2684
        }
2685
        if (($interface == "wan" && $founddefaultgw == false) || $setdefaultgw == true)
2686
                $mpdconf .= <<<EOD
2687
        set iface route default
2688

    
2689
EOD;
2690

    
2691
        $mpdconf .= <<<EOD
2692
	set iface {$ondemand} on-demand
2693
	set iface idle {$idle}
2694
	set iface up-script /usr/local/sbin/ppp-linkup
2695
	set iface down-script /usr/local/sbin/ppp-linkdown
2696

    
2697
EOD;
2698

    
2699
	if (isset($wanfg['ondemand'])) {
2700
		$mpdconf .= <<<EOD
2701
	set iface addrs 10.0.0.1 10.0.0.2
2702

    
2703
EOD;
2704
	}
2705

    
2706
        if (isset($config['system']['dnsallowoverride'])) {
2707
                $mpdconf .= <<<EOD
2708
        set ipcp enable req-pri-dns
2709

    
2710
EOD;
2711
        }
2712

    
2713
        if (!isset($wancfg['dnsnosec']) && isset($config['system']['dnsallowoverride'])) {
2714
                        $mpdconf .= <<<EOD
2715
        set ipcp enable req-sec-dns
2716

    
2717
EOD;
2718
        }
2719

    
2720
	$mpdconf .= <<<EOD
2721
	set ipcp no vjcomp
2722
	set ipcp ranges 0.0.0.0/0 0.0.0.0/0
2723
	create link static {$interface}L1 pptp
2724
	set auth authname "{$wancfg['pptp_username']}"
2725
	set auth password "{$wancfg['pptp_password']}"
2726
	set bundle no noretry
2727
	set link disable incoming
2728
	set link keep-alive 10 60
2729
	set link max-redial 0
2730
	set link no acfcomp protocomp
2731
	set link disable pap chap
2732
	set link accept chap
2733
	set pptp self {$wancfg['local']}
2734
	set pptp peer {$wancfg['remote']}
2735
	set pptp disable windowing
2736
	open
2737

    
2738
EOD;
2739

    
2740
	fwrite($fd, $mpdconf);
2741
	fclose($fd);
2742

    
2743
	/* configure interface */
2744
	if($wancfg['if'])
2745
		mwexec("/sbin/ifconfig " . escapeshellarg($wancfg['if']) . " " .
2746
			escapeshellarg($wancfg['local'] . "/" . $wancfg['subnet']) . " up");
2747
	else 
2748
		log_error("Could not bring interface wancfg['if'] up in interface_pptp_configure()");
2749
	/* fire up mpd */
2750
	mwexec("/usr/local/sbin/mpd5 -b -k -d {$g['varetc_path']} -f mpd_{$interface}.conf -p {$g['varrun_path']}/pptp_{$interface}.pid -s {$interface} pptpclient");
2751

    
2752
	return 0;
2753
}
2754

    
2755
function interfaces_group_setup() {
2756
	global $config;
2757

    
2758
	if (!is_array($config['ifgroups']['ifgroupentry']))
2759
		return;
2760

    
2761
	foreach ($config['ifgroups']['ifgroupentry'] as $groupar)
2762
		interface_group_setup($groupar);
2763

    
2764
	return;
2765
}
2766

    
2767
function interface_group_setup(&$groupname /* The parameter is an array */) {
2768
	global $config;
2769

    
2770
	if (!is_array($groupname))
2771
		return;
2772
	$members = explode(" ", $groupname['members']);
2773
	foreach($members as $ifs) {
2774
		$realif = get_real_interface($ifs);
2775
		if ($realif)
2776
			mwexec("/sbin/ifconfig {$realif} group {$groupname['ifname']}");
2777
	}
2778

    
2779
	return;
2780
}
2781
 
2782
/* COMPAT Function */
2783
function convert_friendly_interface_to_real_interface_name($interface) {
2784
	return get_real_interface($interface);
2785
}
2786

    
2787
/* COMPAT Function */
2788
function get_real_wan_interface($interface = "wan") {
2789
	return get_real_interface($interface);
2790
}
2791

    
2792
/* COMPAT Function */
2793
function get_current_wan_address($interface = "wan") {
2794
	return get_interface_ip($interface);
2795
}
2796

    
2797
/*
2798
 * convert_real_interface_to_friendly_interface_name($interface): convert fxp0 -> wan, etc.
2799
 */
2800
function convert_real_interface_to_friendly_interface_name($interface = "wan") {
2801
        global $config;
2802

    
2803
        if (stristr($interface, "pppoe")) {
2804
                $index = intval(substr($interface, 5));
2805
		if ($interface == "pppoe")
2806
			return "lan";
2807
                if ($index > 0)
2808
                        return "opt{$index}";
2809
                else
2810
                        return "wan";
2811
        } else if (stristr($interface, "pptp")) {
2812
                $index = intval(substr($interface, 4));
2813
		if ($interface == "pptp")
2814
			return "lan";
2815
                if ($index > 0)
2816
                        return "opt{$index}";
2817
                else
2818
                        return "wan";
2819
        } else if (stristr($interface, "ppp")) {
2820
                $index = intval(substr($interface, 3));
2821
		if ($interface == "ppp")
2822
			return "lan";
2823
                if ($index > 0)
2824
                        return "opt{$index}";
2825
                else
2826
                        return "wan";
2827
        } else if (stristr($interface, "l2tp")) {
2828
                $index = intval(substr($interface, 4));
2829
		if ($interface == "l2tp")
2830
			return "lan";
2831
                if ($index > 0)
2832
                        return "opt{$index}";
2833
                else
2834
                        return "wan";
2835
		} else if (stristr($interface, "vip")) {
2836
                $index = intval(substr($interface, 3));
2837
                foreach ($config['virtualip']['vip'] as $counter => $vip) {
2838
                        if ($vip['mode'] == "carpdev-dhcp" || $vip['mode'] == "carp")  {
2839
                                if ($index == $counter)
2840
                                        return $vip['interface'];
2841
                        }
2842
                }
2843
        } else if (stristr($interface, "carp")) {
2844
                $index = intval(substr($interface, 4));
2845
                foreach ($config['virtualip']['vip'] as $counter => $vip) {
2846
                        if ($vip['mode'] == "carpdev-dhcp" || $vip['mode'] == "carp")  {
2847
                                if ($index == $counter)
2848
                                        return $vip['interface'];
2849
                        }
2850
                }
2851
        }
2852

    
2853
        /* XXX: For speed reasons reference directly the interface array */
2854
	$ifdescrs = $config['interfaces'];
2855
        //$ifdescrs = get_configured_interface_list(false, true);
2856

    
2857
        foreach ($ifdescrs as $if => $ifname) {
2858
                if ($config['interfaces'][$if]['if'] == $interface)
2859
                        return $if;
2860

    
2861
                /* XXX: ermal - The 3 lines below are totally bogus code. */
2862
                $int = interface_translate_type_to_real($if);
2863
                if ($int == $interface)
2864
                        return $ifname;
2865
        }
2866
        return NULL;
2867
}
2868

    
2869
/* attempt to resolve interface to friendly descr */
2870
function convert_friendly_interface_to_friendly_descr($interface) {
2871
        global $config;
2872

    
2873
        switch ($interface) {
2874
                case "l2tp":
2875
                                $ifdesc = "L2TP";
2876
                                break;
2877
                case "pptp":
2878
                                $ifdesc = "pptp";
2879
                                break;
2880
                case "pppoe":
2881
                                $ifdesc = "pppoe";
2882
                                break;
2883
                case "openvpn":
2884
                                $ifdesc = "OpenVPN";
2885
                                break;
2886
                case "enc0":
2887
                        case "ipsec":
2888
                                $ifdesc = "IPsec";
2889
                                break;
2890
        default:
2891
                /* if list */
2892
                $ifdescrs = get_configured_interface_with_descr(false, true);
2893
                foreach ($ifdescrs as $if => $ifname) {
2894
                                if ($if == $interface || $ifname == $interface)
2895
                                        return $ifname;
2896
                }
2897
                break;
2898
        }
2899

    
2900
        return $ifdesc;
2901
}
2902

    
2903
function convert_real_interface_to_friendly_descr($interface) {
2904
        global $config;
2905

    
2906
        $ifdesc = convert_real_interface_to_friendly_interface_name("{$interface}");
2907

    
2908
        if ($ifdesc) {
2909
                $iflist = get_configured_interface_with_descr(false, true);
2910
                return $iflist[$ifdesc];
2911
        }
2912

    
2913
        return $interface;
2914
}
2915

    
2916
/*
2917
 *  interface_translate_type_to_real($interface):
2918
 *              returns the real hardware interface name for a friendly interface.  ie: wan
2919
 */
2920
function interface_translate_type_to_real($interface) {
2921
        global $config;
2922

    
2923
        if ($config['interfaces'][$interface]['if'] <> "")
2924
                return $config['interfaces'][$interface]['if'];
2925
        else
2926
		return $interface;
2927
}
2928

    
2929
function interface_is_wireless_clone($wlif) {
2930
	if(!stristr($wlif, "_wlan")) {
2931
		return false;
2932
	} else {
2933
		return true;
2934
	}
2935
}
2936

    
2937
function interface_get_wireless_base($wlif) {
2938
	if(!stristr($wlif, "_wlan")) {
2939
		return $wlif;
2940
	} else {
2941
		return substr($wlif, 0, stripos($wlif, "_wlan"));
2942
	}
2943
}
2944

    
2945
function interface_get_wireless_clone($wlif) {
2946
	if(!stristr($wlif, "_wlan")) {
2947
		return $wlif . "_wlan0";
2948
	} else {
2949
		return $wlif;
2950
	}
2951
}
2952

    
2953
function get_real_interface($interface = "wan", $get_parent = false) {
2954
    global $config;
2955

    
2956
	$wanif = NULL;
2957

    
2958
	switch ($interface) {
2959
	case "l2tp":
2960
		$wanif = "l2tp";
2961
		break;
2962
	case "pptp":
2963
		$wanif = "pptp";
2964
		break;
2965
	case "pppoe":
2966
		$wanif = "pppoe";
2967
		break;
2968
	case "openvpn":
2969
		$wanif = "openvpn";
2970
		break;
2971
	case "ipsec":
2972
	case "enc0":
2973
		$wanif = "enc0";
2974
		break;
2975
	case "ppp":
2976
		$wanif = "ppp";
2977
		break;
2978
	default:
2979
		// If a real interface was alread passed simply
2980
		// pass the real interface back.  This encourages
2981
		// the usage of this function in more cases so that
2982
		// we can combine logic for more flexibility.
2983
		if(does_interface_exist($interface)) {
2984
			$wanif = $interface;
2985
			break;
2986
		}
2987
		if (empty($config['interfaces'][$interface]))
2988
			break;
2989

    
2990
		$cfg =& $config['interfaces'][$interface];
2991

    
2992
		// Wireless cloned NIC support (FreeBSD 8+)
2993
		// interface name format: $parentnic_wlanparentnic#
2994
		// example: ath0_wlan0
2995
		if (is_interface_wireless($cfg['if'])) {
2996
			$wanif = interface_get_wireless_clone($cfg['if']);
2997
			break;
2998
		}
2999
		/*
3000
		if (empty($cfg['if'])) {
3001
			$wancfg = $cfg['if'];
3002
			break;
3003
		}
3004
		*/
3005

    
3006
		switch ($cfg['ipaddr']) {
3007
			case "carpdev-dhcp":
3008
				$viparr = &$config['virtualip']['vip'];
3009
				if(is_array($viparr))
3010
				foreach ($viparr as $counter => $vip) {
3011
					if ($vip['mode'] == "carpdev-dhcp") {
3012
						if($vip['interface'] == $interface) {
3013
							$wanif = "carp{$counter}";
3014
							break;
3015
						}
3016
					}
3017
				}
3018
				break;
3019
			case "pppoe": 
3020
			case "pptp": 
3021
			case "l2tp": 
3022
			case "ppp":
3023
				$wanif = $cfg['if'];
3024
				if ($get_parent && isset($cfg['ptpid']))
3025
					foreach ($config['ppps']['ppp'] as $ppp) {
3026
						if ($ppp['ptpid'] == $cfg['ptpid'])
3027
							$wanif = $ppp['ports'];
3028
					}
3029
				break;
3030
			default:
3031
				$wanif = $cfg['if'];
3032
				break;
3033
		}
3034
		break;
3035
	}
3036

    
3037
    return $wanif;
3038
}
3039

    
3040
/* Guess the physical interface by providing a IP address */
3041
function guess_interface_from_ip($ipaddress) {
3042
	if(! is_ipaddr($ipaddress)) {
3043
		return false;
3044
	}
3045
	/* create a route table we can search */
3046
	exec("netstat -rnW", $output, $ret);
3047
	foreach($output as $line) {
3048
		if(preg_match("/^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\/[0-9]+[ ]+link[#]/", $line)) {
3049
			$fields = preg_split("/[ ]+/", $line);
3050
			if(ip_in_subnet($ipaddress, $fields[0])) {
3051
				return $fields[6];
3052
			}
3053
		}
3054
	}
3055
	$ret = exec_command("/sbin/route -n get {$ipaddress} | /usr/bin/awk '/interface/ { print \$2; };'");
3056
	if(empty($ret)) {
3057
        	return false;
3058
	}
3059
	return $ret;
3060
}
3061

    
3062
/*
3063
 * find_ip_interface($ip): return the interface where an ip is defined
3064
 */
3065
function find_ip_interface($ip)
3066
{
3067
        /* if list */
3068
        $ifdescrs = get_configured_interface_list();
3069

    
3070
        foreach ($ifdescrs as $ifdescr => $ifname) {
3071
		if ($ip == get_interface_ip($ifname)) {
3072
                	$int = get_real_interface($ifname);
3073
			return $int;
3074
		}
3075
        }
3076
        return false;
3077
}
3078

    
3079
/*
3080
 *   find_number_of_created_carp_interfaces: return the number of carp interfaces
3081
 */
3082
function find_number_of_created_carp_interfaces() {
3083
	return `/sbin/ifconfig | grep "carp:" | wc -l`;
3084
}
3085

    
3086
function get_all_carp_interfaces() {
3087
	$ints = str_replace("\n", " ", `ifconfig | grep "carp:" -B2 | grep ": flag" | cut -d: -f1`);
3088
	return $ints;
3089
}
3090

    
3091
/*
3092
 * find_carp_interface($ip): return the carp interface where an ip is defined
3093
 */
3094
function find_carp_interface($ip) {
3095
	global $config;
3096
	if (is_array($config['virtualip']['vip'])) {
3097
		foreach ($config['virtualip']['vip'] as $vip) {
3098
			if ($vip['mode'] == "carp" || $vip['mode'] == "carpdev") {
3099
				$carp_ip = get_interface_ip($vip['interface']);
3100
				$if = `ifconfig | grep '$ip' -B1 | head -n1 | cut -d: -f1`;
3101
				if ($if)
3102
					return $if;
3103
			}
3104
		}
3105
	}
3106
}
3107

    
3108
function link_carp_interface_to_parent($interface) {
3109
        global $config;
3110

    
3111
        if ($interface == "")
3112
                return;
3113

    
3114
        $carp_ip = get_interface_ip($interface);
3115
        if (!is_ipaddr($carp_ip))
3116
                return;
3117

    
3118
        /* if list */
3119
        $ifdescrs = get_configured_interface_list();
3120
        foreach ($ifdescrs as $ifdescr => $ifname) {
3121
                $interfaceip = get_interface_ip($ifname);
3122
                $subnet_bits = get_interface_subnet($ifname);
3123
                $subnet_ip = gen_subnet("{$interfaceip}", "{$subnet_bits}");
3124
                if(ip_in_subnet($carp_ip, "{$subnet_ip}/{$subnet_bits}"))
3125
                        return $ifname;
3126
        }
3127

    
3128
        return "";
3129
}
3130

    
3131
/****f* interfaces/link_ip_to_carp_interface
3132
 * NAME
3133
 *   link_ip_to_carp_interface - Find where a CARP interface links to.
3134
 * INPUTS
3135
 *   $ip
3136
 * RESULT
3137
 *   $carp_ints
3138
 ******/
3139
function link_ip_to_carp_interface($ip) {
3140
        global $config;
3141

    
3142
        if (!is_ipaddr($ip))
3143
                return;
3144

    
3145
        $carp_ints = "";
3146
        if (is_array($config['virtualip']['vip'])) {
3147
		$first = 0;
3148
		$carp_int = array();
3149
                foreach ($config['virtualip']['vip'] as $vip) {
3150
                        if ($vip['mode'] == "carp" || $vip['mode'] == "carpdev") {
3151
                                $carp_ip = $vip['subnet'];
3152
                                $carp_sn = $vip['subnet_bits'];
3153
                                $carp_nw = gen_subnet($carp_ip, $carp_sn);
3154
                                if (ip_in_subnet($ip, "{$carp_nw}/{$carp_sn}"))
3155
					$carp_int[] = "vip{$vip['vhid']}";
3156
                        }
3157
                }
3158
		if (!empty($carp_int))
3159
			$carp_ints = implode(" ", array_unique($carp_int));
3160
        }
3161

    
3162
        return $carp_ints;
3163
}
3164

    
3165
function link_interface_to_vlans($int, $action = "") {
3166
	global $config;
3167

    
3168
	if (empty($int))
3169
		return;
3170

    
3171
	if (is_array($config['vlans']['vlan'])) {
3172
                foreach ($config['vlans']['vlan'] as $vlan) {
3173
			if ($int == $vlan['if']) {
3174
				if ($action == "update") {
3175
					interfaces_bring_up($int);
3176
				} else if ($action == "")
3177
					return $vlan;
3178
			}
3179
		}
3180
	}
3181
}
3182

    
3183
function link_interface_to_vips($int, $action = "") {
3184
        global $config;
3185

    
3186
        if (is_array($config['virtualip']['vip']))
3187
                foreach ($config['virtualip']['vip'] as $vip)
3188
                        if ($int == $vip['interface']) {
3189
				if ($action == "update")
3190
					interfaces_vips_configure($int);
3191
				else
3192
                                	return $vip;
3193
			}
3194
}
3195

    
3196
/****f* interfaces/link_interface_to_bridge
3197
 * NAME
3198
 *   link_interface_to_bridge - Finds out a bridge group for an interface
3199
 * INPUTS
3200
 *   $ip
3201
 * RESULT
3202
 *   bridge[0-99]
3203
 ******/
3204
function link_interface_to_bridge($int) {
3205
        global $config;
3206

    
3207
        if (is_array($config['bridges']['bridged']))
3208
                foreach ($config['bridges']['bridged'] as $bridge)
3209
                        if(stristr($bridge['members'], "{$int}"))
3210
                                return "{$bridge['bridgeif']}";
3211
}
3212

    
3213
function link_interface_to_gre($interface) {
3214
        global $config;
3215

    
3216
        if (is_array($config['gres']['gre']))
3217
                foreach ($config['gres']['gre'] as $gre)
3218
                        if($gre['if'] == $interface)
3219
                                return "{$gre['greif']}";
3220
}
3221

    
3222
function link_interface_to_gif($interface) {
3223
        global $config;
3224

    
3225
        if (is_array($config['gifs']['gif']))
3226
                foreach ($config['gifs']['gif'] as $gif)
3227
                        if($gif['if'] == $interface)
3228
                                return "{$gif['gifif']}";
3229
}
3230

    
3231
/*
3232
 * find_interface_ip($interface): return the interface ip (first found)
3233
 */
3234
function find_interface_ip($interface, $flush = false)
3235
{
3236
	global $interface_ip_arr_cache;
3237

    
3238
	$interface = str_replace("\n", "", $interface);
3239
	
3240
	if (!does_interface_exist($interface))
3241
		return;
3242

    
3243
	/* Setup IP cache */
3244
	if (!isset($interface_ip_arr_cache[$interface]) or $flush) {
3245
		$ifinfo = pfSense_get_interface_addresses($interface);
3246
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
3247
	}
3248

    
3249
	return $interface_ip_arr_cache[$interface];
3250
}
3251

    
3252
function find_interface_subnet($interface, $flush = false)
3253
{
3254
	global $interface_sn_arr_cache;
3255

    
3256
	$interface = str_replace("\n", "", $interface);
3257
	if (does_interface_exist($interface) == false)
3258
		return;
3259

    
3260
	if (!isset($interface_sn_arr_cache[$interface]) or $flush) {
3261
		$ifinfo = pfSense_get_interface_addresses($interface);
3262
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
3263
        }
3264

    
3265
	return $interface_sn_arr_cache[$interface];
3266
}
3267

    
3268
function get_interface_ip($interface = "wan")
3269
{
3270
	$realif = get_real_interface($interface);
3271
	if (!$realif) {
3272
		if (preg_match("/^carp/i", $interface))
3273
			$realif = $interface;
3274
		else if (preg_match("/^vip/i", $interface))
3275
			$realif = $interface;
3276
		else
3277
			return null;
3278
	}
3279

    
3280
	$curip = find_interface_ip($realif);
3281
	if ($curip && is_ipaddr($curip) && ($curip != "0.0.0.0"))
3282
		return $curip;
3283
	else
3284
		return null;
3285
}
3286

    
3287
function get_interface_subnet($interface = "wan")
3288
{
3289
	$realif = get_real_interface($interface);
3290
	if (!$realif) {
3291
                if (preg_match("/^carp/i", $interface))
3292
                        $realif = $interface;
3293
                else if (preg_match("/^vip/i", $interface))
3294
                        $realif = $interface;
3295
                else
3296
                        return null;
3297
        }
3298

    
3299
	$cursn = find_interface_subnet($realif);
3300
	if (!empty($cursn))
3301
		return $cursn;
3302

    
3303
	return null;
3304
}
3305

    
3306
/* return outside interfaces with a gateway */
3307
function get_interfaces_with_gateway() {
3308
	global $config;
3309

    
3310
	$ints = array();
3311

    
3312
	/* loop interfaces, check config for outbound */
3313
	foreach($config['interfaces'] as $ifdescr => $ifname) {
3314

    
3315
		switch ($ifname['ipaddr']) {
3316
			case "dhcp":
3317
			case "carpdev-dhcp":
3318
			case "ppp";
3319
			case "pppoe":
3320
			case "pptp":
3321
			case "l2tp":
3322
			case "ppp";
3323
				$ints[$ifdescr] = $ifdescr;
3324
			break;
3325
			default:
3326
				if (!empty($ifname['gateway']))
3327
					$ints[$ifdescr] = $ifdescr;
3328
			break;
3329
		}
3330
	}
3331
	return $ints;
3332
}
3333

    
3334
/* return true if interface has a gateway */
3335
function interface_has_gateway($friendly) {
3336
	global $config;
3337

    
3338
	if (!empty($config['interfaces'][$friendly])) {
3339
		$ifname =& $config['interfaces'][$friendly];
3340
		switch ($ifname['ipaddr']) {
3341
			case "dhcp":
3342
			case "carpdev-dhcp":
3343
			case "pppoe":
3344
			case "pptp":
3345
			case "l2tp":
3346
			case "ppp";
3347
				return true;
3348
			break;
3349
			default:
3350
				if (!empty($ifname['gateway']))
3351
					return true;
3352
			break;
3353
		}
3354
	}
3355

    
3356
	return false;
3357
}
3358

    
3359
/****f* interfaces/is_altq_capable
3360
 * NAME
3361
 *   is_altq_capable - Test if interface is capable of using ALTQ
3362
 * INPUTS
3363
 *   $int            - string containing interface name
3364
 * RESULT
3365
 *   boolean         - true or false
3366
 ******/
3367

    
3368
function is_altq_capable($int) {
3369
        /* Per:
3370
         * http://www.freebsd.org/cgi/man.cgi?query=altq&manpath=FreeBSD+7.2-current&format=html
3371
         * Only the following drivers have ALTQ support
3372
         */
3373
	$capable = array("age", "ale", "an", "ath", "aue", "awi", "bce",
3374
			"bfe", "bge", "dc", "de", "ed", "em", "ep", "fxp", "gem",
3375
			"hme", "ipw", "iwi", "jme", "le", "msk", "mxge", "my", "nfe",
3376
			"npe", "nve", "ral", "re", "rl", "rum", "sf", "sis", "sk",
3377
			"ste", "stge", "txp", "udav", "ural", "vge", "vr", "wi", "xl",
3378
			"ndis", "tun", "ovpns", "ovpnc", "vlan", "pppoe", "pptp", "ng", "ppp");
3379

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

    
3382
        if (in_array($int_family[0], $capable))
3383
                return true;
3384
	else if (stristr($int_family, "vlan")) /* VLANs are name $parent.$vlan now */
3385
		return true;
3386
        else
3387
                return false;
3388
}
3389

    
3390
/****f* interfaces/is_interface_wireless
3391
 * NAME
3392
 *   is_interface_wireless - Returns if an interface is wireless
3393
 * RESULT
3394
 *   $tmp       - Returns if an interface is wireless
3395
 ******/
3396
function is_interface_wireless($interface) {
3397
        global $config, $g;
3398

    
3399
        $friendly = convert_real_interface_to_friendly_interface_name($interface);
3400
        if(!isset($config['interfaces'][$friendly]['wireless'])) {
3401
                if (preg_match($g['wireless_regex'], $interface)) {
3402
                        $config['interfaces'][$friendly]['wireless'] = array();
3403
                        return true;
3404
                }
3405
                unset($config['interfaces'][$friendly]['wireless']);
3406
                return false;
3407
        } else
3408
                return true;
3409
}
3410

    
3411
function get_wireless_modes($interface) {
3412
	/* return wireless modes and channels */
3413
	$wireless_modes = array();
3414

    
3415
	$wlif = interface_translate_type_to_real($interface);
3416

    
3417
	if(is_interface_wireless($wlif)) {
3418
		$cloned_interface = get_real_interface($interface);
3419
		$chan_list = "/sbin/ifconfig {$cloned_interface} list chan";
3420
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
3421
		$format_list = "/usr/bin/awk '{print \$5 \" \" \$6 \",\" \$1}'";
3422

    
3423
		$interface_channels = "";
3424
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
3425
		$interface_channel_count = count($interface_channels);
3426

    
3427
		$c = 0;
3428
		while ($c < $interface_channel_count)
3429
		{
3430
			$channel_line = explode(",", $interface_channels["$c"]);
3431
			$wireless_mode = trim($channel_line[0]);
3432
			$wireless_channel = trim($channel_line[1]);
3433
			if(trim($wireless_mode) != "") {
3434
				/* if we only have 11g also set 11b channels */
3435
				if($wireless_mode == "11g") {
3436
					if(!isset($wireless_modes["11b"]))
3437
						$wireless_modes["11b"] = array();
3438
				} else if($wireless_mode == "11g ht") {
3439
					if(!isset($wireless_modes["11b"]))
3440
						$wireless_modes["11b"] = array();
3441
					if(!isset($wireless_modes["11g"]))
3442
						$wireless_modes["11g"] = array();
3443
					$wireless_mode = "11ng";
3444
				} else if($wireless_mode == "11a ht") {
3445
					if(!isset($wireless_modes["11a"]))
3446
						$wireless_modes["11a"] = array();
3447
					$wireless_mode = "11na";
3448
				}
3449
				$wireless_modes["$wireless_mode"]["$c"] = $wireless_channel;
3450
			}
3451
			$c++;
3452
		}
3453
	}
3454
	return($wireless_modes);
3455
}
3456

    
3457
/* return channel numbers, frequency, max txpower, and max regulation txpower */
3458
function get_wireless_channel_info($interface) {
3459
	$wireless_channels = array();
3460

    
3461
	$wlif = interface_translate_type_to_real($interface);
3462

    
3463
	if(is_interface_wireless($wlif)) {
3464
		$cloned_interface = get_real_interface($interface);
3465
		$chan_list = "/sbin/ifconfig {$cloned_interface} list txpower";
3466
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
3467
		$format_list = "/usr/bin/awk '{print \$1 \",\" \$3 \" \" \$4 \",\" \$5 \",\" \$7}'";
3468

    
3469
		$interface_channels = "";
3470
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
3471

    
3472
		foreach ($interface_channels as $channel_line) {
3473
			$channel_line = explode(",", $channel_line);
3474
			if(!isset($wireless_channels[$channel_line[0]]))
3475
				$wireless_channels[$channel_line[0]] = $channel_line;
3476
		}
3477
	}
3478
	return($wireless_channels);
3479
}
3480

    
3481
/****f* interfaces/get_interface_mtu
3482
 * NAME
3483
 *   get_interface_mtu - Return the mtu of an interface
3484
 * RESULT
3485
 *   $tmp       - Returns the mtu of an interface
3486
 ******/
3487
function get_interface_mtu($interface) {
3488
        $mtu = pfSense_get_interface_addresses($interface);
3489
        return $mtu['mtu'];
3490
}
3491

    
3492
function get_interface_mac($interface) {
3493

    
3494
	$macinfo = pfSense_get_interface_addresses($interface);
3495
	return $macinfo["macaddr"];
3496
}
3497

    
3498
/****f* pfsense-utils/generate_random_mac_address
3499
 * NAME
3500
 *   generate_random_mac - generates a random mac address
3501
 * INPUTS
3502
 *   none
3503
 * RESULT
3504
 *   $mac - a random mac address
3505
 ******/
3506
function generate_random_mac_address() {
3507
        $mac = "02";
3508
        for($x=0; $x<5; $x++)
3509
                $mac .= ":" . dechex(rand(16, 255));
3510
        return $mac;
3511
}
3512

    
3513
/****f* interfaces/is_jumbo_capable
3514
 * NAME
3515
 *   is_jumbo_capable - Test if interface is jumbo frame capable.  Useful for determining VLAN capability.
3516
 * INPUTS
3517
 *   $int             - string containing interface name
3518
 * RESULT
3519
 *   boolean          - true or false
3520
 ******/
3521
function is_jumbo_capable($int) {
3522
        global $g;
3523

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

    
3526
        if (in_array($int_family[0], $g['vlan_long_frame']))
3527
                return true;
3528
        else
3529
                return false;
3530
}
3531

    
3532
function setup_pppoe_reset_file($pppif, $iface="") {
3533
	global $g;
3534
	$cron_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
3535

    
3536
	if(!empty($iface) && !empty($pppif)){
3537
		$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";
3538
		file_put_contents($cron_file, $cron_cmd);
3539
		chmod($cron_file, 0700);
3540
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
3541
	} else
3542
		unlink_if_exists($cron_file);
3543
}
3544

    
3545
?>
(21-21/50)