Project

General

Profile

Download (81.6 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
	// Start ppp.linkup file
903
	$rclinkup = "default:\n";
904

    
905
    if (is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) {
906
		foreach ($config['ppps']['ppp'] as $ppp) {
907
			$dev = substr($ppp['port'], 5);
908
			$realif  = $ppp['port'];
909
			$peerfile .= "{$dev}:\n";
910
			$peerfile .= " set device {$realif}\n";
911
			if($ppp['dialcmd'])
912
				$peerfile .= " set dial {$ppp['dialcmd']}\n";
913
			$peerfile .= " set speed \"{$ppp['linespeed']}\"\n";
914
			$peerfile .= " add default HISADDR\n";
915
			$peerfile .= " set timeout 0\n";
916
			$endingip = $startingip+1;
917
			if($ppp['localip'])
918
				$startingip = $ppp['localip'];
919
			if($ppp['gateway'])
920
				$endingip = $ppp['gateway'];
921
			$peerfile .= " enable dns\n";
922
			$peerfile .= " set ifaddr 10.0.0.{$startingip}/0 10.0.0.{$endingip}/0 255.255.255.0 0.0.0.0\n";
923
			$peerfile .= " set phone \"{$ppp['phone']}\"\n";
924
			$peerfile .= " set authname \"{$ppp['username']}\"\n";
925
			$peerfile .= " set authkey \"{$ppp['password']}\"\n";
926
			$peerfile .= "\n";
927
			$i++;
928
			$startingip++;
929
			$rclinkup.= "{$dev}:\n";
930
			$rclinkup.= "	! sh -c \"/sbin/ppp-script HISADDR INTERFACE DNS0 DNS1 \"\n";
931
			$rclinkup.= "	! sh -c \"/etc/rc.linkup INTERFACE start\"\n";
932
		}
933
    }
934

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

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

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

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

    
950
function interfaces_carp_setup() {
951
	global $g, $config;
952

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

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

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

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

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

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

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

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

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

    
1028
	$cmdchain->execute();
1029
	$cmdchain->clear();
1030

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

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

    
1044
        /* kill any running choparp */
1045
        killbyname("choparp");
1046

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

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

    
1058
                                if (!is_array($paa[$if]))
1059
                                        $paa[$proxyif] = array();
1060

    
1061
                                $paa[$proxyif][] = $vipent;
1062
                        }
1063
                }
1064

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

    
1071
                        $args = get_real_interface($paif) . " auto";
1072

    
1073
                        foreach ($paents as $paent) {
1074

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

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

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

    
1121
function interface_ipalias_configure(&$vip) {
1122

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

    
1129
function interface_reload_carps($cif) {
1130
	global $config;
1131

    
1132
	$carpifs = link_ip_to_carp_interface(find_interface_ip($cif));
1133
        if (empty($carpifs))
1134
		return;
1135

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

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

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

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

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

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

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

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

    
1216
	/* invalidate interface cache */
1217
	get_interface_arr(true);
1218

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

    
1227
	/* invalidate interface cache */
1228
	get_interface_arr(true);
1229

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

    
1233
	interfaces_bring_up($vipif);
1234
	
1235
	return $vipif;
1236
}
1237

    
1238
function interface_carpdev_configure(&$vip) {
1239
	global $g;
1240

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

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

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

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

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

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

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

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

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

    
1298
EOD;
1299

    
1300
		fwrite($fd, $dhclientconf);
1301
		fclose($fd);
1302

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

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

    
1314
	return $vipif;
1315
}
1316

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

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

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

    
1353
	// Make read / writable (nano)
1354
	conf_mount_rw();
1355

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1465
	/* generate wpa_supplicant/hostap config if wpa is enabled */
1466

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

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

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

    
1491
				fwrite($fd_set, kill_wpasupplicant($if));
1492
			}
1493
		break;
1494

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

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

    
1530
				fwrite($fd_set, kill_hostapd($if));
1531
			}
1532
		break;
1533

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

    
1540
	/*
1541
	 *    all variables are set, lets start up everything
1542
     */
1543

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

    
1550
	$standard_no_turbo = str_replace(" Turbo", "", $standard);
1551

    
1552
	$settings = <<<EOD
1553

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

    
1570
EOD;
1571

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

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

    
1582
	fclose($fd_set);
1583

    
1584
	conf_mount_ro();
1585

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

    
1592
	return 0;
1593

    
1594
}
1595

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

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

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

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

    
1614
	$wancfg = $config['interfaces'][$interface];
1615

    
1616
	$realif = get_real_interface($interface);
1617

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

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

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

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

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

    
1662
	switch ($wancfg['ipaddr']) {
1663

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

    
1671
		case 'pppoe':
1672
			interface_pppoe_configure($interface);
1673
			break;
1674

    
1675
		case 'pptp':
1676
			interface_pptp_configure($interface);
1677
			break;
1678

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

    
1693
			if (is_ipaddr($wancfg['gateway']))
1694
				file_put_contents("/tmp/{$realif}_router", $wancfg['gateway']);
1695
	}
1696

    
1697
	if(get_real_interface($wancfg['if']) && does_interface_exist($wancfg['if']))
1698
		interfaces_bring_up($wancfg['if']);
1699
	
1700
	interface_reload_carps($realif);
1701

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

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

    
1723
		if ($reloadall == true) {
1724

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

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

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

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

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

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

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

    
1748
	unmute_kernel_msgs();
1749

    
1750
	return 0;
1751
}
1752

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

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

    
1764
	return 0;
1765
}
1766

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

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

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

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

    
1786
	$wanif = get_real_interface($interface);
1787

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

    
1800
EOD;
1801

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

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

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

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

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

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

    
1831
	return 0;
1832
}
1833

    
1834
function interface_pppoe_configure($interface = "wan") {
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($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, "vip")) {
2181
                $index = substr($interface, 3);
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
        } else if (stristr($interface, "carp")) {
2191
                $index = substr($interface, 4);
2192
                $counter = 0;
2193
                foreach ($config['virtualip']['vip'] as $vip) {
2194
                        if ($vip['mode'] == "carpdev-dhcp" || $vip['mode'] == "carp")  {
2195
                                if (intval($index) == $counter)
2196
                                        return $vip['interface'];
2197
                                $counter++;
2198
                        }
2199
                }
2200
        }
2201

    
2202
        /* if list */
2203
        $ifdescrs = get_configured_interface_list(false, true);
2204

    
2205
        foreach ($ifdescrs as $if => $ifname) {
2206
                if($config['interfaces'][$if]['if'] == $interface)
2207
                        return $ifname;
2208

    
2209
                /* XXX: ermal - The 3 lines below are totally bogus code. */
2210
                $int = interface_translate_type_to_real($if);
2211
                if($ifname == $interface)
2212
                        return $ifname;
2213

    
2214
                if($int == $interface)
2215
                        return $ifname;
2216
        }
2217
        return NULL;
2218
}
2219

    
2220
/* attempt to resolve interface to friendly descr */
2221
function convert_friendly_interface_to_friendly_descr($interface) {
2222
        global $config;
2223

    
2224
        switch ($interface) {
2225
                case "l2tp":
2226
                                $ifdesc = "L2TP";
2227
                                break;
2228
                case "pptp":
2229
                                $ifdesc = "pptp";
2230
                                break;
2231
                case "pppoe":
2232
                                $ifdesc = "pppoe";
2233
                                break;
2234
                case "openvpn":
2235
                                $ifdesc = "OpenVPN";
2236
                                break;
2237
                case "enc0":
2238
                        case "ipsec":
2239
                                $ifdesc = "IPsec";
2240
                                break;
2241
        default:
2242
                /* if list */
2243
                $ifdescrs = get_configured_interface_with_descr(false, true);
2244
                foreach ($ifdescrs as $if => $ifname) {
2245
                                if ($if == $interface || $ifname == $interface)
2246
                                        return $ifname;
2247
                }
2248
                break;
2249
        }
2250

    
2251
        return $ifdesc;
2252
}
2253

    
2254
function convert_real_interface_to_friendly_descr($interface) {
2255
        global $config;
2256

    
2257
        $ifdesc = convert_real_interface_to_friendly_interface_name("{$interface}");
2258

    
2259
        if ($ifdesc) {
2260
                $iflist = get_configured_interface_with_descr();
2261
                return $iflist[$ifdesc];
2262
        }
2263

    
2264
        return $interface;
2265
}
2266

    
2267
/*
2268
 *  interface_translate_type_to_real($interface):
2269
 *              returns the real hardware interface name for a friendly interface.  ie: wan
2270
 */
2271
function interface_translate_type_to_real($interface) {
2272
        global $config;
2273

    
2274
        if ($config['interfaces'][$interface]['if'] <> "")
2275
                return $config['interfaces'][$interface]['if'];
2276
        else
2277
		return $interface;
2278
}
2279

    
2280
function get_real_interface($interface = "wan") {
2281
    global $config;
2282

    
2283
	$wanif = NULL;
2284

    
2285
	switch ($interface) {
2286
	case "l2tp":
2287
		$wanif = "l2tp";
2288
		break;
2289
	case "pptp":
2290
		$wanif = "pptp";
2291
		break;
2292
	case "pppoe":
2293
		$wanif = "pppoe";
2294
		break;
2295
	case "openvpn":
2296
		$wanif = "openvpn";
2297
		break;
2298
	case "enc0":
2299
		$wanif = "enc0";
2300
		break;
2301
	case "ppp":
2302
		$wanif = "ppp";
2303
		break;
2304
	default:
2305
		$iflist = get_configured_interface_with_descr(false, true);
2306

    
2307
		foreach ($iflist as $if => $ifdesc) {
2308
			// If a real interface was alread passed simply
2309
			// pass the real interface back.  This encourages
2310
			// the usage of this function in more cases so that
2311
			// we can combine logic for more flexibility.
2312
			if($config['interfaces'][$if]['if'] == $interface) {
2313
				if(does_interface_exist($interface)) {
2314
					$wanif = $interface;
2315
					break;
2316
				}
2317
			}
2318

    
2319
			if ($interface == $if || $interface == $ifdesc) {
2320

    
2321
			// PPP Support
2322
			if($config['interfaces'][$if]['serialport']) {
2323
				$dev = $config['interfaces'][$if]['serialport'];
2324
				$ps = trim(`ps awux | grep -v grep | grep "$dev" | awk '{ print \$2 }'`);
2325
				if($ps) {
2326
					$int = trim(`/sbin/ifconfig | grep -v grep | grep -B2 "$ps" | head -n1 | cut -d: -f1`);
2327
					if($int) {
2328
						$wanif = $int;
2329
						break;
2330
					}
2331
				}
2332
			}
2333

    
2334
			$cfg = $config['interfaces'][$if];
2335

    
2336
			// Wireless cloned NIC support (FreeBSD 8+)
2337
			// interface name format: $parentnic_wlanparentnic#
2338
			// example: ath0_wlan0
2339
			if(is_interface_wireless($interface)) {
2340
				$interface_num = substr($cfg['if'], 3);
2341
				$wanif = $cfg['if'] . "_wlan" . $interface_num;
2342
				break;
2343
			}
2344

    
2345
			if (empty($cfg['ipaddr'])) {
2346
				$wanif = $cfg['if'];
2347
				break;
2348
			}
2349

    
2350
			switch ($cfg['ipaddr']) {
2351
				case "carpdev-dhcp":
2352
					$viparr = &$config['virtualip']['vip'];
2353
					$counter = 0;
2354
					if(is_array($viparr))
2355
					foreach ($viparr as $vip) {
2356
						if ($vip['mode'] == "carpdev-dhcp") {
2357
							if($vip['interface'] == $if) {
2358
								$wanif =  "carp{$counter}";
2359
								break;
2360
							}
2361
							$counter++;
2362
						} else if ($vip['mode'] = "carp") 
2363
							$counter++;
2364
					}
2365
					break;
2366
				case "pppoe": 
2367
					if ($if == "wan")
2368
						$wanif = "pppoe0";
2369
					else
2370
						$wanif = "pppoe" . substr($if,3);
2371
					break;
2372
				case "pptp": 
2373
					if ($if == "wan")
2374
						$wanif = "pptp0";
2375
					else
2376
						$wanif = "pptp" . substr($if, 3);
2377
					break;
2378
				default:
2379
					$wanif = $cfg['if'];
2380
					break;
2381
				}
2382
			
2383
				break;
2384
			}
2385
		}
2386
		break;
2387
	}
2388

    
2389
    return $wanif;
2390
}
2391

    
2392
function guess_interface_from_ip($ipaddress) {
2393
        $ret = `/usr/bin/netstat -rn | /usr/bin/awk '/^{$ipaddress}/ {printf "%s", \$6}'`;
2394
        if (empty($ret))
2395
                return false;
2396

    
2397
        return $ret;
2398
}
2399

    
2400
/*
2401
 * find_ip_interface($ip): return the interface where an ip is defined
2402
 */
2403
function find_ip_interface($ip)
2404
{
2405
        /* if list */
2406
        $ifdescrs = get_configured_interface_list();
2407

    
2408
        foreach ($ifdescrs as $ifdescr => $ifname) {
2409
		if ($ip == get_interface_ip($ifname)) {
2410
                	$int = get_real_interface($ifname);
2411
			return $int;
2412
		}
2413
        }
2414
        return false;
2415
}
2416

    
2417
/*
2418
 *   find_number_of_created_carp_interfaces: return the number of carp interfaces
2419
 */
2420
function find_number_of_created_carp_interfaces() {
2421
	return `/sbin/ifconfig | grep "carp:" | wc -l`;
2422
}
2423

    
2424
function get_all_carp_interfaces() {
2425
	$ints = str_replace("\n", " ", `ifconfig | grep "carp:" -B2 | grep ": flag" | cut -d: -f1`);
2426
	return $ints;
2427
}
2428

    
2429
/*
2430
 * find_carp_interface($ip): return the carp interface where an ip is defined
2431
 */
2432
function find_carp_interface($ip) {
2433
	global $config;
2434
	if (is_array($config['virtualip']['vip'])) {
2435
		foreach ($config['virtualip']['vip'] as $vip) {
2436
			if ($vip['mode'] == "carp" || $vip['mode'] == "carpdev") {
2437
				$carp_ip = get_interface_ip($vip['interface']);
2438
				$if = `ifconfig | grep '$ip' -B1 | head -n1 | cut -d: -f1`;
2439
				if ($if)
2440
					return $if;
2441
			}
2442
		}
2443
	}
2444
}
2445

    
2446
function link_carp_interface_to_parent($interface) {
2447
        global $config;
2448

    
2449
        if ($interface == "")
2450
                return;
2451

    
2452
        $carp_ip = get_interface_ip($interface);
2453
        if (!is_ipaddr($carp_ip))
2454
                return;
2455

    
2456
        /* if list */
2457
        $ifdescrs = get_configured_interface_list();
2458
        foreach ($ifdescrs as $ifdescr => $ifname) {
2459
                $interfaceip = get_interface_ip($ifname);
2460
                $subnet_bits = get_interface_subnet($ifname);
2461
                $subnet_ip = gen_subnet("{$interfaceip}", "{$subnet_bits}");
2462
                if(ip_in_subnet($carp_ip, "{$subnet_ip}/{$subnet_bits}"))
2463
                        return $ifname;
2464
        }
2465

    
2466
        return "";
2467
}
2468

    
2469
/****f* interfaces/link_ip_to_carp_interface
2470
 * NAME
2471
 *   link_ip_to_carp_interface - Find where a CARP interface links to.
2472
 * INPUTS
2473
 *   $ip
2474
 * RESULT
2475
 *   $carp_ints
2476
 ******/
2477
function link_ip_to_carp_interface($ip) {
2478
        global $config;
2479

    
2480
        if (!is_ipaddr($ip))
2481
                return;
2482

    
2483
        $carp_ints = "";
2484
        if (is_array($config['virtualip']['vip'])) {
2485
                foreach ($config['virtualip']['vip'] as $vip) {
2486
                        if ($vip['mode'] == "carp" || $vip['mode'] == "carpdev") {
2487
                                $carp_ip = $vip['subnet'];
2488
                                $carp_sn = $vip['subnet_bits'];
2489
                                $carp_nw = gen_subnet($carp_ip, $carp_sn);
2490
                                if (ip_in_subnet($ip, "{$carp_nw}/{$carp_sn}")) {
2491
                                        if (!stristr($carp_ints, $carp_int))
2492
                                                $carp_ints .= " {$carp_int}";
2493
                                }
2494
                        }
2495
                }
2496
        }
2497

    
2498
        return $carp_ints;
2499
}
2500

    
2501
/****f* interfaces/link_interface_to_bridge
2502
 * NAME
2503
 *   link_interface_to_bridge - Finds out a bridge group for an interface
2504
 * INPUTS
2505
 *   $ip
2506
 * RESULT
2507
 *   bridge[0-99]
2508
 ******/
2509
function link_interface_to_bridge($int) {
2510
        global $config;
2511

    
2512
        if (is_array($config['bridges']['bridged']))
2513
                foreach ($config['bridges']['bridged'] as $bridge)
2514
                        if(stristr($bridge['members'], "{$int}"))
2515
                                return "{$bridge['bridgeif']}";
2516
}
2517

    
2518
function link_interface_to_gre($interface) {
2519
        global $config;
2520

    
2521
        if (is_array($config['gres']['gre']))
2522
                foreach ($config['gres']['gre'] as $gre)
2523
                        if($gre['if'] == $interface)
2524
                                return "{$gre['greif']}";
2525
}
2526

    
2527
function link_interface_to_gif($interface) {
2528
        global $config;
2529

    
2530
        if (is_array($config['gifs']['gif']))
2531
                foreach ($config['gifs']['gif'] as $gif)
2532
                        if($gif['if'] == $interface)
2533
                                return "{$gif['gifif']}";
2534
}
2535

    
2536
/*
2537
 * find_interface_ip($interface): return the interface ip (first found)
2538
 */
2539
function find_interface_ip($interface, $flush = false)
2540
{
2541
	global $interface_ip_arr_cache;
2542

    
2543
	$interface = str_replace("\n", "", $interface);
2544
	
2545
	if (does_interface_exist($interface) == false)
2546
		return;
2547

    
2548
	/* Setup IP cache */
2549
	if (!isset($interface_ip_arr_cache[$interface]) or $flush) {
2550
		$interface_ip_arr_cache[$interface] = `/sbin/ifconfig {$interface} | /usr/bin/grep -w "inet" | /usr/bin/cut -d" " -f 2| /usr/bin/head -1`;
2551
		$interface_ip_arr_cache[$interface] = str_replace("\n", "", $interface_ip_arr_cache[$interface]);
2552
	}
2553

    
2554
	return $interface_ip_arr_cache[$interface];
2555
}
2556

    
2557
function find_interface_subnet($interface, $flush = false)
2558
{
2559
	global $interface_sn_arr_cache;
2560

    
2561
	$interface = str_replace("\n", "", $interface);
2562
	if (does_interface_exist($interface) == false)
2563
		return;
2564

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

    
2570
	return $interface_sn_arr_cache[$interface];
2571
}
2572

    
2573
function get_interface_ip($interface = "wan")
2574
{
2575
	$realif = get_real_interface($interface);
2576
	if (!$realif) {
2577
		if (preg_match("/^carp/i", $interface))
2578
			$realif = $interface;
2579
		else if (preg_match("/^vip/i", $interface))
2580
			$realif = $interface;
2581
		else
2582
			return null;
2583
	}
2584

    
2585
	/* Do we really come here for these interfaces ?! */
2586
	if (in_array($realif, array("pptp", "pppoe", "l2tp", "openvpn", "enc0" /* , "ppp" */)))
2587
			return "";
2588

    
2589
	$curip = find_interface_ip($realif);
2590
	if ($curip && is_ipaddr($curip) && ($curip != "0.0.0.0"))
2591
		return $curip;
2592

    
2593
	return null;
2594
}
2595

    
2596
function get_interface_subnet($interface = "wan")
2597
{
2598
	$realif = get_real_interface($interface);
2599
	if (!$realif) {
2600
                if (preg_match("/^carp/i", $interface))
2601
                        $realif = $interface;
2602
                else if (preg_match("/^vip/i", $interface))
2603
                        $realif = $interface;
2604
                else
2605
                        return null;
2606
        }
2607

    
2608
	/* Do we really come here for these interfaces ?! */
2609
	if (in_array($realif, array("pptp", "pppoe", "l2tp", "openvpn", "enc0" /* , "ppp" */)))
2610
		return "";
2611

    
2612
	$cursn = find_interface_subnet($realif);
2613
	if (!empty($cursn))
2614
		return $cursn;
2615

    
2616
	return null;
2617
}
2618

    
2619
/* return outside interfaces with a gateway */
2620
function get_interfaces_with_gateway() {
2621
	global $config;
2622

    
2623
	$ints = array();
2624

    
2625
	/* loop interfaces, check config for outbound */
2626
	foreach($config['interfaces'] as $ifdescr => $ifname) {
2627
		if($ifname['serialport']) {
2628
			$ints[] = $ifdescr;
2629
			continue;
2630
		}
2631
		switch ($ifname['ipaddr']) {
2632
			case "dhcp":
2633
			case "carpdev-dhcp":
2634
			case "pppoe":
2635
			case "pptp":
2636
			$ints[] = $ifdescr;
2637
			break;
2638
			default:
2639
			if ($ifname['pointtopoint'])
2640
				$ints[] = $ifdescr;
2641
			else if (!empty($ifname['gateway']))
2642
				$ints[] = $ifdescr;
2643
			break;
2644
		}
2645
	}
2646
	return $ints;
2647
}
2648

    
2649
/* return true if interface has a gateway */
2650
function interface_has_gateway($friendly) {
2651

    
2652
        $friendly = strtolower($friendly);
2653
        if (in_array($friendly, get_interfaces_with_gateway()))
2654
                return true;
2655

    
2656
	return false;
2657
}
2658

    
2659
/****f* interfaces/is_altq_capable
2660
 * NAME
2661
 *   is_altq_capable - Test if interface is capable of using ALTQ
2662
 * INPUTS
2663
 *   $int            - string containing interface name
2664
 * RESULT
2665
 *   boolean         - true or false
2666
 ******/
2667

    
2668
function is_altq_capable($int) {
2669
        /* Per:
2670
         * http://www.freebsd.org/cgi/man.cgi?query=altq&manpath=FreeBSD+7.2-current&format=html
2671
         * Only the following drivers have ALTQ support
2672
         */
2673
	$capable = array("age", "ale", "an", "ath", "aue", "awi", "bce",
2674
			"bfe", "bge", "dc", "de", "ed", "em", "ep", "fxp", "gem",
2675
			"hme", "ipw", "iwi", "jme", "le", "msk", "mxge", "my", "nfe",
2676
			"npe", "nve", "ral", "re", "rl", "rum", "sf", "sis", "sk",
2677
			"ste", "stge", "txp", "udav", "ural", "vge", "vr", "wi", "xl",
2678
			"ndis", "tun", "vlan", "pppoe", "pptp", "ng", "ppp");
2679

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

    
2682
        if (in_array($int_family[0], $capable))
2683
                return true;
2684
	else if (stristr($int_family, "vlan")) /* VLANs are name $parent.$vlan now */
2685
		return true;
2686
        else
2687
                return false;
2688
}
2689

    
2690
/****f* interfaces/is_interface_wireless
2691
 * NAME
2692
 *   is_interface_wireless - Returns if an interface is wireless
2693
 * RESULT
2694
 *   $tmp       - Returns if an interface is wireless
2695
 ******/
2696
function is_interface_wireless($interface) {
2697
        global $config, $g;
2698

    
2699
        $friendly = convert_real_interface_to_friendly_interface_name($interface);
2700
        if(!isset($config['interfaces'][$friendly]['wireless'])) {
2701
                if (preg_match($g['wireless_regex'], $interface)) {
2702
                        $config['interfaces'][$friendly]['wireless'] = array();
2703
                        return true;
2704
                }
2705
                unset($config['interfaces'][$friendly]['wireless']);
2706
                return false;
2707
        } else
2708
                return true;
2709
}
2710

    
2711
function get_wireless_modes($interface) {
2712
	/* return wireless modes and channels */
2713
	$wireless_modes = array();
2714

    
2715
	if(is_interface_wireless($interface)) {
2716
		$cloned_interface = get_real_interface($interface);
2717
		$wi = 1;
2718
		$ifconfig = "/sbin/ifconfig";
2719
		$awk = "/usr/bin/awk";
2720
		$chan_list = "$ifconfig $cloned_interface list chan";
2721
		$stack_list = "$awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
2722
		$format_list = "$awk '{print \$5 \" \" \$6 \",\" \$1}'";
2723

    
2724
		$interface_channels = "";
2725
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
2726
		$interface_channel_count = count($interface_channels);
2727

    
2728
		$c = 0;
2729
		while ($c < $interface_channel_count)
2730
		{
2731
			$channel_line = explode(",", $interface_channels["$c"]);
2732
			$wireless_mode = trim($channel_line[0]);
2733
			$wireless_channel = trim($channel_line[1]);
2734
			if(trim($wireless_mode) != "") {
2735
				/* if we only have 11g also set 11b channels */
2736
				if($wireless_mode == "11g") {
2737
					$wireless_modes["11b"] = array();
2738
				}
2739
				$wireless_modes["$wireless_mode"]["$c"] = $wireless_channel;
2740
			}
2741
			$c++;
2742
		}
2743
	}
2744
	return($wireless_modes);
2745
}
2746

    
2747
/****f* interfaces/get_interface_mtu
2748
 * NAME
2749
 *   get_interface_mtu - Return the mtu of an interface
2750
 * RESULT
2751
 *   $tmp       - Returns the mtu of an interface
2752
 ******/
2753
function get_interface_mtu($interface) {
2754
        $mtu = `/sbin/ifconfig {$interface} | /usr/bin/grep mtu | /usr/bin/cut -d" " -f6`;
2755
        return $mtu;
2756
}
2757

    
2758
function get_interface_mac($interface) {
2759
	$mac = array();
2760
        exec("/sbin/ifconfig {$interface} | /usr/bin/awk '/ether/ {print $2}'", $mac);
2761
        if(is_macaddr($mac)) {
2762
                return trim($mac);
2763
        } else {
2764
                return "";
2765
        }
2766
}
2767

    
2768
/****f* pfsense-utils/generate_random_mac_address
2769
 * NAME
2770
 *   generate_random_mac - generates a random mac address
2771
 * INPUTS
2772
 *   none
2773
 * RESULT
2774
 *   $mac - a random mac address
2775
 ******/
2776
function generate_random_mac_address() {
2777
        $mac = "02";
2778
        for($x=0; $x<5; $x++)
2779
                $mac .= ":" . dechex(rand(16, 255));
2780
        return $mac;
2781
}
2782

    
2783
/****f* interfaces/is_jumbo_capable
2784
 * NAME
2785
 *   is_jumbo_capable - Test if interface is jumbo frame capable.  Useful for determining VLAN capability.
2786
 * INPUTS
2787
 *   $int             - string containing interface name
2788
 * RESULT
2789
 *   boolean          - true or false
2790
 ******/
2791
function is_jumbo_capable($int) {
2792
        global $g;
2793

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

    
2796
        if (in_array($int_family[0], $g['vlan_long_frame']))
2797
                return true;
2798
        else
2799
                return false;
2800
}
2801

    
2802
function setup_pppoe_reset_file($interface, $status) {
2803
	define("CRON_PPPOE_CMD_FILE", "/conf/pppoe{$interface}restart");
2804
	define("CRON_PPPOE_CMD", "#!/bin/sh\necho '<?php require(\"config.inc\"); require(\"interfaces.inc\"); interface_reconfigure({$interface}); ?>' | /usr/local/bin/php -q");
2805
	if ($status == true) {
2806
		if (!file_exists(CRON_PPPOE_CMD_FILE)) {
2807
			file_put_contents(CRON_PPPOE_CMD_FILE, CRON_PPPOE_CMD);
2808
			chmod(CRON_PPPOE_CMD_FILE, 0700);
2809
		}	
2810
	} else
2811
		unlink_if_exists(CRON_PPPOE_CMD_FILE);
2812
}
2813

    
2814
?>
(19-19/48)