Project

General

Profile

Download (81.1 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("interfaces_bring_up() was called but no variable defined.");
50
		log_error( "Backtrace: " . 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
	if($g['booting'])
88
		echo "Configuring loopback interface...";
89
	mwexec("/sbin/ifconfig lo0 127.0.0.1");
90
	interfaces_bring_up("lo0");
91
	exec("/sbin/route add 127.0.0.2 127.0.0.1");
92
	if($g['booting'])
93
		echo "done.\n";
94
	return 0;
95
}
96

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

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

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

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

    
129
        /* make sure the parent interface is up */
130
	interfaces_bring_up($if);
131
	/* Since we are going to add vlan(4) try to enable all that hardware supports. */
132
	mwexec("/sbin/ifconfig {$if} vlanhwtag");
133
	mwexec("/sbin/ifconfig {$if} vlanmtu");
134

    
135
	if (!empty($vlanif) && does_interface_exist($vlanif)) {
136
		mwexec("/sbin/ifconfig {$vlanif} delete");
137
	} else {
138
		$tmpvlanif = exec("/sbin/ifconfig vlan create");
139
		mwexec("/sbin/ifconfig {$tmpvlanif} name {$vlanif}");
140
	}
141
	
142
	mwexec("/sbin/ifconfig {$vlanif} vlan " .
143
		escapeshellarg($tag) . " vlandev " .
144
		escapeshellarg($if));
145

    
146
	interfaces_bring_up($vlanif);
147

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

    
151
    /*   all vlans need to spoof their parent mac address, too.  see
152
     *   ticket #1514: http://cvstrac.pfsense.com/tktview?tn=1514,33
153
     */
154
    foreach($config['interfaces'] as $interfaces) {
155
		if($interfaces['if'] == $if && $interfaces['spoofmac']) {
156
			mwexec("/sbin/ifconfig " . escapeshellarg($vlanif) .
157
				" link " . escapeshellarg($interfaces['spoofmac']));
158
		}
159
	}
160

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

    
164
	return $vlanif;
165
}
166

    
167
function interface_qinq_configure(&$vlan, $fd = NULL) {
168
        global $config, $g;
169

    
170
        if (!is_array($vlan)) {
171
                log_error("QinQ compat VLAN: called with wrong options. Problems with config!\n");
172
                return;
173
        }
174

    
175
        $if = $vlan['if'];
176
        $vlanif = empty($vlan['vlanif']) ? "vlan{$vlan['tag']}" : $vlan['vlanif'];
177
        $tag = $vlan['tag'];
178
        if(empty($if)) {
179
                log_error("interface_qinq_confgure called with if undefined.\n");
180
                return;
181
        }
182

    
183
        if ($fd == NULL) {
184
                $exec = true;
185
                $fd = fopen("{$g['tmp_path']}/netgraphcmd", "w");
186
        } else
187
                $exec = false;
188
        /* make sure the parent is converted to ng_vlan(4) and is up */
189
        interfaces_bring_up($if);
190
        /* Since we are going to add ng_vlan(4) try to enable all that hardware supports. */
191
        mwexec("/sbin/ifconfig {$if} vlanhwtag\n");
192
        mwexec("/sbin/ifconfig {$if} vlanmtu\n");
193

    
194
        if (!empty($vlanif) && does_interface_exist($vlanif)) {
195
                fwrite($fd, "shutdown {$if}qinq:\n");
196
                exec("/usr/sbin/ngctl msg {$if}qinq: gettable", $result);
197
                if (empty($result)) {
198
                        fwrite($fd, "mkpeer {$if}: vlan lower downstream\n");
199
                        fwrite($fd, "name {$if}:lower {$if}qinq\n");
200
                        fwrite($fd, "connect {$if}: {$if}qinq: upper nomatch\n");
201
                }
202
        } else {
203
                fwrite($fd, "mkpeer {$if}: vlan lower downstream\n");
204
                fwrite($fd, "name {$if}:lower {$if}qinq\n");
205
                fwrite($fd, "connect {$if}: {$if}qinq: upper nomatch\n");
206
        }
207

    
208
        if (!$g['booting']) {
209
                if (!empty($vlan['members'])) {
210
                        $members = explode(" ", $vlan['members']);
211
                        foreach ($members as $qtag) {
212
                                fwrite($fd, "shutdown {$vlanif}h{$qtag}:\n");
213
                        }
214
                }
215
                fwrite($fd, "shutdown vlanh{$tag}:\n");
216
        }
217
        fwrite($fd, "mkpeer {$if}qinq: eiface vlan{$tag} ether\n");
218
        fwrite($fd, "name {$if}qinq:vlan{$tag} vlanh{$tag}\n");
219
        fwrite($fd, "msg {$if}qinq: addfilter { vlan={$tag} hook=\"vlan{$tag}\" }\n");
220
        fwrite($fd, "msg vlanh{$tag}: setifname \"{$vlanif}\"\n");
221
        $macaddr = get_interface_mac($if);
222
        fwrite($fd, "msg {$vlanif}: setenaddr {$macaddr}\n");
223

    
224
        interfaces_bring_up($vlanif);
225

    
226
        /* invalidate interface cache */
227
        get_interface_arr(true);
228

    
229
        if (!stristr($if, "vlan"))
230
                mwexec("/sbin/ifconfig {$if} promisc\n");
231

    
232
        if (!empty($vlan['members'])) {
233
                $members = explode(" ", $vlan['members']);
234
                foreach ($members as $qtag) {
235
                        $qinq = array();
236
                        $qinq['tag'] = $qtag;
237
                        $qinq['if'] = $vlanif;
238
                        interface_qinq2_configure($qinq, $fd, $macaddr);
239
                }
240
        }
241
        if ($exec == true) {
242
                fclose($fd);
243
                mwexec("/usr/sbin/ngctl -f {$g['tmp_path']}/netgraphcmd");
244
        }
245

    
246
        interfaces_bring_up($if);
247
        if (!empty($vlan['members'])) {
248
                $members = explode(" ", $vlan['members']);
249
                foreach ($members as $qif)
250
                        interfaces_bring_up("{$vlanif}.{$qif}");
251
        }
252

    
253
        return $vlanif;
254
}
255

    
256
function interfaces_qinq_configure() {
257
	global $config, $g;
258
	if($g['booting'])
259
		echo "Configuring QinQ interfaces...";
260
	if (is_array($config['qinqs']['qinqentry']) && count($config['qinqs']['qinqentry'])) {
261
		$fd = fopen("{$g['tmp_path']}/netgraphcmd", "w");
262
		foreach ($config['qinqs']['qinqentry'] as $qinq) {
263
			/* XXX: Maybe we should report any errors?! */
264
			interface_qinq_configure($qinq, $fd);
265
		}
266
		fclose($fd);
267
		mwexec("/usr/sbin/ngctl -f {$g['tmp_path']}/netgraphcmd");
268
		}
269
		if($g['booting'])
270
			echo "done.\n";
271
}
272

    
273
function interface_qinq2_configure(&$qinq, $fd, $macaddr) {
274
        global $config, $g;
275

    
276
        if (!is_array($qinq)) {
277
                log_error("QinQ compat VLAN: called with wrong options. Problems with config!\n");
278
                return;
279
        }
280

    
281
        $if = $qinq['if'];
282
        $tag = $qinq['tag'];
283
        $vlanif = "{$if}_{$tag}";
284
        if(empty($if)) {
285
                log_error("interface_qinq_confgure called with if undefined.\n");
286
                return;
287
        }
288

    
289
        $result = array();
290
        exec("/usr/sbin/ngctl msg {$if}qinq: gettable", $result);
291
        if (empty($result)) {
292
                fwrite($fd, "mkpeer {$if}: vlan lower downstream\n");
293
                fwrite($fd, "name {$if}:lower {$if}qinq \n");
294
                fwrite($fd, "connect {$if}: {$if}qinq: upper nomatch\n");
295
        }
296

    
297
        //fwrite($fd, "shutdown ${if}h{$tag}:\n");
298
        fwrite($fd, "mkpeer {$if}qinq: eiface {$if}{$tag} ether\n");
299
        fwrite($fd, "name {$if}qinq:{$if}{$tag} {$if}h{$tag}\n");
300
        fwrite($fd, "msg {$if}qinq: addfilter { vlan={$tag} hook=\"{$if}{$tag}\" }\n");
301
        fwrite($fd, "msg {$if}h{$tag}: setifname \"{$vlanif}\"\n");
302
        fwrite($fd, "msg {$vlanif}: setenaddr {$macaddr}\n");
303
        interfaces_bring_up($vlanif);
304

    
305
        /* invalidate interface cache */
306
        get_interface_arr(true);
307

    
308
        return $vlanif;
309
}
310

    
311
function interfaces_bridge_configure() {
312
        global $config;
313

    
314
        $i = 0;
315
        if (is_array($config['bridges']['bridged']) && count($config['bridges']['bridged'])) {
316
                foreach ($config['bridges']['bridged'] as $bridge) {
317
                        if(empty($bridge['bridgeif']))
318
                                $bridge['bridgeif'] = "bridge{$i}";
319
                        /* XXX: Maybe we should report any errors?! */
320
                        interface_bridge_configure($bridge);
321
                        $i++;
322
                }
323
        }
324
}
325

    
326
function interface_bridge_configure(&$bridge) {
327
	global $config, $g;
328

    
329
	if (!is_array($bridge))
330
	        return -1;
331

    
332
	if (empty($bridge['members'])) {
333
		log_error("No members found on {$bridge['bridgeif']}");
334
		return -1;
335
	}
336

    
337
	$members = explode(',', $bridge['members']);
338
	if (!count($members))
339
		return -1;
340
	
341
	$checklist = get_configured_interface_list();
342

    
343
	if ($g['booting'] || !empty($bridge['bridgeif'])) {
344
		mwexec("/sbin/ifconfig {$bridge['bridgeif']} destroy");
345
		mwexec("/sbin/ifconfig {$bridge['bridgeif']} create");
346
		$bridgeif = $bridge['bridgeif'];
347
	} else {
348
		$bridgeif = exec("/sbin/ifconfig bridge create");
349
	}
350

    
351
	/* Calculate smaller mtu and enforce it */
352
	$smallermtu = 0;
353
	foreach ($members as $member) {
354
		$realif = get_real_interface($member);
355
		$mtu = get_interface_mtu($realif);
356
		if ($smallermtu == 0 && !empty($mtu))
357
			$smallermtu = $mtu;
358
		else if (!empty($mtu) && $mtu < $smallermtu)
359
			$smallermtu = $mtu;
360
	}
361
	 
362
	/* Just in case anything is not working well */
363
	if ($smallermtu == 0)
364
		$smallermtu = 1500; 
365

    
366
	/* Add interfaces to bridge */
367
	foreach ($members as $member) {
368
		if (!array_key_exists($member, $checklist))
369
			continue;
370
		$realif = get_real_interface($member);
371
		$realif =  escapeshellarg($realif);
372
		/* make sure the parent interface is up */
373
		mwexec("/sbin/ifconfig {$realif} mtu {$smallermtu}");
374
		if(!$realif) 
375
			log_error("realif not defined in interfaces bridge - up");
376
		interfaces_bring_up($realif);
377
		mwexec("/sbin/ifconfig {$bridgeif} addm {$realif}");	
378
	}
379

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

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

    
480
	if($bridgeif)
481
		interfaces_bring_up($bridgeif);	
482
	else 
483
		log_error("bridgeif not defined -- could not bring interface up");
484

    
485
	return $bridgeif;
486
}
487

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

    
507
function interface_lagg_configure(&$lagg) {
508
        global $config, $g;
509

    
510
        if (!is_array($lagg))
511
		return -1;
512

    
513
	$members = explode(',', $lagg['members']);
514
	if (!count($members))
515
		return -1;
516
	
517
	$checklist = get_interface_list();
518

    
519
	if ($g['booting'] || !(empty($lagg['laggif']))) {
520
                mwexec("/sbin/ifconfig {$lagg['laggif']} destroy");
521
                mwexec("/sbin/ifconfig {$lagg['laggif']} create");
522
                $laggif = $lagg['laggif'];
523
        } else
524
                $laggif = exec("/sbin/ifconfig lagg create");
525

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

    
536
	/* Just in case anything is not working well */
537
        if ($smallermtu == 0)
538
                $smallermtu = 1500;
539

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

    
551
	interfaces_bring_up($laggif);
552

    
553
	return $laggif;
554
}
555

    
556
function interfaces_gre_configure() {
557
        global $config;
558

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

    
571
function interface_gre_configure(&$gre) {
572
        global $config, $g;
573

    
574
	if (!is_array($gre))
575
		return -1;
576

    
577
	$realif = get_real_interface($gre['if']);
578
	$realifip = get_interface_ip($gre['if']);
579

    
580
	/* make sure the parent interface is up */
581
	interfaces_bring_up($realif);
582

    
583
	if ($g['booting'] || !(empty($gre['greif']))) {
584
		mwexec("/sbin/ifconfig {$gre['greif']} destroy");
585
		mwexec("/sbin/ifconfig {$gre['greif']} create");
586
		$greif = $gre['greif'];
587
	} else {
588
		$greif = exec("/sbin/ifconfig gre create");
589
	}
590

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

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

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

    
609
	return $greif;
610
}
611

    
612
function interfaces_gif_configure() {
613
        global $config;
614

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

    
627
function interface_gif_configure(&$gif) {
628
        global $config, $g;
629

    
630
        if (!is_array($gif))
631
                return -1;
632

    
633
        $realif = get_real_interface($gif['if']);
634
        $realifip = get_interface_ip($gif['if']);
635

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

    
642
        if ($g['booting'] || !(empty($gif['gifif']))) {
643
                mwexec("/sbin/ifconfig {$gif['gifif']} destroy");
644
                mwexec("/sbin/ifconfig {$gif['gifif']} create");
645
                $gifif = $gif['gifif'];
646
        } else
647
                $gifif = exec("/sbin/ifconfig gif create");
648

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

    
663
        return $gifif;
664
}
665

    
666
function interfaces_configure() {
667
	global $config, $g;
668

    
669
	/* Set up our loopback interface */
670
	interfaces_loopback_configure();
671

    
672
	/* set up LAGG virtual interfaces */
673
	interfaces_lagg_configure();
674

    
675
	/* set up VLAN virtual interfaces */
676
	interfaces_vlan_configure();
677

    
678
	interfaces_qinq_configure();
679

    
680
	/* Set up PPP interfaces */
681
	interfaces_ppp_configure();
682

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

    
710
	/* set up GRE virtual interfaces */
711
	interfaces_gre_configure();
712

    
713
	/* set up GIF virtual interfaces */
714
	interfaces_gif_configure();
715
	
716
	foreach ($delayed_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
	/* set up BRIDGe virtual interfaces */
729
	interfaces_bridge_configure();
730

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

    
737
		interface_configure($if, true);
738

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

    
743
	/* bring up vip interfaces */
744
	interfaces_vips_configure();
745

    
746
	/* configure interface groups */
747
	interfaces_group_setup();
748

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

    
753
		/* reload IPsec tunnels */
754
		vpn_ipsec_configure();
755

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

    
759
		/* restart dnsmasq */
760
		services_dnsmasq_configure();
761

    
762
		/* reload captive portal */
763
		captiveportal_configure();
764

    
765
		/* set the reload filter dity flag */
766
		filter_configure();
767
	}
768

    
769
	return 0;
770
}
771

    
772
function interface_reconfigure($interface = "wan") {
773
	interface_bring_down($interface);
774
	sleep(1);
775
	interface_configure($interface);
776
}
777

    
778
function interface_vip_bring_down(&$vip) {
779

    
780
	switch ($vip['mode']) {
781
	case "proxyarp":
782
		interfaces_proxyarp_configure();
783
		break;
784
	case "ipalias":
785
		mwexec("/sbin/ifconfig " . get_real_interface($vip['interface']) . " delete {$vip['subnet']}");
786
		break;
787
	case "carp":
788
	case "carpdev-dhcp":
789
		$vipif = "vip" . $vip['vhid'];
790
		mwexec("/sbin/ifconfig {$vipif} delete");
791
                mwexec("/sbin/ifconfig {$vipif} down");
792
		mwexec("/sbin/ifconfig {$vipif} destroy");
793
		break;
794
	}
795

    
796
}
797

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

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

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

    
806
	$realif = get_real_interface($interface);
807

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

    
810
        /* remove interface up file if it exists */
811
        unlink_if_exists("{$g['tmp_path']}/{$realif}up");
812
        unlink_if_exists("{$g['vardb_path']}/{$interface}ip");
813
		unlink_if_exists("/tmp/{$realif}_router");
814
        //unlink_if_exists("{$g['varetc_path']}/nameservers.conf");
815

    
816
	switch ($ifcfg['ipaddr']) {
817
	case "pppoe":
818
		killbypid("{$g['varrun_path']}/pppoe_{$interface}.pid");
819
        	sleep(2);
820
                unlink_if_exists("{$g['varetc_path']}/mpd_{$interface}.conf");
821
                unlink_if_exists("{$g['varetc_path']}/mpd_{$interface}.links");
822
		break;
823
	case "pptp":
824
		killbypid("{$g['varrun_path']}/pptp_{$interface}.pid");
825
        	sleep(2);
826
                unlink_if_exists("{$g['varetc_path']}/mpd_{$interface}.conf");
827
                unlink_if_exists("{$g['varetc_path']}/mpd_{$interface}.links");
828
		break;
829
	case "carpdev-dhcp":
830
		/* 
831
		 * NB: When carpdev gets enabled it would be better to be handled as all
832
		 *	other interfaces! 
833
		 */
834
	case "dhcp":
835
        	$pid = find_dhclient_process($interface);
836
        	if($pid)
837
                	mwexec("kill {$pid}");
838
               	sleep(1);
839
                unlink_if_exists("{$g['varetc_path']}/dhclient_{$interface}.conf");
840
		mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete");
841
		mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " down");
842
		break;
843
	default:
844
		mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete");
845
		mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " down");
846
		break;
847
	}
848

    
849
	if ($destroy == true) {
850
		if (preg_match("/^tun|^ppp|^ovpn|^gif|^gre|^lagg|^bridge|vlan/i", $realif))
851
                	mwexec("/sbin/ifconfig {$realif} destroy");
852
	}
853
	
854
	return;
855
}
856

    
857
function interfaces_ppp_configure() {
858
	global $config, $g;
859
	if(!$g['booting']) 
860
		conf_mount_rw();
861
	if($g['booting'])
862
		echo "Configuring PPP interfaces...";
863
	if($config['ppps']['ppp']) {
864
		foreach($config['ppps']['ppp'] as $ppp) {
865
			$dev = substr($ppp['port'], 5);
866
			interface_ppp_configure($dev);
867
		}
868
	}
869
	if(!$g['booting']) 
870
		conf_mount_ro();
871
	if($g['booting'])
872
		echo "done.\n";
873
}
874

    
875
function interface_ppp_configure($ifcfg) {
876
	global $config, $g;
877
	
878
	/* Remove  the /dev/ from the device name. */
879
	$orig_dev = $ifcfg;
880

    
881
	// ppp (userland) requires a /var/spool/lock directory
882
	if(!is_dir("/var/spool/lock")) {
883
		exec("mkdir -p /var/spool/lock");
884
		exec("chmod a+rw /var/spool/lock/.");
885
	}
886

    
887
	// Construct the ppp.conf file
888
	$peerfile .= "default:\n";
889
	$peerfile .= " set log Phase Chat LCP IPCP CCP tun command\n";
890
	$peerfile .= " ident user-ppp VERSION (built COMPILATIONDATE)\n";
891
	$peerfile .= " set dial \"ABORT BUSY ABORT NO\\\sCARRIER TIMEOUT 5 \\\n";
892
	$peerfile .= " 		\\\"\\\" AT OK-AT-OK ATE1Q0 OK \\\dATDT\\\T TIMEOUT 40 CONNECT\"\n";
893
	$peerfile .= " enable dns\n";
894
	$peerfile .= " nat enable yes\n";
895
	$peerfile .= " set reconnect {$ifcfg['connect-max-attempts']} 5\n";
896
	$peerfile .= " allow users root\n\n";
897

    
898
	// Loop variables
899
    $i = 0;
900
	$startingip = 1;
901
	
902
    if (is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) {
903
		foreach ($config['ppps']['ppp'] as $ppp) {
904
			$dev = substr($ppp['port'], 5);
905
			$realif  = $ppp['port'];
906
			$peerfile .= "{$dev}:\n";
907
			$peerfile .= " set device {$realif}\n";
908
			if($ppp['dialcmd'])
909
				$peerfile .= " set dial {$ppp['dialcmd']}\n";
910
			$peerfile .= " set speed \"{$ppp['linespeed']}\"\n";
911
			$peerfile .= " add default HISADDR\n";
912
			$peerfile .= " set timeout 0\n";
913
			$endingip = $startingip+1;
914
			if($ppp['localip'])
915
				$startingip = $ppp['localip'];
916
			if($ppp['gateway'])
917
				$endingip = $ppp['gateway'];
918
			$peerfile .= " enable dns\n";
919
			$peerfile .= " set ifaddr 10.0.0.{$startingip}/0 10.0.0.{$endingip}/0 255.255.255.0 0.0.0.0\n";
920
			$peerfile .= " set phone \"{$ppp['phone']}\"\n";
921
			$peerfile .= " set authname \"{$ppp['username']}\"\n";
922
			$peerfile .= " set authkey \"{$ppp['password']}\"\n";
923
			$peerfile .= "\n";
924
			$i++;
925
			$startingip++;
926
		}
927
    }
928

    
929
	$rclinkup = "default:\n";
930
	$rclinkup.= "! sh -c \"echo HISADDR\" > /tmp/INTERFACE_router\n";
931
	$rclinkup.= "! sh -c \"/etc/rc.linkup INTERFACE start\"\n";
932

    
933
	// Write out configuration for ppp.conf
934
	file_put_contents("/etc/ppp/ppp.conf", $peerfile);
935

    
936
	// Write out linkup file
937
	file_put_contents("/etc/ppp/ppp.linkup", $rclinkup);
938

    
939
	// Make executable
940
	exec("chmod a+rx /etc/ppp/ppp.linkup");
941

    
942
	// Launch specified ppp instance
943
	$running = `ps awux | grep ppp | grep -v grep | grep $orig_dev`;
944
	if(!$running)
945
		mwexec("/usr/sbin/ppp -background {$orig_dev}");
946
}
947

    
948
function interfaces_carp_setup() {
949
	global $g, $config;
950

    
951
	$balanacing = "";
952
	$pfsyncinterface = "";
953
	$pfsyncenabled = "";
954
	if(isset($config['system']['developerspew'])) {
955
		$mt = microtime();
956
		echo "interfaces_carp_setup() being called $mt\n";
957
	}
958

    
959
	// Prepare CmdCHAIN that will be used to execute commands.
960
	$cmdchain = new CmdCHAIN();	
961

    
962
	if ($g['booting']) {
963
		echo "Configuring CARP settings...";
964
		mute_kernel_msgs();
965
	}
966

    
967
	/* suck in configuration items */
968
	if($config['installedpackages']['carpsettings']) {
969
		if($config['installedpackages']['carpsettings']['config']) {
970
			foreach($config['installedpackages']['carpsettings']['config'] as $carp) {
971
				$pfsyncenabled = $carp['pfsyncenabled'];
972
				$balanacing = $carp['balancing'];
973
				$pfsyncinterface = $carp['pfsyncinterface'];
974
				$pfsyncpeerip = $carp['pfsyncpeerip'];
975
			}
976
		}
977
	} else {
978
		unset($pfsyncinterface);
979
		unset($balanacing);
980
		unset($pfsyncenabled);
981
	}
982

    
983
	$cmdchain->add("Allow CARP", "/sbin/sysctl net.inet.carp.allow=1", true);			
984
	if($balanacing) {
985
		$cmdchain->add("Enable CARP ARP-balancing", "/sbin/sysctl net.inet.carp.arpbalance=1", true);
986
		$cmdchain->add("Disallow CARP preemption", "/sbin/sysctl net.inet.carp.preempt=0", true);
987
	} else
988
		$cmdchain->add("Enable CARP preemption", "/sbin/sysctl net.inet.carp.preempt=1", true);		
989

    
990
	$cmdchain->add("Enable CARP logging", "/sbin/sysctl net.inet.carp.log=2", true);
991
	if (!empty($pfsyncinterface))
992
		$carp_sync_int = get_real_interface($pfsyncinterface);
993

    
994
	if($g['booting']) {
995
		/*    install rules to alllow pfsync to sync up during boot
996
		 *    carp interfaces will remain down until the bootup sequence finishes
997
		 */
998
		$fd = fopen("{$g['tmp_path']}/rules.boot", "w");
999
		if ($fd) {
1000
			fwrite($fd, "pass quick proto carp all keep state\n");
1001
			fwrite($fd, "pass quick proto pfsync all\n");
1002
			fwrite($fd, "pass out quick from any to any keep state\n");
1003
			fclose($fd);
1004
			mwexec("/sbin/pfctl -f {$g['tmp_path']}/rules.boot");
1005
		} else
1006
			log_error("Could not create rules.boot file!");
1007
	}
1008

    
1009
	/* setup pfsync interface */
1010
	if($carp_sync_int and $pfsyncenabled) {
1011
		if (is_ipaddr($pfsyncpeerip))
1012
			$cmdchain->add("Bring up pfsync0 syncpeer", "/sbin/ifconfig pfsync0 syncdev {$carp_sync_int} syncpeer {$pfsyncpeerip} up", false);						
1013
		else
1014
			$cmdchain->add("Bring up pfsync0 syncdev", "/sbin/ifconfig pfsync0 syncdev {$carp_sync_int} up", false);			
1015
	} else
1016
		$cmdchain->add("Bring up pfsync0", "/sbin/ifconfig pfsync0 syncdev lo0 up", false);						
1017

    
1018
	if($config['virtualip']['vip'])
1019
		$cmdchain->add("Allow CARP.", "/sbin/sysctl net.inet.carp.allow=1", true);				
1020
	else
1021
		$cmdchain->add("Disallow CARP.", "/sbin/sysctl net.inet.carp.allow=0", true);		
1022
	
1023
	if($g['debug'])
1024
		$cmdchain->setdebug(); // optional for verbose logging
1025

    
1026
	$cmdchain->execute();
1027
	$cmdchain->clear();
1028

    
1029
	if ($g['booting']) {
1030
		unmute_kernel_msgs();
1031
		echo "done.\n";
1032
	}
1033
}
1034

    
1035
function interfaces_proxyarp_configure() {
1036
        global $config, $g;
1037
        if(isset($config['system']['developerspew'])) {
1038
                $mt = microtime();
1039
                echo "interfaces_proxyarp_configure() being called $mt\n";
1040
        }
1041

    
1042
        /* kill any running choparp */
1043
        killbyname("choparp");
1044

    
1045
        if (isset($config['virtualip']) && is_array($config['virtualip']['vip'])) {
1046
                $paa = array();
1047

    
1048
                /* group by interface */
1049
                foreach ($config['virtualip']['vip'] as $vipent) {
1050
                        if ($vipent['mode'] === "proxyarp") {
1051
                                if ($vipent['interface'])
1052
                                        $proxyif = $vipent['interface'];
1053
                                else
1054
                                        $proxyif = "wan";
1055

    
1056
                                if (!is_array($paa[$if]))
1057
                                        $paa[$proxyif] = array();
1058

    
1059
                                $paa[$proxyif][] = $vipent;
1060
                        }
1061
                }
1062

    
1063
                if (count($paa))
1064
                foreach ($paa as $paif => $paents) {
1065
                        $paaifip = get_interface_ip($paif);
1066
                        if (!(is_ipaddr($paaifip)))
1067
                               continue;
1068

    
1069
                        $args = get_real_interface($paif) . " auto";
1070

    
1071
                        foreach ($paents as $paent) {
1072

    
1073
                                if (isset($paent['subnet']))
1074
                                        $args .= " " . escapeshellarg("{$paent['subnet']}/{$paent['subnet_bits']}");
1075
                                else if (isset($paent['range']))
1076
                                        $args .= " " . escapeshellarg($paent['range']['from'] . "-" .
1077
                                                $paent['range']['to']);
1078
                        }
1079

    
1080
                        mwexec_bg("/usr/local/sbin/choparp " . $args);
1081
                }
1082
        }
1083
}
1084

    
1085
function interfaces_vips_configure() {
1086
	global $g, $config;
1087
	if(isset($config['system']['developerspew'])) {
1088
		$mt = microtime();
1089
		echo "interfaces_ipalias_configure() being called $mt\n";
1090
	}
1091
	$paa = array();
1092
	if(is_array($config['virtualip']['vip'])) {
1093
		$carp_setuped = false;
1094
		foreach ($config['virtualip']['vip'] as $vip) {
1095
			switch ($vip['mode']) {
1096
			case "proxyarp":
1097
				/* nothing it is handled on interfaces_proxyarp_configure() */
1098
				break;
1099
			case "ipalias":
1100
				interface_ipalias_configure(&$vip);
1101
				break;
1102
			case "carp":
1103
				if ($carp_setuped == false) {
1104
					interfaces_carp_setup();
1105
					$carp_setuped = true;
1106
				}
1107
				interface_carp_configure($vip);
1108
				break;
1109
			case "carpdev-dhcp":
1110
				interface_carpdev_configure($vip);
1111
				break;
1112
			}
1113
		}
1114
		
1115
		interfaces_proxyarp_configure();
1116
	}
1117
}
1118

    
1119
function interface_ipalias_configure(&$vip) {
1120

    
1121
	if ($vip['mode'] == "ipalias") {
1122
		$if = get_real_interface($vip['interface']);
1123
		mwexec("/sbin/ifconfig " . escapeshellarg($if) . " " . $vip['subnet'] . "/" . escapeshellarg($vip['subnet_bits']) . " alias");
1124
	}
1125
}
1126

    
1127
function interface_reload_carps($cif) {
1128
	global $config;
1129

    
1130
	$carpifs = link_ip_to_carp_interface(find_interface_ip($cif));
1131
        if (empty($carpifs))
1132
		return;
1133

    
1134
	$carps = explode(" ", $carpifs);
1135
	if(is_array($config['virtualip']['vip'])) {
1136
                $viparr = &$config['virtualip']['vip'];
1137
                foreach ($viparr as $vip) {
1138
			if (in_array($vip['carpif'], $carps)) {
1139
                        	switch ($vip['mode']) {
1140
                        	case "carp":
1141
					interface_vip_bring_down($vip);
1142
					sleep(1);
1143
                                	interface_carp_configure($vip);
1144
                                	break;
1145
                        	case "carpdev-dhcp":
1146
					interface_vip_bring_down($vip);
1147
					sleep(1);
1148
                                	interface_carpdev_configure($vip);
1149
                                	break;
1150
				}
1151
                        }
1152
                }
1153
        }
1154
}
1155

    
1156
// Returns the first available vhid interface
1157
function find_next_available_vip() {
1158
	for($x=0; $x<9999; $x++) {
1159
		if(!does_interface_exist("vip{$x}")) 
1160
			return "vip{$x}";
1161
	}
1162
	return false;
1163
}
1164

    
1165
function interface_carp_configure(&$vip) {
1166
	global $config, $g;
1167
	if(isset($config['system']['developerspew'])) {
1168
		$mt = microtime();
1169
		echo "interfaces_carp_configure() being called $mt\n";
1170
	}
1171

    
1172
	if ($vip['mode'] != "carp")
1173
		return;
1174

    
1175
	$vip_password = $vip['password'];
1176
	$vip_password = str_replace(" ", "", $vip_password);
1177
	if ($vip['password'] != "")
1178
		$password = " pass \"" . $vip_password . "\"";
1179

    
1180
	// Setting the VIP to the VHID ID has to be the 
1181
	// single most brain-headed decision in the history
1182
	// of man-kind.  Do this correctly by finding the first
1183
	// available vip interface.
1184
	$vipif = find_next_available_vip();
1185

    
1186
	$interface = interface_translate_type_to_real($vip['interface']);
1187
	/*
1188
	 * ensure the interface containing the VIP really exists
1189
 	 * prevents a panic if the interface is missing or invalid
1190
	 */
1191
	$realif = get_real_interface($vip['interface']);
1192
	if (!does_interface_exist($realif)) {
1193
		file_notice("CARP", "Interface specified for the virtual IP address {$vip['subnet']} does not exist. Skipping this VIP.", "Firewall: Virtual IP", "");
1194
		return;
1195
	}
1196

    
1197
	/* ensure CARP IP really exists prior to loading up */
1198
	/* XXX: this can be bound to only the interface choosen in the carp creation. Not yet since upgrade is needed! */
1199
	$found = false;
1200
	$iflist = get_configured_interface_list();
1201
	foreach($iflist as $if) {
1202
		$ww_subnet_ip = get_interface_ip($if);
1203
		$ww_subnet_bits = get_interface_subnet($if);
1204
		if (ip_in_subnet($vip['subnet'], gen_subnet($ww_subnet_ip, $ww_subnet_bits) . "/" . $ww_subnet_bits)) {
1205
			$found = true;
1206
			break;
1207
		}
1208
	}
1209
	if($found == false) {
1210
		file_notice("CARP", "Sorry but we could not find a matching real interface subnet for the virtual IP address {$vip['subnet']}.", "Firewall: Virtual IP", "");
1211
		return;
1212
	}
1213

    
1214
	/* invalidate interface cache */
1215
	get_interface_arr(true);
1216

    
1217
	/* create the carp interface and setup */
1218
	if (does_interface_exist($vipif))
1219
		mwexec("/sbin/ifconfig {$vipif} delete");
1220
	else {
1221
		$carpif = exec("/sbin/ifconfig carp create");
1222
		mwexec("/sbin/ifconfig {$carpif} name {$vipif}");
1223
	}
1224

    
1225
	/* invalidate interface cache */
1226
	get_interface_arr(true);
1227

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

    
1231
	interfaces_bring_up($vipif);
1232
	
1233
	return $vipif;
1234
}
1235

    
1236
function interface_carpdev_configure(&$vip) {
1237
	global $g;
1238

    
1239
	if ($vip['mode'] != "carpdev-dhcp")
1240
                return;
1241

    
1242
        $vip_password = $vip['password'];
1243
        $vip_password = str_replace(" ", "", $vip_password);
1244
        if($vip['password'] != "")
1245
                $password = " pass \"" . $vip_password . "\"";
1246

    
1247
	log_error("Found carpdev interface {$vip['interface']} on top of interface {$interface}");
1248
	if (empty($vip['interface']))
1249
		return;
1250

    
1251
	$vipif = "vip" . $vip['vhid'];
1252
	$realif = interface_translate_type_to_real($vip['interface']);
1253
	interfaces_bring_up($realif);
1254
        /*
1255
         * ensure the interface containing the VIP really exists
1256
         * prevents a panic if the interface is missing or invalid
1257
         */
1258
        if (!does_interface_exist($realif)) {
1259
                file_notice("CARP", "Interface specified for the virtual IP address {$vip['subnet']} does not exist. Skipping this VIP.", "Firewall: Virtual IP", "");
1260
                return;
1261
        }
1262

    
1263
	if (does_interface_exist($vipif))
1264
		mwexec("/sbin/ifconfig {$vipif} delete");
1265
	else  {
1266
		$carpdevif = exec("/sbin/ifconfig carp create");
1267
		mwexec("/sbin/ifconfig {$carpdevif} name {$vipif}");
1268
	}
1269

    
1270
	mwexec("/sbin/ifconfig {$vipif} carpdev {$realif} vhid {$vip['vhid']} advskew {$vip['advskew']} {$password}");
1271
	interfaces_bring_up($vipif);
1272

    
1273
	/*
1274
	 * XXX: BIG HACK but carpdev needs ip services active
1275
	 *      before even starting something as dhclient.
1276
	 *      I do not know if this is a feature or a bug
1277
	 *      but better than track it make it work ;) .
1278
	 */
1279
	//$fakeiptouse = "10.254.254." . ($carp_instances_counter+1);
1280
	//$cmdchain->add("CarpDEV hack", "/sbin/ifconfig {$carpint} inet {$fakeiptouse}", false);
1281

    
1282
	/* generate dhclient_wan.conf */
1283
	$fd = fopen("{$g['varetc_path']}/dhclient_{$vipif}.conf", "w");
1284
	if ($fd) {
1285
		$dhclientconf = "";
1286

    
1287
		$dhclientconf .= <<<EOD
1288
interface "{$vipif}" {
1289
timeout 60;
1290
retry 1;
1291
select-timeout 0;
1292
initial-interval 1;
1293
script "/sbin/dhclient-script";
1294
}
1295

    
1296
EOD;
1297

    
1298
		fwrite($fd, $dhclientconf);
1299
		fclose($fd);
1300

    
1301
		/* fire up dhclient */
1302
		mwexec("/sbin/dhclient -c {$g['varetc_path']}/dhclient_{$vipif}.conf {$vipif} >/tmp/{$vipif}_output >/tmp/{$vipif}_error_output", false);
1303
	} else {
1304
		log_error("Error: cannot open dhclient_{$vipif}.conf in interfaces_carpdev_configure() for writing.\n");
1305
		mwexec("/sbin/dhclient -b {$vipif}");
1306
	}
1307

    
1308
	$fout = fopen("/tmp/ifconfig_{$vipif}","w");
1309
	fwrite($fout, "/sbin/dhclient -c {$g['varetc_path']}/dhclient_{$vipif}.conf {$vipif}");
1310
	fclose($fout);
1311

    
1312
	return $vipif;
1313
}
1314

    
1315
function interface_wireless_clone($if, $wlcfg) {
1316
	global $config, $g;
1317
	/*   Check to see if interface has been cloned as of yet.  
1318
	 *   If it has not been cloned then go ahead and clone it.
1319
	 */
1320
	$needs_clone = true;
1321
	$interface_num = substr($wlcfg['if'], 3);
1322
	if(does_interface_exist("{$wlcfg['if']}_wlan{$interface_num}")) {
1323
		$hostap_enabled = `/sbin/ifconfig | grep {$wlcfg['if']}_wlan{$interface_num} | grep hostap`;
1324
		if($hostap_enabled) 
1325
			$needs_clone = false;
1326
		else 
1327
			exec("/sbin/ifconfig {$wlcfg['if']}_wlan{$interface_num} destroy");
1328
	}
1329
	if($needs_clone == true) {
1330
		// Setup wireless nic
1331
		if($wlcfg['wireless']['mode'] == "hostap") 
1332
			$mode = "wlanmode hostap";
1333
		// Create the new wlan interface. FreeBSD returns the new interface name.
1334
		// example:  wlan2
1335
		$newif = trim(`/sbin/ifconfig wlan create wlandev {$wlcfg['if']} {$mode}`);
1336
		// Rename the interface to $parentnic_wlan$parentnic#: EX: ath0_wlan0
1337
		exec("/sbin/ifconfig {$newif} name {$wlcfg['if']}_wlan{$interface_num}");
1338
	}
1339
}
1340

    
1341
function interface_wireless_configure($if, &$wl, &$wlcfg) {
1342
	global $config, $g;
1343

    
1344
	/*    open up a shell script that will be used to output the commands.
1345
	 *    since wireless is changing a lot, these series of commands are fragile
1346
     *    and will sometimes need to be verified by a operator by executing the command
1347
     *    and returning the output of the command to the developers for inspection.  please
1348
     *    do not change this routine from a shell script to individul exec commands.  -sullrich
1349
	 */
1350

    
1351
	// Make read / writable (nano)
1352
	conf_mount_rw();
1353

    
1354
	// Remove script file
1355
	unlink_if_exists("{$g['tmp_path']}/{$if}_setup.sh");
1356

    
1357
	// Clone wireless nic if needed.
1358
	interface_wireless_clone($if, $wl);
1359
	
1360
	$fd_set = fopen("/tmp/{$if}_setup.sh","w");
1361
	fwrite($fd_set, "#!/bin/sh\n");
1362
	fwrite($fd_set, "# {$g['product_name']} wireless configuration script.\n\n");
1363

    
1364
	fwrite($fd_set, "# enable shell debugging\n");
1365
	fwrite($fd_set, "set -x\n");
1366

    
1367
	/* set values for /path/program */
1368
	$hostapd = "/usr/sbin/hostapd";
1369
	$wpa_supplicant = "/usr/sbin/wpa_supplicant";
1370
	$ifconfig = "/sbin/ifconfig";
1371
	$killall = "/usr/bin/killall";
1372

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

    
1375
	/* Set a/b/g standard */
1376
	$standard = "mode " . escapeshellarg($wlcfg['standard']);
1377

    
1378
	/* Set 802.11g protection mode */
1379
	$protmode = "protmode " . escapeshellarg($wlcfg['protmode']);
1380

    
1381
	/* set wireless channel value */
1382
	if(isset($wlcfg['channel']))
1383
		if($wlcfg['channel'] == "0")
1384
			$channel = "channel any";
1385
		else
1386
			$channel = "channel " . escapeshellarg($wlcfg['channel']);
1387

    
1388
	/* set Distance value */
1389
	if($wlcfg['distance'])
1390
		$distance = escapeshellarg($wlcfg['distance']);
1391

    
1392
	/* Set ssid */
1393
	if($wlcfg['ssid'])
1394
		$ssid = "ssid " . escapeshellarg($wlcfg['ssid']);
1395

    
1396
	/* Set wireless hostap mode */
1397
	if ($wlcfg['mode'] == "hostap")
1398
		$hostapmode = "mediaopt hostap";
1399
	else
1400
		$hostapmode = "-mediaopt hostap";
1401

    
1402
	/* Set wireless adhoc mode */
1403
	if ($wlcfg['mode'] == "adhoc")
1404
		$adhocmode = "mediaopt adhoc";
1405
	else
1406
		$adhocmode = "-mediaopt adhoc";
1407

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

    
1410
	/* handle hide ssid option */
1411
	if(isset($wlcfg['hidessid']['enable']))
1412
		$hidessid = "hidessid";
1413
	else
1414
		$hidessid = "-hidessid";
1415

    
1416
	/* handle pureg (802.11g) only option */
1417
	if(isset($wlcfg['pureg']['enable']))
1418
		$pureg = "mode 11g pureg";
1419
	else
1420
		$pureg = "-pureg";
1421

    
1422
	/* enable apbridge option */
1423
	if(isset($wlcfg['apbridge']['enable']))
1424
		$apbridge = "apbridge";
1425
	else
1426
		$apbridge = "-apbridge";
1427

    
1428
	/* handle turbo option */
1429
	if(isset($wlcfg['turbo']['enable']))
1430
		$turbo = "mediaopt turbo";
1431
	else
1432
		$turbo = "-mediaopt turbo";
1433

    
1434
	/* handle txpower setting */
1435
	if($wlcfg['txpower'] <> "")
1436
		$txpower = "txpower " . escapeshellarg($wlcfg['txpower']);
1437

    
1438
	/* handle wme option */
1439
	if(isset($wlcfg['wme']['enable']))
1440
		$wme = "wme";
1441
	else
1442
		$wme = "-wme";
1443

    
1444
	/* set up wep if enabled */
1445
    if (isset($wlcfg['wep']['enable']) && is_array($wlcfg['wep']['key'])) {
1446
		if($wlcfg['wpa']['auth_algs'] == "1")
1447
			$wepset .= "authmode open wepmode on ";
1448
		else if($wlcfg['wpa']['auth_algs'] == "2")
1449
			$wepset .= "authmode shared wepmode on ";
1450
		else if($wlcfg['wpa']['auth_algs'] == "3")
1451
			$wepset .= "authmode mixed wepmode on ";
1452
		$i = 1;
1453
		foreach ($wlcfg['wep']['key'] as $wepkey) {
1454
			$wepset .= "wepkey " . escapeshellarg("{$i}:{$wepkey['value']}") . " ";
1455
			if (isset($wepkey['txkey']))
1456
				$wepset .= "weptxkey {$i} ";
1457
			$i++;
1458
		}
1459
    } else {
1460
    	$wepset .= "authmode open wepmode off ";
1461
	}
1462

    
1463
	/* generate wpa_supplicant/hostap config if wpa is enabled */
1464

    
1465
	switch ($wlcfg['mode']) {
1466
		case 'bss':
1467
			if (isset($wlcfg['wpa']['enable'])) {
1468

    
1469
				$wpa .= <<<EOD
1470
ctrl_interface={$g['varrun_path']}/wpa_supplicant
1471
ctrl_interface_group=0
1472
ap_scan=1
1473
#fast_reauth=1
1474
network={
1475
ssid="{$wlcfg['ssid']}"
1476
scan_ssid=1
1477
priority=5
1478
key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
1479
psk="{$wlcfg['wpa']['passphrase']}"
1480
pairwise={$wlcfg['wpa']['wpa_pairwise']}
1481
group={$wlcfg['wpa']['wpa_pairwise']}
1482
}
1483
EOD;
1484

    
1485
				$fd = fopen("{$g['varetc_path']}/wpa_supplicant_{$if}.conf", "w");
1486
				fwrite($fd, "{$wpa}");
1487
				fclose($fd);
1488

    
1489
				fwrite($fd_set, kill_wpasupplicant($if));
1490
			}
1491
		break;
1492

    
1493
		case 'hostap':
1494
			if (isset($wlcfg['wpa']['enable'])) {
1495
				$wpa .= <<<EOD
1496
interface={$if}
1497
driver=bsd
1498
logger_syslog=-1
1499
logger_syslog_level=0
1500
logger_stdout=-1
1501
logger_stdout_level=0
1502
dump_file={$g['tmp_path']}/hostapd_{$if}.dump
1503
ctrl_interface={$g['varrun_path']}/hostapd
1504
ctrl_interface_group=wheel
1505
#accept_mac_file={$g['tmp_path']}/hostapd_{$if}.accept
1506
#deny_mac_file={$g['tmp_path']}/hostapd_{$if}.deny
1507
#macaddr_acl={$wlcfg['wpa']['macaddr_acl']}
1508
ssid={$wlcfg['ssid']}
1509
debug={$wlcfg['wpa']['debug_mode']}
1510
auth_algs={$wlcfg['wpa']['auth_algs']}
1511
wpa={$wlcfg['wpa']['wpa_mode']}
1512
wpa_key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
1513
wpa_pairwise={$wlcfg['wpa']['wpa_pairwise']}
1514
wpa_group_rekey={$wlcfg['wpa']['wpa_group_rekey']}
1515
wpa_gmk_rekey={$wlcfg['wpa']['wpa_gmk_rekey']}
1516
wpa_strict_rekey={$wlcfg['wpa']['wpa_strict_rekey']}
1517
wpa_passphrase={$wlcfg['wpa']['passphrase']}
1518
ieee8021x={$wlcfg['wpa']['ieee8021x']}
1519
#Enable the next lines for preauth when roaming. Interface = wired or wireless interface talking to the AP you want to roam from/to
1520
#rsn_preauth=1
1521
#rsn_preauth_interfaces=eth0
1522
EOD;
1523

    
1524
				$fd = fopen("{$g['varetc_path']}/hostapd_{$if}.conf", "w");
1525
				fwrite($fd, "{$wpa}");
1526
				fclose($fd);
1527

    
1528
				fwrite($fd_set, kill_hostapd($if));
1529
			}
1530
		break;
1531

    
1532
		case 'adhoc':
1533
			fwrite($fd_set, kill_hostapd($if));
1534
			fwrite($fd_set, kill_wpasupplicant($if));
1535
		break;
1536
	}
1537

    
1538
	/*
1539
	 *    all variables are set, lets start up everything
1540
     */
1541

    
1542
	/* set ack timers according to users preference (if he/she has any) */
1543
	if($distance) {
1544
		fwrite($fd_set, "# Enable ATH distance settings\n");
1545
		fwrite($fd_set, "/sbin/athctrl.sh -i {$if} -d {$distance}\n");
1546
	}
1547

    
1548
	$standard_no_turbo = str_replace(" Turbo", "", $standard);
1549

    
1550
	$settings = <<<EOD
1551

    
1552
{$ifconfig} {$if} down
1553
{$ifconfig} {$if} {$standard_no_turbo}
1554
{$ifconfig} {$if} {$channel}
1555
{$ifconfig} {$if} {$turbo}
1556
{$ifconfig} {$if} {$ssid}
1557
{$ifconfig} {$if} {$hidessid}
1558
{$ifconfig} {$if} {$adhocmode}
1559
{$ifconfig} {$if} {$protmode}
1560
{$ifconfig} {$if} {$pureg}
1561
{$ifconfig} {$if} {$apbridge}
1562
{$ifconfig} {$if} {$wme}
1563
{$ifconfig} {$if} {$wepset}
1564
{$ifconfig} {$if} {$txpower}
1565
{$ifconfig} {$if} {$hostapmode}
1566
{$ifconfig} {$if} up
1567

    
1568
EOD;
1569

    
1570
	/* write out above <<EOD stuff */
1571
	fwrite($fd_set, $settings);
1572

    
1573
	if (isset($wlcfg['wpa']['enable'])) {
1574
		if ($wlcfg['mode'] == "bss")
1575
			fwrite($fd_set, "{$wpa_supplicant} -B -i {$if} -c {$g['varetc_path']}/wpa_supplicant_{$if}.conf\n");
1576
		if ($wlcfg['mode'] == "hostap")
1577
			fwrite($fd_set, "{$hostapd} -B {$g['varetc_path']}/hostapd_{$if}.conf\n");
1578
	}
1579

    
1580
	fclose($fd_set);
1581

    
1582
	conf_mount_ro();
1583

    
1584
	/* execute commands now in shell */
1585
	mwexec("/bin/sh /tmp/{$if}_setup.sh");
1586
	sleep(2);
1587
	// XXX: ermal - This seems like not needed!? 
1588
	//mwexec("/bin/sh /tmp/{$if}_setup.sh");
1589

    
1590
	return 0;
1591

    
1592
}
1593

    
1594
function kill_hostapd($interface) {
1595
	return "/bin/ps awwuxx | grep hostapd | grep $interface | awk '{ print \$2 }' | xargs kill\n";
1596
}
1597

    
1598
function kill_wpasupplicant($interface) {
1599
	return "/bin/ps awwuxx | grep wpa_supplicant | grep $interface | awk '{ print \$2 }' | xargs kill\n";
1600
}
1601

    
1602
function find_dhclient_process($interface) {
1603
	if($interface)
1604
		$pid = `ps awwwux | grep dhclient | grep -v grep | grep {$interface} | awk '{ print \$2 }'`;
1605
	return $pid;
1606
}
1607

    
1608
function interface_configure($interface = "wan", $reloadall = false) {
1609
	global $config, $g;
1610
	global $interface_sn_arr_cache, $interface_ip_arr_cache;
1611

    
1612
	$wancfg = $config['interfaces'][$interface];
1613

    
1614
	$realif = get_real_interface($interface);
1615

    
1616
	if (!$g['booting']) {
1617
		/* remove all IPv4 addresses */
1618
		while (mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " -alias", true) == 0);
1619
			interface_bring_down($interface);
1620
	}
1621

    
1622
	/* wireless configuration? */
1623
	if (is_array($wancfg['wireless']))
1624
		interface_wireless_configure($realif, $wancfg, $wancfg['wireless']);
1625

    
1626
	if ($wancfg['spoofmac']) {
1627
		mwexec("/sbin/ifconfig " . escapeshellarg($realif) .
1628
			" link " . escapeshellarg($wancfg['spoofmac']));
1629
	}  else {
1630
		$mac = get_interface_mac(get_real_interface(get_real_interface($wancfg['if'])));
1631
		if($mac == "ff:ff:ff:ff:ff:ff") {
1632
			/*   this is not a valid mac address.  generate a
1633
			 *   temporary mac address so the machine can get online.
1634
			 */
1635
			echo "Generating new MAC address.";
1636
			$random_mac = generate_random_mac_address();
1637
			mwexec("/sbin/ifconfig " . escapeshellarg(get_real_interface($wancfg['if'])) .
1638
				" link " . escapeshellarg($random_mac));
1639
			$wancfg['spoofmac'] = $random_mac;
1640
			write_config();
1641
			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");
1642
		}
1643
	}
1644

    
1645
	/* media */
1646
	if ($wancfg['media'] || $wancfg['mediaopt']) {
1647
		$cmd = "/sbin/ifconfig " . escapeshellarg(get_real_interface($wancfg['if']));
1648
		if ($wancfg['media'])
1649
			$cmd .= " media " . escapeshellarg($wancfg['media']);
1650
		if ($wancfg['mediaopt'])
1651
			$cmd .= " mediaopt " . escapeshellarg($wancfg['mediaopt']);
1652
		mwexec($cmd);
1653
	}
1654

    
1655
	/* invalidate interface/ip/sn cache */
1656
	get_interface_arr(true);
1657
	unset($interface_ip_arr_cache[$realif]);
1658
	unset($interface_sn_arr_cache[$realif]);
1659

    
1660
	switch ($wancfg['ipaddr']) {
1661

    
1662
		case 'carpdev-dhcp':
1663
			interface_carpdev_dhcp_configure($interface);
1664
			break;
1665
		case 'dhcp':
1666
			interface_dhcp_configure($interface);
1667
			break;
1668

    
1669
		case 'pppoe':
1670
			interface_pppoe_configure($interface);
1671
			break;
1672

    
1673
		case 'pptp':
1674
			interface_pptp_configure($interface);
1675
			break;
1676

    
1677
		default:
1678
			if ($wancfg['ipaddr'] <> "" && $wancfg['subnet'] <> "") {
1679
				if (isset($wancfg['ispointtopoint']) && $wancfg['pointtopoint']) {
1680
					mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " " .
1681
						escapeshellarg($wancfg['ipaddr'] . "/" . $wancfg['subnet']) .
1682
						" " . escapeshellarg($wancfg['pointtopoint']) . " up");
1683
				} else {
1684
					if($wancfg['ipaddr'] && $wancfg['subnet'])
1685
						mwexec("/sbin/ifconfig " . escapeshellarg($realif) .
1686
							" " . escapeshellarg($wancfg['ipaddr'] . "/" . 
1687
							$wancfg['subnet']));
1688
				}
1689
			}
1690

    
1691
			if (is_ipaddr($wancfg['gateway']))
1692
				file_put_contents("/tmp/{$realif}_router", $wancfg['gateway']);
1693
	}
1694
	if($wancfg['if'])
1695
		interfaces_bring_up(get_real_interface(get_real_interface($wancfg['if'])));
1696
	else 
1697
		log_error("Could not bring wancfg['if'] up -- variable not defined in interface_configure()");
1698
	
1699
	interface_reload_carps($realif);
1700

    
1701
	if (!$g['booting']) {
1702
		if (link_interface_to_gre($interface)) {
1703
			foreach ($config['gres']['gre'] as $gre)
1704
				if ($gre['if'] == $interface)
1705
					interface_gre_configure($gre);
1706
		}
1707
		if (link_interface_to_gif($interface)) {
1708
                	foreach ($config['gifs']['gif'] as $gif)
1709
				if ($gif['if'] == $interface)
1710
                        		interface_gre_configure($gif);
1711
        	}
1712
		if (link_interface_to_bridge($interface)) {
1713
			foreach ($config['bridges']['bridged'] as $bridge)
1714
				if (stristr($bridge['members'], "{$interface}"))
1715
					interface_bridge_configure($bridge);
1716
		}
1717

    
1718
		if ($interface == "lan")
1719
			/* make new hosts file */
1720
               		system_hosts_generate();
1721

    
1722
		if ($reloadall == true) {
1723

    
1724
			/* reconfigure static routes (kernel may have deleted them) */
1725
			system_routing_configure();
1726

    
1727
			/* reload ipsec tunnels */
1728
			vpn_ipsec_configure();
1729

    
1730
			/* update dyndns */
1731
			services_dyndns_configure();
1732

    
1733
			/* force DNS update */
1734
			services_dnsupdate_process();
1735

    
1736
			/* restart dnsmasq */
1737
			services_dnsmasq_configure();
1738

    
1739
			/* reload captive portal */
1740
			captiveportal_configure();
1741

    
1742
			/* set the reload filter dity flag */
1743
			filter_configure();
1744
		}
1745
	}
1746

    
1747
	unmute_kernel_msgs();
1748

    
1749
	return 0;
1750
}
1751

    
1752
function interface_carpdev_dhcp_configure($interface = "wan") {
1753
	global $config, $g;
1754

    
1755
	$wancfg = $config['interfaces'][$interface];
1756
	$wanif = $wancfg['if'];
1757
	/* bring wan interface up before starting dhclient */
1758
	if($wanif)
1759
		interfaces_bring_up($wanif);
1760
	else 
1761
		log_error("Could not bring wanif up in terface_carpdev_dhcp_configure()");
1762

    
1763
	return 0;
1764
}
1765

    
1766
function interface_dhcp_configure($interface = "wan") {
1767
	global $config, $g;
1768

    
1769
	$wancfg = $config['interfaces'][$interface];
1770

    
1771
	/* generate dhclient_wan.conf */
1772
	$fd = fopen("{$g['varetc_path']}/dhclient_{$interface}.conf", "w");
1773
	if (!$fd) {
1774
		printf("Error: cannot open dhclient_{$interface}.conf in interfaces_wan_dhcp_configure() for writing.\n");
1775
		return 1;
1776
	}
1777

    
1778
	if ($wancfg['dhcphostname']) {
1779
		$dhclientconf_hostname = "send dhcp-client-identifier \"{$wancfg['dhcphostname']}\";\n";
1780
		$dhclientconf_hostname .= "\tsend host-name \"{$wancfg['dhcphostname']}\";\n";
1781
	} else {
1782
		$dhclientconf_hostname = "";
1783
	}
1784

    
1785
	$wanif = get_real_interface($interface);
1786

    
1787
 	$dhclientconf = "";
1788
	
1789
	$dhclientconf .= <<<EOD
1790
interface "{$wanif}" {
1791
timeout 60;
1792
retry 1;
1793
select-timeout 0;
1794
initial-interval 1;
1795
	{$dhclientconf_hostname}
1796
	script "/sbin/dhclient-script";
1797
}
1798

    
1799
EOD;
1800

    
1801
if(is_ipaddr($wancfg['alias-address'])) {
1802
	$subnetmask = gen_subnet_mask($wancfg['alias-subnet']);
1803
	$dhclientconf .= <<<EOD
1804
alias {
1805
	interface  "{$wanif}";
1806
	fixed-address {$wancfg['alias-address']};
1807
	option subnet-mask {$subnetmask};
1808
}
1809

    
1810
EOD;
1811
}
1812
	fwrite($fd, $dhclientconf);
1813
	fclose($fd);
1814

    
1815
	$realwanif = $wancfg['if'];
1816

    
1817
	/* bring wan interface up before starting dhclient */
1818
	if($realwanif)
1819
		interfaces_bring_up(get_real_interface($realwanif));
1820
	else 
1821
		log_error("Could not bring realwanif up in interface_dhcp_configure()");
1822

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

    
1826
	$fout = fopen("/tmp/ifconfig_{$wanif}","w");
1827
	fwrite($fout, "/sbin/dhclient -c {$g['varetc_path']}/dhclient_{$interface}.conf {$wanif}");
1828
	fclose($fout);
1829

    
1830
	return 0;
1831
}
1832

    
1833
function interface_pppoe_configure($interface = "wan") 
1834
{
1835
	global $config, $g;
1836

    
1837
	$wancfg = $config['interfaces'][$interface];
1838

    
1839
	/* generate mpd.conf */
1840
	$fd = fopen("{$g['varetc_path']}/mpd_{$interface}.conf", "w");
1841
	if (!$fd) {
1842
		printf("Error: cannot open mpd_{$interface}.conf in interface_pppoe_configure().\n");
1843
		return 1;
1844
	}
1845

    
1846
	$idle = 0;
1847

    
1848
	if (isset($wancfg['ondemand'])) {
1849
		$ondemand = "enable";
1850
		if ($wancfg['timeout'])
1851
			$idle = $wancfg['timeout'];
1852
	} else {
1853
		$ondemand = "disable";
1854
	}
1855

    
1856
	$mpdconf = <<<EOD
1857
startup:
1858
pppoeclient:
1859

    
1860
EOD;
1861

    
1862
	if ($interface == "wan")
1863
		$realif = "pppoe0";
1864
	else {
1865
		// Here code assumes only that strings of form "opt#" will be passed.
1866
		$realif = "pppoe" . substr($interface, 3); 
1867
	}
1868
	
1869
	$mpdconf .= <<<EOD
1870
	new -i {$realif} pppoeclient pppoeclient
1871

    
1872
EOD;
1873
	if ($interface == "wan")
1874
		$mpdconf .= <<<EOD
1875
	set iface route default
1876

    
1877
EOD;
1878
	
1879
	$mpdconf .= <<<EOD
1880
	set iface {$ondemand} on-demand
1881
	set iface idle {$idle}
1882
	set iface enable tcpmssfix
1883
	set iface up-script /usr/local/sbin/ppp-linkup
1884
	set iface down-script /usr/local/sbin/ppp-linkdown
1885

    
1886
EOD;
1887

    
1888
	if (isset($wancfg['ondemand'])) {
1889
		if (isset($wancfg['local-ip']) && isset($wancfg['remote-ip'])) {
1890
			$mpdconf .= <<<EOD
1891
	set iface addrs {$wancfg['local-ip']} {$wancfg['remote-ip']}
1892

    
1893
EOD;
1894
		} else {
1895
			$mpdconf .= <<<EOD
1896
	set iface addrs 192.0.2.112 192.0.2.113
1897

    
1898
EOD;
1899
		}
1900
	}
1901

    
1902
	$mpdconf .= <<<EOD
1903
	set bundle disable multilink
1904
	set auth authname "{$wancfg['pppoe_username']}"
1905
	set auth password "{$wancfg['pppoe_password']}"
1906
	set link keep-alive 10 60
1907
	set link max-redial 0
1908
	set link no acfcomp protocomp
1909
	set link disable pap chap
1910
	set link accept chap
1911
	
1912
EOD;
1913
	if (empty($wancfg['mtu']))
1914
		$mpdmtu = "1492";
1915
	else 
1916
		$mpdmtu = "{$wancfg['mtu']}";
1917

    
1918
	$mpdconf .= <<<EOD
1919
	set link mtu {$mpdmtu}
1920
	set ipcp yes vjcomp
1921
	set ipcp ranges 0.0.0.0/0 0.0.0.0/0
1922

    
1923
EOD;
1924

    
1925
	if (isset($config['system']['dnsallowoverride'])) {
1926
		$mpdconf .= <<<EOD
1927
	set ipcp enable req-pri-dns
1928

    
1929
EOD;
1930
	}
1931

    
1932
	if (!isset($wancfg['dnsnosec']) && isset($config['system']['dnsallowoverride'])) {
1933
			$mpdconf .= <<<EOD
1934
	set ipcp enable req-sec-dns
1935

    
1936
EOD;
1937
	}
1938
	
1939
	$mpdconf .= <<<EOD
1940
	open
1941

    
1942
EOD;
1943

    
1944
	fwrite($fd, $mpdconf);
1945
	fclose($fd);
1946

    
1947
	/* generate mpd.links */
1948
	$fd = fopen("{$g['varetc_path']}/mpd_{$interface}.links", "w");
1949
	if (!$fd) {
1950
		printf("Error: cannot open mpd_{$interface}.links in interface_pppoe_configure().\n");
1951
		return 1;
1952
	}
1953

    
1954
	$mpdconf = <<<EOD
1955
pppoeclient:
1956
	set link type pppoe
1957
	set pppoe iface {$wancfg['if']}
1958
	set pppoe service "{$wancfg['provider']}"
1959
	set pppoe enable originate
1960
	set pppoe disable incoming
1961

    
1962
EOD;
1963

    
1964
	fwrite($fd, $mpdconf);
1965
	fclose($fd);
1966

    
1967
	if(file_exists("{$g['varrun_path']}/pppoe_{$interface}.pid") and $g['booting']) {
1968
		/* if we are booting and mpd has already been started then don't start again. */
1969
	} else {
1970
		/* if mpd is active, lets take it down */
1971
		if(file_exists("{$g['varrun_path']}/pppoe_{$interface}.pid")) {
1972
			killbypid("{$g['varrun_path']}/pppoe_{$interface}.pid");
1973
			sleep(3);
1974
		}
1975

    
1976
		/* Bring the parent interface up */
1977
		if($wancfg['if'])
1978
			interfaces_bring_up(get_real_interface($wancfg['if']));
1979
		else 
1980
			log_error("Could not bring wancfg['if'] up in interface_pppoe_configure()");
1981

    
1982
		/* fire up mpd */
1983
		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");
1984
	}
1985

    
1986
	/* sleep until wan is up - or 30 seconds, whichever comes first */
1987
	for ($count = 0; $count < 30; $count++) {
1988
		if(file_exists("{$g['tmp_path']}/{$realif}up")) {
1989
			break;
1990
		}
1991
		sleep(1);
1992
	}
1993

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

    
1996
	return 0;
1997
}
1998

    
1999
function interface_pptp_configure($interface) {
2000
	global $config, $g;
2001

    
2002
	$wancfg = $config['interfaces'][$interface];
2003

    
2004
	/* generate mpd.conf */
2005
	$fd = fopen("{$g['varetc_path']}/mpd_{$interface}.conf", "w");
2006
	if (!$fd) {
2007
		printf("Error: cannot open mpd_{$interface}.conf in interface_pptp_configure().\n");
2008
		return 1;
2009
	}
2010

    
2011
	$idle = 0;
2012

    
2013
	if (isset($wancfg['ondemand'])) {
2014
		$ondemand = "enable";
2015
		if ($wancfg['timeout'])
2016
			$idle = $wancfg['timeout'];
2017
	} else {
2018
		$ondemand = "disable";
2019
	}
2020

    
2021
	$mpdconf = <<<EOD
2022
startup:
2023
pptp:
2024

    
2025
EOD;
2026

    
2027
        if ($interface == "wan")
2028
                $realif = "pptp0";
2029
        else {
2030
                // Here code assumes only that strings of form "opt#" will be passed.
2031
                $realif = "pptp" . substr($interface, 3);
2032
	}
2033

    
2034
        $mpdconf .= <<<EOD
2035
        new -i {$realif} pptp pptp 
2036

    
2037
EOD;
2038
        if ($interface == "wan")
2039
                $mpdconf .= <<<EOD
2040
        set iface route default
2041

    
2042
EOD;
2043

    
2044
        $mpdconf .= <<<EOD
2045
	set iface {$ondemand} on-demand
2046
	set iface idle {$idle}
2047
	set iface up-script /usr/local/sbin/ppp-linkup
2048
	set iface down-script /usr/local/sbin/ppp-linkdown
2049

    
2050
EOD;
2051

    
2052
	if (isset($wanfg['ondemand'])) {
2053
		$mpdconf .= <<<EOD
2054
	set iface addrs 10.0.0.1 10.0.0.2
2055

    
2056
EOD;
2057
	}
2058

    
2059
	$mpdconf .= <<<EOD
2060
	set bundle disable multilink
2061
	set auth authname "{$wancfg['pptp_username']}"
2062
	set auth password "{$wancfg['pptp_password']}"
2063
	set bundle no noretry
2064
	set link keep-alive 10 60
2065
	set link max-redial 0
2066
	set link no acfcomp protocomp
2067
	set link disable pap chap
2068
	set link accept chap
2069
	set ipcp no vjcomp
2070
	set ipcp ranges 0.0.0.0/0 0.0.0.0/0
2071

    
2072
EOD;
2073
	if (isset($config['system']['dnsallowoverride'])) {
2074
		$mpdconf .= <<<EOD
2075
	set ipcp enable req-pri-dns
2076

    
2077
EOD;
2078
	}
2079

    
2080
	$mpdconf .= <<<EOD
2081
	open
2082

    
2083
EOD;
2084

    
2085
	fwrite($fd, $mpdconf);
2086
	fclose($fd);
2087

    
2088
	/* generate mpd.links */
2089
	$fd = fopen("{$g['varetc_path']}/mpd_{$interface}.links", "w");
2090
	if (!$fd) {
2091
		printf("Error: cannot open mpd_{$interface}.links in interface_pptp_configure().\n");
2092
		return 1;
2093
	}
2094

    
2095
	$mpdconf = <<<EOD
2096
pptp:
2097
	set link type pptp
2098
	set pptp enable originate outcall
2099
	set pptp disable windowing
2100
	set pptp self {$wancfg['local']}
2101
	set pptp peer {$wancfg['remote']}
2102

    
2103
EOD;
2104

    
2105
	fwrite($fd, $mpdconf);
2106
	fclose($fd);
2107

    
2108
	/* configure interface */
2109
	if($wancfg['if'])
2110
		mwexec("/sbin/ifconfig " . escapeshellarg($wancfg['if']) . " " .
2111
			escapeshellarg($wancfg['local'] . "/" . $wancfg['subnet']) . " up");
2112
	else 
2113
		log_error("Could not bring interface wancfg['if'] up in interface_pptp_configure()");
2114
	/* fire up mpd */
2115
	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");
2116

    
2117
	return 0;
2118
}
2119

    
2120
function interfaces_group_setup() {
2121
	global $config;
2122

    
2123
	if (!is_array($config['ifgroups']['ifgroupentry']))
2124
		return;
2125

    
2126
	foreach ($config['ifgroups']['ifgroupentry'] as $groupar)
2127
		interface_group_setup($groupar);
2128

    
2129
	return;
2130
}
2131

    
2132
function interface_group_setup(&$groupname /* The parameter is an array */) {
2133
	global $config;
2134

    
2135
	if (!is_array($groupname))
2136
		return;
2137
	$members = explode(" ", $groupname['members']);
2138
	foreach($members as $ifs) {
2139
		$realif = get_real_interface($ifs);
2140
		if ($realif)
2141
			mwexec("/sbin/ifconfig {$realif} group {$groupname['ifname']}");
2142
	}
2143

    
2144
	return;
2145
}
2146
 
2147
/* COMPAT Function */
2148
function convert_friendly_interface_to_real_interface_name($interface) {
2149
	return get_real_interface($interface);
2150
}
2151

    
2152
/* COMPAT Function */
2153
function get_real_wan_interface($interface = "wan") {
2154
	return get_real_interface($interface);
2155
}
2156

    
2157
/* COMPAT Function */
2158
function get_current_wan_address($interface = "wan") {
2159
	return get_interface_ip($interface);
2160
}
2161

    
2162
/*
2163
 * convert_real_interface_to_friendly_interface_name($interface): convert fxp0 -> wan, etc.
2164
 */
2165
function convert_real_interface_to_friendly_interface_name($interface = "wan") {
2166
        global $config;
2167

    
2168
        if (stristr($interface, "pppoe")) {
2169
                $index = substr($interface, 5);
2170
                if (intval($index) > 0)
2171
                        return "opt{$index}";
2172
                else
2173
                        return "wan";
2174
        } else if (stristr($interface, "pptp")) {
2175
                $index = substr($interface, 4);
2176
                if (intval($index) > 0)
2177
                        return "opt{$index}";
2178
                else
2179
                        return "wan";
2180
        } else if (stristr($interface, "carp")) {
2181
                $index = substr($interface, 4);
2182
                $counter = 0;
2183
                foreach ($config['virtualip']['vip'] as $vip) {
2184
                        if ($vip['mode'] == "carpdev-dhcp" || $vip['mode'] == "carp")  {
2185
                                if (intval($index) == $counter)
2186
                                        return $vip['interface'];
2187
                                $counter++;
2188
                        }
2189
                }
2190
        }
2191

    
2192
        /* if list */
2193
        $ifdescrs = get_configured_interface_list(false, true);
2194

    
2195
        foreach ($ifdescrs as $if => $ifname) {
2196
                if($config['interfaces'][$if]['if'] == $interface)
2197
                        return $ifname;
2198

    
2199
                /* XXX: ermal - The 3 lines below are totally bogus code. */
2200
                $int = interface_translate_type_to_real($if);
2201
                if($ifname == $interface)
2202
                        return $ifname;
2203

    
2204
                if($int == $interface)
2205
                        return $ifname;
2206
        }
2207
        return NULL;
2208
}
2209

    
2210
/* attempt to resolve interface to friendly descr */
2211
function convert_friendly_interface_to_friendly_descr($interface) {
2212
        global $config;
2213

    
2214
        switch ($interface) {
2215
                case "l2tp":
2216
                                $ifdesc = "L2TP";
2217
                                break;
2218
                case "pptp":
2219
                                $ifdesc = "pptp";
2220
                                break;
2221
                case "pppoe":
2222
                                $ifdesc = "pppoe";
2223
                                break;
2224
                case "openvpn":
2225
                                $ifdesc = "OpenVPN";
2226
                                break;
2227
                case "enc0":
2228
                        case "ipsec":
2229
                                $ifdesc = "IPsec";
2230
                                break;
2231
        default:
2232
                /* if list */
2233
                $ifdescrs = get_configured_interface_with_descr(false, true);
2234
                foreach ($ifdescrs as $if => $ifname) {
2235
                                if ($if == $interface || $ifname == $interface)
2236
                                        return $ifname;
2237
                }
2238
                break;
2239
        }
2240

    
2241
        return $ifdesc;
2242
}
2243

    
2244
function convert_real_interface_to_friendly_descr($interface) {
2245
        global $config;
2246

    
2247
        $ifdesc = convert_real_interface_to_friendly_interface_name("{$interface}");
2248

    
2249
        if ($ifdesc) {
2250
                $iflist = get_configured_interface_with_descr();
2251
                return $iflist[$ifdesc];
2252
        }
2253

    
2254
        return $interface;
2255
}
2256

    
2257
/*
2258
 *  interface_translate_type_to_real($interface):
2259
 *              returns the real hardware interface name for a friendly interface.  ie: wan
2260
 */
2261
function interface_translate_type_to_real($interface) {
2262
        global $config;
2263

    
2264
        if ($config['interfaces'][$interface]['if'] <> "")
2265
                return $config['interfaces'][$interface]['if'];
2266
        else
2267
		return $interface;
2268
}
2269

    
2270
function get_real_interface($interface = "wan") {
2271
    global $config;
2272

    
2273
	$wanif = NULL;
2274

    
2275
	switch ($interface) {
2276
	case "l2tp":
2277
		$wanif = "l2tp";
2278
		break;
2279
	case "pptp":
2280
		$wanif = "pptp";
2281
		break;
2282
	case "pppoe":
2283
		$wanif = "pppoe";
2284
		break;
2285
	case "openvpn":
2286
		$wanif = "openvpn";
2287
		break;
2288
	case "enc0":
2289
		$wanif = "enc0";
2290
		break;
2291
	case "ppp":
2292
		$wanif = "ppp";
2293
		break;
2294
	default:
2295
		$iflist = get_configured_interface_with_descr(false, true);
2296

    
2297
		foreach ($iflist as $if => $ifdesc) {
2298
			if ($interface == $if || $interface == $ifdesc) {
2299

    
2300
			// If a real interface was alread passed simply
2301
			// pass the real interface back.  This encourages
2302
			// the usage of this function in more cases so that
2303
			// we can combine logic for more flexibility.
2304
			if($config['interfaces'][$if]['if'] == $interface) {
2305
				$wanif = $interface;
2306
				break;
2307
			}
2308

    
2309
			// PPP Support
2310
			if($config['interfaces'][$if]['serialport']) {
2311
				$dev = $config['interfaces'][$if]['serialport'];
2312
				$ps = trim(`ps awux | grep -v grep | grep "$dev" | awk '{ print \$2 }'`);
2313
				if($ps) {
2314
					$int = trim(`/sbin/ifconfig | grep -v grep | grep -B2 "$ps" | head -n1 | cut -d: -f1`);
2315
					if($int) {
2316
						$wanif = $int;
2317
						break;
2318
					}
2319
				}
2320
			}
2321

    
2322
			$cfg = $config['interfaces'][$if];
2323

    
2324
			// Wireless cloned NIC support (FreeBSD 8+)
2325
			// interface name format: $parentnic_wlanparentnic#
2326
			// example: ath0_wlan0
2327
			if(is_interface_wireless($interface)) {
2328
				$interface_num = substr($cfg['if'], 3);
2329
				$wanif = $cfg['if'] . "_wlan" . $interface_num;
2330
				break;
2331
			}
2332

    
2333
			if (empty($cfg['ipaddr'])) {
2334
				$wanif = $cfg['if'];
2335
				break;
2336
			}
2337

    
2338
			switch ($cfg['ipaddr']) {
2339
				case "carpdev-dhcp":
2340
					$viparr = &$config['virtualip']['vip'];
2341
					$counter = 0;
2342
					if(is_array($viparr))
2343
					foreach ($viparr as $vip) {
2344
						if ($vip['mode'] == "carpdev-dhcp") {
2345
							if($vip['interface'] == $if) {
2346
								$wanif =  "carp{$counter}";
2347
								break;
2348
							}
2349
							$counter++;
2350
						} else if ($vip['mode'] = "carp") 
2351
							$counter++;
2352
					}
2353
					break;
2354
				case "pppoe": 
2355
					if ($if == "wan")
2356
						$wanif = "pppoe0";
2357
					else
2358
						$wanif = "pppoe" . substr($if,3);
2359
					break;
2360
				case "pptp": 
2361
					if ($if == "wan")
2362
						$wanif = "pptp0";
2363
					else
2364
						$wanif = "pptp" . substr($if, 3);
2365
					break;
2366
				default:
2367
					$wanif = $cfg['if'];
2368
					break;
2369
				}
2370
			
2371
				break;
2372
			}
2373
		}
2374
		break;
2375
	}
2376

    
2377
    return $wanif;
2378
}
2379

    
2380
function guess_interface_from_ip($ipaddress) {
2381
        $ret = `/usr/bin/netstat -rn | /usr/bin/awk '/^{$ipaddress}/ {printf "%s", \$6}'`;
2382
        if (empty($ret))
2383
                return false;
2384

    
2385
        return $ret;
2386
}
2387

    
2388
/*
2389
 * find_ip_interface($ip): return the interface where an ip is defined
2390
 */
2391
function find_ip_interface($ip)
2392
{
2393
        /* if list */
2394
        $ifdescrs = get_configured_interface_list();
2395

    
2396
        foreach ($ifdescrs as $ifdescr => $ifname) {
2397
		if ($ip == get_interface_ip($ifname)) {
2398
                	$int = get_real_interface($ifname);
2399
			return $int;
2400
		}
2401
        }
2402
        return false;
2403
}
2404

    
2405
/*
2406
 *   find_number_of_created_carp_interfaces: return the number of carp interfaces
2407
 */
2408
function find_number_of_created_carp_interfaces() {
2409
	return `/sbin/ifconfig | grep "carp:" | wc -l`;
2410
}
2411

    
2412
function get_all_carp_interfaces() {
2413
	$ints = str_replace("\n", " ", `ifconfig | grep "carp:" -B2 | grep ": flag" | cut -d: -f1`);
2414
	return $ints;
2415
}
2416

    
2417
/*
2418
 * find_carp_interface($ip): return the carp interface where an ip is defined
2419
 */
2420
function find_carp_interface($ip) {
2421
	global $config;
2422
	if (is_array($config['virtualip']['vip'])) {
2423
		foreach ($config['virtualip']['vip'] as $vip) {
2424
			if ($vip['mode'] == "carp" || $vip['mode'] == "carpdev") {
2425
				$carp_ip = find_interface_ip($vip['interface']);
2426
				$if = `ifconfig | grep '$ip' -B1 | head -n1 | cut -d: -f1`;
2427
				if ($if)
2428
					return $if;
2429
			}
2430
		}
2431
	}
2432
}
2433

    
2434
function link_carp_interface_to_parent($interface) {
2435
        global $config;
2436

    
2437
        if ($interface == "")
2438
                return;
2439

    
2440
        $carp_ip = find_interface_ip($interface);
2441
        if (!is_ipaddr($carp_ip))
2442
                return;
2443

    
2444
        /* if list */
2445
        $ifdescrs = get_configured_interface_list();
2446
        foreach ($ifdescrs as $ifdescr => $ifname) {
2447
                $interfaceip = get_interface_ip($ifname);
2448
                $subnet_bits = get_interface_subnet($ifname);
2449
                $subnet_ip = gen_subnet("{$interfaceip}", "{$subnet_bits}");
2450
                if(ip_in_subnet($carp_ip, "{$subnet_ip}/{$subnet_bits}"))
2451
                        return $ifname;
2452
        }
2453

    
2454
        return "";
2455
}
2456

    
2457
/****f* interfaces/link_ip_to_carp_interface
2458
 * NAME
2459
 *   link_ip_to_carp_interface - Find where a CARP interface links to.
2460
 * INPUTS
2461
 *   $ip
2462
 * RESULT
2463
 *   $carp_ints
2464
 ******/
2465
function link_ip_to_carp_interface($ip) {
2466
        global $config;
2467

    
2468
        if (!is_ipaddr($ip))
2469
                return;
2470

    
2471
        $carp_ints = "";
2472
        if (is_array($config['virtualip']['vip'])) {
2473
                foreach ($config['virtualip']['vip'] as $vip) {
2474
                        if ($vip['mode'] == "carp" || $vip['mode'] == "carpdev") {
2475
                                $carp_ip = $vip['subnet'];
2476
                                $carp_sn = $vip['subnet_bits'];
2477
                                $carp_nw = gen_subnet($carp_ip, $carp_sn);
2478
                                if (ip_in_subnet($ip, "{$carp_nw}/{$carp_sn}")) {
2479
                                        if (!stristr($carp_ints, $carp_int))
2480
                                                $carp_ints .= " {$carp_int}";
2481
                                }
2482
                        }
2483
                }
2484
        }
2485

    
2486
        return $carp_ints;
2487
}
2488

    
2489
/****f* interfaces/link_interface_to_bridge
2490
 * NAME
2491
 *   link_interface_to_bridge - Finds out a bridge group for an interface
2492
 * INPUTS
2493
 *   $ip
2494
 * RESULT
2495
 *   bridge[0-99]
2496
 ******/
2497
function link_interface_to_bridge($int) {
2498
        global $config;
2499

    
2500
        if (is_array($config['bridges']['bridged']))
2501
                foreach ($config['bridges']['bridged'] as $bridge)
2502
                        if(stristr($bridge['members'], "{$int}"))
2503
                                return "{$bridge['bridgeif']}";
2504
}
2505

    
2506
function link_interface_to_gre($interface) {
2507
        global $config;
2508

    
2509
        if (is_array($config['gres']['gre']))
2510
                foreach ($config['gres']['gre'] as $gre)
2511
                        if($gre['if'] == $interface)
2512
                                return "{$gre['greif']}";
2513
}
2514

    
2515
function link_interface_to_gif($interface) {
2516
        global $config;
2517

    
2518
        if (is_array($config['gifs']['gif']))
2519
                foreach ($config['gifs']['gif'] as $gif)
2520
                        if($gif['if'] == $interface)
2521
                                return "{$gif['gifif']}";
2522
}
2523

    
2524
/*
2525
 * find_interface_ip($interface): return the interface ip (first found)
2526
 */
2527
function find_interface_ip($interface, $flush = false)
2528
{
2529
	global $interface_ip_arr_cache;
2530

    
2531
	$interface = str_replace("\n", "", $interface);
2532
	
2533
	if (does_interface_exist($interface) == false)
2534
		$interface = convert_friendly_interface_to_real_interface_name($interface);
2535

    
2536
	if (does_interface_exist($interface) == false)
2537
		return;
2538

    
2539
	/* Setup IP cache */
2540
	if (!isset($interface_ip_arr_cache[$interface]) or $flush) {
2541
		$interface_ip_arr_cache[$interface] = `/sbin/ifconfig {$interface} | /usr/bin/grep -w "inet" | /usr/bin/cut -d" " -f 2| /usr/bin/head -1`;
2542
		$interface_ip_arr_cache[$interface] = str_replace("\n", "", $interface_ip_arr_cache[$interface]);
2543
	}
2544

    
2545
	return $interface_ip_arr_cache[$interface];
2546
}
2547

    
2548
function find_interface_subnet($interface, $flush = false)
2549
{
2550
	global $interface_sn_arr_cache;
2551

    
2552
	$interface = str_replace("\n", "", $interface);
2553
	if (does_interface_exist($interface) == false)
2554
		return;
2555

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

    
2561
	return $interface_sn_arr_cache[$interface];
2562
}
2563

    
2564
function get_interface_ip($interface = "wan")
2565
{
2566
	$realif = get_real_interface($interface);
2567
	if (!$realif) {
2568
		if (preg_match("/^carp/i", $interface))
2569
			$realif = $interface;
2570
		else
2571
			return null;
2572
	}
2573

    
2574
	/* Do we really come here for these interfaces ?! */
2575
	if (in_array($realif, array("pptp", "pppoe", "l2tp", "openvpn", "enc0" /* , "ppp" */)))
2576
			return "";
2577

    
2578
	$curip = find_interface_ip($realif);
2579
	if ($curip && is_ipaddr($curip) && ($curip != "0.0.0.0"))
2580
		return $curip;
2581

    
2582
	return null;
2583
}
2584

    
2585
function get_interface_subnet($interface = "wan")
2586
{
2587
	$realif = get_real_interface($interface);
2588
	if (!$realif) {
2589
                if (preg_match("/^carp/i", $interface))
2590
                        $realif = $interface;
2591
                else
2592
                        return null;
2593
        }
2594

    
2595
	/* Do we really come here for these interfaces ?! */
2596
	if (in_array($realif, array("pptp", "pppoe", "l2tp", "openvpn", "enc0" /* , "ppp" */)))
2597
		return "";
2598

    
2599
	$cursn = find_interface_subnet($realif);
2600
	if (!empty($cursn))
2601
		return $cursn;
2602

    
2603
	return null;
2604
}
2605

    
2606
/* return outside interfaces with a gateway */
2607
function get_interfaces_with_gateway() {
2608
	global $config;
2609

    
2610
	$ints = array();
2611

    
2612
	/* loop interfaces, check config for outbound */
2613
	foreach($config['interfaces'] as $ifdescr => $ifname) {
2614
		if($ifname['serialport']) {
2615
			$ints[] = $ifdescr;
2616
			continue;
2617
		}
2618
		switch ($ifname['ipaddr']) {
2619
			case "dhcp":
2620
			case "carpdev-dhcp":
2621
			case "pppoe":
2622
			case "pptp":
2623
			$ints[] = $ifdescr;
2624
			break;
2625
			default:
2626
			if ($ifname['pointtopoint'])
2627
				$ints[] = $ifdescr;
2628
			else if (!empty($ifname['gateway']))
2629
				$ints[] = $ifdescr;
2630
			break;
2631
		}
2632
	}
2633
	return $ints;
2634
}
2635

    
2636
/* return true if interface has a gateway */
2637
function interface_has_gateway($friendly) {
2638

    
2639
        $friendly = strtolower($friendly);
2640
        if (in_array($friendly, get_interfaces_with_gateway()))
2641
                return true;
2642

    
2643
	return false;
2644
}
2645

    
2646
/****f* interfaces/is_altq_capable
2647
 * NAME
2648
 *   is_altq_capable - Test if interface is capable of using ALTQ
2649
 * INPUTS
2650
 *   $int            - string containing interface name
2651
 * RESULT
2652
 *   boolean         - true or false
2653
 ******/
2654

    
2655
function is_altq_capable($int) {
2656
        /* Per:
2657
         * http://www.freebsd.org/cgi/man.cgi?query=altq&manpath=FreeBSD+7.2-current&format=html
2658
         * Only the following drivers have ALTQ support
2659
         */
2660
	$capable = array("age", "ale", "an", "ath", "aue", "awi", "bce",
2661
			"bfe", "bge", "dc", "de", "ed", "em", "ep", "fxp", "gem",
2662
			"hme", "ipw", "iwi", "jme", "le", "msk", "mxge", "my", "nfe",
2663
			"npe", "nve", "ral", "re", "rl", "rum", "sf", "sis", "sk",
2664
			"ste", "stge", "txp", "udav", "ural", "vge", "vr", "wi", "xl",
2665
			"ndis", "tun", "vlan", "pppoe", "pptp", "ng", "ppp");
2666

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

    
2669
        if (in_array($int_family[0], $capable))
2670
                return true;
2671
	else if (stristr($int_family, "vlan")) /* VLANs are name $parent.$vlan now */
2672
		return true;
2673
        else
2674
                return false;
2675
}
2676

    
2677
/****f* interfaces/is_interface_wireless
2678
 * NAME
2679
 *   is_interface_wireless - Returns if an interface is wireless
2680
 * RESULT
2681
 *   $tmp       - Returns if an interface is wireless
2682
 ******/
2683
function is_interface_wireless($interface) {
2684
        global $config, $g;
2685

    
2686
        $friendly = convert_real_interface_to_friendly_interface_name($interface);
2687
        if(!isset($config['interfaces'][$friendly]['wireless'])) {
2688
                if (preg_match($g['wireless_regex'], $interface)) {
2689
                        $config['interfaces'][$friendly]['wireless'] = array();
2690
                        return true;
2691
                }
2692
                unset($config['interfaces'][$friendly]['wireless']);
2693
                return false;
2694
        } else
2695
                return true;
2696
}
2697

    
2698
function get_wireless_modes($interface) {
2699
	/* return wireless modes and channels */
2700
	$wireless_modes = array();
2701

    
2702
	if(is_interface_wireless($interface)) {
2703
		$cloned_interface = get_real_interface($interface);
2704
		$wi = 1;
2705
		$ifconfig = "/sbin/ifconfig";
2706
		$awk = "/usr/bin/awk";
2707
		$chan_list = "$ifconfig $cloned_interface list chan";
2708
		$stack_list = "$awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
2709
		$format_list = "$awk '{print \$5 \" \" \$6 \",\" \$1}'";
2710

    
2711
		$interface_channels = "";
2712
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
2713
		$interface_channel_count = count($interface_channels);
2714

    
2715
		$c = 0;
2716
		while ($c < $interface_channel_count)
2717
		{
2718
			$channel_line = explode(",", $interface_channels["$c"]);
2719
			$wireless_mode = trim($channel_line[0]);
2720
			$wireless_channel = trim($channel_line[1]);
2721
			if(trim($wireless_mode) != "") {
2722
				/* if we only have 11g also set 11b channels */
2723
				if($wireless_mode == "11g") {
2724
					$wireless_modes["11b"] = array();
2725
				}
2726
				$wireless_modes["$wireless_mode"]["$c"] = $wireless_channel;
2727
			}
2728
			$c++;
2729
		}
2730
	}
2731
	return($wireless_modes);
2732
}
2733

    
2734
/****f* interfaces/get_interface_mtu
2735
 * NAME
2736
 *   get_interface_mtu - Return the mtu of an interface
2737
 * RESULT
2738
 *   $tmp       - Returns the mtu of an interface
2739
 ******/
2740
function get_interface_mtu($interface) {
2741
        $mtu = `/sbin/ifconfig {$interface} | /usr/bin/grep mtu | /usr/bin/cut -d" " -f6`;
2742
        return $mtu;
2743
}
2744

    
2745
function get_interface_mac($interface) {
2746
	$mac = array();
2747
        exec("/sbin/ifconfig {$interface} | /usr/bin/awk '/ether/ {print $2}'", $mac);
2748
        if(is_macaddr($mac)) {
2749
                return trim($mac);
2750
        } else {
2751
                return "";
2752
        }
2753
}
2754

    
2755
/****f* pfsense-utils/generate_random_mac_address
2756
 * NAME
2757
 *   generate_random_mac - generates a random mac address
2758
 * INPUTS
2759
 *   none
2760
 * RESULT
2761
 *   $mac - a random mac address
2762
 ******/
2763
function generate_random_mac_address() {
2764
        $mac = "02";
2765
        for($x=0; $x<5; $x++)
2766
                $mac .= ":" . dechex(rand(16, 255));
2767
        return $mac;
2768
}
2769

    
2770
/****f* interfaces/is_jumbo_capable
2771
 * NAME
2772
 *   is_jumbo_capable - Test if interface is jumbo frame capable.  Useful for determining VLAN capability.
2773
 * INPUTS
2774
 *   $int             - string containing interface name
2775
 * RESULT
2776
 *   boolean          - true or false
2777
 ******/
2778
function is_jumbo_capable($int) {
2779
        global $g;
2780

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

    
2783
        if (in_array($int_family[0], $g['vlan_long_frame']))
2784
                return true;
2785
        else
2786
                return false;
2787
}
2788

    
2789
function setup_pppoe_reset_file($interface, $status) {
2790
	define("CRON_PPPOE_CMD_FILE", "/conf/pppoe{$interface}restart");
2791
	define("CRON_PPPOE_CMD", "#!/bin/sh\necho '<?php require(\"config.inc\"); require(\"interfaces.inc\"); interface_reconfigure({$interface}); ?>' | /usr/local/bin/php -q");
2792
	if ($status == true) {
2793
		if (!file_exists(CRON_PPPOE_CMD_FILE)) {
2794
			file_put_contents(CRON_PPPOE_CMD_FILE, CRON_PPPOE_CMD);
2795
			chmod(CRON_PPPOE_CMD_FILE, 0700);
2796
		}	
2797
	} else
2798
		unlink_if_exists(CRON_PPPOE_CMD_FILE);
2799
}
2800

    
2801
?>
(19-19/47)