Project

General

Profile

Download (82.7 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(false);
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
	mwexec("/usr/sbin/arp -d -i {$realif} -a");
782

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

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

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

    
832
	return;
833
}
834

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

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

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

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

    
885
 	   	if (is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) {
886
			foreach ($config['ppps']['ppp'] as $ppp) {
887
				$dev = substr($ppp['port'], 5);
888
				$realif  = $ppp['port'];
889
				$peerfile .= "{$dev}:\n";
890
				$peerfile .= " set device {$realif}\n";
891
				if($ppp['dialcmd']) {
892
					$peerfile .= " set dial {$ppp['dialcmd']}\n";
893
				} else
894
					$peerfile .= " set dial \"\"\n";
895
				$peerfile .= " set speed \"{$ppp['linespeed']}\"\n";
896
				$peerfile .= " add default HISADDR\n";
897
				$peerfile .= " set timeout 0\n";
898
				$peerfile .= " enable dns\n";
899
				$endingip = $startingip+1;
900
				if($ppp['localip'] && $ppp['gateway'])
901
					$peerfile .= " set ifaddr {$ppp['localip']}/0 {$ppp['gateway']}/0 255.255.255.0 0.0.0.0\n";
902
				if(!$ppp['localip'] && $ppp['gateway'])
903
					$peerfile .= " set ifaddr 10.0.0.{$startingip}/0 {$ppp['gateway']}/0 255.255.255.0 0.0.0.0\n";
904
				if($ppp['localip'] and !$ppp['gateway'])
905
					$peerfile .= " set ifaddr {$ppp['localip']}/0 10.0.0.{$endingip}/0 255.255.255.0 0.0.0.0\n";
906
				if(!$ppp['localip'] and !$ppp['gateway'])	
907
					$peerfile .= " set ifaddr 10.0.0.{$startingip}/0 10.0.0.{$endingip}/0 255.255.255.0 0.0.0.0\n";
908
				$peerfile .= " set phone \"{$ppp['phone']}\"\n";
909
				$peerfile .= " set authname \"{$ppp['username']}\"\n";
910
				$peerfile .= " set authkey \"{$ppp['password']}\"\n";
911
				// Add a local socket for the daemon so we can query it later
912
				$peerfile .= " set server /var/run/{$dev}.sock \"\" 0177\n";
913
				$peerfile .= "\n";
914
				$i++;
915
				$startingip++;
916
				$rclinkup .= "{$dev}:\n";
917
				$rclinkup .= "	! sh -c \"/etc/rc.conf_mount_rw\"\n";
918
 				$rclinkup .= "	! sh -c \"/bin/echo `date -j +%Y.%m.%d-%H:%M:%S` 00:00:00 >> /conf/ppp-up.{$dev}.log\"\n";
919
				$rclinkup .= "	! sh -c \"/sbin/ppp-script HISADDR INTERFACE DNS0 DNS1\"\n";
920
				$rclinkup .= "	! sh -c \"/etc/rc.linkup INTERFACE start\"\n";
921
				$rclinkup .= "	! sh -c \"/etc/rc.conf_mount_ro\"\n";
922
				$rclinkup.= "	! sh -c \"/etc/rc.filter_configure_sync\"\n";
923
				// Link down file
924
				$rclinkdown .= "{$dev}:\n";
925
				$rclinkdown .= "	! sh -c \"/etc/rc.conf_mount_rw\"\n";
926
				$rclinkdown .= "	! sh -c \"/bin/echo `date -j +%Y.%m.%d-%H:%M:%S` UPTIME >> /conf/ppp-up.{$dev}.log\"\n";
927
				$rclinkdown .= "	! sh -c \"/etc/rc.conf_mount_ro\"\n";
928
			}	
929
    		}
930

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

    
934
		// Write out linkup file
935
		file_put_contents("/etc/ppp/ppp.linkup", $rclinkup);
936
		file_put_contents("/etc/ppp/ppp.linkdown", $rclinkdown);
937
		// Make executable
938
		exec("chmod a+rx /etc/ppp/ppp.linkup");
939
		exec("chmod a+rx /etc/ppp/ppp.linkdown");
940
	}
941
	// Launch specified ppp instance
942
	if( !$edit && file_exists("/dev/{$orig_dev}")){
943
		$running = `ps awux | grep ppp | grep -v grep | grep $orig_dev`;
944
		if(!$running)
945
			mwexec("/usr/sbin/ppp -background {$orig_dev}");
946
	}
947
}
948

    
949
function interface_ppp_bring_down($if) {
950
	if(file_exists("/var/run/{$if}.pid")) {
951
		$pid = trim(file_get_contents("/var/run/{$if}.pid"));
952
		mwexec("kill -QUIT {$pid}");
953
	}
954
}
955

    
956
function interfaces_carp_setup() {
957
	global $g, $config;
958

    
959
	$balanacing = "";
960
	$pfsyncinterface = "";
961
	$pfsyncenabled = "";
962
	if(isset($config['system']['developerspew'])) {
963
		$mt = microtime();
964
		echo "interfaces_carp_setup() being called $mt\n";
965
	}
966

    
967
	// Prepare CmdCHAIN that will be used to execute commands.
968
	$cmdchain = new CmdCHAIN();	
969

    
970
	if ($g['booting']) {
971
		echo "Configuring CARP settings...";
972
		mute_kernel_msgs();
973
	}
974

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

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

    
998
	$cmdchain->add("Enable CARP logging", "/sbin/sysctl net.inet.carp.log=2", true);
999
	if (!empty($pfsyncinterface))
1000
		$carp_sync_int = get_real_interface($pfsyncinterface);
1001

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

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

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

    
1034
	$cmdchain->execute();
1035
	$cmdchain->clear();
1036

    
1037
	if ($g['booting']) {
1038
		unmute_kernel_msgs();
1039
		echo "done.\n";
1040
	}
1041
}
1042

    
1043
function interface_proxyarp_configure() {
1044
	global $config, $g;
1045
	if(isset($config['system']['developerspew'])) {
1046
		$mt = microtime();
1047
		echo "interface_proxyarp_configure() being called $mt\n";
1048
	}
1049

    
1050
	/* kill any running choparp */
1051
	killbyname("choparp");
1052

    
1053
	if (isset($config['virtualip']) && is_array($config['virtualip']['vip'])) {
1054
		$paa = array();
1055

    
1056
		/* group by interface */
1057
		foreach ($config['virtualip']['vip'] as $vipent) {
1058
			if ($vipent['mode'] === "proxyarp") {
1059
				if ($vipent['interface'])
1060
					$proxyif = $vipent['interface'];
1061
				else
1062
					$proxyif = "wan";
1063

    
1064
				if (!is_array($paa[$if]))
1065
					$paa[$proxyif] = array();
1066

    
1067
				$paa[$proxyif][] = $vipent;
1068
			}
1069
	}
1070

    
1071
	if (count($paa))
1072
		foreach ($paa as $paif => $paents) {
1073
			$paaifip = get_interface_ip($paif);
1074
			if (!(is_ipaddr($paaifip)))
1075
				continue;
1076
			$args = get_real_interface($paif) . " auto";
1077
			foreach ($paents as $paent) {
1078

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

    
1089
}
1090

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

    
1136
function interface_ipalias_configure(&$vip) {
1137

    
1138
	if ($vip['mode'] == "ipalias") {
1139
		$if = get_real_interface($vip['interface']);
1140
		mwexec("/sbin/ifconfig " . escapeshellarg($if) . " " . $vip['subnet'] . "/" . escapeshellarg($vip['subnet_bits']) . " alias");
1141
	}
1142
}
1143

    
1144
function interface_reload_carps($cif) {
1145
	global $config;
1146

    
1147
	$carpifs = link_ip_to_carp_interface(find_interface_ip($cif));
1148
	if (empty($carpifs))
1149
		return;
1150

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

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

    
1180
	if ($vip['mode'] != "carp")
1181
		return;
1182

    
1183
	$vip_password = $vip['password'];
1184
	$vip_password = escapeshellarg(addslashes(str_replace(" ", "", $vip_password)));
1185
	if ($vip['password'] != "")
1186
		$password = " pass {$vip_password}";
1187

    
1188
	// set the vip interface to the vhid
1189
	$vipif = "vip{$vip['vhid']}";
1190

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

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

    
1219
	/* invalidate interface cache */
1220
	get_interface_arr(true);
1221

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

    
1231
	/* invalidate interface cache */
1232
	get_interface_arr(true);
1233

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

    
1237
	interfaces_bring_up($vipif);
1238
	
1239
	return $vipif;
1240
}
1241

    
1242
function interface_carpdev_configure(&$vip) {
1243
	global $g;
1244

    
1245
	if ($vip['mode'] != "carpdev-dhcp")
1246
		return;
1247

    
1248
	$vip_password = $vip['password'];
1249
	$vip_password = str_replace(" ", "", $vip_password);
1250
	if($vip['password'] != "")
1251
		$password = " pass \"" . $vip_password . "\"";
1252

    
1253
	log_error("Found carpdev interface {$vip['interface']} on top of interface {$interface}");
1254
	if (empty($vip['interface']))
1255
		return;
1256

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

    
1269
	if (does_interface_exist($vipif)) {
1270
		interface_bring_down($vipif);
1271
	} else {
1272
		$carpdevif = exec("/sbin/ifconfig carp create");
1273
		mwexec("/sbin/ifconfig {$carpdevif} name {$vipif}");
1274
		mwexec("/usr/sbin/ngctl name {$carpdevif}: {$vipif}");
1275
	}
1276

    
1277
	mwexec("/sbin/ifconfig {$vipif} carpdev {$realif} vhid {$vip['vhid']} advskew {$vip['advskew']} {$password}");
1278
	interfaces_bring_up($vipif);
1279

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

    
1289
	/* generate dhclient_wan.conf */
1290
	$fd = fopen("{$g['varetc_path']}/dhclient_{$vipif}.conf", "w");
1291
	if ($fd) {
1292
		$dhclientconf = "";
1293

    
1294
		$dhclientconf .= <<<EOD
1295
interface "{$vipif}" {
1296
timeout 60;
1297
retry 1;
1298
select-timeout 0;
1299
initial-interval 1;
1300
script "/sbin/dhclient-script";
1301
}
1302

    
1303
EOD;
1304

    
1305
		fwrite($fd, $dhclientconf);
1306
		fclose($fd);
1307

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

    
1315
	return $vipif;
1316
}
1317

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

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

    
1378
function interface_wireless_configure($if, &$wl, &$wlcfg) {
1379
	global $config, $g;
1380

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

    
1388
	// Remove script file
1389
	unlink_if_exists("{$g['tmp_path']}/{$if}_setup.sh");
1390

    
1391
	// Clone wireless nic if needed.
1392
	interface_wireless_clone($if, $wl);
1393

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

    
1398
	/* set values for /path/program */
1399
	$hostapd = "/usr/sbin/hostapd";
1400
	$wpa_supplicant = "/usr/sbin/wpa_supplicant";
1401
	$ifconfig = "/sbin/ifconfig";
1402
	$killall = "/usr/bin/killall";
1403

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

    
1406
	$wlcmd = array();
1407
	/* Make sure it's up */
1408
	$wlcmd[] = "up";
1409
	/* Set a/b/g standard */
1410
	$wlcmd[] = "mode " . escapeshellarg($wlcfg['standard']);
1411

    
1412
	/* Set ssid */
1413
	if($wlcfg['ssid'])
1414
		$wlcmd[] = "ssid " .escapeshellarg($wlcfg['ssid']);
1415

    
1416
	/* Set 802.11g protection mode */
1417
	$wlcmd[] = "protmode " . escapeshellarg($wlcfg['protmode']);
1418

    
1419
	/* set wireless channel value */
1420
	if(isset($wlcfg['channel'])) {
1421
		if($wlcfg['channel'] == "0") {
1422
			$wlcmd[] = "channel any";
1423
		} else {
1424
			$wlcmd[] = "channel " . escapeshellarg($wlcfg['channel']);
1425
		}
1426
	}
1427

    
1428
	/* set Distance value */
1429
	if($wlcfg['distance'])
1430
		$distance = escapeshellarg($wlcfg['distance']);
1431

    
1432
	/* Set wireless hostap mode */
1433
	if ($wlcfg['mode'] == "hostap") {
1434
		$wlcmd[] = "mediaopt hostap";
1435
	} else {
1436
		$wlcmd[] = "-mediaopt hostap";
1437
	}
1438

    
1439
	/* Set wireless adhoc mode */
1440
	if ($wlcfg['mode'] == "adhoc") {
1441
		$wlcmd[] = "mediaopt adhoc";
1442
	} else {
1443
		$wlcmd[] = "-mediaopt adhoc";
1444
	}
1445

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

    
1448
	/* handle hide ssid option */
1449
	if(isset($wlcfg['hidessid']['enable'])) {
1450
		$wlcmd[] = "hidessid";
1451
	} else {
1452
		$wlcmd[] = "-hidessid";
1453
	}
1454

    
1455
	/* handle pureg (802.11g) only option */
1456
	if(isset($wlcfg['pureg']['enable'])) {
1457
		$wlcmd[] = "mode 11g pureg";
1458
	} else {
1459
		$wlcmd[] = "-pureg";
1460
	}
1461

    
1462
	/* enable apbridge option */
1463
	if(isset($wlcfg['apbridge']['enable'])) {
1464
		$wlcmd[] = "apbridge";
1465
	} else {
1466
		$wlcmd[] = "-apbridge";
1467
	}
1468

    
1469
	/* handle turbo option */
1470
	if(isset($wlcfg['turbo']['enable'])) {
1471
		$wlcmd[] = "mediaopt turbo";
1472
	} else {
1473
		$wlcmd[] = "-mediaopt turbo";
1474
	}
1475

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

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

    
1513
	/* generate wpa_supplicant/hostap config if wpa is enabled */
1514
	conf_mount_rw();
1515

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

    
1535
				$fd = fopen("{$g['varetc_path']}/wpa_supplicant_{$if}.conf", "w");
1536
				fwrite($fd, "{$wpa}");
1537
				fclose($fd);
1538

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

    
1573
				$fd = fopen("{$g['varetc_path']}/hostapd_{$if}.conf", "w");
1574
				fwrite($fd, "{$wpa}");
1575
				fclose($fd);
1576

    
1577
			}
1578
			mwexec(kill_hostapd("{$if}"));
1579
			break;
1580
		case 'adhoc':
1581
			mwexec(kill_hostapd("{$if}"));
1582
			mwexec(kill_wpasupplicant("{$if}"));
1583
			break;
1584
	}
1585

    
1586
	/*
1587
	 *    all variables are set, lets start up everything
1588
	 */
1589

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

    
1596
	$standard_no_turbo = str_replace(" Turbo", "", $standard);
1597

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

    
1607
	fclose($fd_set);
1608
	conf_mount_ro();
1609

    
1610
	/* configure wireless */
1611
	$wlcmd_args = implode(" ", $wlcmd);
1612
	mwexec("/sbin/ifconfig {$if} $wlcmd_args", false);
1613

    
1614
	
1615
	sleep(1);
1616
	/* execute hostapd and wpa_supplicant if required in shell */
1617
	mwexec("/bin/sh {$g['tmp_path']}/{$if}_setup.sh");
1618

    
1619
	return 0;
1620

    
1621
}
1622

    
1623
function kill_hostapd($interface) {
1624
	return "/bin/ps awwuxx | grep hostapd | grep $interface | awk '{ print \$2 }' | xargs kill\n";
1625
}
1626

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

    
1631
function find_dhclient_process($interface) {
1632
	if($interface)
1633
		$pid = `ps awwwux | grep dhclient | grep -v grep | grep {$interface} | awk '{ print \$2 }'`;
1634
	return $pid;
1635
}
1636

    
1637
function interface_configure($interface = "wan", $reloadall = false) {
1638
	global $config, $g;
1639
	global $interface_sn_arr_cache, $interface_ip_arr_cache;
1640

    
1641
	$wancfg = $config['interfaces'][$interface];
1642

    
1643
	$realif = get_real_interface($interface);
1644

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

    
1651
	/* wireless configuration? */
1652
	if (is_array($wancfg['wireless']))
1653
		interface_wireless_configure($realif, $wancfg, $wancfg['wireless']);
1654

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

    
1674
	/* media */
1675
	if ($wancfg['media'] || $wancfg['mediaopt']) {
1676
		$cmd = "/sbin/ifconfig " . escapeshellarg(get_real_interface($wancfg['if']));
1677
		if ($wancfg['media'])
1678
			$cmd .= " media " . escapeshellarg($wancfg['media']);
1679
		if ($wancfg['mediaopt'])
1680
			$cmd .= " mediaopt " . escapeshellarg($wancfg['mediaopt']);
1681
		mwexec($cmd);
1682
	}
1683

    
1684
	/* invalidate interface/ip/sn cache */
1685
	get_interface_arr(true);
1686
	unset($interface_ip_arr_cache[$realif]);
1687
	unset($interface_sn_arr_cache[$realif]);
1688

    
1689
	switch ($wancfg['ipaddr']) {
1690

    
1691
		case 'carpdev-dhcp':
1692
			interface_carpdev_dhcp_configure($interface);
1693
			break;
1694
		case 'dhcp':
1695
			interface_dhcp_configure($interface);
1696
			break;
1697

    
1698
		case 'pppoe':
1699
			interface_pppoe_configure($interface);
1700
			break;
1701

    
1702
		case 'pptp':
1703
			interface_pptp_configure($interface);
1704
			break;
1705

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

    
1720
			if (is_ipaddr($wancfg['gateway']))
1721
				file_put_contents("{$g['tmp_path']}/{$realif}_router", $wancfg['gateway']);
1722
	}
1723

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

    
1749
		link_interface_to_vips($interface, "update");
1750

    
1751
		if ($interface == "lan")
1752
			/* make new hosts file */
1753
			system_hosts_generate();
1754

    
1755
		if ($reloadall == true) {
1756

    
1757
			/* reconfigure static routes (kernel may have deleted them) */
1758
			system_routing_configure();
1759

    
1760
			/* reload ipsec tunnels */
1761
			vpn_ipsec_configure();
1762

    
1763
			/* update dyndns */
1764
			services_dyndns_configure($interface);
1765

    
1766
			/* force DNS update */
1767
			services_dnsupdate_process($interface);
1768

    
1769
			/* restart dnsmasq */
1770
			services_dnsmasq_configure();
1771

    
1772
			/* reload captive portal */
1773
			captiveportal_configure();
1774

    
1775
			/* set the reload filter dity flag */
1776
			filter_configure();
1777
		}
1778
	}
1779

    
1780
	unmute_kernel_msgs();
1781

    
1782
	return 0;
1783
}
1784

    
1785
function interface_carpdev_dhcp_configure($interface = "wan") {
1786
	global $config, $g;
1787

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

    
1796
	return 0;
1797
}
1798

    
1799
function interface_dhcp_configure($interface = "wan") {
1800
	global $config, $g;
1801

    
1802
	$wancfg = $config['interfaces'][$interface];
1803

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

    
1811
	if ($wancfg['dhcphostname']) {
1812
		$dhclientconf_hostname = "send dhcp-client-identifier \"{$wancfg['dhcphostname']}\";\n";
1813
		$dhclientconf_hostname .= "\tsend host-name \"{$wancfg['dhcphostname']}\";\n";
1814
	} else {
1815
		$dhclientconf_hostname = "";
1816
	}
1817

    
1818
	$wanif = get_real_interface($interface);
1819

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

    
1832
EOD;
1833

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

    
1843
EOD;
1844
}
1845
	fwrite($fd, $dhclientconf);
1846
	fclose($fd);
1847

    
1848
	$realwanif = $wancfg['if'];
1849

    
1850
	/* bring wan interface up before starting dhclient */
1851
	if($realwanif)
1852
		interfaces_bring_up($realwanif);
1853
	else 
1854
		log_error("Could not bring realwanif up in interface_dhcp_configure()");
1855

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

    
1859
	return 0;
1860
}
1861

    
1862
function interface_pppoe_configure($interface = "wan") {
1863
	global $config, $g;
1864

    
1865
	$wancfg = $config['interfaces'][$interface];
1866

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

    
1874
	$idle = 0;
1875

    
1876
	if (isset($wancfg['ondemand'])) {
1877
		$ondemand = "enable";
1878
		if ($wancfg['timeout'])
1879
			$idle = $wancfg['timeout'];
1880
	} else {
1881
		$ondemand = "disable";
1882
	}
1883

    
1884
	$mpdconf = <<<EOD
1885
startup:
1886
pppoeclient:
1887

    
1888
EOD;
1889

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

    
1900
EOD;
1901
	if ($interface == "wan")
1902
		$mpdconf .= <<<EOD
1903
	set iface route default
1904

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

    
1914
EOD;
1915

    
1916
	if (isset($wancfg['ondemand'])) {
1917
		if (isset($wancfg['local-ip']) && isset($wancfg['remote-ip'])) {
1918
			$mpdconf .= <<<EOD
1919
	set iface addrs {$wancfg['local-ip']} {$wancfg['remote-ip']}
1920

    
1921
EOD;
1922
		} else {
1923
			$mpdconf .= <<<EOD
1924
	set iface addrs 192.0.2.112 192.0.2.113
1925

    
1926
EOD;
1927
		}
1928
	}
1929

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

    
1946
	$mpdconf .= <<<EOD
1947
	set link mtu {$mpdmtu}
1948
	set ipcp yes vjcomp
1949
	set ipcp ranges 0.0.0.0/0 0.0.0.0/0
1950

    
1951
EOD;
1952

    
1953
	if (isset($config['system']['dnsallowoverride'])) {
1954
		$mpdconf .= <<<EOD
1955
	set ipcp enable req-pri-dns
1956

    
1957
EOD;
1958
	}
1959

    
1960
	if (!isset($wancfg['dnsnosec']) && isset($config['system']['dnsallowoverride'])) {
1961
			$mpdconf .= <<<EOD
1962
	set ipcp enable req-sec-dns
1963

    
1964
EOD;
1965
	}
1966
	
1967
	$mpdconf .= <<<EOD
1968
	open
1969

    
1970
EOD;
1971

    
1972
	fwrite($fd, $mpdconf);
1973
	fclose($fd);
1974

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

    
1982
	$mpdconf = <<<EOD
1983
pppoeclient:
1984
	set link type pppoe
1985
	set pppoe iface {$wancfg['if']}
1986
	set pppoe service "{$wancfg['provider']}"
1987
	set pppoe enable originate
1988
	set pppoe disable incoming
1989

    
1990
EOD;
1991

    
1992
	fwrite($fd, $mpdconf);
1993
	fclose($fd);
1994

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

    
2004
		/* Bring the parent interface up */
2005
		if($wancfg['if'])
2006
			interfaces_bring_up($wancfg['if']);
2007
		else 
2008
			log_error("Could not bring wancfg['if'] up in interface_pppoe_configure()");
2009

    
2010
		/* fire up mpd */
2011
		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");
2012
	}
2013

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

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

    
2024
	return 0;
2025
}
2026

    
2027
function interface_pptp_configure($interface) {
2028
	global $config, $g;
2029

    
2030
	$wancfg = $config['interfaces'][$interface];
2031

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

    
2039
	$idle = 0;
2040

    
2041
	if (isset($wancfg['ondemand'])) {
2042
		$ondemand = "enable";
2043
		if ($wancfg['timeout'])
2044
			$idle = $wancfg['timeout'];
2045
	} else {
2046
		$ondemand = "disable";
2047
	}
2048

    
2049
	$mpdconf = <<<EOD
2050
startup:
2051
pptp:
2052

    
2053
EOD;
2054

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

    
2062
        $mpdconf .= <<<EOD
2063
        new -i {$realif} pptp pptp 
2064

    
2065
EOD;
2066
        if ($interface == "wan")
2067
                $mpdconf .= <<<EOD
2068
        set iface route default
2069

    
2070
EOD;
2071

    
2072
        $mpdconf .= <<<EOD
2073
	set iface {$ondemand} on-demand
2074
	set iface idle {$idle}
2075
	set iface up-script /usr/local/sbin/ppp-linkup
2076
	set iface down-script /usr/local/sbin/ppp-linkdown
2077

    
2078
EOD;
2079

    
2080
	if (isset($wanfg['ondemand'])) {
2081
		$mpdconf .= <<<EOD
2082
	set iface addrs 10.0.0.1 10.0.0.2
2083

    
2084
EOD;
2085
	}
2086

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

    
2100
EOD;
2101
	if (isset($config['system']['dnsallowoverride'])) {
2102
		$mpdconf .= <<<EOD
2103
	set ipcp enable req-pri-dns
2104

    
2105
EOD;
2106
	}
2107

    
2108
	$mpdconf .= <<<EOD
2109
	open
2110

    
2111
EOD;
2112

    
2113
	fwrite($fd, $mpdconf);
2114
	fclose($fd);
2115

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

    
2123
	$mpdconf = <<<EOD
2124
pptp:
2125
	set link type pptp
2126
	set pptp enable originate outcall
2127
	set pptp disable windowing
2128
	set pptp self {$wancfg['local']}
2129
	set pptp peer {$wancfg['remote']}
2130

    
2131
EOD;
2132

    
2133
	fwrite($fd, $mpdconf);
2134
	fclose($fd);
2135

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

    
2145
	return 0;
2146
}
2147

    
2148
function interfaces_group_setup() {
2149
	global $config;
2150

    
2151
	if (!is_array($config['ifgroups']['ifgroupentry']))
2152
		return;
2153

    
2154
	foreach ($config['ifgroups']['ifgroupentry'] as $groupar)
2155
		interface_group_setup($groupar);
2156

    
2157
	return;
2158
}
2159

    
2160
function interface_group_setup(&$groupname /* The parameter is an array */) {
2161
	global $config;
2162

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

    
2172
	return;
2173
}
2174
 
2175
/* COMPAT Function */
2176
function convert_friendly_interface_to_real_interface_name($interface) {
2177
	return get_real_interface($interface);
2178
}
2179

    
2180
/* COMPAT Function */
2181
function get_real_wan_interface($interface = "wan") {
2182
	return get_real_interface($interface);
2183
}
2184

    
2185
/* COMPAT Function */
2186
function get_current_wan_address($interface = "wan") {
2187
	return get_interface_ip($interface);
2188
}
2189

    
2190
/*
2191
 * convert_real_interface_to_friendly_interface_name($interface): convert fxp0 -> wan, etc.
2192
 */
2193
function convert_real_interface_to_friendly_interface_name($interface = "wan") {
2194
        global $config;
2195

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

    
2230
        /* if list */
2231
        $ifdescrs = get_configured_interface_list(false, true);
2232

    
2233
        foreach ($ifdescrs as $if => $ifname) {
2234
                if($config['interfaces'][$if]['if'] == $interface)
2235
                        return $ifname;
2236

    
2237
                /* XXX: ermal - The 3 lines below are totally bogus code. */
2238
                $int = interface_translate_type_to_real($if);
2239
                if($ifname == $interface)
2240
                        return $ifname;
2241

    
2242
                if($int == $interface)
2243
                        return $ifname;
2244
        }
2245
        return NULL;
2246
}
2247

    
2248
/* attempt to resolve interface to friendly descr */
2249
function convert_friendly_interface_to_friendly_descr($interface) {
2250
        global $config;
2251

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

    
2279
        return $ifdesc;
2280
}
2281

    
2282
function convert_real_interface_to_friendly_descr($interface) {
2283
        global $config;
2284

    
2285
        $ifdesc = convert_real_interface_to_friendly_interface_name("{$interface}");
2286

    
2287
        if ($ifdesc) {
2288
                $iflist = get_configured_interface_with_descr(false, true);
2289
                return $iflist[$ifdesc];
2290
        }
2291

    
2292
        return $interface;
2293
}
2294

    
2295
/*
2296
 *  interface_translate_type_to_real($interface):
2297
 *              returns the real hardware interface name for a friendly interface.  ie: wan
2298
 */
2299
function interface_translate_type_to_real($interface) {
2300
        global $config;
2301

    
2302
        if ($config['interfaces'][$interface]['if'] <> "")
2303
                return $config['interfaces'][$interface]['if'];
2304
        else
2305
		return $interface;
2306
}
2307

    
2308
function get_real_interface($interface = "wan") {
2309
    global $config;
2310

    
2311
	$wanif = NULL;
2312

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

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

    
2348
			if ($interface == $if || $interface == $ifdesc) {
2349

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

    
2362
			$cfg = $config['interfaces'][$if];
2363

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

    
2373
			if (empty($cfg['ipaddr'])) {
2374
				$wanif = $cfg['if'];
2375
				break;
2376
			}
2377

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

    
2417
    return $wanif;
2418
}
2419

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

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

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

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

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

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

    
2488
function link_carp_interface_to_parent($interface) {
2489
        global $config;
2490

    
2491
        if ($interface == "")
2492
                return;
2493

    
2494
        $carp_ip = get_interface_ip($interface);
2495
        if (!is_ipaddr($carp_ip))
2496
                return;
2497

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

    
2508
        return "";
2509
}
2510

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

    
2522
        if (!is_ipaddr($ip))
2523
                return;
2524

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

    
2540
        return $carp_ints;
2541
}
2542

    
2543
function link_interface_to_vlans($int, $action = "") {
2544
	global $config;
2545

    
2546
	if (empty($int))
2547
		return;
2548

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

    
2566
function link_interface_to_vips($int, $action = "") {
2567
        global $config;
2568

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

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

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

    
2596
function link_interface_to_gre($interface) {
2597
        global $config;
2598

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

    
2605
function link_interface_to_gif($interface) {
2606
        global $config;
2607

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

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

    
2621
	$interface = str_replace("\n", "", $interface);
2622
	
2623
	if (does_interface_exist($interface) == false)
2624
		return;
2625

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

    
2632
	return $interface_ip_arr_cache[$interface];
2633
}
2634

    
2635
function find_interface_subnet($interface, $flush = false)
2636
{
2637
	global $interface_sn_arr_cache;
2638

    
2639
	$interface = str_replace("\n", "", $interface);
2640
	if (does_interface_exist($interface) == false)
2641
		return;
2642

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

    
2648
	return $interface_sn_arr_cache[$interface];
2649
}
2650

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

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

    
2667
	$curip = find_interface_ip($realif);
2668
	if ($curip && is_ipaddr($curip) && ($curip != "0.0.0.0"))
2669
		return $curip;
2670

    
2671
	return null;
2672
}
2673

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

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

    
2690
	$cursn = find_interface_subnet($realif);
2691
	if (!empty($cursn))
2692
		return $cursn;
2693

    
2694
	return null;
2695
}
2696

    
2697
/* return outside interfaces with a gateway */
2698
function get_interfaces_with_gateway() {
2699
	global $config;
2700

    
2701
	$ints = array();
2702

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

    
2727
/* return true if interface has a gateway */
2728
function interface_has_gateway($friendly) {
2729

    
2730
        $friendly = strtolower($friendly);
2731
        if (in_array($friendly, get_interfaces_with_gateway()))
2732
                return true;
2733

    
2734
	return false;
2735
}
2736

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

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

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

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

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

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

    
2789
function get_wireless_modes($interface) {
2790
	/* return wireless modes and channels */
2791
	$wireless_modes = array();
2792

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

    
2802
		$interface_channels = "";
2803
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
2804
		$interface_channel_count = count($interface_channels);
2805

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

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

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

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

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

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

    
2874
        if (in_array($int_family[0], $g['vlan_long_frame']))
2875
                return true;
2876
        else
2877
                return false;
2878
}
2879

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

    
2892
?>
(21-21/51)