Project

General

Profile

Download (80.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/mpd4
40
	pfSense_MODULE:	interfaces
41

    
42
*/
43

    
44
/* include all configuration functions */
45
require_once("globals.inc");
46

    
47
function interfaces_bring_up($interface) {
48
	if(!$interface) {
49
		log_error("bring_interface_up was called but no variable defined.");
50
		log_error( "Backtrace: " . var_dump(debug_backtrace()) );
51
		return;
52
	}
53
	mwexec("/sbin/ifconfig " . escapeshellarg($interface) . " up");
54
}
55

    
56
/*
57
 * Return the interface array
58
 */
59
function get_interface_arr($flush = false) {
60
        global $interface_arr_cache;
61

    
62
        /* If the cache doesn't exist, build it */
63
        if (!isset($interface_arr_cache) or $flush)
64
                $interface_arr_cache = `/sbin/ifconfig -l`;
65

    
66
        return $interface_arr_cache;
67
}
68

    
69
/*
70
 * does_interface_exist($interface): return true or false if a interface is
71
 * detected.
72
 */
73
function does_interface_exist($interface) {
74
        global $config;
75

    
76
        if(!$interface)
77
                return false;
78

    
79
        $ints = get_interface_arr();
80
        if(stristr($ints, $interface) !== false)
81
                return true;
82
        else
83
                return false;
84
}
85

    
86
function interfaces_loopback_configure() {
87
	mwexec("/sbin/ifconfig lo0 127.0.0.1");
88
	interfaces_bring_up("lo0");
89
	exec("/sbin/route add 127.0.0.2 127.0.0.1");
90
	return 0;
91
}
92

    
93
function interfaces_vlan_configure() {
94
	global $config;
95
	if (is_array($config['vlans']['vlan']) && count($config['vlans']['vlan'])) {
96
		foreach ($config['vlans']['vlan'] as $vlan) {
97
			if(empty($vlan['vlanif']))
98
				$vlan['vlanif'] = "{$vlan['if']}_vlan{$vlan['tag']}";
99
			/* XXX: Maybe we should report any errors?! */
100
			interface_vlan_configure($vlan);
101
		}
102
	}
103
}
104

    
105
function interface_vlan_configure(&$vlan) {
106
        global $config, $g;
107

    
108
	if (!is_array($vlan)) {
109
		log_error("VLAN: called with wrong options. Problems with config!");
110
		return;
111
	}
112
	$if = $vlan['if'];
113
	$vlanif  = empty($vlan['vlanif']) ? "{$if}_vlan{$vlan['tag']}" : $vlan['vlanif'];
114
	$tag = $vlan['tag'];
115

    
116
	if(empty($if)) {
117
		log_error("interface_vlan_confgure called with if undefined.");
118
		return;
119
	}
120

    
121
        /* make sure the parent interface is up */
122
	interfaces_bring_up($if);
123
	/* Since we are going to add vlan(4) try to enable all that hardware supports. */
124
	mwexec("/sbin/ifconfig {$if} vlanhwtag");
125
	mwexec("/sbin/ifconfig {$if} vlanmtu");
126

    
127
	if (!empty($vlanif) && does_interface_exist($vlanif)) {
128
		mwexec("/sbin/ifconfig {$vlanif} delete");
129
	} else {
130
		$tmpvlanif = exec("/sbin/ifconfig vlan create");
131
		mwexec("/sbin/ifconfig {$tmpvlanif} name {$vlanif}");
132
	}
133
	
134
	mwexec("/sbin/ifconfig {$vlanif} vlan " .
135
		escapeshellarg($tag) . " vlandev " .
136
		escapeshellarg($if));
137

    
138
	interfaces_bring_up($vlanif);
139

    
140
    /* invalidate interface cache */
141
    get_interface_arr(true);
142

    
143
    /*   all vlans need to spoof their parent mac address, too.  see
144
     *   ticket #1514: http://cvstrac.pfsense.com/tktview?tn=1514,33
145
     */
146
    foreach($config['interfaces'] as $interfaces) {
147
		if($interfaces['if'] == $if && $interfaces['spoofmac']) {
148
			mwexec("/sbin/ifconfig " . escapeshellarg($vlanif) .
149
				" link " . escapeshellarg($interfaces['spoofmac']));
150
		}
151
	}
152

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

    
156
	return $vlanif;
157
}
158

    
159
function interface_qinq_configure(&$vlan, $fd = NULL) {
160
        global $config, $g;
161

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

    
167
        $if = $vlan['if'];
168
        $vlanif = empty($vlan['vlanif']) ? "vlan{$vlan['tag']}" : $vlan['vlanif'];
169
        $tag = $vlan['tag'];
170
        if(empty($if)) {
171
                log_error("interface_qinq_confgure called with if undefined.\n");
172
                return;
173
        }
174

    
175
        if ($fd == NULL) {
176
                $exec = true;
177
                $fd = fopen("{$g['tmp_path']}/netgraphcmd", "w");
178
        } else
179
                $exec = false;
180
        /* make sure the parent is converted to ng_vlan(4) and is up */
181
        interfaces_bring_up($if);
182
        /* Since we are going to add ng_vlan(4) try to enable all that hardware supports. */
183
        mwexec("/sbin/ifconfig {$if} vlanhwtag\n");
184
        mwexec("/sbin/ifconfig {$if} vlanmtu\n");
185

    
186
        if (!empty($vlanif) && does_interface_exist($vlanif)) {
187
                fwrite($fd, "shutdown {$if}qinq:\n");
188
                exec("/usr/sbin/ngctl msg {$if}qinq: gettable", $result);
189
                if (empty($result)) {
190
                        fwrite($fd, "mkpeer {$if}: vlan lower downstream\n");
191
                        fwrite($fd, "name {$if}:lower {$if}qinq\n");
192
                        fwrite($fd, "connect {$if}: {$if}qinq: upper nomatch\n");
193
                }
194
        } else {
195
                fwrite($fd, "mkpeer {$if}: vlan lower downstream\n");
196
                fwrite($fd, "name {$if}:lower {$if}qinq\n");
197
                fwrite($fd, "connect {$if}: {$if}qinq: upper nomatch\n");
198
        }
199

    
200
        if (!$g['booting']) {
201
                if (!empty($vlan['members'])) {
202
                        $members = explode(" ", $vlan['members']);
203
                        foreach ($members as $qtag) {
204
                                fwrite($fd, "shutdown {$vlanif}h{$qtag}:\n");
205
                        }
206
                }
207
                fwrite($fd, "shutdown vlanh{$tag}:\n");
208
        }
209
        fwrite($fd, "mkpeer {$if}qinq: eiface vlan{$tag} ether\n");
210
        fwrite($fd, "name {$if}qinq:vlan{$tag} vlanh{$tag}\n");
211
        fwrite($fd, "msg {$if}qinq: addfilter { vlan={$tag} hook=\"vlan{$tag}\" }\n");
212
        fwrite($fd, "msg vlanh{$tag}: setifname \"{$vlanif}\"\n");
213
        $macaddr = get_interface_mac($if);
214
        fwrite($fd, "msg {$vlanif}: setenaddr {$macaddr}\n");
215

    
216
        interfaces_bring_up($vlanif);
217

    
218
        /* invalidate interface cache */
219
        get_interface_arr(true);
220

    
221
        if (!stristr($if, "vlan"))
222
                mwexec("/sbin/ifconfig {$if} promisc\n");
223

    
224
        if (!empty($vlan['members'])) {
225
                $members = explode(" ", $vlan['members']);
226
                foreach ($members as $qtag) {
227
                        $qinq = array();
228
                        $qinq['tag'] = $qtag;
229
                        $qinq['if'] = $vlanif;
230
                        interface_qinq2_configure($qinq, $fd, $macaddr);
231
                }
232
        }
233
        if ($exec == true) {
234
                fclose($fd);
235
                mwexec("/usr/sbin/ngctl -f {$g['tmp_path']}/netgraphcmd");
236
        }
237

    
238
        interfaces_bring_up($if);
239
        if (!empty($vlan['members'])) {
240
                $members = explode(" ", $vlan['members']);
241
                foreach ($members as $qif)
242
                        interfaces_bring_up("{$vlanif}.{$qif}");
243
        }
244

    
245
        return $vlanif;
246
}
247

    
248
function interfaces_qinq_configure() {
249
        global $config, $g;
250
        if (is_array($config['qinqs']['qinqentry']) && count($config['qinqs']['qinqentry'])) {
251
                $fd = fopen("{$g['tmp_path']}/netgraphcmd", "w");
252
                foreach ($config['qinqs']['qinqentry'] as $qinq) {
253
                        /* XXX: Maybe we should report any errors?! */
254
                        interface_qinq_configure($qinq, $fd);
255
                }
256
                fclose($fd);
257
                mwexec("/usr/sbin/ngctl -f {$g['tmp_path']}/netgraphcmd");
258
        }
259
}
260

    
261
function interface_qinq2_configure(&$qinq, $fd, $macaddr) {
262
        global $config, $g;
263

    
264
        if (!is_array($qinq)) {
265
                log_error("QinQ compat VLAN: called with wrong options. Problems with config!\n");
266
                return;
267
        }
268

    
269
        $if = $qinq['if'];
270
        $tag = $qinq['tag'];
271
        $vlanif = "{$if}_{$tag}";
272
        if(empty($if)) {
273
                log_error("interface_qinq_confgure called with if undefined.\n");
274
                return;
275
        }
276

    
277
        $result = array();
278
        exec("/usr/sbin/ngctl msg {$if}qinq: gettable", $result);
279
        if (empty($result)) {
280
                fwrite($fd, "mkpeer {$if}: vlan lower downstream\n");
281
                fwrite($fd, "name {$if}:lower {$if}qinq \n");
282
                fwrite($fd, "connect {$if}: {$if}qinq: upper nomatch\n");
283
        }
284

    
285
        //fwrite($fd, "shutdown ${if}h{$tag}:\n");
286
        fwrite($fd, "mkpeer {$if}qinq: eiface {$if}{$tag} ether\n");
287
        fwrite($fd, "name {$if}qinq:{$if}{$tag} {$if}h{$tag}\n");
288
        fwrite($fd, "msg {$if}qinq: addfilter { vlan={$tag} hook=\"{$if}{$tag}\" }\n");
289
        fwrite($fd, "msg {$if}h{$tag}: setifname \"{$vlanif}\"\n");
290
        fwrite($fd, "msg {$vlanif}: setenaddr {$macaddr}\n");
291
        interfaces_bring_up($vlanif);
292

    
293
        /* invalidate interface cache */
294
        get_interface_arr(true);
295

    
296
        return $vlanif;
297
}
298

    
299
function interfaces_bridge_configure() {
300
        global $config;
301

    
302
        $i = 0;
303
        if (is_array($config['bridges']['bridged']) && count($config['bridges']['bridged'])) {
304
                foreach ($config['bridges']['bridged'] as $bridge) {
305
                        if(empty($bridge['bridgeif']))
306
                                $bridge['bridgeif'] = "bridge{$i}";
307
                        /* XXX: Maybe we should report any errors?! */
308
                        interface_bridge_configure($bridge);
309
                        $i++;
310
                }
311
        }
312
}
313

    
314
function interface_bridge_configure(&$bridge) {
315
	global $config, $g;
316

    
317
	if (!is_array($bridge))
318
	        return -1;
319

    
320
	if (empty($bridge['members'])) {
321
		log_error("No members found on {$bridge['bridgeif']}");
322
		return -1;
323
	}
324

    
325
	$members = explode(',', $bridge['members']);
326
	if (!count($members))
327
		return -1;
328
	
329
	$checklist = get_configured_interface_list();
330

    
331
	if ($g['booting'] || !empty($bridge['bridgeif'])) {
332
		mwexec("/sbin/ifconfig {$bridge['bridgeif']} destroy");
333
		mwexec("/sbin/ifconfig {$bridge['bridgeif']} create");
334
		$bridgeif = $bridge['bridgeif'];
335
	} else {
336
		$bridgeif = exec("/sbin/ifconfig bridge create");
337
	}
338

    
339
	/* Calculate smaller mtu and enforce it */
340
	$smallermtu = 0;
341
	foreach ($members as $member) {
342
		$realif = get_real_interface($member);
343
		$mtu = get_interface_mtu($realif);
344
		if ($smallermtu == 0 && !empty($mtu))
345
			$smallermtu = $mtu;
346
		else if (!empty($mtu) && $mtu < $smallermtu)
347
			$smallermtu = $mtu;
348
	}
349
	 
350
	/* Just in case anything is not working well */
351
	if ($smallermtu == 0)
352
		$smallermtu = 1500; 
353

    
354
	/* Add interfaces to bridge */
355
	foreach ($members as $member) {
356
		if (!array_key_exists($member, $checklist))
357
			continue;
358
		$realif = get_real_interface($member);
359
		$realif =  escapeshellarg($realif);
360
		/* make sure the parent interface is up */
361
		mwexec("/sbin/ifconfig {$realif} mtu {$smallermtu}");
362
		if(!$realif) 
363
			log_error("realif not defined in interfaces bridge - up");
364
		interfaces_bring_up($realif);
365
		mwexec("/sbin/ifconfig {$bridgeif} addm {$realif}");	
366
	}
367

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

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

    
468
	if($bridgeif)
469
		interfaces_bring_up($bridgeif);	
470
	else 
471
		log_error("bridgeif not defined -- could not bring interface up");
472

    
473
	return $bridgeif;
474
}
475

    
476
function interfaces_lagg_configure() 
477
{
478
        global $config;
479

    
480
        $i = 0;
481
        if (is_array($config['laggs']['lagg']) && count($config['laggs']['lagg'])) {
482
                foreach ($config['laggs']['lagg'] as $lagg) {
483
                        if(empty($lagg['laggif']))
484
                                $lagg['laggif'] = "lagg{$i}";
485
                        /* XXX: Maybe we should report any errors?! */
486
                        interface_lagg_configure($lagg);
487
                        $i++;
488
                }
489
        }
490
}
491

    
492
function interface_lagg_configure(&$lagg) {
493
        global $config, $g;
494

    
495
        if (!is_array($lagg))
496
		return -1;
497

    
498
	$members = explode(',', $lagg['members']);
499
	if (!count($members))
500
		return -1;
501
	
502
	$checklist = get_interface_list();
503

    
504
	if ($g['booting'] || !(empty($lagg['laggif']))) {
505
                mwexec("/sbin/ifconfig {$lagg['laggif']} destroy");
506
                mwexec("/sbin/ifconfig {$lagg['laggif']} create");
507
                $laggif = $lagg['laggif'];
508
        } else
509
                $laggif = exec("/sbin/ifconfig lagg create");
510

    
511
	/* Calculate smaller mtu and enforce it */
512
        $smallermtu = 0;
513
        foreach ($members as $member) {
514
                $mtu = get_interface_mtu($member);
515
		if ($smallermtu == 0 && !empty($mtu))
516
			$smallermtu = $mtu;
517
                else if (!empty($mtu) && $mtu < $smallermtu)
518
                        $smallermtu = $mtu;
519
        }
520

    
521
	/* Just in case anything is not working well */
522
        if ($smallermtu == 0)
523
                $smallermtu = 1500;
524

    
525
	foreach ($members as $member) {
526
		if (!array_key_exists($member, $checklist))
527
			continue;
528
		/* make sure the parent interface is up */
529
		mwexec("/sbin/ifconfig {$member} mtu {$smallermtu}");
530
		interfaces_bring_up($member);
531
		mwexec("/sbin/ifconfig {$laggif} laggport {$member}");
532
	}
533
	
534
	mwexec("/sbin/ifconfig {$laggif} laggproto {$lagg['proto']}");
535

    
536
	interfaces_bring_up($laggif);
537

    
538
	return $laggif;
539
}
540

    
541
function interfaces_gre_configure() {
542
        global $config;
543

    
544
        $i = 0;
545
        if (is_array($config['gres']['gre']) && count($config['gres']['gre'])) {
546
                foreach ($config['gres']['gre'] as $gre) {
547
                        if(empty($gre['greif']))
548
                                $gre['greif'] = "gre{$i}";
549
                        /* XXX: Maybe we should report any errors?! */
550
                        interface_gre_configure($gre);
551
                        $i++;
552
                }
553
        }
554
}
555

    
556
function interface_gre_configure(&$gre) {
557
        global $config, $g;
558

    
559
	if (!is_array($gre))
560
		return -1;
561

    
562
	$realif = get_real_interface($gre['if']);
563
	$realifip = get_interface_ip($gre['if']);
564

    
565
	/* make sure the parent interface is up */
566
	interfaces_bring_up($realif);
567

    
568
	if ($g['booting'] || !(empty($gre['greif']))) {
569
		mwexec("/sbin/ifconfig {$gre['greif']} destroy");
570
		mwexec("/sbin/ifconfig {$gre['greif']} create");
571
		$greif = $gre['greif'];
572
	} else {
573
		$greif = exec("/sbin/ifconfig gre create");
574
	}
575

    
576
	/* Do not change the order here for more see gre(4) NOTES section. */
577
	mwexec("/sbin/ifconfig {$greif} tunnel {$realifip} {$gre['remote-addr']}");
578
	mwexec("/sbin/ifconfig {$greif} {$gre['tunnel-local-addr']} {$gre['tunnel-remote-addr']} netmask " . gen_subnet_mask($gre['tunnel-remote-net']));
579
	if (isset($gre['link0']) && $gre['link0'])
580
		mwexec("/sbin/ifconfig {$greif} link0");
581
	if (isset($gre['link1']) && $gre['link1'])
582
		mwexec("/sbin/ifconfig {$greif} link1");
583
	if (isset($gre['link2']) && $gre['link2'])
584
		mwexec("/sbin/ifconfig {$greif} link2");
585

    
586
	if($greif)
587
		interfaces_bring_up($greif);
588
	else 
589
		log_error("Could not bring greif up -- variable not defined.");
590

    
591
	mwexec("/sbin/route add {$gre['remote-addr']}/{$gre['tunnel-remote-net']} {$realifip}");
592
	file_put_contents("/tmp/{$greif}_router", $gre['tunnel-remote-addr']);
593

    
594
	return $greif;
595
}
596

    
597
function interfaces_gif_configure() {
598
        global $config;
599

    
600
        $i = 0;
601
        if (is_array($config['gifs']['gif']) && count($config['gifs']['gif'])) {
602
                foreach ($config['gifs']['gif'] as $gif) {
603
                        if(empty($gif['gifif']))
604
                                $gre['gifif'] = "gif{$i}";
605
                        /* XXX: Maybe we should report any errors?! */
606
                        interface_gif_configure($gif);
607
                        $i++;
608
                }
609
        }
610
}
611

    
612
function interface_gif_configure(&$gif) {
613
        global $config, $g;
614

    
615
        if (!is_array($gif))
616
                return -1;
617

    
618
        $realif = get_real_interface($gif['if']);
619
        $realifip = get_interface_ip($gif['if']);
620

    
621
        /* make sure the parent interface is up */
622
		if($realif)
623
			interfaces_bring_up($realif);
624
		else 
625
			log_error("could not bring realif up -- variable not defined -- interface_gif_configure()");
626

    
627
        if ($g['booting'] || !(empty($gif['gifif']))) {
628
                mwexec("/sbin/ifconfig {$gif['gifif']} destroy");
629
                mwexec("/sbin/ifconfig {$gif['gifif']} create");
630
                $gifif = $gif['gifif'];
631
        } else
632
                $gifif = exec("/sbin/ifconfig gif create");
633

    
634
        /* Do not change the order here for more see gif(4) NOTES section. */
635
        mwexec("/sbin/ifconfig {$gifif} tunnel {$realifip} {$gif['remote-addr']}");
636
        mwexec("/sbin/ifconfig {$gifif} {$gif['tunnel-local-addr']} {$gif['tunnel-remote-addr']} netmask " . gen_subnet_mask($gif['tunnel-remote-net']));
637
        if (isset($gif['link0']) && $gif['link0'])
638
                mwexec("/sbin/ifconfig {$gifif} link0");
639
        if (isset($gif['link1']) && $gif['link1'])
640
                mwexec("/sbin/ifconfig {$gifif} link1");
641
		if($gifif)
642
			interfaces_bring_up($gifif);
643
		else
644
		 	log_error("could not bring gifif up -- variable not defined");
645
        mwexec("/sbin/route add {$gif['remote-addr']}/{$gif['tunnel-remote-net']} {$realifip}");
646
		file_put_contents("/tmp/{$gifif}_router", $gif['tunnel-remote-addr']);
647

    
648
        return $gifif;
649
}
650

    
651
function interfaces_configure() {
652
	global $config, $g;
653

    
654
	/* Set up our loopback interface */
655
	interfaces_loopback_configure();
656

    
657
	/* set up LAGG virtual interfaces */
658
	interfaces_lagg_configure();
659

    
660
	/* set up VLAN virtual interfaces */
661
	interfaces_vlan_configure();
662

    
663
	interfaces_qinq_configure();
664

    
665
	/* Set up PPP interfaces */
666
	interfaces_ppp_configure();
667

    
668
	$iflist = get_configured_interface_with_descr();
669
	$delayed_list = array();
670
	$bridge_list = array();
671
	
672
	foreach($iflist as $if => $ifname) {
673
		$realif = $config['interfaces'][$if]['if'];
674
		if(is_array($realif['pppoe']) && isset($realif['pppoe']['pppoe-reset-type']))
675
			setup_pppoe_reset_file($if, true);
676
		else 
677
			setup_pppoe_reset_file($if, false);
678
		if (strstr($realif, "bridge")) 
679
			$bridge_list[$if] = $ifname;
680
		else if (strstr($realif, "gre"))
681
			$delayed_list[$if] = $ifname;
682
		else if (strstr($realif, "gif"))
683
			$delayed_list[$if] = $ifname;
684
		else {
685
			if ($g['booting'])
686
				echo "Configuring {$ifname} interface...";
687
        		if($g['debug'])
688
				log_error("Configuring {$ifname}");
689
			interface_configure($if, true);
690
			if ($g['booting']) 
691
				echo "done.\n";
692
		}
693
	}
694

    
695
	/* set up GRE virtual interfaces */
696
	interfaces_gre_configure();
697

    
698
	/* set up GIF virtual interfaces */
699
	interfaces_gif_configure();
700
	
701
	foreach ($delayed_list as $if => $ifname) {
702
		if ($g['booting'])
703
			echo "Configuring {$ifname} interface...";
704
        	if ($g['debug'])
705
        		log_error("Configuring {$ifname}");
706

    
707
		interface_configure($if, true);
708

    
709
		if ($g['booting'])
710
			echo "done.\n";
711
	}
712

    
713
	/* set up BRIDGe virtual interfaces */
714
	interfaces_bridge_configure();
715

    
716
	foreach ($bridge_list as $if => $ifname) {
717
		if ($g['booting'])
718
			echo "Configuring {$ifname} interface...";
719
		if($g['debug'])
720
			log_error("Configuring {$ifname}");
721

    
722
		interface_configure($if, true);
723

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

    
728
	/* bring up vip interfaces */
729
	interfaces_vips_configure();
730

    
731
	/* configure interface groups */
732
	interfaces_group_setup();
733

    
734
	if (!$g['booting']) {
735
		/* reconfigure static routes (kernel may have deleted them) */
736
		system_routing_configure();
737

    
738
		/* reload IPsec tunnels */
739
		vpn_ipsec_configure();
740

    
741
		/* reload dhcpd (interface enabled/disabled status may have changed) */
742
		services_dhcpd_configure();
743

    
744
		/* restart dnsmasq */
745
		services_dnsmasq_configure();
746

    
747
		/* reload captive portal */
748
		captiveportal_configure();
749

    
750
		/* set the reload filter dity flag */
751
		filter_configure();
752
	}
753

    
754
	return 0;
755
}
756

    
757
function interface_reconfigure($interface = "wan") {
758
	interface_bring_down($interface);
759
	sleep(1);
760
	interface_configure($interface);
761
}
762

    
763
function interface_vip_bring_down(&$vip) {
764

    
765
	switch ($vip['mode']) {
766
	case "proxyarp":
767
		interfaces_proxyarp_configure();
768
		break;
769
	case "ipalias":
770
		mwexec("/sbin/ifconfig " . get_real_interface($vip['interface']) . " delete {$vip['subnet']}");
771
		break;
772
	case "carp":
773
	case "carpdev-dhcp":
774
		$vipif = "vip" . $vip['vhid'];
775
		mwexec("/sbin/ifconfig {$vipif} delete");
776
                mwexec("/sbin/ifconfig {$vipif} down");
777
		mwexec("/sbin/ifconfig {$vipif} destroy");
778
		break;
779
	}
780

    
781
}
782

    
783
function interface_bring_down($interface = "wan", $destroy = false) {
784
	global $config, $g;
785

    
786
	if (!isset($config['interfaces'][$interface]))
787
		return; 
788

    
789
	$ifcfg = $config['interfaces'][$interface];
790

    
791
	$realif = get_real_interface($interface);
792

    
793
	mwexec("/usr/sbin/arp -d -i {$realif} -a");
794

    
795
        /* remove interface up file if it exists */
796
        unlink_if_exists("{$g['tmp_path']}/{$realif}up");
797
        unlink_if_exists("{$g['vardb_path']}/{$interface}ip");
798
		unlink_if_exists("/tmp/{$realif}_router");
799
        //unlink_if_exists("{$g['varetc_path']}/nameservers.conf");
800

    
801
	switch ($ifcfg['ipaddr']) {
802
	case "pppoe":
803
		killbypid("{$g['varrun_path']}/pppoe_{$interface}.pid");
804
        	sleep(2);
805
                unlink_if_exists("{$g['varetc_path']}/mpd_{$interface}.conf");
806
                unlink_if_exists("{$g['varetc_path']}/mpd_{$interface}.links");
807
		break;
808
	case "pptp":
809
		killbypid("{$g['varrun_path']}/pptp_{$interface}.pid");
810
        	sleep(2);
811
                unlink_if_exists("{$g['varetc_path']}/mpd_{$interface}.conf");
812
                unlink_if_exists("{$g['varetc_path']}/mpd_{$interface}.links");
813
		break;
814
	case "carpdev-dhcp":
815
		/* 
816
		 * NB: When carpdev gets enabled it would be better to be handled as all
817
		 *	other interfaces! 
818
		 */
819
	case "dhcp":
820
        	$pid = find_dhclient_process($interface);
821
        	if($pid)
822
                	mwexec("kill {$pid}");
823
               	sleep(1);
824
                unlink_if_exists("{$g['varetc_path']}/dhclient_{$interface}.conf");
825
		mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete");
826
		mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " down");
827
		break;
828
	default:
829
		mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete");
830
		mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " down");
831
		break;
832
	}
833

    
834
	if ($destroy == true) {
835
		if (preg_match("/^tun|^ppp|^ovpn|^gif|^gre|^lagg|^bridge|vlan/i", $realif))
836
                	mwexec("/sbin/ifconfig {$realif} destroy");
837
	}
838
	
839
	return;
840
}
841

    
842
function interfaces_ppp_configure() {
843
	global $config;
844
	if($g['booting']) 
845
		conf_mount_rw();
846
	if($config['ppps']['ppp']) {
847
		foreach($config['ppps']['ppp'] as $ppp) {
848
			$dev = substr($ppp['port'], 5);
849
			interface_ppp_configure($dev);
850
		}
851
	}
852
	if(!$g['booting']) 
853
		conf_mount_ro();
854
}
855

    
856
function interface_ppp_configure($ifcfg) {
857
	global $config, $g;
858
	
859
	/* Remove  the /dev/ from the device name. */
860
	$orig_dev = $ifcfg;
861

    
862
	// ppp (userland) requires a /var/spool/lock directory
863
	if(!is_dir("/var/spool/lock")) {
864
		exec("mkdir -p /var/spool/lock");
865
		exec("chmod a+rw /var/spool/lock/.");
866
	}
867

    
868
	// Construct the ppp.conf file
869
	$peerfile .= "default:\n";
870
	$peerfile .= " set log Phase Chat LCP IPCP CCP tun command\n";
871
	$peerfile .= " ident user-ppp VERSION (built COMPILATIONDATE)\n";
872
	$peerfile .= " set dial \"ABORT BUSY ABORT NO\\\sCARRIER TIMEOUT 5 \\\n";
873
	$peerfile .= " 		\\\"\\\" AT OK-AT-OK ATE1Q0 OK \\\dATDT\\\T TIMEOUT 40 CONNECT\"\n";
874
	$peerfile .= " enable dns\n";
875
	$peerfile .= " nat enable yes\n";
876
	$peerfile .= " set reconnect {$ifcfg['connect-max-attempts']} 5\n";
877
	$peerfile .= " allow users root\n\n";
878

    
879
	// Loop variables
880
    $i = 0;
881
	$startingip = 1;
882
	
883
    if (is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) {
884
		foreach ($config['ppps']['ppp'] as $ppp) {
885
			$dev = substr($ppp['port'], 5);
886
			$realif  = $ppp['port'];
887
			$peerfile .= "{$dev}:\n";
888
			$peerfile .= " set device {$realif}\n";
889
			if($ppp['dialcmd'])
890
				$peerfile .= " set dial {$ppp['dialcmd']}\n";
891
			$peerfile .= " set speed \"{$ppp['linespeed']}\"\n";
892
			$peerfile .= " add default HISADDR\n";
893
			$peerfile .= " set timeout 0\n";
894
			$endingip = $startingip+1;
895
			if($ppp['localip'])
896
				$startingip = $ppp['localip'];
897
			if($ppp['gateway'])
898
				$endingip = $ppp['gateway'];
899
			$peerfile .= " set ifaddr 10.0.0.{$startingip}/0 10.0.0.{$endingip}/0 255.255.255.0 0.0.0.0\n";
900
			$peerfile .= " set phone \"{$ppp['phone']}\"\n";
901
			$peerfile .= " set authname \"{$ppp['username']}\"\n";
902
			$peerfile .= " set authkey \"{$ppp['password']}\"\n";
903
			$peerfile .= "\n";
904
			$i++;
905
			$startingip++;
906
		}
907
    }
908

    
909
	$rclinkup = "default:\n";
910
	$rclinkup.= "! sh -c \"/etc/rc.filter_configure_sync\"";
911

    
912
	// Write out configuration for ppp.conf
913
	file_put_contents("/etc/ppp/ppp.conf", $peerfile);
914

    
915
	// Write out linkup file
916
	file_put_contents("/etc/ppp/ppp.linkup", $rclinkup);
917

    
918
	// Launch specified ppp instance
919
	$running = `ps awux | grep ppp | grep -v grep | grep $orig_dev`;
920
	if(!$running)
921
		mwexec("/usr/sbin/ppp -background {$orig_dev}");
922
}
923

    
924
function interfaces_carp_setup() {
925
	global $g, $config;
926

    
927
	$balanacing = "";
928
	$pfsyncinterface = "";
929
	$pfsyncenabled = "";
930
	if(isset($config['system']['developerspew'])) {
931
		$mt = microtime();
932
		echo "interfaces_carp_setup() being called $mt\n";
933
	}
934

    
935
	// Prepare CmdCHAIN that will be used to execute commands.
936
	$cmdchain = new CmdCHAIN();	
937

    
938
	if ($g['booting']) {
939
		echo "Configuring CARP settings...";
940
		mute_kernel_msgs();
941
	}
942

    
943
	/* suck in configuration items */
944
	if($config['installedpackages']['carpsettings']) {
945
		if($config['installedpackages']['carpsettings']['config']) {
946
			foreach($config['installedpackages']['carpsettings']['config'] as $carp) {
947
				$pfsyncenabled = $carp['pfsyncenabled'];
948
				$balanacing = $carp['balancing'];
949
				$pfsyncinterface = $carp['pfsyncinterface'];
950
				$pfsyncpeerip = $carp['pfsyncpeerip'];
951
			}
952
		}
953
	} else {
954
		unset($pfsyncinterface);
955
		unset($balanacing);
956
		unset($pfsyncenabled);
957
	}
958

    
959
	$cmdchain->add("Allow CARP", "/sbin/sysctl net.inet.carp.allow=1", true);			
960
	if($balanacing) {
961
		$cmdchain->add("Enable CARP ARP-balancing", "/sbin/sysctl net.inet.carp.arpbalance=1", true);
962
		$cmdchain->add("Disallow CARP preemption", "/sbin/sysctl net.inet.carp.preempt=0", true);
963
	} else
964
		$cmdchain->add("Enable CARP preemption", "/sbin/sysctl net.inet.carp.preempt=1", true);		
965

    
966
	$cmdchain->add("Enable CARP logging", "/sbin/sysctl net.inet.carp.log=2", true);
967
	if (!empty($pfsyncinterface))
968
		$carp_sync_int = get_real_interface($pfsyncinterface);
969

    
970
	if($g['booting']) {
971
		/*    install rules to alllow pfsync to sync up during boot
972
		 *    carp interfaces will remain down until the bootup sequence finishes
973
		 */
974
		$fd = fopen("{$g['tmp_path']}/rules.boot", "w");
975
		if ($fd) {
976
			fwrite($fd, "pass quick proto carp all keep state\n");
977
			fwrite($fd, "pass quick proto pfsync all\n");
978
			fwrite($fd, "pass out quick from any to any keep state\n");
979
			fclose($fd);
980
			mwexec("/sbin/pfctl -f {$g['tmp_path']}/rules.boot");
981
		} else
982
			log_error("Could not create rules.boot file!");
983
	}
984

    
985
	/* setup pfsync interface */
986
	if($carp_sync_int and $pfsyncenabled) {
987
		if (is_ipaddr($pfsyncpeerip))
988
			$cmdchain->add("Bring up pfsync0 syncpeer", "/sbin/ifconfig pfsync0 syncdev {$carp_sync_int} syncpeer {$pfsyncpeerip} up", false);						
989
		else
990
			$cmdchain->add("Bring up pfsync0 syncdev", "/sbin/ifconfig pfsync0 syncdev {$carp_sync_int} up", false);			
991
	} else
992
		$cmdchain->add("Bring up pfsync0", "/sbin/ifconfig pfsync0 syncdev lo0 up", false);						
993

    
994
	if($config['virtualip']['vip'])
995
		$cmdchain->add("Allow CARP.", "/sbin/sysctl net.inet.carp.allow=1", true);				
996
	else
997
		$cmdchain->add("Disallow CARP.", "/sbin/sysctl net.inet.carp.allow=0", true);		
998
	
999
	if($g['debug'])
1000
		$cmdchain->setdebug(); // optional for verbose logging
1001

    
1002
	$cmdchain->execute();
1003
	$cmdchain->clear();
1004

    
1005
	if ($g['booting']) {
1006
		unmute_kernel_msgs();
1007
		echo "done.\n";
1008
	}
1009
}
1010

    
1011
function interfaces_proxyarp_configure() {
1012
        global $config, $g;
1013
        if(isset($config['system']['developerspew'])) {
1014
                $mt = microtime();
1015
                echo "interfaces_proxyarp_configure() being called $mt\n";
1016
        }
1017

    
1018
        /* kill any running choparp */
1019
        killbyname("choparp");
1020

    
1021
        if (isset($config['virtualip']) && is_array($config['virtualip']['vip'])) {
1022
                $paa = array();
1023

    
1024
                /* group by interface */
1025
                foreach ($config['virtualip']['vip'] as $vipent) {
1026
                        if ($vipent['mode'] === "proxyarp") {
1027
                                if ($vipent['interface'])
1028
                                        $proxyif = $vipent['interface'];
1029
                                else
1030
                                        $proxyif = "wan";
1031

    
1032
                                if (!is_array($paa[$if]))
1033
                                        $paa[$proxyif] = array();
1034

    
1035
                                $paa[$proxyif][] = $vipent;
1036
                        }
1037
                }
1038

    
1039
                if (count($paa))
1040
                foreach ($paa as $paif => $paents) {
1041
                        $paaifip = get_interface_ip($paif);
1042
                        if (!(is_ipaddr($paaifip)))
1043
                               continue;
1044

    
1045
                        $args = get_real_interface($paif) . " auto";
1046

    
1047
                        foreach ($paents as $paent) {
1048

    
1049
                                if (isset($paent['subnet']))
1050
                                        $args .= " " . escapeshellarg("{$paent['subnet']}/{$paent['subnet_bits']}");
1051
                                else if (isset($paent['range']))
1052
                                        $args .= " " . escapeshellarg($paent['range']['from'] . "-" .
1053
                                                $paent['range']['to']);
1054
                        }
1055

    
1056
                        mwexec_bg("/usr/local/sbin/choparp " . $args);
1057
                }
1058
        }
1059
}
1060

    
1061
function interfaces_vips_configure() {
1062
	global $g, $config;
1063
	if(isset($config['system']['developerspew'])) {
1064
		$mt = microtime();
1065
		echo "interfaces_ipalias_configure() being called $mt\n";
1066
	}
1067
	$paa = array();
1068
	if(is_array($config['virtualip']['vip'])) {
1069
		$carp_setuped = false;
1070
		foreach ($config['virtualip']['vip'] as $vip) {
1071
			switch ($vip['mode']) {
1072
			case "proxyarp":
1073
				/* nothing it is handled on interfaces_proxyarp_configure() */
1074
				break;
1075
			case "ipalias":
1076
				interface_ipalias_configure(&$vip);
1077
				break;
1078
			case "carp":
1079
				if ($carp_setuped == false) {
1080
					interfaces_carp_setup();
1081
					$carp_setuped = true;
1082
				}
1083
				interface_carp_configure($vip);
1084
				break;
1085
			case "carpdev-dhcp":
1086
				interface_carpdev_configure($vip);
1087
				break;
1088
			}
1089
		}
1090
		
1091
		interfaces_proxyarp_configure();
1092
	}
1093
}
1094

    
1095
function interface_ipalias_configure(&$vip) {
1096

    
1097
	if ($vip['mode'] == "ipalias") {
1098
		$if = get_real_interface($vip['interface']);
1099
		mwexec("/sbin/ifconfig " . escapeshellarg($if) . " " . $vip['subnet'] . "/" . escapeshellarg($vip['subnet_bits']) . " alias");
1100
	}
1101
}
1102

    
1103
function interface_reload_carps($cif) {
1104
	global $config;
1105

    
1106
	$carpifs = link_ip_to_carp_interface(find_interface_ip($cif));
1107
        if (empty($carpifs))
1108
		return;
1109

    
1110
	$carps = explode(" ", $carpifs);
1111
	if(is_array($config['virtualip']['vip'])) {
1112
                $viparr = &$config['virtualip']['vip'];
1113
                foreach ($viparr as $vip) {
1114
			if (in_array($vip['carpif'], $carps)) {
1115
                        	switch ($vip['mode']) {
1116
                        	case "carp":
1117
					interface_vip_bring_down($vip);
1118
					sleep(1);
1119
                                	interface_carp_configure($vip);
1120
                                	break;
1121
                        	case "carpdev-dhcp":
1122
					interface_vip_bring_down($vip);
1123
					sleep(1);
1124
                                	interface_carpdev_configure($vip);
1125
                                	break;
1126
				}
1127
                        }
1128
                }
1129
        }
1130
}
1131

    
1132
// Returns the first available vhid interface
1133
function find_next_available_vip() {
1134
	for($x=0; $x<9999; $x++) {
1135
		if(!does_interface_exist("vip{$x}")) 
1136
			return "vip{$x}";
1137
	}
1138
	return false;
1139
}
1140

    
1141
function interface_carp_configure(&$vip) {
1142
	global $config, $g;
1143
	if(isset($config['system']['developerspew'])) {
1144
		$mt = microtime();
1145
		echo "interfaces_carp_configure() being called $mt\n";
1146
	}
1147

    
1148
	if ($vip['mode'] != "carp")
1149
		return;
1150

    
1151
	$vip_password = $vip['password'];
1152
	$vip_password = str_replace(" ", "", $vip_password);
1153
	if ($vip['password'] != "")
1154
		$password = " pass \"" . $vip_password . "\"";
1155

    
1156
	// Setting the VIP to the VHID ID has to be the 
1157
	// single most brain-headed decision in the history
1158
	// of man-kind.  Do this correctly by finding the first
1159
	// available vip interface.
1160
	$vipif = find_next_available_vip();
1161

    
1162
	$interface = interface_translate_type_to_real($vip['interface']);
1163
	/*
1164
	 * ensure the interface containing the VIP really exists
1165
 	 * prevents a panic if the interface is missing or invalid
1166
	 */
1167
	$realif = get_real_interface($vip['interface']);
1168
	if (!does_interface_exist($realif)) {
1169
		file_notice("CARP", "Interface specified for the virtual IP address {$vip['subnet']} does not exist. Skipping this VIP.", "Firewall: Virtual IP", "");
1170
		return;
1171
	}
1172

    
1173
	/* ensure CARP IP really exists prior to loading up */
1174
	/* XXX: this can be bound to only the interface choosen in the carp creation. Not yet since upgrade is needed! */
1175
	$found = false;
1176
	$iflist = get_configured_interface_list();
1177
	foreach($iflist as $if) {
1178
		$ww_subnet_ip = get_interface_ip($if);
1179
		$ww_subnet_bits = get_interface_subnet($if);
1180
		if (ip_in_subnet($vip['subnet'], gen_subnet($ww_subnet_ip, $ww_subnet_bits) . "/" . $ww_subnet_bits)) {
1181
			$found = true;
1182
			break;
1183
		}
1184
	}
1185
	if($found == false) {
1186
		file_notice("CARP", "Sorry but we could not find a matching real interface subnet for the virtual IP address {$vip['subnet']}.", "Firewall: Virtual IP", "");
1187
		return;
1188
	}
1189

    
1190
	/* invalidate interface cache */
1191
	get_interface_arr(true);
1192

    
1193
	/* create the carp interface and setup */
1194
	if (does_interface_exist($vipif))
1195
		mwexec("/sbin/ifconfig {$vipif} delete");
1196
	else {
1197
		$carpif = exec("/sbin/ifconfig carp create");
1198
		mwexec("/sbin/ifconfig {$carpif} name {$vipif}");
1199
	}
1200

    
1201
	/* invalidate interface cache */
1202
	get_interface_arr(true);
1203

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

    
1207
	interfaces_bring_up($vipif);
1208
	
1209
	return $vipif;
1210
}
1211

    
1212
function interface_carpdev_configure(&$vip) {
1213
	global $g;
1214

    
1215
	if ($vip['mode'] != "carpdev-dhcp")
1216
                return;
1217

    
1218
        $vip_password = $vip['password'];
1219
        $vip_password = str_replace(" ", "", $vip_password);
1220
        if($vip['password'] != "")
1221
                $password = " pass \"" . $vip_password . "\"";
1222

    
1223
	log_error("Found carpdev interface {$vip['interface']} on top of interface {$interface}");
1224
	if (empty($vip['interface']))
1225
		return;
1226

    
1227
	$vipif = "vip" . $vip['vhid'];
1228
	$realif = interface_translate_type_to_real($vip['interface']);
1229
	interface_bring_up($realif);
1230
        /*
1231
         * ensure the interface containing the VIP really exists
1232
         * prevents a panic if the interface is missing or invalid
1233
         */
1234
        if (!does_interface_exist($realif)) {
1235
                file_notice("CARP", "Interface specified for the virtual IP address {$vip['subnet']} does not exist. Skipping this VIP.", "Firewall: Virtual IP", "");
1236
                return;
1237
        }
1238

    
1239
	if (does_interface_exist($vipif))
1240
		mwexec("/sbin/ifconfig {$vipif} delete");
1241
	else  {
1242
		$carpdevif = exec("/sbin/ifconfig carp create");
1243
		mwexec("/sbin/ifconfig {$carpdevif} name {$vipif}");
1244
	}
1245

    
1246
	mwexec("/sbin/ifconfig {$vipif} carpdev {$realif} vhid {$vip['vhid']} advskew {$vip['advskew']} {$password}");
1247
	interface_bring_up($vipif);
1248

    
1249
	/*
1250
	 * XXX: BIG HACK but carpdev needs ip services active
1251
	 *      before even starting something as dhclient.
1252
	 *      I do not know if this is a feature or a bug
1253
	 *      but better than track it make it work ;) .
1254
	 */
1255
	//$fakeiptouse = "10.254.254." . ($carp_instances_counter+1);
1256
	//$cmdchain->add("CarpDEV hack", "/sbin/ifconfig {$carpint} inet {$fakeiptouse}", false);
1257

    
1258
	/* generate dhclient_wan.conf */
1259
	$fd = fopen("{$g['varetc_path']}/dhclient_{$vipif}.conf", "w");
1260
	if ($fd) {
1261
		$dhclientconf = "";
1262

    
1263
		$dhclientconf .= <<<EOD
1264
interface "{$vipif}" {
1265
timeout 60;
1266
retry 1;
1267
select-timeout 0;
1268
initial-interval 1;
1269
script "/sbin/dhclient-script";
1270
}
1271

    
1272
EOD;
1273

    
1274
		fwrite($fd, $dhclientconf);
1275
		fclose($fd);
1276

    
1277
		/* fire up dhclient */
1278
		mwexec("/sbin/dhclient -c {$g['varetc_path']}/dhclient_{$vipif}.conf {$vipif} >/tmp/{$vipif}_output >/tmp/{$vipif}_error_output", false);
1279
	} else {
1280
		log_error("Error: cannot open dhclient_{$vipif}.conf in interfaces_carpdev_configure() for writing.\n");
1281
		mwexec("/sbin/dhclient -b {$vipif}");
1282
	}
1283

    
1284
	$fout = fopen("/tmp/ifconfig_{$vipif}","w");
1285
	fwrite($fout, "/sbin/dhclient -c {$g['varetc_path']}/dhclient_{$vipif}.conf {$vipif}");
1286
	fclose($fout);
1287

    
1288
	return $vipif;
1289
}
1290

    
1291
function interface_wireless_clone($if, $wlcfg) {
1292
	global $config;
1293
	/*   Check to see if interface has been cloned as of yet.  
1294
	 *   If it has not been cloned then go ahead and clone it.
1295
	 */
1296
	$needs_clone = true;
1297
	$interface_num = substr($wlcfg['if'], 3);
1298
	if(does_interface_exist("{$wlcfg['if']}_wlan{$interface_num}")) {
1299
		$hostap_enabled = `/sbin/ifconfig {$wlcfg['if']}_wlan{$interface_num} | grep hostap`;
1300
		if($hostap_enabled) 
1301
			$needs_clone = false;
1302
		else 
1303
			exec("/sbin/ifconfig {$wlcfg['if']}_wlan{$interface_num} destroy");
1304
	}
1305
	if($needs_clone == true) {
1306
		// Setup wireless nic
1307
		if($wlcfg['wireless']['mode'] == "hostap") 
1308
			$mode = "wlanmode hostap";
1309
		exec("/sbin/ifconfig wlan{$interface_num} create wlandev {$wlcfg['if']} {$mode}");
1310
		exec("/sbin/ifconfig wlan{$interface_num} name {$wlcfg['if']}_wlan{$interface_num}");
1311
	}
1312
}
1313

    
1314
function interface_wireless_configure($if, &$wl, &$wlcfg) {
1315
	global $config, $g;
1316

    
1317
	/*    open up a shell script that will be used to output the commands.
1318
	 *    since wireless is changing a lot, these series of commands are fragile
1319
     *    and will sometimes need to be verified by a operator by executing the command
1320
     *    and returning the output of the command to the developers for inspection.  please
1321
     *    do not change this routine from a shell script to individul exec commands.  -sullrich
1322
	 */
1323

    
1324
	conf_mount_rw();
1325

    
1326
	unlink_if_exists("{$g['tmp_path']}/{$if}_setup.sh");
1327

    
1328
	interface_wireless_clone($if, $wl);
1329
	
1330
	$fd_set = fopen("/tmp/{$if}_setup.sh","w");
1331
	fwrite($fd_set, "#!/bin/sh\n");
1332
	fwrite($fd_set, "# {$g['product_name']} wireless configuration script.\n\n");
1333

    
1334
	fwrite($fd_set, "# enable shell debugging\n");
1335
	fwrite($fd_set, "set -x\n");
1336

    
1337
	/* set values for /path/program */
1338
	$hostapd = "/usr/sbin/hostapd";
1339
	$wpa_supplicant = "/usr/sbin/wpa_supplicant";
1340
	$ifconfig = "/sbin/ifconfig";
1341
	$killall = "/usr/bin/killall";
1342

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

    
1345
	/* Set a/b/g standard */
1346
	$standard = "mode " . escapeshellarg($wlcfg['standard']);
1347

    
1348
	/* Set 802.11g protection mode */
1349
	$protmode = "protmode " . escapeshellarg($wlcfg['protmode']);
1350

    
1351
	/* set wireless channel value */
1352
	if(isset($wlcfg['channel']))
1353
		if($wlcfg['channel'] == "0")
1354
			$channel = "channel any";
1355
		else
1356
			$channel = "channel " . escapeshellarg($wlcfg['channel']);
1357

    
1358
	/* set Distance value */
1359
	if($wlcfg['distance'])
1360
		$distance = escapeshellarg($wlcfg['distance']);
1361

    
1362
	/* Set ssid */
1363
	if($wlcfg['ssid'])
1364
		$ssid = "ssid " . escapeshellarg($wlcfg['ssid']);
1365

    
1366
	/* Set wireless hostap mode */
1367
	if ($wlcfg['mode'] == "hostap")
1368
		$hostapmode = "mediaopt hostap";
1369
	else
1370
		$hostapmode = "-mediaopt hostap";
1371

    
1372
	/* Set wireless adhoc mode */
1373
	if ($wlcfg['mode'] == "adhoc")
1374
		$adhocmode = "mediaopt adhoc";
1375
	else
1376
		$adhocmode = "-mediaopt adhoc";
1377

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

    
1380
	/* handle hide ssid option */
1381
	if(isset($wlcfg['hidessid']['enable']))
1382
		$hidessid = "hidessid";
1383
	else
1384
		$hidessid = "-hidessid";
1385

    
1386
	/* handle pureg (802.11g) only option */
1387
	if(isset($wlcfg['pureg']['enable']))
1388
		$pureg = "mode 11g pureg";
1389
	else
1390
		$pureg = "-pureg";
1391

    
1392
	/* enable apbridge option */
1393
	if(isset($wlcfg['apbridge']['enable']))
1394
		$apbridge = "apbridge";
1395
	else
1396
		$apbridge = "-apbridge";
1397

    
1398
	/* handle turbo option */
1399
	if(isset($wlcfg['turbo']['enable']))
1400
		$turbo = "mediaopt turbo";
1401
	else
1402
		$turbo = "-mediaopt turbo";
1403

    
1404
	/* handle txpower setting */
1405
	if($wlcfg['txpower'] <> "")
1406
		$txpower = "txpower " . escapeshellarg($wlcfg['txpower']);
1407

    
1408
	/* handle wme option */
1409
	if(isset($wlcfg['wme']['enable']))
1410
		$wme = "wme";
1411
	else
1412
		$wme = "-wme";
1413

    
1414
	/* set up wep if enabled */
1415
    if (isset($wlcfg['wep']['enable']) && is_array($wlcfg['wep']['key'])) {
1416
		if($wlcfg['wpa']['auth_algs'] == "1")
1417
			$wepset .= "authmode open wepmode on ";
1418
		else if($wlcfg['wpa']['auth_algs'] == "2")
1419
			$wepset .= "authmode shared wepmode on ";
1420
		else if($wlcfg['wpa']['auth_algs'] == "3")
1421
			$wepset .= "authmode mixed wepmode on ";
1422
		$i = 1;
1423
		foreach ($wlcfg['wep']['key'] as $wepkey) {
1424
			$wepset .= "wepkey " . escapeshellarg("{$i}:{$wepkey['value']}") . " ";
1425
			if (isset($wepkey['txkey']))
1426
				$wepset .= "weptxkey {$i} ";
1427
			$i++;
1428
		}
1429
    } else {
1430
    	$wepset .= "authmode open wepmode off ";
1431
	}
1432

    
1433
	/* generate wpa_supplicant/hostap config if wpa is enabled */
1434

    
1435
	switch ($wlcfg['mode']) {
1436
		case 'bss':
1437
			if (isset($wlcfg['wpa']['enable'])) {
1438

    
1439
				$wpa .= <<<EOD
1440
ctrl_interface={$g['varrun_path']}/wpa_supplicant
1441
ctrl_interface_group=0
1442
ap_scan=1
1443
#fast_reauth=1
1444
network={
1445
ssid="{$wlcfg['ssid']}"
1446
scan_ssid=1
1447
priority=5
1448
key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
1449
psk="{$wlcfg['wpa']['passphrase']}"
1450
pairwise={$wlcfg['wpa']['wpa_pairwise']}
1451
group={$wlcfg['wpa']['wpa_pairwise']}
1452
}
1453
EOD;
1454

    
1455
				$fd = fopen("{$g['varetc_path']}/wpa_supplicant_{$if}.conf", "w");
1456
				fwrite($fd, "{$wpa}");
1457
				fclose($fd);
1458

    
1459
				fwrite($fd_set, kill_wpasupplicant($if));
1460
			}
1461
		break;
1462

    
1463
		case 'hostap':
1464
			if (isset($wlcfg['wpa']['enable'])) {
1465
				$wpa .= <<<EOD
1466
interface={$if}
1467
driver=bsd
1468
logger_syslog=-1
1469
logger_syslog_level=0
1470
logger_stdout=-1
1471
logger_stdout_level=0
1472
dump_file={$g['tmp_path']}/hostapd_{$if}.dump
1473
ctrl_interface={$g['varrun_path']}/hostapd
1474
ctrl_interface_group=wheel
1475
#accept_mac_file={$g['tmp_path']}/hostapd_{$if}.accept
1476
#deny_mac_file={$g['tmp_path']}/hostapd_{$if}.deny
1477
#macaddr_acl={$wlcfg['wpa']['macaddr_acl']}
1478
ssid={$wlcfg['ssid']}
1479
debug={$wlcfg['wpa']['debug_mode']}
1480
auth_algs={$wlcfg['wpa']['auth_algs']}
1481
wpa={$wlcfg['wpa']['wpa_mode']}
1482
wpa_key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
1483
wpa_pairwise={$wlcfg['wpa']['wpa_pairwise']}
1484
wpa_group_rekey={$wlcfg['wpa']['wpa_group_rekey']}
1485
wpa_gmk_rekey={$wlcfg['wpa']['wpa_gmk_rekey']}
1486
wpa_strict_rekey={$wlcfg['wpa']['wpa_strict_rekey']}
1487
wpa_passphrase={$wlcfg['wpa']['passphrase']}
1488
ieee8021x={$wlcfg['wpa']['ieee8021x']}
1489
#Enable the next lines for preauth when roaming. Interface = wired or wireless interface talking to the AP you want to roam from/to
1490
#rsn_preauth=1
1491
#rsn_preauth_interfaces=eth0
1492
EOD;
1493

    
1494
				$fd = fopen("{$g['varetc_path']}/hostapd_{$if}.conf", "w");
1495
				fwrite($fd, "{$wpa}");
1496
				fclose($fd);
1497

    
1498
				fwrite($fd_set, kill_hostapd($if));
1499
			}
1500
		break;
1501

    
1502
		case 'adhoc':
1503
			fwrite($fd_set, kill_hostapd($if));
1504
			fwrite($fd_set, kill_wpasupplicant($if));
1505
		break;
1506
	}
1507

    
1508
	/*
1509
	 *    all variables are set, lets start up everything
1510
     */
1511

    
1512
	/* set ack timers according to users preference (if he/she has any) */
1513
	if($distance) {
1514
		fwrite($fd_set, "# Enable ATH distance settings\n");
1515
		fwrite($fd_set, "/sbin/athctrl.sh -i {$if} -d {$distance}\n");
1516
	}
1517

    
1518
	$standard_no_turbo = str_replace(" Turbo", "", $standard);
1519

    
1520
	$settings = <<<EOD
1521

    
1522
{$ifconfig} {$if} down
1523
{$ifconfig} {$if} {$standard_no_turbo}
1524
{$ifconfig} {$if} {$channel}
1525
{$ifconfig} {$if} {$turbo}
1526
{$ifconfig} {$if} {$ssid}
1527
{$ifconfig} {$if} {$hidessid}
1528
{$ifconfig} {$if} {$adhocmode}
1529
{$ifconfig} {$if} {$protmode}
1530
{$ifconfig} {$if} {$pureg}
1531
{$ifconfig} {$if} {$apbridge}
1532
{$ifconfig} {$if} {$wme}
1533
{$ifconfig} {$if} {$wepset}
1534
{$ifconfig} {$if} {$txpower}
1535
{$ifconfig} {$if} {$hostapmode}
1536
{$ifconfig} {$if} up
1537

    
1538
EOD;
1539

    
1540
	/* write out above <<EOD stuff */
1541
	fwrite($fd_set, $settings);
1542

    
1543
	if (isset($wlcfg['wpa']['enable'])) {
1544
		if ($wlcfg['mode'] == "bss")
1545
			fwrite($fd_set, "{$wpa_supplicant} -B -i {$if} -c {$g['varetc_path']}/wpa_supplicant_{$if}.conf\n");
1546
		if ($wlcfg['mode'] == "hostap")
1547
			fwrite($fd_set, "{$hostapd} -B {$g['varetc_path']}/hostapd_{$if}.conf\n");
1548
	}
1549

    
1550
	fclose($fd_set);
1551

    
1552
	conf_mount_ro();
1553

    
1554
	/* execute commands now in shell */
1555
	mwexec("/bin/sh /tmp/{$if}_setup.sh");
1556
	sleep(2);
1557
	// XXX: ermal - This seems like not needed!? 
1558
	//mwexec("/bin/sh /tmp/{$if}_setup.sh");
1559

    
1560
	return 0;
1561

    
1562
}
1563

    
1564
function kill_hostapd($interface) {
1565
	return "/bin/ps awwuxx | grep hostapd | grep $interface | awk '{ print \$2 }' | xargs kill\n";
1566
}
1567

    
1568
function kill_wpasupplicant($interface) {
1569
	return "/bin/ps awwuxx | grep wpa_supplicant | grep $interface | awk '{ print \$2 }' | xargs kill\n";
1570
}
1571

    
1572
function find_dhclient_process($interface) {
1573
	if($interface)
1574
		$pid = `ps awwwux | grep dhclient | grep -v grep | grep {$interface} | awk '{ print \$2 }'`;
1575
	return $pid;
1576
}
1577

    
1578
function interface_configure($interface = "wan", $reloadall = false) {
1579
	global $config, $g;
1580
	global $interface_sn_arr_cache, $interface_ip_arr_cache;
1581

    
1582
	$wancfg = $config['interfaces'][$interface];
1583

    
1584
	$realif = get_real_interface($interface);
1585

    
1586
	if (!$g['booting']) {
1587
		/* remove all IPv4 addresses */
1588
		while (mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " -alias", true) == 0);
1589
			interface_bring_down($interface);
1590
	}
1591

    
1592
	/* wireless configuration? */
1593
	if (is_array($wancfg['wireless']))
1594
		interface_wireless_configure($realif, $wancfg, $wancfg['wireless']);
1595

    
1596
	if ($wancfg['spoofmac']) {
1597
		mwexec("/sbin/ifconfig " . escapeshellarg($wancfg['if']) .
1598
			" link " . escapeshellarg($wancfg['spoofmac']));
1599
	}  else {
1600
		$mac = get_interface_mac($wancfg['if']);
1601
		if($mac == "ff:ff:ff:ff:ff:ff") {
1602
			/*   this is not a valid mac address.  generate a
1603
			 *   temporary mac address so the machine can get online.
1604
			 */
1605
			echo "Generating new MAC address.";
1606
			$random_mac = generate_random_mac_address();
1607
			mwexec("/sbin/ifconfig " . escapeshellarg($wancfg['if']) .
1608
				" link " . escapeshellarg($random_mac));
1609
			$wancfg['spoofmac'] = $random_mac;
1610
			write_config();
1611
			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");
1612
		}
1613
	}
1614

    
1615
	/* media */
1616
	if ($wancfg['media'] || $wancfg['mediaopt']) {
1617
		$cmd = "/sbin/ifconfig " . escapeshellarg($wancfg['if']);
1618
		if ($wancfg['media'])
1619
			$cmd .= " media " . escapeshellarg($wancfg['media']);
1620
		if ($wancfg['mediaopt'])
1621
			$cmd .= " mediaopt " . escapeshellarg($wancfg['mediaopt']);
1622
		mwexec($cmd);
1623
	}
1624

    
1625
	/* invalidate interface/ip/sn cache */
1626
	get_interface_arr(true);
1627
	unset($interface_ip_arr_cache[$realif]);
1628
	unset($interface_sn_arr_cache[$realif]);
1629

    
1630
	switch ($wancfg['ipaddr']) {
1631

    
1632
		case 'carpdev-dhcp':
1633
			interface_carpdev_dhcp_configure($interface);
1634
			break;
1635
		case 'dhcp':
1636
			interface_dhcp_configure($interface);
1637
			break;
1638

    
1639
		case 'pppoe':
1640
			interface_pppoe_configure($interface);
1641
			break;
1642

    
1643
		case 'pptp':
1644
			interface_pptp_configure($interface);
1645
			break;
1646

    
1647
		default:
1648
			if ($wancfg['ipaddr'] <> "" && $wancfg['subnet'] <> "") {
1649
				if (isset($wancfg['ispointtopoint']) && $wancfg['pointtopoint']) {
1650
					mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " " .
1651
						escapeshellarg($wancfg['ipaddr'] . "/" . $wancfg['subnet']) .
1652
						" " . escapeshellarg($wancfg['pointtopoint']) . " up");
1653
				} else {
1654
					if($wancfg['ipaddr'] && $wancfg['subnet'])
1655
						mwexec("/sbin/ifconfig " . escapeshellarg($realif) .
1656
							" " . escapeshellarg($wancfg['ipaddr'] . "/" . 
1657
							$wancfg['subnet']));
1658
				}
1659
			}
1660

    
1661
			if (is_ipaddr($wancfg['gateway']))
1662
				file_put_contents("/tmp/{$realif}_router", $wancfg['gateway']);
1663
	}
1664
	if($wancfg['if'])
1665
		interfaces_bring_up($wancfg['if']);
1666
	else 
1667
		log_error("Could not bring wancfg['if'] up -- variable not defined in interface_configure()");
1668
	
1669
	interface_reload_carps($realif);
1670

    
1671
	if (!$g['booting']) {
1672
		if (link_interface_to_gre($interface)) {
1673
			foreach ($config['gres']['gre'] as $gre)
1674
				if ($gre['if'] == $interface)
1675
					interface_gre_configure($gre);
1676
		}
1677
		if (link_interface_to_gif($interface)) {
1678
                	foreach ($config['gifs']['gif'] as $gif)
1679
				if ($gif['if'] == $interface)
1680
                        		interface_gre_configure($gif);
1681
        	}
1682
		if (link_interface_to_bridge($interface)) {
1683
			foreach ($config['bridges']['bridged'] as $bridge)
1684
				if (stristr($bridge['members'], "{$interface}"))
1685
					interface_bridge_configure($bridge);
1686
		}
1687

    
1688
		/* XXX: Shouldn't the caller do all this reconfiguring?! */
1689
		if ($interface == "lan")
1690
			/* make new hosts file */
1691
               		system_hosts_generate();
1692

    
1693
		if ($reloadall == true) {
1694

    
1695
			/* reconfigure static routes (kernel may have deleted them) */
1696
			system_routing_configure();
1697

    
1698
			/* reload ipsec tunnels */
1699
			vpn_ipsec_configure();
1700

    
1701
			/* update dyndns */
1702
			services_dyndns_configure();
1703

    
1704
			/* force DNS update */
1705
			services_dnsupdate_process();
1706

    
1707
			/* restart dnsmasq */
1708
			services_dnsmasq_configure();
1709

    
1710
			/* reload captive portal */
1711
			captiveportal_configure();
1712

    
1713
			/* set the reload filter dity flag */
1714
			filter_configure();
1715
		}
1716
	}
1717

    
1718

    
1719
	unmute_kernel_msgs();
1720

    
1721
	return 0;
1722
}
1723

    
1724
function interface_carpdev_dhcp_configure($interface = "wan") {
1725
	global $config, $g;
1726

    
1727
	$wancfg = $config['interfaces'][$interface];
1728
	$wanif = $wancfg['if'];
1729
	/* bring wan interface up before starting dhclient */
1730
	if($wanif)
1731
		interfaces_bring_up($wanif);
1732
	else 
1733
		log_error("Could not bring wanif up in terface_carpdev_dhcp_configure()");
1734

    
1735
	return 0;
1736
}
1737

    
1738
function interface_dhcp_configure($interface = "wan") {
1739
	global $config, $g;
1740

    
1741
	$wancfg = $config['interfaces'][$interface];
1742

    
1743
	/* generate dhclient_wan.conf */
1744
	$fd = fopen("{$g['varetc_path']}/dhclient_{$interface}.conf", "w");
1745
	if (!$fd) {
1746
		printf("Error: cannot open dhclient_{$interface}.conf in interfaces_wan_dhcp_configure() for writing.\n");
1747
		return 1;
1748
	}
1749

    
1750
	if ($wancfg['dhcphostname']) {
1751
		$dhclientconf_hostname = "send dhcp-client-identifier \"{$wancfg['dhcphostname']}\";\n";
1752
		$dhclientconf_hostname .= "\tsend host-name \"{$wancfg['dhcphostname']}\";\n";
1753
	} else {
1754
		$dhclientconf_hostname = "";
1755
	}
1756

    
1757
	$wanif = get_real_interface($interface);
1758

    
1759
 	$dhclientconf = "";
1760
	
1761
	$dhclientconf .= <<<EOD
1762
interface "{$wanif}" {
1763
timeout 60;
1764
retry 1;
1765
select-timeout 0;
1766
initial-interval 1;
1767
	{$dhclientconf_hostname}
1768
	script "/sbin/dhclient-script";
1769
}
1770

    
1771
EOD;
1772

    
1773
if(is_ipaddr($wancfg['alias-address'])) {
1774
	$subnetmask = gen_subnet_mask($wancfg['alias-subnet']);
1775
	$dhclientconf .= <<<EOD
1776
alias {
1777
	interface  "{$wanif}";
1778
	fixed-address {$wancfg['alias-address']};
1779
	option subnet-mask {$subnetmask};
1780
}
1781

    
1782
EOD;
1783
}
1784
	fwrite($fd, $dhclientconf);
1785
	fclose($fd);
1786

    
1787
	$realwanif = $wancfg['if'];
1788

    
1789
	/* bring wan interface up before starting dhclient */
1790
	if($realwanif)
1791
		interfaces_bring_up($realwanif);
1792
	else 
1793
		log_error("Could not bring realwanif up in interface_dhcp_configure()");
1794

    
1795
	/* fire up dhclient */
1796
	mwexec("/sbin/dhclient -c {$g['varetc_path']}/dhclient_{$interface}.conf {$wanif} >/tmp/{$wanif}_output >/tmp/{$wanif}_error_output");
1797

    
1798
	$fout = fopen("/tmp/ifconfig_{$wanif}","w");
1799
	fwrite($fout, "/sbin/dhclient -c {$g['varetc_path']}/dhclient_{$interface}.conf {$wanif}");
1800
	fclose($fout);
1801

    
1802
	return 0;
1803
}
1804

    
1805
function interface_pppoe_configure($interface = "wan") 
1806
{
1807
	global $config, $g;
1808

    
1809
	$wancfg = $config['interfaces'][$interface];
1810

    
1811
	/* generate mpd.conf */
1812
	$fd = fopen("{$g['varetc_path']}/mpd_{$interface}.conf", "w");
1813
	if (!$fd) {
1814
		printf("Error: cannot open mpd_{$interface}.conf in interface_pppoe_configure().\n");
1815
		return 1;
1816
	}
1817

    
1818
	$idle = 0;
1819

    
1820
	if (isset($wancfg['ondemand'])) {
1821
		$ondemand = "enable";
1822
		if ($wancfg['timeout'])
1823
			$idle = $wancfg['timeout'];
1824
	} else {
1825
		$ondemand = "disable";
1826
	}
1827

    
1828
	$mpdconf = <<<EOD
1829
startup:
1830
pppoeclient:
1831

    
1832
EOD;
1833

    
1834
	if ($interface == "wan")
1835
		$realif = "pppoe0";
1836
	else {
1837
		// Here code assumes only that strings of form "opt#" will be passed.
1838
		$realif = "pppoe" . substr($interface, 3); 
1839
	}
1840
	
1841
	$mpdconf .= <<<EOD
1842
	new -i {$realif} pppoeclient pppoeclient
1843

    
1844
EOD;
1845
	if ($interface == "wan")
1846
		$mpdconf .= <<<EOD
1847
	set iface route default
1848

    
1849
EOD;
1850
	
1851
	$mpdconf .= <<<EOD
1852
	set iface {$ondemand} on-demand
1853
	set iface idle {$idle}
1854
	set iface enable tcpmssfix
1855
	set iface up-script /usr/local/sbin/ppp-linkup
1856
	set iface down-script /usr/local/sbin/ppp-linkdown
1857

    
1858
EOD;
1859

    
1860
	if (isset($wancfg['ondemand'])) {
1861
		if (isset($wancfg['local-ip']) && isset($wancfg['remote-ip'])) {
1862
			$mpdconf .= <<<EOD
1863
	set iface addrs {$wancfg['local-ip']} {$wancfg['remote-ip']}
1864

    
1865
EOD;
1866
		} else {
1867
			$mpdconf .= <<<EOD
1868
	set iface addrs 192.0.2.112 192.0.2.113
1869

    
1870
EOD;
1871
		}
1872
	}
1873

    
1874
	$mpdconf .= <<<EOD
1875
	set bundle disable multilink
1876
	set auth authname "{$wancfg['pppoe_username']}"
1877
	set auth password "{$wancfg['pppoe_password']}"
1878
	set link keep-alive 10 60
1879
	set link max-redial 0
1880
	set link no acfcomp protocomp
1881
	set link disable pap chap
1882
	set link accept chap
1883
	
1884
EOD;
1885
	if (empty($wancfg['mtu']))
1886
		$mpdmtu = "1492";
1887
	else 
1888
		$mpdmtu = "{$wancfg['mtu']}";
1889

    
1890
	$mpdconf .= <<<EOD
1891
	set link mtu {$mpdmtu}
1892
	set ipcp yes vjcomp
1893
	set ipcp ranges 0.0.0.0/0 0.0.0.0/0
1894

    
1895
EOD;
1896

    
1897
	if (isset($config['system']['dnsallowoverride'])) {
1898
		$mpdconf .= <<<EOD
1899
	set ipcp enable req-pri-dns
1900

    
1901
EOD;
1902
	}
1903

    
1904
	if (!isset($wancfg['dnsnosec']) && isset($config['system']['dnsallowoverride'])) {
1905
			$mpdconf .= <<<EOD
1906
	set ipcp enable req-sec-dns
1907

    
1908
EOD;
1909
	}
1910
	
1911
	$mpdconf .= <<<EOD
1912
	open
1913

    
1914
EOD;
1915

    
1916
	fwrite($fd, $mpdconf);
1917
	fclose($fd);
1918

    
1919
	/* generate mpd.links */
1920
	$fd = fopen("{$g['varetc_path']}/mpd_{$interface}.links", "w");
1921
	if (!$fd) {
1922
		printf("Error: cannot open mpd_{$interface}.links in interface_pppoe_configure().\n");
1923
		return 1;
1924
	}
1925

    
1926
	$mpdconf = <<<EOD
1927
pppoeclient:
1928
	set link type pppoe
1929
	set pppoe iface {$wancfg['if']}
1930
	set pppoe service "{$wancfg['provider']}"
1931
	set pppoe enable originate
1932
	set pppoe disable incoming
1933

    
1934
EOD;
1935

    
1936
	fwrite($fd, $mpdconf);
1937
	fclose($fd);
1938

    
1939
	if(file_exists("{$g['varrun_path']}/pppoe_{$interface}.pid") and $g['booting']) {
1940
		/* if we are booting and mpd has already been started then don't start again. */
1941
	} else {
1942
		/* if mpd is active, lets take it down */
1943
		if(file_exists("{$g['varrun_path']}/pppoe_{$interface}.pid")) {
1944
			killbypid("{$g['varrun_path']}/pppoe_{$interface}.pid");
1945
			sleep(3);
1946
		}
1947

    
1948
		/* Bring the parent interface up */
1949
		if($wancfg['if'])
1950
			interfaces_bring_up($wancfg['if']);
1951
		else 
1952
			log_error("Could not bring wancfg['if'] up in interface_pppoe_configure()");
1953

    
1954
		/* fire up mpd */
1955
		mwexec("/usr/local/sbin/mpd4 -b -d {$g['varetc_path']} -f mpd_{$interface}.conf -l mpd_{$interface}.links -p {$g['varrun_path']}/pppoe_{$interface}.pid pppoeclient");
1956
	}
1957

    
1958
	/* sleep until wan is up - or 30 seconds, whichever comes first */
1959
	for ($count = 0; $count < 30; $count++) {
1960
		if(file_exists("{$g['tmp_path']}/{$realif}up")) {
1961
			break;
1962
		}
1963
		sleep(1);
1964
	}
1965

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

    
1968
	return 0;
1969
}
1970

    
1971
function interface_pptp_configure($interface) {
1972
	global $config, $g;
1973

    
1974
	$wancfg = $config['interfaces'][$interface];
1975

    
1976
	/* generate mpd.conf */
1977
	$fd = fopen("{$g['varetc_path']}/mpd_{$interface}.conf", "w");
1978
	if (!$fd) {
1979
		printf("Error: cannot open mpd_{$interface}.conf in interface_pptp_configure().\n");
1980
		return 1;
1981
	}
1982

    
1983
	$idle = 0;
1984

    
1985
	if (isset($wancfg['ondemand'])) {
1986
		$ondemand = "enable";
1987
		if ($wancfg['timeout'])
1988
			$idle = $wancfg['timeout'];
1989
	} else {
1990
		$ondemand = "disable";
1991
	}
1992

    
1993
	$mpdconf = <<<EOD
1994
startup:
1995
pptp:
1996

    
1997
EOD;
1998

    
1999
        if ($interface == "wan")
2000
                $realif = "pptp0";
2001
        else {
2002
                // Here code assumes only that strings of form "opt#" will be passed.
2003
                $realif = "pptp" . substr($interface, 3);
2004
	}
2005

    
2006
        $mpdconf .= <<<EOD
2007
        new -i {$realif} pptp pptp 
2008

    
2009
EOD;
2010
        if ($interface == "wan")
2011
                $mpdconf .= <<<EOD
2012
        set iface route default
2013

    
2014
EOD;
2015

    
2016
        $mpdconf .= <<<EOD
2017
	set iface {$ondemand} on-demand
2018
	set iface idle {$idle}
2019
	set iface up-script /usr/local/sbin/ppp-linkup
2020
	set iface down-script /usr/local/sbin/ppp-linkdown
2021

    
2022
EOD;
2023

    
2024
	if (isset($wanfg['ondemand'])) {
2025
		$mpdconf .= <<<EOD
2026
	set iface addrs 10.0.0.1 10.0.0.2
2027

    
2028
EOD;
2029
	}
2030

    
2031
	$mpdconf .= <<<EOD
2032
	set bundle disable multilink
2033
	set auth authname "{$wancfg['pptp_username']}"
2034
	set auth password "{$wancfg['pptp_password']}"
2035
	set bundle no noretry
2036
	set link keep-alive 10 60
2037
	set link max-redial 0
2038
	set link no acfcomp protocomp
2039
	set link disable pap chap
2040
	set link accept chap
2041
	set ipcp no vjcomp
2042
	set ipcp ranges 0.0.0.0/0 0.0.0.0/0
2043

    
2044
EOD;
2045
	if (isset($config['system']['dnsallowoverride'])) {
2046
		$mpdconf .= <<<EOD
2047
	set ipcp enable req-pri-dns
2048

    
2049
EOD;
2050
	}
2051

    
2052
	$mpdconf .= <<<EOD
2053
	open
2054

    
2055
EOD;
2056

    
2057
	fwrite($fd, $mpdconf);
2058
	fclose($fd);
2059

    
2060
	/* generate mpd.links */
2061
	$fd = fopen("{$g['varetc_path']}/mpd_{$interface}.links", "w");
2062
	if (!$fd) {
2063
		printf("Error: cannot open mpd_{$interface}.links in interface_pptp_configure().\n");
2064
		return 1;
2065
	}
2066

    
2067
	$mpdconf = <<<EOD
2068
pptp:
2069
	set link type pptp
2070
	set pptp enable originate outcall
2071
	set pptp disable windowing
2072
	set pptp self {$wancfg['local']}
2073
	set pptp peer {$wancfg['remote']}
2074

    
2075
EOD;
2076

    
2077
	fwrite($fd, $mpdconf);
2078
	fclose($fd);
2079

    
2080
	/* configure interface */
2081
	if($wancfg['if'])
2082
		mwexec("/sbin/ifconfig " . escapeshellarg($wancfg['if']) . " " .
2083
			escapeshellarg($wancfg['local'] . "/" . $wancfg['subnet']) . " up");
2084
	else 
2085
		log_error("Could not bring interface wancfg['if'] up in interface_pptp_configure()");
2086
	/* fire up mpd */
2087
	mwexec("/usr/local/sbin/mpd4 -b -d {$g['varetc_path']} -f mpd_{$interface}.conf -l mpd_{$interface}.links -p {$g['varrun_path']}/pptp_{$interface}.pid pptp");
2088

    
2089
	return 0;
2090
}
2091

    
2092
function interfaces_group_setup() {
2093
	global $config;
2094

    
2095
	if (!is_array($config['ifgroups']['ifgroupentry']))
2096
		return;
2097

    
2098
	foreach ($config['ifgroups']['ifgroupentry'] as $groupar)
2099
		interface_group_setup($groupar);
2100

    
2101
	return;
2102
}
2103

    
2104
function interface_group_setup(&$groupname /* The parameter is an array */) {
2105
	global $config;
2106

    
2107
	if (!is_array($groupname))
2108
		return;
2109
	$members = explode(" ", $groupname['members']);
2110
	foreach($members as $ifs) {
2111
		$realif = get_real_interface($ifs);
2112
		if ($realif)
2113
			mwexec("/sbin/ifconfig {$realif} group {$groupname['ifname']}");
2114
	}
2115

    
2116
	return;
2117
}
2118
 
2119
/* COMPAT Function */
2120
function convert_friendly_interface_to_real_interface_name($interface) {
2121
	return get_real_interface($interface);
2122
}
2123

    
2124
/* COMPAT Function */
2125
function get_real_wan_interface($interface = "wan") {
2126
	return get_real_interface($interface);
2127
}
2128

    
2129
/* COMPAT Function */
2130
function get_current_wan_address($interface = "wan") {
2131
	return get_interface_ip($interface);
2132
}
2133

    
2134
/*
2135
 * convert_real_interface_to_friendly_interface_name($interface): convert fxp0 -> wan, etc.
2136
 */
2137
function convert_real_interface_to_friendly_interface_name($interface = "wan") {
2138
        global $config;
2139

    
2140
        if (stristr($interface, "pppoe")) {
2141
                $index = substr($interface, 5);
2142
                if (intval($index) > 0)
2143
                        return "opt{$index}";
2144
                else
2145
                        return "wan";
2146
        } else if (stristr($interface, "pptp")) {
2147
                $index = substr($interface, 4);
2148
                if (intval($index) > 0)
2149
                        return "opt{$index}";
2150
                else
2151
                        return "wan";
2152
        } else if (stristr($interface, "carp")) {
2153
                $index = substr($interface, 4);
2154
                $counter = 0;
2155
                foreach ($config['virtualip']['vip'] as $vip) {
2156
                        if ($vip['mode'] == "carpdev-dhcp" || $vip['mode'] == "carp")  {
2157
                                if (intval($index) == $counter)
2158
                                        return $vip['interface'];
2159
                                $counter++;
2160
                        }
2161
                }
2162
        }
2163

    
2164
        /* if list */
2165
        $ifdescrs = get_configured_interface_list(false, true);
2166

    
2167
        foreach ($ifdescrs as $if => $ifname) {
2168
                if($config['interfaces'][$if]['if'] == $interface)
2169
                        return $ifname;
2170

    
2171
                /* XXX: ermal - The 3 lines below are totally bogus code. */
2172
                $int = interface_translate_type_to_real($if);
2173
                if($ifname == $interface)
2174
                        return $ifname;
2175

    
2176
                if($int == $interface)
2177
                        return $ifname;
2178
        }
2179
        return NULL;
2180
}
2181

    
2182
/* attempt to resolve interface to friendly descr */
2183
function convert_friendly_interface_to_friendly_descr($interface) {
2184
        global $config;
2185

    
2186
        switch ($interface) {
2187
                case "l2tp":
2188
                                $ifdesc = "L2TP";
2189
                                break;
2190
                case "pptp":
2191
                                $ifdesc = "pptp";
2192
                                break;
2193
                case "pppoe":
2194
                                $ifdesc = "pppoe";
2195
                                break;
2196
                case "openvpn":
2197
                                $ifdesc = "OpenVPN";
2198
                                break;
2199
                case "enc0":
2200
                        case "ipsec":
2201
                                $ifdesc = "IPsec";
2202
                                break;
2203
        default:
2204
                /* if list */
2205
                $ifdescrs = get_configured_interface_with_descr(false, true);
2206
                foreach ($ifdescrs as $if => $ifname) {
2207
                                if ($if == $interface || $ifname == $interface)
2208
                                        return $ifname;
2209
                }
2210
                break;
2211
        }
2212

    
2213
        return $ifdesc;
2214
}
2215

    
2216
function convert_real_interface_to_friendly_descr($interface) {
2217
        global $config;
2218

    
2219
        $ifdesc = convert_real_interface_to_friendly_interface_name("{$interface}");
2220

    
2221
        if ($ifdesc) {
2222
                $iflist = get_configured_interface_with_descr();
2223
                return $iflist[$ifdesc];
2224
        }
2225

    
2226
        return $interface;
2227
}
2228

    
2229
/*
2230
 *  interface_translate_type_to_real($interface):
2231
 *              returns the real hardware interface name for a friendly interface.  ie: wan
2232
 */
2233
function interface_translate_type_to_real($interface) {
2234
        global $config;
2235

    
2236
        if ($config['interfaces'][$interface]['if'] <> "")
2237
                return $config['interfaces'][$interface]['if'];
2238
        else
2239
		return $interface;
2240
}
2241

    
2242
function get_real_interface($interface = "wan") {
2243
    global $config;
2244

    
2245
	$wanif = NULL;
2246

    
2247
	switch ($interface) {
2248
	case "l2tp":
2249
		$wanif = "l2tp";
2250
		break;
2251
	case "pptp":
2252
		$wanif = "pptp";
2253
		break;
2254
	case "pppoe":
2255
		$wanif = "pppoe";
2256
		break;
2257
	case "openvpn":
2258
		$wanif = "openvpn";
2259
		break;
2260
	case "enc0":
2261
		$wanif = "enc0";
2262
		break;
2263
	case "ppp":
2264
		$wanif = "ppp";
2265
		break;
2266
	default:
2267
		$iflist = get_configured_interface_with_descr(false, true);
2268

    
2269
		foreach ($iflist as $if => $ifdesc) {
2270
			if ($interface == $if || $interface == $ifdesc) {
2271

    
2272
			// PPP Support
2273
			if($config['interfaces'][$if]['serialport']) {
2274
				$dev = $config['interfaces'][$if]['serialport'];
2275
				$ps = trim(`ps awux | grep -v grep | grep "$dev" | awk '{ print \$2 }'`);
2276
				if($ps) {
2277
					$int = trim(`ifconfig | grep -v grep | grep -B2 "$ps" | head -n1 | cut -d: -f1`);
2278
					if($int) {
2279
						$wanif = $int;
2280
						break;
2281
					}
2282
				}
2283
			}
2284

    
2285
			$cfg = $config['interfaces'][$if];
2286

    
2287
			if(is_interface_wireless($interface)) {
2288
				$interface_num = substr($cfg['if'], 3);
2289
				$wanif = $cfg['if'] . "_wlan" . $interface_num;
2290
				break;
2291
			}
2292

    
2293
			if (empty($cfg['ipaddr'])) {
2294
				$wanif = $cfg['if'];
2295
				break;
2296
			}
2297

    
2298
			switch ($cfg['ipaddr']) {
2299
			case "carpdev-dhcp":
2300
				$viparr = &$config['virtualip']['vip'];
2301
				$counter = 0;
2302
				if(is_array($viparr))
2303
				foreach ($viparr as $vip) {
2304
					if ($vip['mode'] == "carpdev-dhcp") {
2305
						if($vip['interface'] == $if) {
2306
							$wanif =  "carp{$counter}";
2307
							break;
2308
						}
2309
						$counter++;
2310
					} else if ($vip['mode'] = "carp") 
2311
						$counter++;
2312
				}
2313
				break;
2314
			case "pppoe": 
2315
				if ($if == "wan")
2316
					$wanif = "pppoe0";
2317
				else
2318
					$wanif = "pppoe" . substr($if,3);
2319
				break;
2320
			case "pptp": 
2321
				if ($if == "wan")
2322
					$wanif = "pptp0";
2323
				else
2324
					$wanif = "pptp" . substr($if, 3);
2325
				break;
2326
			default:
2327
				$wanif = $cfg['if'];
2328
				break;
2329
			}
2330
			
2331
			break;
2332
			}
2333
		}
2334
		break;
2335
	}
2336

    
2337
    return $wanif;
2338
}
2339

    
2340
function guess_interface_from_ip($ipaddress) {
2341
        $ret = `/usr/bin/netstat -rn | /usr/bin/awk '/^{$ipaddress}/ {printf "%s", \$6}'`;
2342
        if (empty($ret))
2343
                return false;
2344

    
2345
        return $ret;
2346
}
2347

    
2348
/*
2349
 * find_ip_interface($ip): return the interface where an ip is defined
2350
 */
2351
function find_ip_interface($ip)
2352
{
2353
        /* if list */
2354
        $ifdescrs = get_configured_interface_list();
2355

    
2356
        foreach ($ifdescrs as $ifdescr => $ifname) {
2357
		if ($ip == get_interface_ip($ifname)) {
2358
                	$int = get_real_interface($ifname);
2359
			return $int;
2360
		}
2361
        }
2362
        return false;
2363
}
2364

    
2365
/*
2366
 *   find_number_of_created_carp_interfaces: return the number of carp interfaces
2367
 */
2368
function find_number_of_created_carp_interfaces() {
2369
	return `/sbin/ifconfig | grep "carp:" | wc -l`;
2370
}
2371

    
2372
function get_all_carp_interfaces() {
2373
	$ints = str_replace("\n", " ", `ifconfig | grep "carp:" -B2 | grep ": flag" | cut -d: -f1`);
2374
	return $ints;
2375
}
2376

    
2377
/*
2378
 * find_carp_interface($ip): return the carp interface where an ip is defined
2379
 */
2380
function find_carp_interface($ip) {
2381
	global $config;
2382
	if (is_array($config['virtualip']['vip'])) {
2383
		foreach ($config['virtualip']['vip'] as $vip) {
2384
			if ($vip['mode'] == "carp" || $vip['mode'] == "carpdev") {
2385
				$carp_ip = find_interface_ip($vip['interface']);
2386
				$if = `ifconfig | grep '$ip' -B1 | head -n1 | cut -d: -f1`;
2387
				if ($if)
2388
					return $if;
2389
			}
2390
		}
2391
	}
2392
}
2393

    
2394
function link_carp_interface_to_parent($interface) {
2395
        global $config;
2396

    
2397
        if ($interface == "")
2398
                return;
2399

    
2400
        $carp_ip = find_interface_ip($interface);
2401
        if (!is_ipaddr($carp_ip))
2402
                return;
2403

    
2404
        /* if list */
2405
        $ifdescrs = get_configured_interface_list();
2406
        foreach ($ifdescrs as $ifdescr => $ifname) {
2407
                $interfaceip = get_interface_ip($ifname);
2408
                $subnet_bits = get_interface_subnet($ifname);
2409
                $subnet_ip = gen_subnet("{$interfaceip}", "{$subnet_bits}");
2410
                if(ip_in_subnet($carp_ip, "{$subnet_ip}/{$subnet_bits}"))
2411
                        return $ifname;
2412
        }
2413

    
2414
        return "";
2415
}
2416

    
2417
/****f* interfaces/link_ip_to_carp_interface
2418
 * NAME
2419
 *   link_ip_to_carp_interface - Find where a CARP interface links to.
2420
 * INPUTS
2421
 *   $ip
2422
 * RESULT
2423
 *   $carp_ints
2424
 ******/
2425
function link_ip_to_carp_interface($ip) {
2426
        global $config;
2427

    
2428
        if (!is_ipaddr($ip))
2429
                return;
2430

    
2431
        $carp_ints = "";
2432
        if (is_array($config['virtualip']['vip'])) {
2433
                foreach ($config['virtualip']['vip'] as $vip) {
2434
                        if ($vip['mode'] == "carp" || $vip['mode'] == "carpdev") {
2435
                                $carp_ip = $vip['subnet'];
2436
                                $carp_sn = $vip['subnet_bits'];
2437
                                $carp_nw = gen_subnet($carp_ip, $carp_sn);
2438
                                if (ip_in_subnet($ip, "{$carp_nw}/{$carp_sn}")) {
2439
                                        if (!stristr($carp_ints, $carp_int))
2440
                                                $carp_ints .= " {$carp_int}";
2441
                                }
2442
                        }
2443
                }
2444
        }
2445

    
2446
        return $carp_ints;
2447
}
2448

    
2449
/****f* interfaces/link_interface_to_bridge
2450
 * NAME
2451
 *   link_interface_to_bridge - Finds out a bridge group for an interface
2452
 * INPUTS
2453
 *   $ip
2454
 * RESULT
2455
 *   bridge[0-99]
2456
 ******/
2457
function link_interface_to_bridge($int) {
2458
        global $config;
2459

    
2460
        if (is_array($config['bridges']['bridged']))
2461
                foreach ($config['bridges']['bridged'] as $bridge)
2462
                        if(stristr($bridge['members'], "{$int}"))
2463
                                return "{$bridge['bridgeif']}";
2464
}
2465

    
2466
function link_interface_to_gre($interface) {
2467
        global $config;
2468

    
2469
        if (is_array($config['gres']['gre']))
2470
                foreach ($config['gres']['gre'] as $gre)
2471
                        if($gre['if'] == $interface)
2472
                                return "{$gre['greif']}";
2473
}
2474

    
2475
function link_interface_to_gif($interface) {
2476
        global $config;
2477

    
2478
        if (is_array($config['gifs']['gif']))
2479
                foreach ($config['gifs']['gif'] as $gif)
2480
                        if($gif['if'] == $interface)
2481
                                return "{$gif['gifif']}";
2482
}
2483

    
2484
/*
2485
 * find_interface_ip($interface): return the interface ip (first found)
2486
 */
2487
function find_interface_ip($interface, $flush = false)
2488
{
2489
	global $interface_ip_arr_cache;
2490

    
2491
	$interface = str_replace("\n", "", $interface);
2492
	
2493
	if (does_interface_exist($interface) == false)
2494
		$interface = convert_friendly_interface_to_real_interface_name($interface);
2495

    
2496
	if (does_interface_exist($interface) == false)
2497
		return;
2498

    
2499
	/* Setup IP cache */
2500
	if (!isset($interface_ip_arr_cache[$interface]) or $flush) {
2501
		$interface_ip_arr_cache[$interface] = `/sbin/ifconfig {$interface} | /usr/bin/grep -w "inet" | /usr/bin/cut -d" " -f 2| /usr/bin/head -1`;
2502
		$interface_ip_arr_cache[$interface] = str_replace("\n", "", $interface_ip_arr_cache[$interface]);
2503
	}
2504

    
2505
	return $interface_ip_arr_cache[$interface];
2506
}
2507

    
2508
function find_interface_subnet($interface, $flush = false)
2509
{
2510
	global $interface_sn_arr_cache;
2511

    
2512
	$interface = str_replace("\n", "", $interface);
2513
	if (does_interface_exist($interface) == false)
2514
		return;
2515

    
2516
	if (!isset($interface_sn_arr_cache[$interface]) or $flush) {
2517
		$interface_sn_arr_cache[$interface] = `/sbin/ifconfig {$interface} | /usr/bin/grep -w "inet" | /usr/bin/cut -d" " -f 4 | /usr/bin/head -1`;
2518
		$interface_sn_arr_cache[$interface] = strlen(str_replace("0", "", base_convert(str_replace("\n", "", $interface_sn_arr_cache[$interface]),16, 2)));
2519
        }
2520

    
2521
	return $interface_sn_arr_cache[$interface];
2522
}
2523

    
2524
function get_interface_ip($interface = "wan")
2525
{
2526
	$realif = get_real_interface($interface);
2527
	if (!$realif) {
2528
		if (preg_match("/^carp/i", $interface))
2529
			$realif = $interface;
2530
		else
2531
			return null;
2532
	}
2533

    
2534
	/* Do we really come here for these interfaces ?! */
2535
	if (in_array($realif, array("pptp", "pppoe", "l2tp", "openvpn", "enc0" /* , "ppp" */)))
2536
			return "";
2537

    
2538
	$curip = find_interface_ip($realif);
2539
	if ($curip && is_ipaddr($curip) && ($curip != "0.0.0.0"))
2540
		return $curip;
2541

    
2542
	return null;
2543
}
2544

    
2545
function get_interface_subnet($interface = "wan")
2546
{
2547
	$realif = get_real_interface($interface);
2548
	if (!$realif) {
2549
                if (preg_match("/^carp/i", $interface))
2550
                        $realif = $interface;
2551
                else
2552
                        return null;
2553
        }
2554

    
2555
	/* Do we really come here for these interfaces ?! */
2556
	if (in_array($realif, array("pptp", "pppoe", "l2tp", "openvpn", "enc0" /* , "ppp" */)))
2557
		return "";
2558

    
2559
	$cursn = find_interface_subnet($realif);
2560
	if (!empty($cursn))
2561
		return $cursn;
2562

    
2563
	return null;
2564
}
2565

    
2566
/* return outside interfaces with a gateway */
2567
function get_interfaces_with_gateway() {
2568
        global $config;
2569

    
2570
	$ints = array();
2571

    
2572
	/* loop interfaces, check config for outbound */
2573
        foreach ($config['interfaces'] as $ifdescr => $ifname) {
2574
                switch ($ifname['ipaddr']) {
2575
                	case "dhcp":
2576
                	case "carpdev-dhcp":
2577
                	case "pppoe":
2578
                	case "pptp":
2579
                        $ints[] = $ifdescr;
2580
                        break;
2581
                default:
2582
                        if ($ifname['pointtopoint'])
2583
                                $ints[] = $ifdescr;
2584
                        else if (!empty($ifname['gateway']))
2585
                                $ints[] = $ifdescr;
2586
                        break;
2587
                }
2588
        }
2589
        return $ints;
2590
}
2591

    
2592
/* return true if interface has a gateway */
2593
function interface_has_gateway($friendly) {
2594

    
2595
        $friendly = strtolower($friendly);
2596
        if (in_array($friendly, get_interfaces_with_gateway()))
2597
                return true;
2598

    
2599
	return false;
2600
}
2601

    
2602
/****f* interfaces/is_altq_capable
2603
 * NAME
2604
 *   is_altq_capable - Test if interface is capable of using ALTQ
2605
 * INPUTS
2606
 *   $int            - string containing interface name
2607
 * RESULT
2608
 *   boolean         - true or false
2609
 ******/
2610

    
2611
function is_altq_capable($int) {
2612
        /* Per:
2613
         * http://www.freebsd.org/cgi/man.cgi?query=altq&manpath=FreeBSD+7.2-current&format=html
2614
         * Only the following drivers have ALTQ support
2615
         */
2616
	$capable = array("age", "ale", "an", "ath", "aue", "awi", "bce",
2617
			"bfe", "bge", "dc", "de", "ed", "em", "ep", "fxp", "gem",
2618
			"hme", "ipw", "iwi", "jme", "le", "msk", "mxge", "my", "nfe",
2619
			"npe", "nve", "ral", "re", "rl", "rum", "sf", "sis", "sk",
2620
			"ste", "stge", "txp", "udav", "ural", "vge", "vr", "wi", "xl",
2621
			"ndis", "tun", "vlan", "pppoe", "pptp", "ng", "ppp");
2622

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

    
2625
        if (in_array($int_family[0], $capable))
2626
                return true;
2627
	else if (stristr($int_family, "vlan")) /* VLANs are name $parent.$vlan now */
2628
		return true;
2629
        else
2630
                return false;
2631
}
2632

    
2633
/****f* interfaces/is_interface_wireless
2634
 * NAME
2635
 *   is_interface_wireless - Returns if an interface is wireless
2636
 * RESULT
2637
 *   $tmp       - Returns if an interface is wireless
2638
 ******/
2639
function is_interface_wireless($interface) {
2640
        global $config, $g;
2641

    
2642
        $friendly = convert_real_interface_to_friendly_interface_name($interface);
2643
        if(!isset($config['interfaces'][$friendly]['wireless'])) {
2644
                if (preg_match($g['wireless_regex'], $interface)) {
2645
                        $config['interfaces'][$friendly]['wireless'] = array();
2646
                        return true;
2647
                }
2648
                unset($config['interfaces'][$friendly]['wireless']);
2649
                return false;
2650
        } else
2651
                return true;
2652
}
2653

    
2654
function get_wireless_modes($interface) {
2655
	/* return wireless modes and channels */
2656
	$wireless_modes = array();
2657

    
2658
	if(is_interface_wireless($interface)) {
2659
		$cloned_interface = get_real_interface($interface);
2660
		$wi = 1;
2661
		$ifconfig = "/sbin/ifconfig";
2662
		$awk = "/usr/bin/awk";
2663
		$chan_list = "$ifconfig $cloned_interface list chan";
2664
		$stack_list = "$awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
2665
		$format_list = "$awk '{print \$5 \" \" \$6 \",\" \$1}'";
2666

    
2667
		$interface_channels = "";
2668
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
2669
		$interface_channel_count = count($interface_channels);
2670

    
2671
		$c = 0;
2672
		while ($c < $interface_channel_count)
2673
		{
2674
			$channel_line = explode(",", $interface_channels["$c"]);
2675
			$wireless_mode = trim($channel_line[0]);
2676
			$wireless_channel = trim($channel_line[1]);
2677
			if(trim($wireless_mode) != "") {
2678
				/* if we only have 11g also set 11b channels */
2679
				if($wireless_mode == "11g") {
2680
					$wireless_modes["11b"] = array();
2681
				}
2682
				$wireless_modes["$wireless_mode"]["$c"] = $wireless_channel;
2683
			}
2684
			$c++;
2685
		}
2686
	}
2687
	return($wireless_modes);
2688
}
2689

    
2690
/****f* interfaces/get_interface_mtu
2691
 * NAME
2692
 *   get_interface_mtu - Return the mtu of an interface
2693
 * RESULT
2694
 *   $tmp       - Returns the mtu of an interface
2695
 ******/
2696
function get_interface_mtu($interface) {
2697
        $mtu = `/sbin/ifconfig {$interface} | /usr/bin/grep mtu | /usr/bin/cut -d" " -f6`;
2698
        return $mtu;
2699
}
2700

    
2701
function get_interface_mac($interface) {
2702
	$mac = array();
2703
        exec("/sbin/ifconfig {$interface} | /usr/bin/awk '/ether/ {print $2}'", $mac);
2704
        if(is_macaddr($mac)) {
2705
                return trim($mac);
2706
        } else {
2707
                return "";
2708
        }
2709
}
2710

    
2711
/****f* pfsense-utils/generate_random_mac_address
2712
 * NAME
2713
 *   generate_random_mac - generates a random mac address
2714
 * INPUTS
2715
 *   none
2716
 * RESULT
2717
 *   $mac - a random mac address
2718
 ******/
2719
function generate_random_mac_address() {
2720
        $mac = "02";
2721
        for($x=0; $x<5; $x++)
2722
                $mac .= ":" . dechex(rand(16, 255));
2723
        return $mac;
2724
}
2725

    
2726
/****f* interfaces/is_jumbo_capable
2727
 * NAME
2728
 *   is_jumbo_capable - Test if interface is jumbo frame capable.  Useful for determining VLAN capability.
2729
 * INPUTS
2730
 *   $int             - string containing interface name
2731
 * RESULT
2732
 *   boolean          - true or false
2733
 ******/
2734
function is_jumbo_capable($int) {
2735
        global $g;
2736

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

    
2739
        if (in_array($int_family[0], $g['vlan_long_frame']))
2740
                return true;
2741
        else
2742
                return false;
2743
}
2744

    
2745
function setup_pppoe_reset_file($interface, $status) {
2746
	define("CRON_PPPOE_CMD_FILE", "/conf/pppoe{$interface}restart");
2747
	define("CRON_PPPOE_CMD", "#!/bin/sh\necho '<?php require(\"config.inc\"); require(\"interfaces.inc\"); interface_reconfigure({$interface}); ?>' | /usr/local/bin/php -q");
2748
	if ($status == true) {
2749
		if (!file_exists(CRON_PPPOE_CMD_FILE)) {
2750
			file_put_contents(CRON_PPPOE_CMD_FILE, CRON_PPPOE_CMD);
2751
			chmod(CRON_PPPOE_CMD_FILE, 0700);
2752
		}	
2753
	} else
2754
		unlink_if_exists(CRON_PPPOE_CMD_FILE);
2755
}
2756

    
2757
?>
(19-19/47)