Project

General

Profile

Download (82.9 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
require_once("cmd_chain.inc");
47

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

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

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

    
67
        return $interface_arr_cache;
68
}
69

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

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

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

    
87
function interfaces_loopback_configure() {
88
	if($g['booting'])
89
		echo "Configuring loopback interface...";
90
	mwexec("/sbin/ifconfig lo0 127.0.0.1");
91
	interfaces_bring_up("lo0");
92
	exec("/sbin/route add 127.0.0.2 127.0.0.1");
93
	if($g['booting'])
94
		echo "done.\n";
95
	return 0;
96
}
97

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

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

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

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

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

    
137
	if (!empty($vlanif) && does_interface_exist($vlanif)) {
138
		interface_bring_down($vlanif);
139
	} else {
140
		$tmpvlanif = exec("/sbin/ifconfig vlan create");
141
		mwexec("/sbin/ifconfig {$tmpvlanif} name {$vlanif}");
142
		mwexec("/usr/sbin/ngctl name {$tmpvlanif}: {$vlanif}");
143
	}
144
	
145
	mwexec("/sbin/ifconfig {$vlanif} vlan " .
146
		escapeshellarg($tag) . " vlandev " .
147
		escapeshellarg($if));
148

    
149
	interfaces_bring_up($vlanif);
150

    
151
    /* invalidate interface cache */
152
    get_interface_arr(true);
153

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

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

    
167
	return $vlanif;
168
}
169

    
170
function interface_qinq_configure(&$vlan, $fd = NULL) {
171
        global $config, $g;
172

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

    
178
        $qinqif = $vlan['if'];
179
        $tag = $vlan['tag'];
180
        if(empty($qinqif)) {
181
                log_error("interface_qinq_confgure called with if undefined.\n");
182
                return;
183
        }
184
	$vlanif = interface_vlan_configure($vlan);
185

    
186
        if ($fd == NULL) {
187
                $exec = true;
188
                $fd = fopen("{$g['tmp_path']}/netgraphcmd", "w");
189
        } else
190
                $exec = false;
191
        /* make sure the parent is converted to ng_vlan(4) and is up */
192
        interfaces_bring_up($qinqif);
193

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

    
208
        /* invalidate interface cache */
209
        get_interface_arr(true);
210

    
211
        if (!stristr($qinqif, "vlan"))
212
                mwexec("/sbin/ifconfig {$qinqif} promisc\n");
213

    
214
        $macaddr = get_interface_mac($qinqif);
215
        if (!empty($vlan['members'])) {
216
                $members = explode(" ", $vlan['members']);
217
                foreach ($members as $qtag) {
218
                        $qinq = array();
219
                        $qinq['tag'] = $qtag;
220
                        $qinq['if'] = $vlanif;
221
                        interface_qinq2_configure($qinq, $fd, $macaddr);
222
                }
223
        }
224
        if ($exec == true) {
225
                fclose($fd);
226
                mwexec("/usr/sbin/ngctl -f {$g['tmp_path']}/netgraphcmd");
227
        }
228

    
229
        interfaces_bring_up($qinqif);
230
        if (!empty($vlan['members'])) {
231
                $members = explode(" ", $vlan['members']);
232
                foreach ($members as $qif)
233
                        interfaces_bring_up("{$vlanif}_{$qif}");
234
        }
235

    
236
        return $vlanif;
237
}
238

    
239
function interfaces_qinq_configure() {
240
	global $config, $g;
241
	if($g['booting'])
242
		echo "Configuring QinQ interfaces...";
243
	if (is_array($config['qinqs']['qinqentry']) && count($config['qinqs']['qinqentry'])) {
244
		foreach ($config['qinqs']['qinqentry'] as $qinq) {
245
			/* XXX: Maybe we should report any errors?! */
246
			interface_qinq_configure($qinq);
247
		}
248
	}
249
	if($g['booting'])
250
		echo "done.\n";
251
}
252

    
253
function interface_qinq2_configure(&$qinq, $fd, $macaddr) {
254
        global $config, $g;
255

    
256
        if (!is_array($qinq)) {
257
                log_error("QinQ compat VLAN: called with wrong options. Problems with config!\n");
258
                return;
259
        }
260

    
261
        $if = $qinq['if'];
262
        $tag = $qinq['tag'];
263
        $vlanif = "{$if}_{$tag}";
264
        if(empty($if)) {
265
                log_error("interface_qinq_confgure called with if undefined.\n");
266
                return;
267
        }
268

    
269
        fwrite($fd, "shutdown {$if}h{$tag}:\n");
270
        fwrite($fd, "mkpeer {$if}qinq: eiface {$if}{$tag} ether\n");
271
        fwrite($fd, "name {$if}qinq:{$if}{$tag} {$if}h{$tag}\n");
272
        fwrite($fd, "msg {$if}qinq: addfilter { vlan={$tag} hook=\"{$if}{$tag}\" }\n");
273
        fwrite($fd, "msg {$if}h{$tag}: setifname \"{$vlanif}\"\n");
274
        fwrite($fd, "msg {$if}h{$tag}: set {$macaddr}\n");
275

    
276
        /* invalidate interface cache */
277
        get_interface_arr(true);
278

    
279
        return $vlanif;
280
}
281

    
282
function interfaces_bridge_configure() {
283
        global $config;
284

    
285
        $i = 0;
286
        if (is_array($config['bridges']['bridged']) && count($config['bridges']['bridged'])) {
287
                foreach ($config['bridges']['bridged'] as $bridge) {
288
                        if(empty($bridge['bridgeif']))
289
                                $bridge['bridgeif'] = "bridge{$i}";
290
                        /* XXX: Maybe we should report any errors?! */
291
                        interface_bridge_configure($bridge);
292
                        $i++;
293
                }
294
        }
295
}
296

    
297
function interface_bridge_configure(&$bridge) {
298
	global $config, $g;
299

    
300
	if (!is_array($bridge))
301
	        return -1;
302

    
303
	if (empty($bridge['members'])) {
304
		log_error("No members found on {$bridge['bridgeif']}");
305
		return -1;
306
	}
307

    
308
	$members = explode(',', $bridge['members']);
309
	if (!count($members))
310
		return -1;
311
	
312
	$checklist = get_configured_interface_list();
313

    
314
	if ($g['booting'] || !empty($bridge['bridgeif'])) {
315
		mwexec("/sbin/ifconfig {$bridge['bridgeif']} destroy");
316
		mwexec("/sbin/ifconfig {$bridge['bridgeif']} create");
317
		$bridgeif = $bridge['bridgeif'];
318
	} else {
319
		$bridgeif = exec("/sbin/ifconfig bridge create");
320
	}
321

    
322
	/* Calculate smaller mtu and enforce it */
323
	$smallermtu = 0;
324
	foreach ($members as $member) {
325
		$realif = get_real_interface($member);
326
		$mtu = get_interface_mtu($realif);
327
		if ($smallermtu == 0 && !empty($mtu))
328
			$smallermtu = $mtu;
329
		else if (!empty($mtu) && $mtu < $smallermtu)
330
			$smallermtu = $mtu;
331
	}
332
	 
333
	/* Just in case anything is not working well */
334
	if ($smallermtu == 0)
335
		$smallermtu = 1500; 
336

    
337
	/* Add interfaces to bridge */
338
	foreach ($members as $member) {
339
		if (!array_key_exists($member, $checklist))
340
			continue;
341
		$realif = get_real_interface($member);
342
		$realif =  escapeshellarg($realif);
343
		/* make sure the parent interface is up */
344
		mwexec("/sbin/ifconfig {$realif} mtu {$smallermtu}");
345
		if(!$realif) 
346
			log_error("realif not defined in interfaces bridge - up");
347
		interfaces_bring_up($realif);
348
		mwexec("/sbin/ifconfig {$bridgeif} addm {$realif}");	
349
	}
350

    
351
	if (isset($bridge['enablestp'])) {
352
		/* Choose spanning tree proto */
353
		mwexec("/sbin/ifconfig {$bridgeif} proto {$bridge['proto']}");	
354
		
355
		if (!empty($bridge['stp'])) {
356
			$stpifs = explode(',', $bridge['stp']);
357
			foreach ($stpifs as $stpif) {
358
				$realif = get_real_interface($stpif);
359
				mwexec("/sbin/ifconfig {$bridgeif} stp {$realif}");
360
			}
361
		}
362
		if (!empty($bridge['maxage']))
363
			mwexec("/sbin/ifconfig {$bridgeif} maxage {$bridge['maxage']}");
364
		if (!empty($brige['fwdelay']))
365
			mwexec("/sbin/ifconfig {$bridgeif} fwddelay {$bridge['fwdelay']}");
366
		if (!empty($brige['hellotime']))
367
                        mwexec("/sbin/ifconfig {$bridgeif} hellotime {$bridge['hellotime']}");
368
		if (!empty($brige['priority']))
369
                        mwexec("/sbin/ifconfig {$bridgeif} priority {$bridge['priority']}");
370
		if (!empty($brige['holdcount']))
371
                        mwexec("/sbin/ifconfig {$bridgeif} holdcnt {$bridge['holdcnt']}");
372
		if (!empty($bridge['ifpriority'])) {
373
			$pconfig = explode(",", $bridge['ifpriority']);
374
			$ifpriority = array();
375
			foreach ($pconfig as $cfg) {
376
				$embcfg = explode(":", $cfg);
377
				foreach ($embcfg as $key => $value)
378
					$ifpriority[$key] = $value;
379
			}
380
			foreach ($ifpriority as $key => $value) {
381
				$realif = get_real_interface($key);
382
				mwexec("/sbin/ifconfig ${bridgeif} ifpriority {$realif} {$value}"); 
383
			}
384
		}
385
		if (!empty($bridge['ifpathcost'])) {
386
			$pconfig = explode(",", $bridges['ifpathcost']);
387
			$ifpathcost = array();
388
			foreach ($pconfig as $cfg) {
389
				$embcfg = explode(":", $cfg);
390
				foreach ($embcfg as $key => $value)
391
					$ifpathcost[$key] = $value;
392
			}
393
			foreach ($ifpathcost as $key => $value) {
394
                        	$realif = get_real_interface($key);
395
                        	mwexec("/sbin/ifconfig ${bridgeif} ifpathcost {$realif} {$value}");
396
                	}
397
		}
398
	}
399

    
400
	if ($bridge['maxaddr'] <> "")
401
		mwexec("/sbin/ifconfig {$bridgeif} maxaddr {$bridge['maxaddr']}");
402
        if ($bridge['timeout'] <> "")
403
                mwexec("/sbin/ifconfig {$bridgeif} timeout {$bridge['timeout']}");
404
        if ($bridge['span'] <> "") {
405
		$realif = get_real_interface($bridge['span']);
406
                mwexec("/sbin/ifconfig {$bridgeif} span {$realif}");
407
	}
408
	if (!empty($bridge['edge'])) {
409
        	$edgeifs = explode(',', $bridge['edge']);
410
        	foreach ($edgeifs as $edgeif) {
411
			$realif = get_real_interface($edgeif);
412
                	mwexec("/sbin/ifconfig {$bridgeif} edge {$realif}");
413
        	}
414
	}
415
	if (!empty($bridge['autoedge'])) {
416
        	$edgeifs = explode(',', $bridge['autoedge']);
417
        	foreach ($edgeifs as $edgeif) {
418
                	$realif = get_real_interface($edgeif);
419
                	mwexec("/sbin/ifconfig {$bridgeif} -autoedge {$realif}");
420
        	}
421
	}
422
	if (!empty($bridge['ptp'])) {
423
        	$ptpifs = explode(',', $bridge['ptp']);
424
        	foreach ($ptpifs as $ptpif) {
425
                	$realif = get_real_interface($ptpif);
426
                	mwexec("/sbin/ifconfig {$bridgeif} ptp {$realif}");
427
        	}
428
	}
429
	if (!empty($bridge['autoptp'])) {
430
        	$ptpifs = explode(',', $bridge['autoptp']);
431
        	foreach ($ptpifs as $ptpif) {
432
                	$realif = get_real_interface($ptpif);
433
                	mwexec("/sbin/ifconfig {$bridgeif} -autoptp {$realif}");
434
        	}
435
	}
436
	if (!empty($bridge['static'])) {
437
        	$stickyifs = explode(',', $bridge['static']);
438
        	foreach ($stickyifs as $stickyif) {
439
                	$realif = get_real_interface($stickyif);
440
                	mwexec("/sbin/ifconfig {$bridgeif} sticky {$realif}");
441
        	}
442
	}
443
	if (!empty($bridge['private'])) {
444
        	$privateifs = explode(',', $bridge['private']);
445
        	foreach ($privateifs as $privateif) {
446
                	$realif = get_real_interface($privateif);
447
               	 	mwexec("/sbin/ifconfig {$bridgeif} private {$realif}");
448
        	}
449
	}
450

    
451
	if($bridgeif)
452
		interfaces_bring_up($bridgeif);	
453
	else 
454
		log_error("bridgeif not defined -- could not bring interface up");
455

    
456
	return $bridgeif;
457
}
458

    
459
function interfaces_lagg_configure() 
460
{
461
        global $config, $g;
462
		if($g['booting']) 
463
			echo "Configuring LAGG interfaces...";
464
        $i = 0;
465
		if (is_array($config['laggs']['lagg']) && count($config['laggs']['lagg'])) {
466
			foreach ($config['laggs']['lagg'] as $lagg) {
467
				if(empty($lagg['laggif']))
468
					$lagg['laggif'] = "lagg{$i}";
469
				/* XXX: Maybe we should report any errors?! */
470
				interface_lagg_configure($lagg);
471
				$i++;
472
			}
473
		}
474
		if($g['booting']) 
475
			echo "done.\n";
476
}
477

    
478
function interface_lagg_configure(&$lagg) {
479
        global $config, $g;
480

    
481
        if (!is_array($lagg))
482
		return -1;
483

    
484
	$members = explode(',', $lagg['members']);
485
	if (!count($members))
486
		return -1;
487
	
488
	$checklist = get_interface_list();
489

    
490
	if ($g['booting'] || !(empty($lagg['laggif']))) {
491
                mwexec("/sbin/ifconfig {$lagg['laggif']} destroy");
492
                mwexec("/sbin/ifconfig {$lagg['laggif']} create");
493
                $laggif = $lagg['laggif'];
494
        } else
495
                $laggif = exec("/sbin/ifconfig lagg create");
496

    
497
	/* Calculate smaller mtu and enforce it */
498
        $smallermtu = 0;
499
        foreach ($members as $member) {
500
                $mtu = get_interface_mtu($member);
501
		if ($smallermtu == 0 && !empty($mtu))
502
			$smallermtu = $mtu;
503
                else if (!empty($mtu) && $mtu < $smallermtu)
504
                        $smallermtu = $mtu;
505
        }
506

    
507
	/* Just in case anything is not working well */
508
        if ($smallermtu == 0)
509
                $smallermtu = 1500;
510

    
511
	foreach ($members as $member) {
512
		if (!array_key_exists($member, $checklist))
513
			continue;
514
		/* make sure the parent interface is up */
515
		mwexec("/sbin/ifconfig {$member} mtu {$smallermtu}");
516
		interfaces_bring_up($member);
517
		mwexec("/sbin/ifconfig {$laggif} laggport {$member}");
518
	}
519
	
520
	mwexec("/sbin/ifconfig {$laggif} laggproto {$lagg['proto']}");
521

    
522
	interfaces_bring_up($laggif);
523

    
524
	return $laggif;
525
}
526

    
527
function interfaces_gre_configure() {
528
        global $config;
529

    
530
        $i = 0;
531
        if (is_array($config['gres']['gre']) && count($config['gres']['gre'])) {
532
                foreach ($config['gres']['gre'] as $gre) {
533
                        if(empty($gre['greif']))
534
                                $gre['greif'] = "gre{$i}";
535
                        /* XXX: Maybe we should report any errors?! */
536
                        interface_gre_configure($gre);
537
                        $i++;
538
                }
539
        }
540
}
541

    
542
function interface_gre_configure(&$gre) {
543
        global $config, $g;
544

    
545
	if (!is_array($gre))
546
		return -1;
547

    
548
	$realif = get_real_interface($gre['if']);
549
	$realifip = get_interface_ip($gre['if']);
550

    
551
	/* make sure the parent interface is up */
552
	interfaces_bring_up($realif);
553

    
554
	if ($g['booting'] || !(empty($gre['greif']))) {
555
		mwexec("/sbin/ifconfig {$gre['greif']} destroy");
556
		mwexec("/sbin/ifconfig {$gre['greif']} create");
557
		$greif = $gre['greif'];
558
	} else {
559
		$greif = exec("/sbin/ifconfig gre create");
560
	}
561

    
562
	/* Do not change the order here for more see gre(4) NOTES section. */
563
	mwexec("/sbin/ifconfig {$greif} tunnel {$realifip} {$gre['remote-addr']}");
564
	mwexec("/sbin/ifconfig {$greif} {$gre['tunnel-local-addr']} {$gre['tunnel-remote-addr']} netmask " . gen_subnet_mask($gre['tunnel-remote-net']));
565
	if (isset($gre['link0']) && $gre['link0'])
566
		mwexec("/sbin/ifconfig {$greif} link0");
567
	if (isset($gre['link1']) && $gre['link1'])
568
		mwexec("/sbin/ifconfig {$greif} link1");
569
	if (isset($gre['link2']) && $gre['link2'])
570
		mwexec("/sbin/ifconfig {$greif} link2");
571

    
572
	if($greif)
573
		interfaces_bring_up($greif);
574
	else 
575
		log_error("Could not bring greif up -- variable not defined.");
576

    
577
	mwexec("/sbin/route add {$gre['remote-addr']}/{$gre['tunnel-remote-net']} {$realifip}");
578
	file_put_contents("{$g['tmp_path']}/{$greif}_router", $gre['tunnel-remote-addr']);
579

    
580
	return $greif;
581
}
582

    
583
function interfaces_gif_configure() {
584
	global $config;
585
	$i = 0;
586
	if (is_array($config['gifs']['gif']) && count($config['gifs']['gif'])) {
587
		foreach ($config['gifs']['gif'] as $gif) {
588
			if(empty($gif['gifif']))
589
				$gre['gifif'] = "gif{$i}";
590
			/* XXX: Maybe we should report any errors?! */
591
			interface_gif_configure($gif);
592
			$i++;
593
		}
594
	}
595
}
596

    
597
function interface_gif_configure(&$gif) {
598
	global $config, $g;
599

    
600
	if (!is_array($gif))
601
		return -1;
602

    
603
	$realif = get_real_interface($gif['if']);
604
	$realifip = get_interface_ip($gif['if']);
605

    
606
	/* make sure the parent interface is up */
607
	if($realif)
608
		interfaces_bring_up($realif);
609
	else 
610
		log_error("could not bring realif up -- variable not defined -- interface_gif_configure()");
611

    
612
	if ($g['booting'] || !(empty($gif['gifif']))) {
613
		mwexec("/sbin/ifconfig {$gif['gifif']} destroy");
614
		mwexec("/sbin/ifconfig {$gif['gifif']} create");
615
		$gifif = $gif['gifif'];
616
	} else
617
		$gifif = exec("/sbin/ifconfig gif create");
618

    
619
	/* Do not change the order here for more see gif(4) NOTES section. */
620
	mwexec("/sbin/ifconfig {$gifif} tunnel {$realifip} {$gif['remote-addr']}");
621
	mwexec("/sbin/ifconfig {$gifif} {$gif['tunnel-local-addr']} {$gif['tunnel-remote-addr']} netmask " . gen_subnet_mask($gif['tunnel-remote-net']));
622
	if (isset($gif['link0']) && $gif['link0'])
623
		mwexec("/sbin/ifconfig {$gifif} link0");
624
	if (isset($gif['link1']) && $gif['link1'])
625
		mwexec("/sbin/ifconfig {$gifif} link1");
626
	if($gifif)
627
		interfaces_bring_up($gifif);
628
	else
629
		log_error("could not bring gifif up -- variable not defined");
630

    
631
	mwexec("/sbin/route add {$gif['remote-addr']}/{$gif['tunnel-remote-net']} {$realifip}");
632
	file_put_contents("{$g['tmp_path']}/{$gifif}_router", $gif['tunnel-remote-addr']);
633

    
634
	return $gifif;
635
}
636

    
637
function interfaces_configure() {
638
	global $config, $g;
639

    
640
	/* Set up our loopback interface */
641
	interfaces_loopback_configure();
642

    
643
	/* set up LAGG virtual interfaces */
644
	interfaces_lagg_configure();
645

    
646
	/* set up VLAN virtual interfaces */
647
	interfaces_vlan_configure();
648

    
649
	interfaces_qinq_configure();
650

    
651
	/* Set up PPP interfaces */
652
	interfaces_ppp_configure();
653

    
654
	$iflist = get_configured_interface_with_descr();
655
	$delayed_list = array();
656
	$bridge_list = array();
657
	
658
	foreach($iflist as $if => $ifname) {
659
		$realif = $config['interfaces'][$if]['if'];
660
		if(is_array($realif['pppoe']) && isset($realif['pppoe']['pppoe-reset-type']))
661
			setup_pppoe_reset_file($if, true);
662
		else 
663
			setup_pppoe_reset_file($if, false);
664
		if (strstr($realif, "bridge")) 
665
			$bridge_list[$if] = $ifname;
666
		else if (strstr($realif, "gre"))
667
			$delayed_list[$if] = $ifname;
668
		else if (strstr($realif, "gif"))
669
			$delayed_list[$if] = $ifname;
670
		else {
671
			if ($g['booting'])
672
				echo "Configuring {$ifname} interface...";
673
			if($g['debug'])
674
				log_error("Configuring {$ifname}");
675
			interface_configure($if, true);
676
			if ($g['booting']) 
677
				echo "done.\n";
678
		}
679
	}
680

    
681
	/* set up GRE virtual interfaces */
682
	interfaces_gre_configure();
683

    
684
	/* set up GIF virtual interfaces */
685
	interfaces_gif_configure();
686
	
687
	foreach ($delayed_list as $if => $ifname) {
688
		if ($g['booting'])
689
			echo "Configuring {$ifname} interface...";
690
        	if ($g['debug'])
691
        		log_error("Configuring {$ifname}");
692

    
693
		interface_configure($if, true);
694

    
695
		if ($g['booting'])
696
			echo "done.\n";
697
	}
698

    
699
	/* set up BRIDGe virtual interfaces */
700
	interfaces_bridge_configure();
701

    
702
	foreach ($bridge_list as $if => $ifname) {
703
		if ($g['booting'])
704
			echo "Configuring {$ifname} interface...";
705
		if($g['debug'])
706
			log_error("Configuring {$ifname}");
707

    
708
		interface_configure($if, true);
709

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

    
714
	/* bring up vip interfaces */
715
	interfaces_vips_configure();
716

    
717
	/* configure interface groups */
718
	interfaces_group_setup();
719

    
720
	if (!$g['booting']) {
721
		/* reconfigure static routes (kernel may have deleted them) */
722
		system_routing_configure();
723

    
724
		/* reload IPsec tunnels */
725
		vpn_ipsec_configure();
726

    
727
		/* reload dhcpd (interface enabled/disabled status may have changed) */
728
		services_dhcpd_configure();
729

    
730
		/* restart dnsmasq */
731
		services_dnsmasq_configure();
732

    
733
		/* reload captive portal */
734
		captiveportal_configure();
735

    
736
		/* set the reload filter dity flag */
737
		filter_configure();
738
	}
739

    
740
	return 0;
741
}
742

    
743
function interface_reconfigure($interface = "wan") {
744
	interface_bring_down($interface);
745
	interface_configure($interface);
746
}
747

    
748
function interface_vip_bring_down(&$vip) {
749
	switch ($vip['mode']) {
750
	case "proxyarp":
751
		interface_proxyarp_configure();
752
		break;
753
	case "ipalias":
754
		$vipif = get_real_interface($vip['interface']);
755
		if(does_interface_exist($vipif))
756
			mwexec("/sbin/ifconfig {$vipif} delete {$vip['subnet']}");
757
		break;
758
	case "carp":
759
		$vipif = "vip" . $vip['vhid'];
760
		if(does_interface_exist($vipif)) 
761
			mwexec("/sbin/ifconfig {$vipif} destroy");
762
		break;
763
	case "carpdev-dhcp":
764
		$vipif = "vip" . $vip['vhid'];
765
		if(does_interface_exist($vipif)) 
766
			mwexec("/sbin/ifconfig {$vipif} destroy");
767
		break;
768
	}
769
}
770

    
771
function interface_bring_down($interface = "wan", $destroy = false) {
772
	global $config, $g;
773

    
774
	if (!isset($config['interfaces'][$interface]))
775
		return; 
776

    
777
	$ifcfg = $config['interfaces'][$interface];
778

    
779
	$realif = get_real_interface($interface);
780

    
781

    
782
	/* remove interface up file if it exists */
783
	unlink_if_exists("{$g['tmp_path']}/{$realif}up");
784
	unlink_if_exists("{$g['vardb_path']}/{$interface}ip");
785
	unlink_if_exists("{$g['tmp_path']}/{$realif}_router");
786
	
787
	interface_ppp_bring_down($realif);
788

    
789
	switch ($ifcfg['ipaddr']) {
790
	case "pppoe":
791
		killbypid("{$g['varrun_path']}/pppoe_{$interface}.pid");
792
		sleep(2);
793
		unlink_if_exists("{$g['varetc_path']}/mpd_{$interface}.conf");
794
		unlink_if_exists("{$g['varetc_path']}/mpd_{$interface}.links");
795
		break;
796
	case "pptp":
797
		killbypid("{$g['varrun_path']}/pptp_{$interface}.pid");
798
		sleep(2);
799
		unlink_if_exists("{$g['varetc_path']}/mpd_{$interface}.conf");
800
		unlink_if_exists("{$g['varetc_path']}/mpd_{$interface}.links");
801
		break;
802
	case "carpdev-dhcp":
803
		/* 
804
		 * NB: When carpdev gets enabled it would be better to be handled as all
805
		 *	   other interfaces! 
806
		 */
807
	case "dhcp":
808
		$pid = find_dhclient_process($interface);
809
		if($pid)
810
			mwexec("kill {$pid}");
811
		sleep(1);
812
		unlink_if_exists("{$g['varetc_path']}/dhclient_{$interface}.conf");
813
		if(does_interface_exist("$realif")) {
814
			mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete", true);
815
			mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " down");
816
			mwexec("/usr/sbin/arp -d -i {$realif} -a");
817
		}
818
		break;
819
	default:
820
		if(does_interface_exist("$realif")) {
821
			mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete", true);
822
			mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " down");
823
			mwexec("/usr/sbin/arp -d -i {$realif} -a");
824
		}
825
		break;
826
	}
827

    
828
	if ($destroy == true) {
829
		if (preg_match("/^tun|^ppp|^ovpn|^gif|^gre|^lagg|^bridge|vlan/i", $realif))
830
			mwexec("/sbin/ifconfig {$realif} destroy");
831
	}	
832

    
833
	return;
834
}
835

    
836
function interfaces_ppp_configure($write_config=true) {
837
	global $config, $g;
838
	if(!$g['booting']) 
839
		conf_mount_rw();
840
	if($g['booting'])
841
		echo "Configuring PPP interfaces...";
842
	if($config['ppps']['ppp']) {
843
		foreach($config['ppps']['ppp'] as $ppp) {
844
			$dev = substr($ppp['port'], 5);
845
			interface_ppp_configure($dev,$write_config);
846
		}
847
	}
848
	if(!$g['booting']) 
849
		conf_mount_ro();
850
	if($g['booting'])
851
		echo "done.\n";
852
}
853

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

    
860
	// ppp (userland) requires a /var/spool/lock directory
861
	if(!is_dir("/var/spool/lock")) {
862
		exec("mkdir -p /var/spool/lock");
863
		exec("chmod a+rw /var/spool/lock/.");
864
	}
865
	if ($edit){
866
		// Construct the ppp.conf file
867
		$peerfile .= "default:\n";
868
		$peerfile .= " set log Phase Chat LCP IPCP CCP tun command\n";
869
		$peerfile .= " ident user-ppp VERSION (built COMPILATIONDATE)\n";
870
		$peerfile .= " set dial \"ABORT BUSY ABORT NO\\\sCARRIER TIMEOUT 5 \\\n";
871
		$peerfile .= " 		\\\"\\\" AT OK-AT-OK ATE1Q0 OK \\\dATDT\\\T TIMEOUT 40 CONNECT\"\n";
872
		$peerfile .= " enable dns\n";
873
		$peerfile .= " nat enable yes\n";
874
		$peerfile .= " set reconnect {$ifcfg['connect-max-attempts']} 5\n";
875
		$peerfile .= " allow users root\n\n";
876
	
877
		// Loop variables
878
    		$i = 0;
879
		$startingip = 1;
880

    
881
		// Start ppp.linkup file
882
		$rclinkup = "default:\n";
883
		// Start ppp.linkdown file
884
		$rclinkdown = "default:\n";
885

    
886
 	   	if (is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) {
887
			foreach ($config['ppps']['ppp'] as $ppp) {
888
				$dev = substr($ppp['port'], 5);
889
				$realif  = $ppp['port'];
890
				$peerfile .= "{$dev}:\n";
891
				$peerfile .= " set device {$realif}\n";
892
				if($ppp['dialcmd']) {
893
					$peerfile .= " set dial " . base64_decode($ppp['dialcmd']) . "\n";
894
				} else
895
					$peerfile .= " set dial \"\"\n";
896
				$peerfile .= " set speed {$ppp['linespeed']}\n";
897
				if (isset($ppp['defaultgw']))
898
					$peerfile .= " add default HISADDR\n";
899
				$peerfile .= " set timeout 0\n";
900
				$peerfile .= " enable dns\n";
901
				$endingip = $startingip+1;
902
				if($ppp['localip'] && $ppp['gateway'])
903
					$peerfile .= " set ifaddr {$ppp['localip']}/0 {$ppp['gateway']}/0 255.255.255.0 0.0.0.0\n";
904
				if(!$ppp['localip'] && $ppp['gateway'])
905
					$peerfile .= " set ifaddr 10.0.0.{$startingip}/0 {$ppp['gateway']}/0 255.255.255.0 0.0.0.0\n";
906
				if($ppp['localip'] and !$ppp['gateway'])
907
					$peerfile .= " set ifaddr {$ppp['localip']}/0 10.0.0.{$endingip}/0 255.255.255.0 0.0.0.0\n";
908
				if(!$ppp['localip'] and !$ppp['gateway'])	
909
					$peerfile .= " set ifaddr 10.0.0.{$startingip}/0 10.0.0.{$endingip}/0 255.255.255.0 0.0.0.0\n";
910
				//$peerfile .= " iface name ppp_{$orig_dev}\n";
911
				$peerfile .= " set phone \"{$ppp['phone']}\"\n";
912
				$peerfile .= " set authname \"{$ppp['username']}\"\n";
913
				$peerfile .= " set authkey \"{$ppp['password']}\"\n";
914
				// Add a local socket for the daemon so we can query it later
915
				$peerfile .= " set server /var/run/{$dev}.sock \"\" 0177\n";
916
				$peerfile .= "\n";
917
				$i++;
918
				$startingip++;
919
				$rclinkup .= "{$dev}:\n";
920
				$rclinkup .= "	! sh -c \"/etc/rc.conf_mount_rw\"\n";
921
 				$rclinkup .= "	! sh -c \"/bin/echo `date -j +%Y.%m.%d-%H:%M:%S` 00:00:00 >> /conf/ppp-up.{$dev}.log\"\n";
922
				$rclinkup .= "	! sh -c \"/sbin/ppp-script HISADDR INTERFACE DNS0 DNS1\"\n";
923
				$rclinkup .= "	! sh -c \"/etc/rc.linkup INTERFACE start\"\n";
924
				$rclinkup .= "	! sh -c \"/etc/rc.conf_mount_ro\"\n";
925
				$rclinkup.= "	! sh -c \"/etc/rc.filter_configure_sync\"\n";
926
				// Link down file
927
				$rclinkdown .= "{$dev}:\n";
928
				$rclinkdown .= "	! sh -c \"/etc/rc.conf_mount_rw\"\n";
929
				$rclinkdown .= "	! sh -c \"/bin/echo `date -j +%Y.%m.%d-%H:%M:%S` UPTIME >> /conf/ppp-up.{$dev}.log\"\n";
930
				$rclinkdown .= "	! sh -c \"/etc/rc.conf_mount_ro\"\n";
931
				$rclinkdown .= "	! sh -c \"/bin/rm -f /var/run/{$dev}.if\"\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
		file_put_contents("/etc/ppp/ppp.linkdown", $rclinkdown);
941
		// Make executable
942
		exec("chmod a+rx /etc/ppp/ppp.linkup");
943
		exec("chmod a+rx /etc/ppp/ppp.linkdown");
944
	}
945
	// Launch specified ppp instance
946
	if( (!$edit || $g['booting']) && file_exists("/dev/{$orig_dev}")){
947
		$running = `ps awux | grep ppp | grep -v grep | grep $orig_dev`;
948
		if(!$running)
949
			mwexec_bg("/usr/sbin/ppp -background {$orig_dev}");
950
	}
951
}
952

    
953
function interface_ppp_bring_down($if) {
954
	if(file_exists("/var/run/{$if}.pid")) {
955
		$pid = trim(file_get_contents("/var/run/{$if}.pid"));
956
		mwexec("kill -QUIT {$pid}");
957
	}
958
}
959

    
960
function interfaces_carp_setup() {
961
	global $g, $config;
962

    
963
	$balanacing = "";
964
	$pfsyncinterface = "";
965
	$pfsyncenabled = "";
966
	if(isset($config['system']['developerspew'])) {
967
		$mt = microtime();
968
		echo "interfaces_carp_setup() being called $mt\n";
969
	}
970

    
971
	// Prepare CmdCHAIN that will be used to execute commands.
972
	$cmdchain = new CmdCHAIN();	
973

    
974
	if ($g['booting']) {
975
		echo "Configuring CARP settings...";
976
		mute_kernel_msgs();
977
	}
978

    
979
	/* suck in configuration items */
980
	if($config['installedpackages']['carpsettings']) {
981
		if($config['installedpackages']['carpsettings']['config']) {
982
			foreach($config['installedpackages']['carpsettings']['config'] as $carp) {
983
				$pfsyncenabled = $carp['pfsyncenabled'];
984
				$balanacing = $carp['balancing'];
985
				$pfsyncinterface = $carp['pfsyncinterface'];
986
				$pfsyncpeerip = $carp['pfsyncpeerip'];
987
			}
988
		}
989
	} else {
990
		unset($pfsyncinterface);
991
		unset($balanacing);
992
		unset($pfsyncenabled);
993
	}
994

    
995
	$cmdchain->add("Allow CARP", "/sbin/sysctl net.inet.carp.allow=1", true);			
996
	if($balanacing) {
997
		$cmdchain->add("Enable CARP ARP-balancing", "/sbin/sysctl net.inet.carp.arpbalance=1", true);
998
		$cmdchain->add("Disallow CARP preemption", "/sbin/sysctl net.inet.carp.preempt=0", true);
999
	} else
1000
		$cmdchain->add("Enable CARP preemption", "/sbin/sysctl net.inet.carp.preempt=1", true);		
1001

    
1002
	$cmdchain->add("Enable CARP logging", "/sbin/sysctl net.inet.carp.log=2", true);
1003
	if (!empty($pfsyncinterface))
1004
		$carp_sync_int = get_real_interface($pfsyncinterface);
1005

    
1006
	if($g['booting']) {
1007
		/*    install rules to alllow pfsync to sync up during boot
1008
		 *    carp interfaces will remain down until the bootup sequence finishes
1009
		 */
1010
		$fd = fopen("{$g['tmp_path']}/rules.boot", "w");
1011
		if ($fd) {
1012
			fwrite($fd, "pass quick proto carp all keep state\n");
1013
			fwrite($fd, "pass quick proto pfsync all\n");
1014
			fwrite($fd, "pass out quick from any to any keep state\n");
1015
			fclose($fd);
1016
			mwexec("/sbin/pfctl -f {$g['tmp_path']}/rules.boot");
1017
		} else
1018
			log_error("Could not create rules.boot file!");
1019
	}
1020

    
1021
	/* setup pfsync interface */
1022
	if($carp_sync_int and $pfsyncenabled) {
1023
		if (is_ipaddr($pfsyncpeerip))
1024
			$cmdchain->add("Bring up pfsync0 syncpeer", "/sbin/ifconfig pfsync0 syncdev {$carp_sync_int} syncpeer {$pfsyncpeerip} up", false);						
1025
		else
1026
			$cmdchain->add("Bring up pfsync0 syncdev", "/sbin/ifconfig pfsync0 syncdev {$carp_sync_int} up", false);			
1027
	} else
1028
		$cmdchain->add("Bring up pfsync0", "/sbin/ifconfig pfsync0 syncdev lo0 up", false);						
1029

    
1030
	if($config['virtualip']['vip'])
1031
		$cmdchain->add("Allow CARP.", "/sbin/sysctl net.inet.carp.allow=1", true);				
1032
	else
1033
		$cmdchain->add("Disallow CARP.", "/sbin/sysctl net.inet.carp.allow=0", true);		
1034
	
1035
	if($g['debug'])
1036
		$cmdchain->setdebug(); // optional for verbose logging
1037

    
1038
	$cmdchain->execute();
1039
	$cmdchain->clear();
1040

    
1041
	if ($g['booting']) {
1042
		unmute_kernel_msgs();
1043
		echo "done.\n";
1044
	}
1045
}
1046

    
1047
function interface_proxyarp_configure() {
1048
	global $config, $g;
1049
	if(isset($config['system']['developerspew'])) {
1050
		$mt = microtime();
1051
		echo "interface_proxyarp_configure() being called $mt\n";
1052
	}
1053

    
1054
	/* kill any running choparp */
1055
	killbyname("choparp");
1056

    
1057
	if (isset($config['virtualip']) && is_array($config['virtualip']['vip'])) {
1058
		$paa = array();
1059

    
1060
		/* group by interface */
1061
		foreach ($config['virtualip']['vip'] as $vipent) {
1062
			if ($vipent['mode'] === "proxyarp") {
1063
				if ($vipent['interface'])
1064
					$proxyif = $vipent['interface'];
1065
				else
1066
					$proxyif = "wan";
1067

    
1068
				if (!is_array($paa[$if]))
1069
					$paa[$proxyif] = array();
1070

    
1071
				$paa[$proxyif][] = $vipent;
1072
			}
1073
	}
1074

    
1075
	if (count($paa))
1076
		foreach ($paa as $paif => $paents) {
1077
			$paaifip = get_interface_ip($paif);
1078
			if (!(is_ipaddr($paaifip)))
1079
				continue;
1080
			$args = get_real_interface($paif) . " auto";
1081
			foreach ($paents as $paent) {
1082

    
1083
				if (isset($paent['subnet']))
1084
					$args .= " " . escapeshellarg("{$paent['subnet']}/{$paent['subnet_bits']}");
1085
				else if (isset($paent['range']))
1086
					$args .= " " . escapeshellarg($paent['range']['from'] . "-" .
1087
					$paent['range']['to']);
1088
			}
1089
			mwexec_bg("/usr/local/sbin/choparp " . $args);
1090
		}
1091
	}
1092

    
1093
}
1094

    
1095
function interfaces_vips_configure($interface = "") {
1096
	global $g, $config;
1097
	if(isset($config['system']['developerspew'])) {
1098
		$mt = microtime();
1099
		echo "interfaces_vips_configure() being called $mt\n";
1100
	}
1101
	$paa = array();
1102
	if(is_array($config['virtualip']['vip'])) {
1103
		$carp_setuped = false;
1104
		$anyproxyarp = false;
1105
		foreach ($config['virtualip']['vip'] as $vip) {
1106
			switch ($vip['mode']) {
1107
			case "proxyarp":
1108
				/* nothing it is handled on interface_proxyarp_configure() */
1109
				if ($interface <> "" && $vip['interface'] <> $interface)
1110
					continue;
1111
				$anyproxyarp = true;
1112
				break;
1113
			case "ipalias":
1114
				if ($interface <> "" && $vip['interface'] <> $interface)
1115
					continue;
1116
				interface_ipalias_configure(&$vip);
1117
				break;
1118
			case "carp":
1119
				if ($interface <> "" && $vip['interface'] <> $interface)
1120
					continue;
1121
				if ($carp_setuped == false) {
1122
					interfaces_carp_setup();
1123
					$carp_setuped = true;
1124
				}
1125
				interface_carp_configure($vip);
1126
				break;
1127
			case "carpdev-dhcp":
1128
				if ($interface <> "" && $vip['interface'] <> $interface)
1129
					continue;
1130
				interface_carpdev_configure($vip);
1131
				break;
1132
			}
1133
		}
1134
		
1135
		if ($anyproxyarp == true)
1136
			interface_proxyarp_configure();
1137
	}
1138
}
1139

    
1140
function interface_ipalias_configure(&$vip) {
1141

    
1142
	if ($vip['mode'] == "ipalias") {
1143
		$if = get_real_interface($vip['interface']);
1144
		mwexec("/sbin/ifconfig " . escapeshellarg($if) . " " . $vip['subnet'] . "/" . escapeshellarg($vip['subnet_bits']) . " alias");
1145
	}
1146
}
1147

    
1148
function interface_reload_carps($cif) {
1149
	global $config;
1150

    
1151
	$carpifs = link_ip_to_carp_interface(find_interface_ip($cif));
1152
	if (empty($carpifs))
1153
		return;
1154

    
1155
	$carps = explode(" ", $carpifs);
1156
	if(is_array($config['virtualip']['vip'])) {
1157
		$viparr = &$config['virtualip']['vip'];
1158
		foreach ($viparr as $vip) {
1159
			if (in_array($vip['carpif'], $carps)) {
1160
				switch ($vip['mode']) {
1161
					case "carp":
1162
					interface_vip_bring_down($vip);
1163
					sleep(1);
1164
					interface_carp_configure($vip);
1165
					break;
1166
					case "carpdev-dhcp":
1167
					interface_vip_bring_down($vip);
1168
					sleep(1);
1169
					interface_carpdev_configure($vip);
1170
					break;
1171
				}
1172
			}
1173
		}
1174
	}
1175
}
1176

    
1177
function interface_carp_configure(&$vip) {
1178
	global $config, $g;
1179
	if(isset($config['system']['developerspew'])) {
1180
		$mt = microtime();
1181
		echo "interface_carp_configure() being called $mt\n";
1182
	}
1183

    
1184
	if ($vip['mode'] != "carp")
1185
		return;
1186

    
1187
	$vip_password = $vip['password'];
1188
	$vip_password = escapeshellarg(addslashes(str_replace(" ", "", $vip_password)));
1189
	if ($vip['password'] != "")
1190
		$password = " pass {$vip_password}";
1191

    
1192
	// set the vip interface to the vhid
1193
	$vipif = "vip{$vip['vhid']}";
1194

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

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

    
1223
	/* invalidate interface cache */
1224
	get_interface_arr(true);
1225

    
1226
	/* create the carp interface and setup */
1227
	if (does_interface_exist($vipif)) {
1228
		interface_bring_down($vipif);
1229
	} else {
1230
		$carpif = exec("/sbin/ifconfig carp create");
1231
		mwexec("/sbin/ifconfig {$carpif} name {$vipif}");
1232
		mwexec("/usr/sbin/ngctl name {$carpif}: {$vipif}");
1233
	}
1234

    
1235
	/* invalidate interface cache */
1236
	get_interface_arr(true);
1237

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

    
1241
	interfaces_bring_up($vipif);
1242
	
1243
	return $vipif;
1244
}
1245

    
1246
function interface_carpdev_configure(&$vip) {
1247
	global $g;
1248

    
1249
	if ($vip['mode'] != "carpdev-dhcp")
1250
		return;
1251

    
1252
	$vip_password = $vip['password'];
1253
	$vip_password = str_replace(" ", "", $vip_password);
1254
	if($vip['password'] != "")
1255
		$password = " pass \"" . $vip_password . "\"";
1256

    
1257
	log_error("Found carpdev interface {$vip['interface']} on top of interface {$interface}");
1258
	if (empty($vip['interface']))
1259
		return;
1260

    
1261
	$vipif = "vip" . $vip['vhid'];
1262
	$realif = interface_translate_type_to_real($vip['interface']);
1263
	interfaces_bring_up($realif);
1264
	/*
1265
	 * ensure the interface containing the VIP really exists
1266
	 * prevents a panic if the interface is missing or invalid
1267
	 */
1268
	if (!does_interface_exist($realif)) {
1269
		file_notice("CARP", "Interface specified for the virtual IP address {$vip['subnet']} does not exist. Skipping this VIP.", "Firewall: Virtual IP", "");
1270
		return;
1271
	}
1272

    
1273
	if (does_interface_exist($vipif)) {
1274
		interface_bring_down($vipif);
1275
	} else {
1276
		$carpdevif = exec("/sbin/ifconfig carp create");
1277
		mwexec("/sbin/ifconfig {$carpdevif} name {$vipif}");
1278
		mwexec("/usr/sbin/ngctl name {$carpdevif}: {$vipif}");
1279
	}
1280

    
1281
	mwexec("/sbin/ifconfig {$vipif} carpdev {$realif} vhid {$vip['vhid']} advskew {$vip['advskew']} {$password}");
1282
	interfaces_bring_up($vipif);
1283

    
1284
	/*
1285
	 * XXX: BIG HACK but carpdev needs ip services active
1286
	 *      before even starting something as dhclient.
1287
	 *      I do not know if this is a feature or a bug
1288
	 *      but better than track it make it work ;) .
1289
	 */
1290
	//$fakeiptouse = "10.254.254." . ($carp_instances_counter+1);
1291
	//$cmdchain->add("CarpDEV hack", "/sbin/ifconfig {$carpint} inet {$fakeiptouse}", false);
1292

    
1293
	/* generate dhclient_wan.conf */
1294
	$fd = fopen("{$g['varetc_path']}/dhclient_{$vipif}.conf", "w");
1295
	if ($fd) {
1296
		$dhclientconf = "";
1297

    
1298
		$dhclientconf .= <<<EOD
1299
interface "{$vipif}" {
1300
timeout 60;
1301
retry 1;
1302
select-timeout 0;
1303
initial-interval 1;
1304
script "/sbin/dhclient-script";
1305
}
1306

    
1307
EOD;
1308

    
1309
		fwrite($fd, $dhclientconf);
1310
		fclose($fd);
1311

    
1312
		/* fire up dhclient */
1313
		mwexec("/sbin/dhclient -c {$g['varetc_path']}/dhclient_{$vipif}.conf {$vipif} > {$g['tmp_path']}/{$vipif}_output > {$g['tmp_path']}/{$vipif}_error_output", false);
1314
	} else {
1315
		log_error("Error: cannot open dhclient_{$vipif}.conf in interfaces_carpdev_configure() for writing.\n");
1316
		mwexec("/sbin/dhclient -b {$vipif}");
1317
	}
1318

    
1319
	return $vipif;
1320
}
1321

    
1322
function interface_wireless_clone($if, $wlcfg) {
1323
	global $config, $g;
1324
	/*   Check to see if interface has been cloned as of yet.  
1325
	 *   If it has not been cloned then go ahead and clone it.
1326
	 */
1327
	$needs_clone = false;
1328
	/* FIXME: Interface num needs to be something else when we
1329
	 * integrate the wireless VAP support */
1330
	/* Setting it to 0 for the time being. */
1331
	$interface_num = 0;
1332
	switch($wlcfg['wireless']['mode']) {
1333
		 case "hostap":
1334
			$mode = "wlanmode hostap";
1335
			break;
1336
		 case "adhoc":
1337
			$mode = "wlanmode adhoc";
1338
			break;
1339
		 default:
1340
			$mode = "";
1341
			break;
1342
	}
1343
	if(does_interface_exist("{$wlcfg['if']}_wlan{$interface_num}")) {
1344
		exec("/sbin/ifconfig {$wlcfg['if']}_wlan{$interface_num}", $output, $ret);
1345
		$ifconfig_str = implode($output);
1346
		if(($wlcfg['wireless']['mode'] == "hostap") && (! preg_match("/hostap/si", $ifconfig_str))) {
1347
			log_error("Interface {$wlcfg['if']}_wlan{$interface_num} changed to hostap mode");
1348
			$needs_clone = true;
1349
		}
1350
		if(($wlcfg['wireless']['mode'] == "adhoc") && (! preg_match("/adhoc/si", $ifconfig_str))) {
1351
			log_error("Interface {$wlcfg['if']}_wlan{$interface_num} changed to adhoc mode");
1352
			$needs_clone = true;
1353
		}
1354
		if(($wlcfg['wireless']['mode'] == "bss") && (preg_match("/hostap|adhoc/si", $ifconfig_str))) {
1355
			log_error("Interface {$wlcfg['if']}_wlan{$interface_num} changed to infrastructure mode");
1356
			$needs_clone = true;
1357
		}
1358
	} else {
1359
		$needs_clone = true;
1360
	}
1361

    
1362
	if($needs_clone == true) {
1363
		/* remove previous instance if it exists */
1364
		if(does_interface_exist("{$wlcfg['if']}_wlan{$interface_num}")) {
1365
			mwexec("/sbin/ifconfig {$wlcfg['if']}_wlan{$interface_num} destroy");			
1366
		}
1367
		log_error("Cloning new wireless interface {$wlcfg['if']}_wlan{$interface_num}");
1368
		// Create the new wlan interface. FreeBSD returns the new interface name.
1369
		// example:  wlan2
1370
		exec("/sbin/ifconfig wlan create wlandev {$wlcfg['if']} {$mode} 2>&1", $out, $ret);
1371
		if($ret <> 0) {
1372
			log_error("Failed to clone interface {$wlcfg['if']} with error code {$ret}, output {$out[0]}");
1373
		}
1374
		$newif = trim($out[0]);
1375
		// Rename the interface to {$parentnic}_wlan{$number}#: EX: ath0_wlan0
1376
		mwexec("/sbin/ifconfig {$newif} name {$wlcfg['if']}_wlan{$interface_num} 2>&1", false);
1377
		// FIXME: not sure what ngctl is for. Doesn't work.
1378
		// mwexec("/usr/sbin/ngctl name {$newif}: {$wlcfg['if']}_wlan{$interface_num}", false);
1379
	}
1380
}
1381

    
1382
function interface_wireless_configure($if, &$wl, &$wlcfg) {
1383
	global $config, $g;
1384

    
1385
	/*    open up a shell script that will be used to output the commands.
1386
	 *    since wireless is changing a lot, these series of commands are fragile
1387
     *    and will sometimes need to be verified by a operator by executing the command
1388
     *    and returning the output of the command to the developers for inspection.  please
1389
     *    do not change this routine from a shell script to individul exec commands.  -sullrich
1390
	 */
1391

    
1392
	// Remove script file
1393
	unlink_if_exists("{$g['tmp_path']}/{$if}_setup.sh");
1394

    
1395
	// Clone wireless nic if needed.
1396
	interface_wireless_clone($if, $wl);
1397

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

    
1402
	/* set values for /path/program */
1403
	$hostapd = "/usr/sbin/hostapd";
1404
	$wpa_supplicant = "/usr/sbin/wpa_supplicant";
1405
	$ifconfig = "/sbin/ifconfig";
1406
	$killall = "/usr/bin/killall";
1407

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

    
1410
	$wlcmd = array();
1411
	/* Make sure it's up */
1412
	$wlcmd[] = "up";
1413
	/* Set a/b/g standard */
1414
	$wlcmd[] = "mode " . escapeshellarg($wlcfg['standard']);
1415

    
1416
	/* Set ssid */
1417
	if($wlcfg['ssid'])
1418
		$wlcmd[] = "ssid " .escapeshellarg($wlcfg['ssid']);
1419

    
1420
	/* Set 802.11g protection mode */
1421
	$wlcmd[] = "protmode " . escapeshellarg($wlcfg['protmode']);
1422

    
1423
	/* set wireless channel value */
1424
	if(isset($wlcfg['channel'])) {
1425
		if($wlcfg['channel'] == "0") {
1426
			$wlcmd[] = "channel any";
1427
		} else {
1428
			$wlcmd[] = "channel " . escapeshellarg($wlcfg['channel']);
1429
		}
1430
	}
1431

    
1432
	/* set Distance value */
1433
	if($wlcfg['distance'])
1434
		$distance = escapeshellarg($wlcfg['distance']);
1435

    
1436
	/* Set wireless hostap mode */
1437
	if ($wlcfg['mode'] == "hostap") {
1438
		$wlcmd[] = "mediaopt hostap";
1439
	} else {
1440
		$wlcmd[] = "-mediaopt hostap";
1441
	}
1442

    
1443
	/* Set wireless adhoc mode */
1444
	if ($wlcfg['mode'] == "adhoc") {
1445
		$wlcmd[] = "mediaopt adhoc";
1446
	} else {
1447
		$wlcmd[] = "-mediaopt adhoc";
1448
	}
1449

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

    
1452
	/* handle hide ssid option */
1453
	if(isset($wlcfg['hidessid']['enable'])) {
1454
		$wlcmd[] = "hidessid";
1455
	} else {
1456
		$wlcmd[] = "-hidessid";
1457
	}
1458

    
1459
	/* handle pureg (802.11g) only option */
1460
	if(isset($wlcfg['pureg']['enable'])) {
1461
		$wlcmd[] = "mode 11g pureg";
1462
	} else {
1463
		$wlcmd[] = "-pureg";
1464
	}
1465

    
1466
	/* enable apbridge option */
1467
	if(isset($wlcfg['apbridge']['enable'])) {
1468
		$wlcmd[] = "apbridge";
1469
	} else {
1470
		$wlcmd[] = "-apbridge";
1471
	}
1472

    
1473
	/* handle turbo option */
1474
	if(isset($wlcfg['turbo']['enable'])) {
1475
		$wlcmd[] = "mediaopt turbo";
1476
	} else {
1477
		$wlcmd[] = "-mediaopt turbo";
1478
	}
1479

    
1480
	/* handle txpower setting */
1481
	/* if($wlcfg['txpower'] <> "")
1482
		$wlcmd[] = "txpower " . escapeshellarg($wlcfg['txpower']);
1483
	*/
1484
	/* handle wme option */
1485
	if(isset($wlcfg['wme']['enable'])) {
1486
		$wlcmd[] = "wme";
1487
	} else {
1488
		$wlcmd[] = "-wme";
1489
	}
1490

    
1491
	/* set up wep if enabled */
1492
	$wepset = "";
1493
	if (isset($wlcfg['wep']['enable']) && is_array($wlcfg['wep']['key'])) {
1494
		switch($wlcfg['wpa']['auth_algs']) {
1495
			case "1":
1496
				$wepset .= "authmode open wepmode on ";
1497
				break;
1498
			case "2":
1499
				$wepset .= "authmode shared wepmode on ";
1500
				break;
1501
			case "3":
1502
				$wepset .= "authmode mixed wepmode on ";
1503
		}
1504
		$i = 1;
1505
		foreach ($wlcfg['wep']['key'] as $wepkey) {
1506
			$wepset .= "wepkey " . escapeshellarg("{$i}:{$wepkey['value']}") . " ";
1507
			if (isset($wepkey['txkey'])) {
1508
				$wlcmd[] = "weptxkey {$i} ";
1509
			}
1510
			$i++;
1511
		}
1512
		$wlcmd[] = $wepset;
1513
	} else {
1514
		$wlcmd[] = "authmode open wepmode off ";
1515
	}
1516

    
1517
	/* generate wpa_supplicant/hostap config if wpa is enabled */
1518
	conf_mount_rw();
1519

    
1520
	switch ($wlcfg['mode']) {
1521
		case 'bss':
1522
			if (isset($wlcfg['wpa']['enable'])) {
1523
				$wpa .= <<<EOD
1524
ctrl_interface={$g['varrun_path']}/wpa_supplicant
1525
ctrl_interface_group=0
1526
ap_scan=1
1527
#fast_reauth=1
1528
network={
1529
ssid="{$wlcfg['ssid']}"
1530
scan_ssid=1
1531
priority=5
1532
key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
1533
psk="{$wlcfg['wpa']['passphrase']}"
1534
pairwise={$wlcfg['wpa']['wpa_pairwise']}
1535
group={$wlcfg['wpa']['wpa_pairwise']}
1536
}
1537
EOD;
1538

    
1539
				$fd = fopen("{$g['varetc_path']}/wpa_supplicant_{$if}.conf", "w");
1540
				fwrite($fd, "{$wpa}");
1541
				fclose($fd);
1542

    
1543
				mwexec(kill_wpasupplicant("{$if}"));
1544
			}
1545
			break;
1546
		case 'hostap':
1547
			if (isset($wlcfg['wpa']['enable'])) {
1548
				$wpa .= <<<EOD
1549
interface={$if}
1550
driver=bsd
1551
logger_syslog=-1
1552
logger_syslog_level=0
1553
logger_stdout=-1
1554
logger_stdout_level=0
1555
dump_file={$g['tmp_path']}/hostapd_{$if}.dump
1556
ctrl_interface={$g['varrun_path']}/hostapd
1557
ctrl_interface_group=wheel
1558
#accept_mac_file={$g['tmp_path']}/hostapd_{$if}.accept
1559
#deny_mac_file={$g['tmp_path']}/hostapd_{$if}.deny
1560
#macaddr_acl={$wlcfg['wpa']['macaddr_acl']}
1561
ssid={$wlcfg['ssid']}
1562
debug={$wlcfg['wpa']['debug_mode']}
1563
auth_algs={$wlcfg['wpa']['auth_algs']}
1564
wpa={$wlcfg['wpa']['wpa_mode']}
1565
wpa_key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
1566
wpa_pairwise={$wlcfg['wpa']['wpa_pairwise']}
1567
wpa_group_rekey={$wlcfg['wpa']['wpa_group_rekey']}
1568
wpa_gmk_rekey={$wlcfg['wpa']['wpa_gmk_rekey']}
1569
wpa_strict_rekey={$wlcfg['wpa']['wpa_strict_rekey']}
1570
wpa_passphrase={$wlcfg['wpa']['passphrase']}
1571
ieee8021x={$wlcfg['wpa']['ieee8021x']}
1572
#Enable the next lines for preauth when roaming. Interface = wired or wireless interface talking to the AP you want to roam from/to
1573
#rsn_preauth=1
1574
#rsn_preauth_interfaces=eth0
1575
EOD;
1576

    
1577
				$fd = fopen("{$g['varetc_path']}/hostapd_{$if}.conf", "w");
1578
				fwrite($fd, "{$wpa}");
1579
				fclose($fd);
1580

    
1581
			}
1582
			mwexec(kill_hostapd("{$if}"));
1583
			break;
1584
		case 'adhoc':
1585
			mwexec(kill_hostapd("{$if}"));
1586
			mwexec(kill_wpasupplicant("{$if}"));
1587
			break;
1588
	}
1589

    
1590
	/*
1591
	 *    all variables are set, lets start up everything
1592
	 */
1593

    
1594
	/* set ack timers according to users preference (if he/she has any) */
1595
	if($distance) {
1596
		fwrite($fd_set, "# Enable ATH distance settings\n");
1597
		fwrite($fd_set, "/sbin/athctrl.sh -i {$if} -d {$distance}\n");
1598
	}
1599

    
1600
	$standard_no_turbo = str_replace(" Turbo", "", $standard);
1601

    
1602
	if (isset($wlcfg['wpa']['enable'])) {
1603
		if ($wlcfg['mode'] == "bss") {
1604
			fwrite($fd_set, "{$wpa_supplicant} -B -i {$if} -c {$g['varetc_path']}/wpa_supplicant_{$if}.conf\n");
1605
		}
1606
		if ($wlcfg['mode'] == "hostap") {
1607
			fwrite($fd_set, "{$hostapd} -B {$g['varetc_path']}/hostapd_{$if}.conf\n");
1608
		}
1609
	}
1610

    
1611
	fclose($fd_set);
1612
	conf_mount_ro();
1613

    
1614
	/* configure wireless */
1615
	$wlcmd_args = implode(" ", $wlcmd);
1616
	mwexec("/sbin/ifconfig {$if} $wlcmd_args", false);
1617

    
1618
	
1619
	sleep(1);
1620
	/* execute hostapd and wpa_supplicant if required in shell */
1621
	mwexec("/bin/sh {$g['tmp_path']}/{$if}_setup.sh");
1622

    
1623
	return 0;
1624

    
1625
}
1626

    
1627
function kill_hostapd($interface) {
1628
	return "/bin/ps awwuxx | grep hostapd | grep $interface | awk '{ print \$2 }' | xargs kill\n";
1629
}
1630

    
1631
function kill_wpasupplicant($interface) {
1632
	return "/bin/ps awwuxx | grep wpa_supplicant | grep $interface | awk '{ print \$2 }' | xargs kill\n";
1633
}
1634

    
1635
function find_dhclient_process($interface) {
1636
	if($interface)
1637
		$pid = `ps awwwux | grep dhclient | grep -v grep | grep {$interface} | awk '{ print \$2 }'`;
1638
	return $pid;
1639
}
1640

    
1641
function interface_configure($interface = "wan", $reloadall = false) {
1642
	global $config, $g;
1643
	global $interface_sn_arr_cache, $interface_ip_arr_cache;
1644

    
1645
	$wancfg = $config['interfaces'][$interface];
1646

    
1647
	$realif = get_real_interface($interface);
1648

    
1649
	if (!$g['booting']) {
1650
		/* remove all IPv4 addresses */
1651
		while (mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " -alias", true) == 0);
1652
			interface_bring_down($interface);
1653
	}
1654

    
1655
	/* wireless configuration? */
1656
	if (is_array($wancfg['wireless']))
1657
		interface_wireless_configure($realif, $wancfg, $wancfg['wireless']);
1658

    
1659
	if ($wancfg['spoofmac']) {
1660
		mwexec("/sbin/ifconfig " . escapeshellarg($realif) .
1661
			" link " . escapeshellarg($wancfg['spoofmac']));
1662
	}  else {
1663
		$mac = get_interface_mac(get_real_interface(get_real_interface($wancfg['if'])));
1664
		if($mac == "ff:ff:ff:ff:ff:ff") {
1665
			/*   this is not a valid mac address.  generate a
1666
			 *   temporary mac address so the machine can get online.
1667
			 */
1668
			echo "Generating new MAC address.";
1669
			$random_mac = generate_random_mac_address();
1670
			mwexec("/sbin/ifconfig " . escapeshellarg(get_real_interface($wancfg['if'])) .
1671
				" link " . escapeshellarg($random_mac));
1672
			$wancfg['spoofmac'] = $random_mac;
1673
			write_config();
1674
			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");
1675
		}
1676
	}
1677

    
1678
	/* media */
1679
	if ($wancfg['media'] || $wancfg['mediaopt']) {
1680
		$cmd = "/sbin/ifconfig " . escapeshellarg(get_real_interface($wancfg['if']));
1681
		if ($wancfg['media'])
1682
			$cmd .= " media " . escapeshellarg($wancfg['media']);
1683
		if ($wancfg['mediaopt'])
1684
			$cmd .= " mediaopt " . escapeshellarg($wancfg['mediaopt']);
1685
		mwexec($cmd);
1686
	}
1687

    
1688
	/* invalidate interface/ip/sn cache */
1689
	get_interface_arr(true);
1690
	unset($interface_ip_arr_cache[$realif]);
1691
	unset($interface_sn_arr_cache[$realif]);
1692

    
1693
	switch ($wancfg['ipaddr']) {
1694

    
1695
		case 'carpdev-dhcp':
1696
			interface_carpdev_dhcp_configure($interface);
1697
			break;
1698
		case 'dhcp':
1699
			interface_dhcp_configure($interface);
1700
			break;
1701

    
1702
		case 'pppoe':
1703
			interface_pppoe_configure($interface);
1704
			break;
1705

    
1706
		case 'pptp':
1707
			interface_pptp_configure($interface);
1708
			break;
1709

    
1710
		default:
1711
			if ($wancfg['ipaddr'] <> "" && $wancfg['subnet'] <> "") {
1712
				if (isset($wancfg['ispointtopoint']) && $wancfg['pointtopoint']) {
1713
					mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " " .
1714
						escapeshellarg($wancfg['ipaddr'] . "/" . $wancfg['subnet']) .
1715
						" " . escapeshellarg($wancfg['pointtopoint']) . " up");
1716
				} else {
1717
					if($wancfg['ipaddr'] && $wancfg['subnet'])
1718
						mwexec("/sbin/ifconfig " . escapeshellarg($realif) .
1719
							" " . escapeshellarg($wancfg['ipaddr'] . "/" . 
1720
							$wancfg['subnet']));
1721
				}
1722
			}
1723

    
1724
			if (is_ipaddr($wancfg['gateway']))
1725
				file_put_contents("{$g['tmp_path']}/{$realif}_router", $wancfg['gateway']);
1726
	}
1727

    
1728
	if(does_interface_exist($wancfg['if']))
1729
		interfaces_bring_up($wancfg['if']);
1730
 	
1731
	interface_reload_carps($realif);
1732
	
1733
	if($wancfg['serialport'])
1734
		interface_ppp_configure($wancfg['serialport']);
1735
	
1736
	if (!$g['booting']) {
1737
		if (link_interface_to_gre($interface)) {
1738
			foreach ($config['gres']['gre'] as $gre)
1739
				if ($gre['if'] == $interface)
1740
					interface_gre_configure($gre);
1741
		}
1742
		if (link_interface_to_gif($interface)) {
1743
                	foreach ($config['gifs']['gif'] as $gif)
1744
				if ($gif['if'] == $interface)
1745
                        		interface_gre_configure($gif);
1746
        	}
1747
		if (link_interface_to_bridge($interface)) {
1748
			foreach ($config['bridges']['bridged'] as $bridge)
1749
				if (stristr($bridge['members'], "{$interface}"))
1750
					interface_bridge_configure($bridge);
1751
		}
1752

    
1753
		link_interface_to_vips($interface, "update");
1754

    
1755
		if ($interface == "lan")
1756
			/* make new hosts file */
1757
			system_hosts_generate();
1758

    
1759
		if ($reloadall == true) {
1760

    
1761
			/* reconfigure static routes (kernel may have deleted them) */
1762
			system_routing_configure();
1763

    
1764
			/* reload ipsec tunnels */
1765
			vpn_ipsec_configure();
1766

    
1767
			/* update dyndns */
1768
			services_dyndns_configure($interface);
1769

    
1770
			/* force DNS update */
1771
			services_dnsupdate_process($interface);
1772

    
1773
			/* restart dnsmasq */
1774
			services_dnsmasq_configure();
1775

    
1776
			/* reload captive portal */
1777
			captiveportal_configure();
1778

    
1779
			/* set the reload filter dity flag */
1780
			filter_configure();
1781
		}
1782
	}
1783

    
1784
	unmute_kernel_msgs();
1785

    
1786
	return 0;
1787
}
1788

    
1789
function interface_carpdev_dhcp_configure($interface = "wan") {
1790
	global $config, $g;
1791

    
1792
	$wancfg = $config['interfaces'][$interface];
1793
	$wanif = $wancfg['if'];
1794
	/* bring wan interface up before starting dhclient */
1795
	if($wanif)
1796
		interfaces_bring_up($wanif);
1797
	else 
1798
		log_error("Could not bring wanif up in terface_carpdev_dhcp_configure()");
1799

    
1800
	return 0;
1801
}
1802

    
1803
function interface_dhcp_configure($interface = "wan") {
1804
	global $config, $g;
1805

    
1806
	$wancfg = $config['interfaces'][$interface];
1807

    
1808
	/* generate dhclient_wan.conf */
1809
	$fd = fopen("{$g['varetc_path']}/dhclient_{$interface}.conf", "w");
1810
	if (!$fd) {
1811
		printf("Error: cannot open dhclient_{$interface}.conf in interfaces_wan_dhcp_configure() for writing.\n");
1812
		return 1;
1813
	}
1814

    
1815
	if ($wancfg['dhcphostname']) {
1816
		$dhclientconf_hostname = "send dhcp-client-identifier \"{$wancfg['dhcphostname']}\";\n";
1817
		$dhclientconf_hostname .= "\tsend host-name \"{$wancfg['dhcphostname']}\";\n";
1818
	} else {
1819
		$dhclientconf_hostname = "";
1820
	}
1821

    
1822
	$wanif = get_real_interface($interface);
1823

    
1824
 	$dhclientconf = "";
1825
	
1826
	$dhclientconf .= <<<EOD
1827
interface "{$wanif}" {
1828
timeout 60;
1829
retry 1;
1830
select-timeout 0;
1831
initial-interval 1;
1832
	{$dhclientconf_hostname}
1833
	script "/sbin/dhclient-script";
1834
}
1835

    
1836
EOD;
1837

    
1838
if(is_ipaddr($wancfg['alias-address'])) {
1839
	$subnetmask = gen_subnet_mask($wancfg['alias-subnet']);
1840
	$dhclientconf .= <<<EOD
1841
alias {
1842
	interface  "{$wanif}";
1843
	fixed-address {$wancfg['alias-address']};
1844
	option subnet-mask {$subnetmask};
1845
}
1846

    
1847
EOD;
1848
}
1849
	fwrite($fd, $dhclientconf);
1850
	fclose($fd);
1851

    
1852
	$realwanif = $wancfg['if'];
1853

    
1854
	/* bring wan interface up before starting dhclient */
1855
	if($realwanif)
1856
		interfaces_bring_up($realwanif);
1857
	else 
1858
		log_error("Could not bring realwanif up in interface_dhcp_configure()");
1859

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

    
1863
	return 0;
1864
}
1865

    
1866
function interface_pppoe_configure($interface = "wan") {
1867
	global $config, $g;
1868

    
1869
	$wancfg = $config['interfaces'][$interface];
1870

    
1871
	/* generate mpd.conf */
1872
	$fd = fopen("{$g['varetc_path']}/mpd_{$interface}.conf", "w");
1873
	if (!$fd) {
1874
		printf("Error: cannot open mpd_{$interface}.conf in interface_pppoe_configure().\n");
1875
		return 1;
1876
	}
1877

    
1878
	$idle = 0;
1879

    
1880
	if (isset($wancfg['ondemand'])) {
1881
		$ondemand = "enable";
1882
		if ($wancfg['timeout'])
1883
			$idle = $wancfg['timeout'];
1884
	} else {
1885
		$ondemand = "disable";
1886
	}
1887

    
1888
	$mpdconf = <<<EOD
1889
startup:
1890
pppoeclient:
1891

    
1892
EOD;
1893

    
1894
	if ($interface == "wan")
1895
		$realif = "pppoe0";
1896
	else {
1897
		// Here code assumes only that strings of form "opt#" will be passed.
1898
		$realif = "pppoe" . substr($interface, 3); 
1899
	}
1900
	
1901
	$mpdconf .= <<<EOD
1902
	new -i {$realif} pppoeclient pppoeclient
1903

    
1904
EOD;
1905
	if ($interface == "wan")
1906
		$mpdconf .= <<<EOD
1907
	set iface route default
1908

    
1909
EOD;
1910
	
1911
	$mpdconf .= <<<EOD
1912
	set iface {$ondemand} on-demand
1913
	set iface idle {$idle}
1914
	set iface enable tcpmssfix
1915
	set iface up-script /usr/local/sbin/ppp-linkup
1916
	set iface down-script /usr/local/sbin/ppp-linkdown
1917

    
1918
EOD;
1919

    
1920
	if (isset($wancfg['ondemand'])) {
1921
		if (isset($wancfg['local-ip']) && isset($wancfg['remote-ip'])) {
1922
			$mpdconf .= <<<EOD
1923
	set iface addrs {$wancfg['local-ip']} {$wancfg['remote-ip']}
1924

    
1925
EOD;
1926
		} else {
1927
			$mpdconf .= <<<EOD
1928
	set iface addrs 192.0.2.112 192.0.2.113
1929

    
1930
EOD;
1931
		}
1932
	}
1933

    
1934
	$mpdconf .= <<<EOD
1935
	set bundle disable multilink
1936
	set auth authname "{$wancfg['pppoe_username']}"
1937
	set auth password "{$wancfg['pppoe_password']}"
1938
	set link keep-alive 10 60
1939
	set link max-redial 0
1940
	set link no acfcomp protocomp
1941
	set link disable pap chap
1942
	set link accept chap
1943
	
1944
EOD;
1945
	if (empty($wancfg['mtu']))
1946
		$mpdmtu = "1492";
1947
	else 
1948
		$mpdmtu = "{$wancfg['mtu']}";
1949

    
1950
	$mpdconf .= <<<EOD
1951
	set link mtu {$mpdmtu}
1952
	set ipcp yes vjcomp
1953
	set ipcp ranges 0.0.0.0/0 0.0.0.0/0
1954

    
1955
EOD;
1956

    
1957
	if (isset($config['system']['dnsallowoverride'])) {
1958
		$mpdconf .= <<<EOD
1959
	set ipcp enable req-pri-dns
1960

    
1961
EOD;
1962
	}
1963

    
1964
	if (!isset($wancfg['dnsnosec']) && isset($config['system']['dnsallowoverride'])) {
1965
			$mpdconf .= <<<EOD
1966
	set ipcp enable req-sec-dns
1967

    
1968
EOD;
1969
	}
1970
	
1971
	$mpdconf .= <<<EOD
1972
	open
1973

    
1974
EOD;
1975

    
1976
	fwrite($fd, $mpdconf);
1977
	fclose($fd);
1978

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

    
1986
	$mpdconf = <<<EOD
1987
pppoeclient:
1988
	set link type pppoe
1989
	set pppoe iface {$wancfg['if']}
1990
	set pppoe service "{$wancfg['provider']}"
1991
	set pppoe enable originate
1992
	set pppoe disable incoming
1993

    
1994
EOD;
1995

    
1996
	fwrite($fd, $mpdconf);
1997
	fclose($fd);
1998

    
1999
	if(file_exists("{$g['varrun_path']}/pppoe_{$interface}.pid") and $g['booting']) {
2000
		/* if we are booting and mpd has already been started then don't start again. */
2001
	} else {
2002
		/* if mpd is active, lets take it down */
2003
		if(file_exists("{$g['varrun_path']}/pppoe_{$interface}.pid")) {
2004
			killbypid("{$g['varrun_path']}/pppoe_{$interface}.pid");
2005
			sleep(3);
2006
		}
2007

    
2008
		/* Bring the parent interface up */
2009
		if($wancfg['if'])
2010
			interfaces_bring_up($wancfg['if']);
2011
		else 
2012
			log_error("Could not bring wancfg['if'] up in interface_pppoe_configure()");
2013

    
2014
		/* fire up mpd */
2015
		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");
2016
	}
2017

    
2018
	/* sleep until wan is up - or 30 seconds, whichever comes first */
2019
	for ($count = 0; $count < 30; $count++) {
2020
		if(file_exists("{$g['tmp_path']}/{$realif}up")) {
2021
			break;
2022
		}
2023
		sleep(1);
2024
	}
2025

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

    
2028
	return 0;
2029
}
2030

    
2031
function interface_pptp_configure($interface) {
2032
	global $config, $g;
2033

    
2034
	$wancfg = $config['interfaces'][$interface];
2035

    
2036
	/* generate mpd.conf */
2037
	$fd = fopen("{$g['varetc_path']}/mpd_{$interface}.conf", "w");
2038
	if (!$fd) {
2039
		printf("Error: cannot open mpd_{$interface}.conf in interface_pptp_configure().\n");
2040
		return 1;
2041
	}
2042

    
2043
	$idle = 0;
2044

    
2045
	if (isset($wancfg['ondemand'])) {
2046
		$ondemand = "enable";
2047
		if ($wancfg['timeout'])
2048
			$idle = $wancfg['timeout'];
2049
	} else {
2050
		$ondemand = "disable";
2051
	}
2052

    
2053
	$mpdconf = <<<EOD
2054
startup:
2055
pptp:
2056

    
2057
EOD;
2058

    
2059
        if ($interface == "wan")
2060
                $realif = "pptp0";
2061
        else {
2062
                // Here code assumes only that strings of form "opt#" will be passed.
2063
                $realif = "pptp" . substr($interface, 3);
2064
	}
2065

    
2066
        $mpdconf .= <<<EOD
2067
        new -i {$realif} pptp pptp 
2068

    
2069
EOD;
2070
        if ($interface == "wan")
2071
                $mpdconf .= <<<EOD
2072
        set iface route default
2073

    
2074
EOD;
2075

    
2076
        $mpdconf .= <<<EOD
2077
	set iface {$ondemand} on-demand
2078
	set iface idle {$idle}
2079
	set iface up-script /usr/local/sbin/ppp-linkup
2080
	set iface down-script /usr/local/sbin/ppp-linkdown
2081

    
2082
EOD;
2083

    
2084
	if (isset($wanfg['ondemand'])) {
2085
		$mpdconf .= <<<EOD
2086
	set iface addrs 10.0.0.1 10.0.0.2
2087

    
2088
EOD;
2089
	}
2090

    
2091
	$mpdconf .= <<<EOD
2092
	set bundle disable multilink
2093
	set auth authname "{$wancfg['pptp_username']}"
2094
	set auth password "{$wancfg['pptp_password']}"
2095
	set bundle no noretry
2096
	set link keep-alive 10 60
2097
	set link max-redial 0
2098
	set link no acfcomp protocomp
2099
	set link disable pap chap
2100
	set link accept chap
2101
	set ipcp no vjcomp
2102
	set ipcp ranges 0.0.0.0/0 0.0.0.0/0
2103

    
2104
EOD;
2105
	if (isset($config['system']['dnsallowoverride'])) {
2106
		$mpdconf .= <<<EOD
2107
	set ipcp enable req-pri-dns
2108

    
2109
EOD;
2110
	}
2111

    
2112
	$mpdconf .= <<<EOD
2113
	open
2114

    
2115
EOD;
2116

    
2117
	fwrite($fd, $mpdconf);
2118
	fclose($fd);
2119

    
2120
	/* generate mpd.links */
2121
	$fd = fopen("{$g['varetc_path']}/mpd_{$interface}.links", "w");
2122
	if (!$fd) {
2123
		printf("Error: cannot open mpd_{$interface}.links in interface_pptp_configure().\n");
2124
		return 1;
2125
	}
2126

    
2127
	$mpdconf = <<<EOD
2128
pptp:
2129
	set link type pptp
2130
	set pptp enable originate outcall
2131
	set pptp disable windowing
2132
	set pptp self {$wancfg['local']}
2133
	set pptp peer {$wancfg['remote']}
2134

    
2135
EOD;
2136

    
2137
	fwrite($fd, $mpdconf);
2138
	fclose($fd);
2139

    
2140
	/* configure interface */
2141
	if($wancfg['if'])
2142
		mwexec("/sbin/ifconfig " . escapeshellarg($wancfg['if']) . " " .
2143
			escapeshellarg($wancfg['local'] . "/" . $wancfg['subnet']) . " up");
2144
	else 
2145
		log_error("Could not bring interface wancfg['if'] up in interface_pptp_configure()");
2146
	/* fire up mpd */
2147
	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");
2148

    
2149
	return 0;
2150
}
2151

    
2152
function interfaces_group_setup() {
2153
	global $config;
2154

    
2155
	if (!is_array($config['ifgroups']['ifgroupentry']))
2156
		return;
2157

    
2158
	foreach ($config['ifgroups']['ifgroupentry'] as $groupar)
2159
		interface_group_setup($groupar);
2160

    
2161
	return;
2162
}
2163

    
2164
function interface_group_setup(&$groupname /* The parameter is an array */) {
2165
	global $config;
2166

    
2167
	if (!is_array($groupname))
2168
		return;
2169
	$members = explode(" ", $groupname['members']);
2170
	foreach($members as $ifs) {
2171
		$realif = get_real_interface($ifs);
2172
		if ($realif)
2173
			mwexec("/sbin/ifconfig {$realif} group {$groupname['ifname']}");
2174
	}
2175

    
2176
	return;
2177
}
2178
 
2179
/* COMPAT Function */
2180
function convert_friendly_interface_to_real_interface_name($interface) {
2181
	return get_real_interface($interface);
2182
}
2183

    
2184
/* COMPAT Function */
2185
function get_real_wan_interface($interface = "wan") {
2186
	return get_real_interface($interface);
2187
}
2188

    
2189
/* COMPAT Function */
2190
function get_current_wan_address($interface = "wan") {
2191
	return get_interface_ip($interface);
2192
}
2193

    
2194
/*
2195
 * convert_real_interface_to_friendly_interface_name($interface): convert fxp0 -> wan, etc.
2196
 */
2197
function convert_real_interface_to_friendly_interface_name($interface = "wan") {
2198
        global $config;
2199

    
2200
        if (stristr($interface, "pppoe")) {
2201
                $index = substr($interface, 5);
2202
                if (intval($index) > 0)
2203
                        return "opt{$index}";
2204
                else
2205
                        return "wan";
2206
        } else if (stristr($interface, "pptp")) {
2207
                $index = substr($interface, 4);
2208
                if (intval($index) > 0)
2209
                        return "opt{$index}";
2210
                else
2211
                        return "wan";
2212
	} else if (stristr($interface, "vip")) {
2213
                $index = substr($interface, 3);
2214
                $counter = 0;
2215
                foreach ($config['virtualip']['vip'] as $vip) {
2216
                        if ($vip['mode'] == "carpdev-dhcp" || $vip['mode'] == "carp")  {
2217
                                if (intval($index) == $counter)
2218
                                        return $vip['interface'];
2219
                                $counter++;
2220
                        }
2221
                }
2222
        } else if (stristr($interface, "carp")) {
2223
                $index = substr($interface, 4);
2224
                $counter = 0;
2225
                foreach ($config['virtualip']['vip'] as $vip) {
2226
                        if ($vip['mode'] == "carpdev-dhcp" || $vip['mode'] == "carp")  {
2227
                                if (intval($index) == $counter)
2228
                                        return $vip['interface'];
2229
                                $counter++;
2230
                        }
2231
                }
2232
        }
2233

    
2234
        /* if list */
2235
        $ifdescrs = get_configured_interface_list(false, true);
2236

    
2237
        foreach ($ifdescrs as $if => $ifname) {
2238
                if($config['interfaces'][$if]['if'] == $interface)
2239
                        return $ifname;
2240

    
2241
                /* XXX: ermal - The 3 lines below are totally bogus code. */
2242
                $int = interface_translate_type_to_real($if);
2243
                if($ifname == $interface)
2244
                        return $ifname;
2245

    
2246
                if($int == $interface)
2247
                        return $ifname;
2248
        }
2249
        return NULL;
2250
}
2251

    
2252
/* attempt to resolve interface to friendly descr */
2253
function convert_friendly_interface_to_friendly_descr($interface) {
2254
        global $config;
2255

    
2256
        switch ($interface) {
2257
                case "l2tp":
2258
                                $ifdesc = "L2TP";
2259
                                break;
2260
                case "pptp":
2261
                                $ifdesc = "pptp";
2262
                                break;
2263
                case "pppoe":
2264
                                $ifdesc = "pppoe";
2265
                                break;
2266
                case "openvpn":
2267
                                $ifdesc = "OpenVPN";
2268
                                break;
2269
                case "enc0":
2270
                        case "ipsec":
2271
                                $ifdesc = "IPsec";
2272
                                break;
2273
        default:
2274
                /* if list */
2275
                $ifdescrs = get_configured_interface_with_descr(false, true);
2276
                foreach ($ifdescrs as $if => $ifname) {
2277
                                if ($if == $interface || $ifname == $interface)
2278
                                        return $ifname;
2279
                }
2280
                break;
2281
        }
2282

    
2283
        return $ifdesc;
2284
}
2285

    
2286
function convert_real_interface_to_friendly_descr($interface) {
2287
        global $config;
2288

    
2289
        $ifdesc = convert_real_interface_to_friendly_interface_name("{$interface}");
2290

    
2291
        if ($ifdesc) {
2292
                $iflist = get_configured_interface_with_descr(false, true);
2293
                return $iflist[$ifdesc];
2294
        }
2295

    
2296
        return $interface;
2297
}
2298

    
2299
/*
2300
 *  interface_translate_type_to_real($interface):
2301
 *              returns the real hardware interface name for a friendly interface.  ie: wan
2302
 */
2303
function interface_translate_type_to_real($interface) {
2304
        global $config;
2305

    
2306
        if ($config['interfaces'][$interface]['if'] <> "")
2307
                return $config['interfaces'][$interface]['if'];
2308
        else
2309
		return $interface;
2310
}
2311

    
2312
function get_real_interface($interface = "wan") {
2313
    global $config;
2314

    
2315
	$wanif = NULL;
2316

    
2317
	switch ($interface) {
2318
	case "l2tp":
2319
		$wanif = "l2tp";
2320
		break;
2321
	case "pptp":
2322
		$wanif = "pptp";
2323
		break;
2324
	case "pppoe":
2325
		$wanif = "pppoe";
2326
		break;
2327
	case "openvpn":
2328
		$wanif = "openvpn";
2329
		break;
2330
	case "ipsec":
2331
	case "enc0":
2332
		$wanif = "enc0";
2333
		break;
2334
	case "ppp":
2335
		$wanif = "ppp";
2336
		break;
2337
	default:
2338
		$iflist = get_configured_interface_with_descr(false, true);
2339

    
2340
		foreach ($iflist as $if => $ifdesc) {
2341
			// If a real interface was alread passed simply
2342
			// pass the real interface back.  This encourages
2343
			// the usage of this function in more cases so that
2344
			// we can combine logic for more flexibility.
2345
			if($config['interfaces'][$if]['if'] == $interface) {
2346
				if(does_interface_exist($interface)) {
2347
					$wanif = $interface;
2348
					break;
2349
				}
2350
			}
2351

    
2352
			if ($interface == $if || $interface == $ifdesc) {
2353

    
2354
			// PPP Support
2355
			if($config['interfaces'][$if]['serialport']) {
2356
				$dev = $config['interfaces'][$if]['serialport'];
2357
				if(file_exists("/var/run/{$dev}.if")) {
2358
					$wanif = trim(file_get_contents("/var/run/{$dev}.if"));
2359
				} else
2360
					$wanif = "Not connected";
2361

    
2362
				break;
2363
			}
2364

    
2365
			$cfg = $config['interfaces'][$if];
2366

    
2367
			// Wireless cloned NIC support (FreeBSD 8+)
2368
			// interface name format: $parentnic_wlanparentnic#
2369
			// example: ath0_wlan0
2370
			if(is_interface_wireless($interface)) {
2371
				$interface_num = substr($cfg['if'], 3);
2372
				$wanif = $cfg['if'] . "_wlan" . $interface_num;
2373
				break;
2374
			}
2375

    
2376
			if (empty($cfg['ipaddr'])) {
2377
				$wanif = $cfg['if'];
2378
				break;
2379
			}
2380

    
2381
			switch ($cfg['ipaddr']) {
2382
				case "carpdev-dhcp":
2383
					$viparr = &$config['virtualip']['vip'];
2384
					$counter = 0;
2385
					if(is_array($viparr))
2386
					foreach ($viparr as $vip) {
2387
						if ($vip['mode'] == "carpdev-dhcp") {
2388
							if($vip['interface'] == $if) {
2389
								$wanif =  "carp{$counter}";
2390
								break;
2391
							}
2392
							$counter++;
2393
						} else if ($vip['mode'] = "carp") 
2394
							$counter++;
2395
					}
2396
					break;
2397
				case "pppoe": 
2398
					if ($if == "wan")
2399
						$wanif = "pppoe0";
2400
					else
2401
						$wanif = "pppoe" . substr($if,3);
2402
					break;
2403
				case "pptp": 
2404
					if ($if == "wan")
2405
						$wanif = "pptp0";
2406
					else
2407
						$wanif = "pptp" . substr($if, 3);
2408
					break;
2409
				default:
2410
					$wanif = $cfg['if'];
2411
					break;
2412
				}
2413
			
2414
				break;
2415
			}
2416
		}
2417
		break;
2418
	}
2419

    
2420
    return $wanif;
2421
}
2422

    
2423
/* Guess the physical interface by providing a IP address */
2424
function guess_interface_from_ip($ipaddress) {
2425
	if(! is_ipaddr($ipaddress)) {
2426
		return false;
2427
	}
2428
	/* create a route table we can search */
2429
	exec("netstat -rn", $output, $ret);
2430
	foreach($output as $line) {
2431
		if(preg_match("/^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\/[0-9]+[ ]+link[#]/", $line)) {
2432
			$fields = preg_split("/[ ]+/", $line);
2433
			if(ip_in_subnet($ipaddress, $fields[0])) {
2434
				return $fields[5];
2435
			}
2436
		}
2437
	}
2438
	$ret = exec_command("/sbin/route -n get {$ipaddress} | /usr/bin/awk '/interface/ { print \$2; };'");
2439
	if(empty($ret)) {
2440
        	return false;
2441
	}
2442
	return $ret;
2443
}
2444

    
2445
/*
2446
 * find_ip_interface($ip): return the interface where an ip is defined
2447
 */
2448
function find_ip_interface($ip)
2449
{
2450
        /* if list */
2451
        $ifdescrs = get_configured_interface_list();
2452

    
2453
        foreach ($ifdescrs as $ifdescr => $ifname) {
2454
		if ($ip == get_interface_ip($ifname)) {
2455
                	$int = get_real_interface($ifname);
2456
			return $int;
2457
		}
2458
        }
2459
        return false;
2460
}
2461

    
2462
/*
2463
 *   find_number_of_created_carp_interfaces: return the number of carp interfaces
2464
 */
2465
function find_number_of_created_carp_interfaces() {
2466
	return `/sbin/ifconfig | grep "carp:" | wc -l`;
2467
}
2468

    
2469
function get_all_carp_interfaces() {
2470
	$ints = str_replace("\n", " ", `ifconfig | grep "carp:" -B2 | grep ": flag" | cut -d: -f1`);
2471
	return $ints;
2472
}
2473

    
2474
/*
2475
 * find_carp_interface($ip): return the carp interface where an ip is defined
2476
 */
2477
function find_carp_interface($ip) {
2478
	global $config;
2479
	if (is_array($config['virtualip']['vip'])) {
2480
		foreach ($config['virtualip']['vip'] as $vip) {
2481
			if ($vip['mode'] == "carp" || $vip['mode'] == "carpdev") {
2482
				$carp_ip = get_interface_ip($vip['interface']);
2483
				$if = `ifconfig | grep '$ip' -B1 | head -n1 | cut -d: -f1`;
2484
				if ($if)
2485
					return $if;
2486
			}
2487
		}
2488
	}
2489
}
2490

    
2491
function link_carp_interface_to_parent($interface) {
2492
        global $config;
2493

    
2494
        if ($interface == "")
2495
                return;
2496

    
2497
        $carp_ip = get_interface_ip($interface);
2498
        if (!is_ipaddr($carp_ip))
2499
                return;
2500

    
2501
        /* if list */
2502
        $ifdescrs = get_configured_interface_list();
2503
        foreach ($ifdescrs as $ifdescr => $ifname) {
2504
                $interfaceip = get_interface_ip($ifname);
2505
                $subnet_bits = get_interface_subnet($ifname);
2506
                $subnet_ip = gen_subnet("{$interfaceip}", "{$subnet_bits}");
2507
                if(ip_in_subnet($carp_ip, "{$subnet_ip}/{$subnet_bits}"))
2508
                        return $ifname;
2509
        }
2510

    
2511
        return "";
2512
}
2513

    
2514
/****f* interfaces/link_ip_to_carp_interface
2515
 * NAME
2516
 *   link_ip_to_carp_interface - Find where a CARP interface links to.
2517
 * INPUTS
2518
 *   $ip
2519
 * RESULT
2520
 *   $carp_ints
2521
 ******/
2522
function link_ip_to_carp_interface($ip) {
2523
        global $config;
2524

    
2525
        if (!is_ipaddr($ip))
2526
                return;
2527

    
2528
        $carp_ints = "";
2529
        if (is_array($config['virtualip']['vip'])) {
2530
                foreach ($config['virtualip']['vip'] as $vip) {
2531
                        if ($vip['mode'] == "carp" || $vip['mode'] == "carpdev") {
2532
                                $carp_ip = $vip['subnet'];
2533
                                $carp_sn = $vip['subnet_bits'];
2534
                                $carp_nw = gen_subnet($carp_ip, $carp_sn);
2535
                                if (ip_in_subnet($ip, "{$carp_nw}/{$carp_sn}")) {
2536
                                        if (!stristr($carp_ints, $carp_int))
2537
                                                $carp_ints .= " {$carp_int}";
2538
                                }
2539
                        }
2540
                }
2541
        }
2542

    
2543
        return $carp_ints;
2544
}
2545

    
2546
function link_interface_to_vlans($int, $action = "") {
2547
	global $config;
2548

    
2549
	if (empty($int))
2550
		return;
2551

    
2552
	$real_if = get_real_interface($int);
2553
	if (is_array($config['vlans']['vlan'])) {
2554
                foreach ($config['vlans']['vlan'] as $vlan) {
2555
			if ($real_int == $vlan['if']) {
2556
				if ($action == "update") {
2557
					foreach ($config['interfaces'] as $ifname => $ifcfg) {
2558
						if ($ifcfg['if'] == $vlan['vlanif'])
2559
							interface_vlan_configure($vlan);
2560
							interface_configure($ifname);
2561
					}
2562
				} else if ($action == "")
2563
					return $vlan;
2564
			}
2565
		}
2566
	}
2567
}
2568

    
2569
function link_interface_to_vips($int, $action = "") {
2570
        global $config;
2571

    
2572
        if (is_array($config['virtualip']['vip']))
2573
                foreach ($config['virtualip']['vip'] as $vip)
2574
                        if ($int == $vip['interface']) {
2575
				if ($action == "update")
2576
					interfaces_vips_configure($int);
2577
				else
2578
                                	return $vip;
2579
			}
2580
}
2581

    
2582
/****f* interfaces/link_interface_to_bridge
2583
 * NAME
2584
 *   link_interface_to_bridge - Finds out a bridge group for an interface
2585
 * INPUTS
2586
 *   $ip
2587
 * RESULT
2588
 *   bridge[0-99]
2589
 ******/
2590
function link_interface_to_bridge($int) {
2591
        global $config;
2592

    
2593
        if (is_array($config['bridges']['bridged']))
2594
                foreach ($config['bridges']['bridged'] as $bridge)
2595
                        if(stristr($bridge['members'], "{$int}"))
2596
                                return "{$bridge['bridgeif']}";
2597
}
2598

    
2599
function link_interface_to_gre($interface) {
2600
        global $config;
2601

    
2602
        if (is_array($config['gres']['gre']))
2603
                foreach ($config['gres']['gre'] as $gre)
2604
                        if($gre['if'] == $interface)
2605
                                return "{$gre['greif']}";
2606
}
2607

    
2608
function link_interface_to_gif($interface) {
2609
        global $config;
2610

    
2611
        if (is_array($config['gifs']['gif']))
2612
                foreach ($config['gifs']['gif'] as $gif)
2613
                        if($gif['if'] == $interface)
2614
                                return "{$gif['gifif']}";
2615
}
2616

    
2617
/*
2618
 * find_interface_ip($interface): return the interface ip (first found)
2619
 */
2620
function find_interface_ip($interface, $flush = false)
2621
{
2622
	global $interface_ip_arr_cache;
2623

    
2624
	$interface = str_replace("\n", "", $interface);
2625
	
2626
	if (does_interface_exist($interface) == false)
2627
		return;
2628

    
2629
	/* Setup IP cache */
2630
	if (!isset($interface_ip_arr_cache[$interface]) or $flush) {
2631
		$interface_ip_arr_cache[$interface] = `/sbin/ifconfig {$interface} | /usr/bin/grep -w "inet" | /usr/bin/cut -d" " -f 2| /usr/bin/head -1`;
2632
		$interface_ip_arr_cache[$interface] = str_replace("\n", "", $interface_ip_arr_cache[$interface]);
2633
	}
2634

    
2635
	return $interface_ip_arr_cache[$interface];
2636
}
2637

    
2638
function find_interface_subnet($interface, $flush = false)
2639
{
2640
	global $interface_sn_arr_cache;
2641

    
2642
	$interface = str_replace("\n", "", $interface);
2643
	if (does_interface_exist($interface) == false)
2644
		return;
2645

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

    
2651
	return $interface_sn_arr_cache[$interface];
2652
}
2653

    
2654
function get_interface_ip($interface = "wan")
2655
{
2656
	$realif = get_real_interface($interface);
2657
	if (!$realif) {
2658
		if (preg_match("/^carp/i", $interface))
2659
			$realif = $interface;
2660
		else if (preg_match("/^vip/i", $interface))
2661
			$realif = $interface;
2662
		else
2663
			return null;
2664
	}
2665

    
2666
	/* Do we really come here for these interfaces ?! */
2667
	if (in_array($realif, array("pptp", "pppoe", "l2tp", "openvpn", "enc0" /* , "ppp" */)))
2668
			return "";
2669

    
2670
	$curip = find_interface_ip($realif);
2671
	if ($curip && is_ipaddr($curip) && ($curip != "0.0.0.0"))
2672
		return $curip;
2673

    
2674
	return null;
2675
}
2676

    
2677
function get_interface_subnet($interface = "wan")
2678
{
2679
	$realif = get_real_interface($interface);
2680
	if (!$realif) {
2681
                if (preg_match("/^carp/i", $interface))
2682
                        $realif = $interface;
2683
                else if (preg_match("/^vip/i", $interface))
2684
                        $realif = $interface;
2685
                else
2686
                        return null;
2687
        }
2688

    
2689
	/* Do we really come here for these interfaces ?! */
2690
	if (in_array($realif, array("pptp", "pppoe", "l2tp", "openvpn", "enc0" /* , "ppp" */)))
2691
		return "";
2692

    
2693
	$cursn = find_interface_subnet($realif);
2694
	if (!empty($cursn))
2695
		return $cursn;
2696

    
2697
	return null;
2698
}
2699

    
2700
/* return outside interfaces with a gateway */
2701
function get_interfaces_with_gateway() {
2702
	global $config;
2703

    
2704
	$ints = array();
2705

    
2706
	/* loop interfaces, check config for outbound */
2707
	foreach($config['interfaces'] as $ifdescr => $ifname) {
2708
		if($ifname['serialport']) {
2709
			$ints[] = $ifdescr;
2710
			continue;
2711
		}
2712
		switch ($ifname['ipaddr']) {
2713
			case "dhcp":
2714
			case "carpdev-dhcp":
2715
			case "pppoe":
2716
			case "pptp":
2717
			$ints[] = $ifdescr;
2718
			break;
2719
			default:
2720
			if ($ifname['pointtopoint'])
2721
				$ints[] = $ifdescr;
2722
			else if (!empty($ifname['gateway']))
2723
				$ints[] = $ifdescr;
2724
			break;
2725
		}
2726
	}
2727
	return $ints;
2728
}
2729

    
2730
/* return true if interface has a gateway */
2731
function interface_has_gateway($friendly) {
2732

    
2733
        $friendly = strtolower($friendly);
2734
        if (in_array($friendly, get_interfaces_with_gateway()))
2735
                return true;
2736

    
2737
	return false;
2738
}
2739

    
2740
/****f* interfaces/is_altq_capable
2741
 * NAME
2742
 *   is_altq_capable - Test if interface is capable of using ALTQ
2743
 * INPUTS
2744
 *   $int            - string containing interface name
2745
 * RESULT
2746
 *   boolean         - true or false
2747
 ******/
2748

    
2749
function is_altq_capable($int) {
2750
        /* Per:
2751
         * http://www.freebsd.org/cgi/man.cgi?query=altq&manpath=FreeBSD+7.2-current&format=html
2752
         * Only the following drivers have ALTQ support
2753
         */
2754
	$capable = array("age", "ale", "an", "ath", "aue", "awi", "bce",
2755
			"bfe", "bge", "dc", "de", "ed", "em", "ep", "fxp", "gem",
2756
			"hme", "ipw", "iwi", "jme", "le", "msk", "mxge", "my", "nfe",
2757
			"npe", "nve", "ral", "re", "rl", "rum", "sf", "sis", "sk",
2758
			"ste", "stge", "txp", "udav", "ural", "vge", "vr", "wi", "xl",
2759
			"ndis", "tun", "vlan", "pppoe", "pptp", "ng", "ppp");
2760

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

    
2763
        if (in_array($int_family[0], $capable))
2764
                return true;
2765
	else if (stristr($int_family, "vlan")) /* VLANs are name $parent.$vlan now */
2766
		return true;
2767
        else
2768
                return false;
2769
}
2770

    
2771
/****f* interfaces/is_interface_wireless
2772
 * NAME
2773
 *   is_interface_wireless - Returns if an interface is wireless
2774
 * RESULT
2775
 *   $tmp       - Returns if an interface is wireless
2776
 ******/
2777
function is_interface_wireless($interface) {
2778
        global $config, $g;
2779

    
2780
        $friendly = convert_real_interface_to_friendly_interface_name($interface);
2781
        if(!isset($config['interfaces'][$friendly]['wireless'])) {
2782
                if (preg_match($g['wireless_regex'], $interface)) {
2783
                        $config['interfaces'][$friendly]['wireless'] = array();
2784
                        return true;
2785
                }
2786
                unset($config['interfaces'][$friendly]['wireless']);
2787
                return false;
2788
        } else
2789
                return true;
2790
}
2791

    
2792
function get_wireless_modes($interface) {
2793
	/* return wireless modes and channels */
2794
	$wireless_modes = array();
2795

    
2796
	if(is_interface_wireless($interface)) {
2797
		$cloned_interface = get_real_interface($interface);
2798
		$wi = 1;
2799
		$ifconfig = "/sbin/ifconfig";
2800
		$awk = "/usr/bin/awk";
2801
		$chan_list = "$ifconfig $cloned_interface list chan";
2802
		$stack_list = "$awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
2803
		$format_list = "$awk '{print \$5 \" \" \$6 \",\" \$1}'";
2804

    
2805
		$interface_channels = "";
2806
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
2807
		$interface_channel_count = count($interface_channels);
2808

    
2809
		$c = 0;
2810
		while ($c < $interface_channel_count)
2811
		{
2812
			$channel_line = explode(",", $interface_channels["$c"]);
2813
			$wireless_mode = trim($channel_line[0]);
2814
			$wireless_channel = trim($channel_line[1]);
2815
			if(trim($wireless_mode) != "") {
2816
				/* if we only have 11g also set 11b channels */
2817
				if($wireless_mode == "11g") {
2818
					$wireless_modes["11b"] = array();
2819
				}
2820
				$wireless_modes["$wireless_mode"]["$c"] = $wireless_channel;
2821
			}
2822
			$c++;
2823
		}
2824
	}
2825
	return($wireless_modes);
2826
}
2827

    
2828
/****f* interfaces/get_interface_mtu
2829
 * NAME
2830
 *   get_interface_mtu - Return the mtu of an interface
2831
 * RESULT
2832
 *   $tmp       - Returns the mtu of an interface
2833
 ******/
2834
function get_interface_mtu($interface) {
2835
        $mtu = `/sbin/ifconfig {$interface} | /usr/bin/grep mtu | /usr/bin/cut -d" " -f6`;
2836
        return $mtu;
2837
}
2838

    
2839
function get_interface_mac($interface) {
2840
	$mac = array();
2841
        exec("/sbin/ifconfig {$interface} | /usr/bin/awk '/ether/ {print $2}'", $mac);
2842
        if(is_macaddr($mac[0])) {
2843
                return trim($mac[0]);
2844
        } else {
2845
                return "";
2846
        }
2847
}
2848

    
2849
/****f* pfsense-utils/generate_random_mac_address
2850
 * NAME
2851
 *   generate_random_mac - generates a random mac address
2852
 * INPUTS
2853
 *   none
2854
 * RESULT
2855
 *   $mac - a random mac address
2856
 ******/
2857
function generate_random_mac_address() {
2858
        $mac = "02";
2859
        for($x=0; $x<5; $x++)
2860
                $mac .= ":" . dechex(rand(16, 255));
2861
        return $mac;
2862
}
2863

    
2864
/****f* interfaces/is_jumbo_capable
2865
 * NAME
2866
 *   is_jumbo_capable - Test if interface is jumbo frame capable.  Useful for determining VLAN capability.
2867
 * INPUTS
2868
 *   $int             - string containing interface name
2869
 * RESULT
2870
 *   boolean          - true or false
2871
 ******/
2872
function is_jumbo_capable($int) {
2873
        global $g;
2874

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

    
2877
        if (in_array($int_family[0], $g['vlan_long_frame']))
2878
                return true;
2879
        else
2880
                return false;
2881
}
2882

    
2883
function setup_pppoe_reset_file($interface, $status) {
2884
	define("CRON_PPPOE_CMD_FILE", "/conf/pppoe{$interface}restart");
2885
	define("CRON_PPPOE_CMD", "#!/bin/sh\necho '<?php require(\"config.inc\"); require(\"interfaces.inc\"); interface_reconfigure({$interface}); ?>' | /usr/local/bin/php -q");
2886
	if ($status == true) {
2887
		if (!file_exists(CRON_PPPOE_CMD_FILE)) {
2888
			file_put_contents(CRON_PPPOE_CMD_FILE, CRON_PPPOE_CMD);
2889
			chmod(CRON_PPPOE_CMD_FILE, 0700);
2890
		}	
2891
	} else
2892
		unlink_if_exists(CRON_PPPOE_CMD_FILE);
2893
}
2894

    
2895
?>
(21-21/50)