Project

General

Profile

Download (81.6 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/* $Id$ */
3
/*
4
	interfaces.inc
5
	Copyright (C) 2004-2008 Scott Ullrich
6
	Copyright (C) 2008-2009 Ermal Lu?i
7
	All rights reserved.
8

    
9
	function interfaces_wireless_configure is
10
	Copyright (C) 2005 Espen Johansen
11
	All rights reserved.
12

    
13
	originally part of m0n0wall (http://m0n0.ch/wall)
14
	Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>.
15
	All rights reserved.
16

    
17
	Redistribution and use in source and binary forms, with or without
18
	modification, are permitted provided that the following conditions are met:
19

    
20
	1. Redistributions of source code must retain the above copyright notices,
21
	   this list of conditions and the following disclaimer.
22

    
23
	2. Redistributions in binary form must reproduce the above copyright
24
	   notices, this list of conditions and the following disclaimer in the
25
	   documentation and/or other materials provided with the distribution.
26

    
27
	THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
28
	INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
29
	AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
30
	AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
31
	OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32
	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33
	INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34
	CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35
	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36
	POSSIBILITY OF SUCH DAMAGE.
37

    
38
	pfSense_BUILDER_BINARIES:	/usr/sbin/pppd	/sbin/dhclient	/bin/sh	/usr/bin/grep	/usr/bin/xargs	/usr/bin/awk	/usr/local/sbin/choparp
39
	pfSense_BUILDER_BINARIES:	/sbin/ifconfig	/sbin/route	/usr/sbin/ngctl	/usr/sbin/arp	/bin/kill	/usr/local/sbin/mpd4
40
	pfSense_MODULE:	interfaces
41

    
42
*/
43

    
44
/* include all configuration functions */
45
require_once("globals.inc");
46
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("/tmp/{$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("/tmp/{$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
			interface_bring_down($vipif);
762
		break;
763
	case "carpdev-dhcp":
764
		$vipif = "vip" . $vip['vhid'];
765
		if(does_interface_exist("$vipif")) 
766
			interface_bring_down($vipif);
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("/tmp/{$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

    
883
 	   	if (is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) {
884
			foreach ($config['ppps']['ppp'] as $ppp) {
885
				$dev = substr($ppp['port'], 5);
886
				$realif  = $ppp['port'];
887
				$peerfile .= "{$dev}:\n";
888
				$peerfile .= " set device {$realif}\n";
889
				if($ppp['dialcmd']) {
890
					$peerfile .= " set dial {$ppp['dialcmd']}\n";
891
				} else
892
					$peerfile .= " set dial \"\"\n";
893
				$peerfile .= " set speed \"{$ppp['linespeed']}\"\n";
894
				$peerfile .= " add default HISADDR\n";
895
				$peerfile .= " set timeout 0\n";
896
				$peerfile .= " enable dns\n";
897
				$endingip = $startingip+1;
898
				if($ppp['localip'] && $ppp['gateway'])
899
					$peerfile .= " set ifaddr {$ppp['localip']}/0 {$ppp['gateway']}/0 255.255.255.0 0.0.0.0\n";
900
				if(!$ppp['localip'] && $ppp['gateway'])
901
					$peerfile .= " set ifaddr 10.0.0.{$startingip}/0 {$ppp['gateway']}/0 255.255.255.0 0.0.0.0\n";
902
				if($ppp['localip'] and !$ppp['gateway'])
903
					$peerfile .= " set ifaddr {$ppp['localip']}/0 10.0.0.{$endingip}/0 255.255.255.0 0.0.0.0\n";
904
				if(!$ppp['localip'] and !$ppp['gateway'])	
905
					$peerfile .= " set ifaddr 10.0.0.{$startingip}/0 10.0.0.{$endingip}/0 255.255.255.0 0.0.0.0\n";
906
				$peerfile .= " set phone \"{$ppp['phone']}\"\n";
907
				$peerfile .= " set authname \"{$ppp['username']}\"\n";
908
				$peerfile .= " set authkey \"{$ppp['password']}\"\n";
909
				// Add a local socket for the daemon so we can query it later
910
				$peerfile .= " set server /var/run/{$dev}.sock \"\" 0177\n";
911
				$peerfile .= "\n";
912
				$i++;
913
				$startingip++;
914
				$rclinkup.= "{$dev}:\n";
915
				$rclinkup.= "	! sh -c \"/sbin/ppp-script HISADDR INTERFACE DNS0 DNS1 \"\n";
916
				$rclinkup.= "	! sh -c \"/etc/rc.linkup INTERFACE start\"\n";
917
				$rclinkup.= "	! sh -c \"/etc/rc.filter_configure_sync\"\n";
918
			}	
919
    		}
920

    
921
		// Write out configuration for ppp.conf
922
		file_put_contents("/etc/ppp/ppp.conf", $peerfile);
923

    
924
		// Write out linkup file
925
		file_put_contents("/etc/ppp/ppp.linkup", $rclinkup);
926

    
927
		// Make executable
928
		exec("chmod a+rx /etc/ppp/ppp.linkup");
929
	}
930
	// Launch specified ppp instance
931
	if( !$edit){
932
		$running = `ps awux | grep ppp | grep -v grep | grep $orig_dev`;
933
		if(!$running)
934
			mwexec("/usr/sbin/ppp -background {$orig_dev}");
935
	}
936
}
937

    
938
function interface_ppp_bring_down($if) {
939
	if(file_exists("/var/run/{$if}.pid")) {
940
		$pid = trim(file_get_contents("/var/run/{$if}.pid"));
941
		mwexec("kill -QUIT {$pid}");
942
	}
943
}
944

    
945
function interfaces_carp_setup() {
946
	global $g, $config;
947

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

    
956
	// Prepare CmdCHAIN that will be used to execute commands.
957
	$cmdchain = new CmdCHAIN();	
958

    
959
	if ($g['booting']) {
960
		echo "Configuring CARP settings...";
961
		mute_kernel_msgs();
962
	}
963

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

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

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

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

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

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

    
1023
	$cmdchain->execute();
1024
	$cmdchain->clear();
1025

    
1026
	if ($g['booting']) {
1027
		unmute_kernel_msgs();
1028
		echo "done.\n";
1029
	}
1030
}
1031

    
1032
function interface_proxyarp_configure() {
1033
	global $config, $g;
1034
	if(isset($config['system']['developerspew'])) {
1035
		$mt = microtime();
1036
		echo "interface_proxyarp_configure() being called $mt\n";
1037
	}
1038

    
1039
	/* kill any running choparp */
1040
	killbyname("choparp");
1041

    
1042
	if (isset($config['virtualip']) && is_array($config['virtualip']['vip'])) {
1043
		$paa = array();
1044

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

    
1053
				if (!is_array($paa[$if]))
1054
					$paa[$proxyif] = array();
1055

    
1056
				$paa[$proxyif][] = $vipent;
1057
			}
1058
	}
1059

    
1060
	if (count($paa))
1061
		foreach ($paa as $paif => $paents) {
1062
			$paaifip = get_interface_ip($paif);
1063
			if (!(is_ipaddr($paaifip)))
1064
				continue;
1065
			$args = get_real_interface($paif) . " auto";
1066
			foreach ($paents as $paent) {
1067

    
1068
				if (isset($paent['subnet']))
1069
					$args .= " " . escapeshellarg("{$paent['subnet']}/{$paent['subnet_bits']}");
1070
				else if (isset($paent['range']))
1071
					$args .= " " . escapeshellarg($paent['range']['from'] . "-" .
1072
					$paent['range']['to']);
1073
			}
1074
			mwexec_bg("/usr/local/sbin/choparp " . $args);
1075
		}
1076
	}
1077

    
1078
}
1079

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

    
1125
function interface_ipalias_configure(&$vip) {
1126

    
1127
	if ($vip['mode'] == "ipalias") {
1128
		$if = get_real_interface($vip['interface']);
1129
		mwexec("/sbin/ifconfig " . escapeshellarg($if) . " " . $vip['subnet'] . "/" . escapeshellarg($vip['subnet_bits']) . " alias");
1130
	}
1131
}
1132

    
1133
function interface_reload_carps($cif) {
1134
	global $config;
1135

    
1136
	$carpifs = link_ip_to_carp_interface(find_interface_ip($cif));
1137
	if (empty($carpifs))
1138
		return;
1139

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

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

    
1169
	if ($vip['mode'] != "carp")
1170
		return;
1171

    
1172
	$vip_password = $vip['password'];
1173
	$vip_password = escapeshellarg(addslashes(str_replace(" ", "", $vip_password)));
1174
	if ($vip['password'] != "")
1175
		$password = " pass {$vip_password}";
1176

    
1177
	// set the vip interface to the vhid
1178
	$vipif = "vip{$vip['vhid']}";
1179

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

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

    
1208
	/* invalidate interface cache */
1209
	get_interface_arr(true);
1210

    
1211
	/* create the carp interface and setup */
1212
	if (does_interface_exist($vipif)) {
1213
		interface_bring_down($vipif);
1214
	} else {
1215
		$carpif = exec("/sbin/ifconfig carp create");
1216
		mwexec("/sbin/ifconfig {$carpif} name {$vipif}");
1217
		mwexec("/usr/sbin/ngctl name {$carpif}: {$vipif}");
1218
	}
1219

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

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

    
1226
	interfaces_bring_up($vipif);
1227
	
1228
	return $vipif;
1229
}
1230

    
1231
function interface_carpdev_configure(&$vip) {
1232
	global $g;
1233

    
1234
	if ($vip['mode'] != "carpdev-dhcp")
1235
		return;
1236

    
1237
	$vip_password = $vip['password'];
1238
	$vip_password = str_replace(" ", "", $vip_password);
1239
	if($vip['password'] != "")
1240
		$password = " pass \"" . $vip_password . "\"";
1241

    
1242
	log_error("Found carpdev interface {$vip['interface']} on top of interface {$interface}");
1243
	if (empty($vip['interface']))
1244
		return;
1245

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

    
1258
	if (does_interface_exist($vipif)) {
1259
		interface_bring_down($vipif);
1260
	} else {
1261
		$carpdevif = exec("/sbin/ifconfig carp create");
1262
		mwexec("/sbin/ifconfig {$carpdevif} name {$vipif}");
1263
		mwexec("/usr/sbin/ngctl name {$carpdevif}: {$vipif}");
1264
	}
1265

    
1266
	mwexec("/sbin/ifconfig {$vipif} carpdev {$realif} vhid {$vip['vhid']} advskew {$vip['advskew']} {$password}");
1267
	interfaces_bring_up($vipif);
1268

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

    
1278
	/* generate dhclient_wan.conf */
1279
	$fd = fopen("{$g['varetc_path']}/dhclient_{$vipif}.conf", "w");
1280
	if ($fd) {
1281
		$dhclientconf = "";
1282

    
1283
		$dhclientconf .= <<<EOD
1284
interface "{$vipif}" {
1285
timeout 60;
1286
retry 1;
1287
select-timeout 0;
1288
initial-interval 1;
1289
script "/sbin/dhclient-script";
1290
}
1291

    
1292
EOD;
1293

    
1294
		fwrite($fd, $dhclientconf);
1295
		fclose($fd);
1296

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

    
1304
	$fout = fopen("/tmp/ifconfig_{$vipif}","w");
1305
	fwrite($fout, "/sbin/dhclient -c {$g['varetc_path']}/dhclient_{$vipif}.conf {$vipif}");
1306
	fclose($fout);
1307

    
1308
	return $vipif;
1309
}
1310

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

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

    
1371
function interface_wireless_configure($if, &$wl, &$wlcfg) {
1372
	global $config, $g;
1373

    
1374
	/*    open up a shell script that will be used to output the commands.
1375
	 *    since wireless is changing a lot, these series of commands are fragile
1376
     *    and will sometimes need to be verified by a operator by executing the command
1377
     *    and returning the output of the command to the developers for inspection.  please
1378
     *    do not change this routine from a shell script to individul exec commands.  -sullrich
1379
	 */
1380

    
1381
	// Remove script file
1382
	unlink_if_exists("{$g['tmp_path']}/{$if}_setup.sh");
1383

    
1384
	// Clone wireless nic if needed.
1385
	interface_wireless_clone($if, $wl);
1386

    
1387
	$fd_set = fopen("/tmp/{$if}_setup.sh","w");
1388
	fwrite($fd_set, "#!/bin/sh\n");
1389
	fwrite($fd_set, "# {$g['product_name']} wireless configuration script.\n\n");
1390

    
1391
	/* set values for /path/program */
1392
	$hostapd = "/usr/sbin/hostapd";
1393
	$wpa_supplicant = "/usr/sbin/wpa_supplicant";
1394
	$ifconfig = "/sbin/ifconfig";
1395
	$killall = "/usr/bin/killall";
1396

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

    
1399
	$wlcmd = array();
1400
	/* Make sure it's up */
1401
	$wlcmd[] = "up";
1402
	/* Set a/b/g standard */
1403
	$wlcmd[] = "mode " . escapeshellarg($wlcfg['standard']);
1404

    
1405
	/* Set ssid */
1406
	if($wlcfg['ssid'])
1407
		$wlcmd[] = "ssid " .escapeshellarg($wlcfg['ssid']);
1408

    
1409
	/* Set 802.11g protection mode */
1410
	$wlcmd[] = "protmode " . escapeshellarg($wlcfg['protmode']);
1411

    
1412
	/* set wireless channel value */
1413
	if(isset($wlcfg['channel'])) {
1414
		if($wlcfg['channel'] == "0") {
1415
			$wlcmd[] = "channel any";
1416
		} else {
1417
			$wlcmd[] = "channel " . escapeshellarg($wlcfg['channel']);
1418
		}
1419
	}
1420

    
1421
	/* set Distance value */
1422
	if($wlcfg['distance'])
1423
		$distance = escapeshellarg($wlcfg['distance']);
1424

    
1425
	/* Set wireless hostap mode */
1426
	if ($wlcfg['mode'] == "hostap") {
1427
		$wlcmd[] = "mediaopt hostap";
1428
	} else {
1429
		$wlcmd[] = "-mediaopt hostap";
1430
	}
1431

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

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

    
1441
	/* handle hide ssid option */
1442
	if(isset($wlcfg['hidessid']['enable'])) {
1443
		$wlcmd[] = "hidessid";
1444
	} else {
1445
		$wlcmd[] = "-hidessid";
1446
	}
1447

    
1448
	/* handle pureg (802.11g) only option */
1449
	if(isset($wlcfg['pureg']['enable'])) {
1450
		$wlcmd[] = "mode 11g pureg";
1451
	} else {
1452
		$wlcmd[] = "-pureg";
1453
	}
1454

    
1455
	/* enable apbridge option */
1456
	if(isset($wlcfg['apbridge']['enable'])) {
1457
		$wlcmd[] = "apbridge";
1458
	} else {
1459
		$wlcmd[] = "-apbridge";
1460
	}
1461

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

    
1469
	/* handle txpower setting */
1470
	/* if($wlcfg['txpower'] <> "")
1471
		$wlcmd[] = "txpower " . escapeshellarg($wlcfg['txpower']);
1472
	*/
1473
	/* handle wme option */
1474
	if(isset($wlcfg['wme']['enable'])) {
1475
		$wlcmd[] = "wme";
1476
	} else {
1477
		$wlcmd[] = "-wme";
1478
	}
1479

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

    
1506
	/* generate wpa_supplicant/hostap config if wpa is enabled */
1507
	conf_mount_rw();
1508

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

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

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

    
1566
				$fd = fopen("{$g['varetc_path']}/hostapd_{$if}.conf", "w");
1567
				fwrite($fd, "{$wpa}");
1568
				fclose($fd);
1569

    
1570
			}
1571
			mwexec(kill_hostapd("{$if}"));
1572
			break;
1573
		case 'adhoc':
1574
			mwexec(kill_hostapd("{$if}"));
1575
			mwexec(kill_wpasupplicant("{$if}"));
1576
			break;
1577
	}
1578

    
1579
	/*
1580
	 *    all variables are set, lets start up everything
1581
	 */
1582

    
1583
	/* set ack timers according to users preference (if he/she has any) */
1584
	if($distance) {
1585
		fwrite($fd_set, "# Enable ATH distance settings\n");
1586
		fwrite($fd_set, "/sbin/athctrl.sh -i {$if} -d {$distance}\n");
1587
	}
1588

    
1589
	$standard_no_turbo = str_replace(" Turbo", "", $standard);
1590

    
1591
	if (isset($wlcfg['wpa']['enable'])) {
1592
		if ($wlcfg['mode'] == "bss") {
1593
			fwrite($fd_set, "{$wpa_supplicant} -B -i {$if} -c {$g['varetc_path']}/wpa_supplicant_{$if}.conf\n");
1594
		}
1595
		if ($wlcfg['mode'] == "hostap") {
1596
			fwrite($fd_set, "{$hostapd} -B {$g['varetc_path']}/hostapd_{$if}.conf\n");
1597
		}
1598
	}
1599

    
1600
	fclose($fd_set);
1601
	conf_mount_ro();
1602

    
1603
	/* configure wireless */
1604
	$wlcmd_args = implode(" ", $wlcmd);
1605
	mwexec("/sbin/ifconfig {$if} $wlcmd_args", false);
1606

    
1607
	
1608
	sleep(1);
1609
	/* execute hostapd and wpa_supplicant if required in shell */
1610
	mwexec("/bin/sh /tmp/{$if}_setup.sh");
1611

    
1612
	return 0;
1613

    
1614
}
1615

    
1616
function kill_hostapd($interface) {
1617
	return "/bin/ps awwuxx | grep hostapd | grep $interface | awk '{ print \$2 }' | xargs kill\n";
1618
}
1619

    
1620
function kill_wpasupplicant($interface) {
1621
	return "/bin/ps awwuxx | grep wpa_supplicant | grep $interface | awk '{ print \$2 }' | xargs kill\n";
1622
}
1623

    
1624
function find_dhclient_process($interface) {
1625
	if($interface)
1626
		$pid = `ps awwwux | grep dhclient | grep -v grep | grep {$interface} | awk '{ print \$2 }'`;
1627
	return $pid;
1628
}
1629

    
1630
function interface_configure($interface = "wan", $reloadall = false) {
1631
	global $config, $g;
1632
	global $interface_sn_arr_cache, $interface_ip_arr_cache;
1633

    
1634
	$wancfg = $config['interfaces'][$interface];
1635

    
1636
	$realif = get_real_interface($interface);
1637

    
1638
	if (!$g['booting']) {
1639
		/* remove all IPv4 addresses */
1640
		while (mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " -alias", true) == 0);
1641
			interface_bring_down($interface);
1642
	}
1643

    
1644
	/* wireless configuration? */
1645
	if (is_array($wancfg['wireless']))
1646
		interface_wireless_configure($realif, $wancfg, $wancfg['wireless']);
1647

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

    
1667
	/* media */
1668
	if ($wancfg['media'] || $wancfg['mediaopt']) {
1669
		$cmd = "/sbin/ifconfig " . escapeshellarg(get_real_interface($wancfg['if']));
1670
		if ($wancfg['media'])
1671
			$cmd .= " media " . escapeshellarg($wancfg['media']);
1672
		if ($wancfg['mediaopt'])
1673
			$cmd .= " mediaopt " . escapeshellarg($wancfg['mediaopt']);
1674
		mwexec($cmd);
1675
	}
1676

    
1677
	/* invalidate interface/ip/sn cache */
1678
	get_interface_arr(true);
1679
	unset($interface_ip_arr_cache[$realif]);
1680
	unset($interface_sn_arr_cache[$realif]);
1681

    
1682
	switch ($wancfg['ipaddr']) {
1683

    
1684
		case 'carpdev-dhcp':
1685
			interface_carpdev_dhcp_configure($interface);
1686
			break;
1687
		case 'dhcp':
1688
			interface_dhcp_configure($interface);
1689
			break;
1690

    
1691
		case 'pppoe':
1692
			interface_pppoe_configure($interface);
1693
			break;
1694

    
1695
		case 'pptp':
1696
			interface_pptp_configure($interface);
1697
			break;
1698

    
1699
		default:
1700
			if ($wancfg['ipaddr'] <> "" && $wancfg['subnet'] <> "") {
1701
				if (isset($wancfg['ispointtopoint']) && $wancfg['pointtopoint']) {
1702
					mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " " .
1703
						escapeshellarg($wancfg['ipaddr'] . "/" . $wancfg['subnet']) .
1704
						" " . escapeshellarg($wancfg['pointtopoint']) . " up");
1705
				} else {
1706
					if($wancfg['ipaddr'] && $wancfg['subnet'])
1707
						mwexec("/sbin/ifconfig " . escapeshellarg($realif) .
1708
							" " . escapeshellarg($wancfg['ipaddr'] . "/" . 
1709
							$wancfg['subnet']));
1710
				}
1711
			}
1712

    
1713
			if (is_ipaddr($wancfg['gateway']))
1714
				file_put_contents("/tmp/{$realif}_router", $wancfg['gateway']);
1715
	}
1716

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

    
1742
		if (link_interface_to_vips($interface))
1743
			interfaces_vips_configure($interface);
1744

    
1745
		if ($interface == "lan")
1746
			/* make new hosts file */
1747
			system_hosts_generate();
1748

    
1749
		if ($reloadall == true) {
1750

    
1751
			/* reconfigure static routes (kernel may have deleted them) */
1752
			system_routing_configure();
1753

    
1754
			/* reload ipsec tunnels */
1755
			vpn_ipsec_configure();
1756

    
1757
			/* update dyndns */
1758
			services_dyndns_configure($interface);
1759

    
1760
			/* force DNS update */
1761
			services_dnsupdate_process($interface);
1762

    
1763
			/* restart dnsmasq */
1764
			services_dnsmasq_configure();
1765

    
1766
			/* reload captive portal */
1767
			captiveportal_configure();
1768

    
1769
			/* set the reload filter dity flag */
1770
			filter_configure();
1771
		}
1772
	}
1773

    
1774
	unmute_kernel_msgs();
1775

    
1776
	return 0;
1777
}
1778

    
1779
function interface_carpdev_dhcp_configure($interface = "wan") {
1780
	global $config, $g;
1781

    
1782
	$wancfg = $config['interfaces'][$interface];
1783
	$wanif = $wancfg['if'];
1784
	/* bring wan interface up before starting dhclient */
1785
	if($wanif)
1786
		interfaces_bring_up($wanif);
1787
	else 
1788
		log_error("Could not bring wanif up in terface_carpdev_dhcp_configure()");
1789

    
1790
	return 0;
1791
}
1792

    
1793
function interface_dhcp_configure($interface = "wan") {
1794
	global $config, $g;
1795

    
1796
	$wancfg = $config['interfaces'][$interface];
1797

    
1798
	/* generate dhclient_wan.conf */
1799
	$fd = fopen("{$g['varetc_path']}/dhclient_{$interface}.conf", "w");
1800
	if (!$fd) {
1801
		printf("Error: cannot open dhclient_{$interface}.conf in interfaces_wan_dhcp_configure() for writing.\n");
1802
		return 1;
1803
	}
1804

    
1805
	if ($wancfg['dhcphostname']) {
1806
		$dhclientconf_hostname = "send dhcp-client-identifier \"{$wancfg['dhcphostname']}\";\n";
1807
		$dhclientconf_hostname .= "\tsend host-name \"{$wancfg['dhcphostname']}\";\n";
1808
	} else {
1809
		$dhclientconf_hostname = "";
1810
	}
1811

    
1812
	$wanif = get_real_interface($interface);
1813

    
1814
 	$dhclientconf = "";
1815
	
1816
	$dhclientconf .= <<<EOD
1817
interface "{$wanif}" {
1818
timeout 60;
1819
retry 1;
1820
select-timeout 0;
1821
initial-interval 1;
1822
	{$dhclientconf_hostname}
1823
	script "/sbin/dhclient-script";
1824
}
1825

    
1826
EOD;
1827

    
1828
if(is_ipaddr($wancfg['alias-address'])) {
1829
	$subnetmask = gen_subnet_mask($wancfg['alias-subnet']);
1830
	$dhclientconf .= <<<EOD
1831
alias {
1832
	interface  "{$wanif}";
1833
	fixed-address {$wancfg['alias-address']};
1834
	option subnet-mask {$subnetmask};
1835
}
1836

    
1837
EOD;
1838
}
1839
	fwrite($fd, $dhclientconf);
1840
	fclose($fd);
1841

    
1842
	$realwanif = $wancfg['if'];
1843

    
1844
	/* bring wan interface up before starting dhclient */
1845
	if($realwanif)
1846
		interfaces_bring_up($realwanif);
1847
	else 
1848
		log_error("Could not bring realwanif up in interface_dhcp_configure()");
1849

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

    
1853
	$fout = fopen("/tmp/ifconfig_{$wanif}","w");
1854
	fwrite($fout, "/sbin/dhclient -c {$g['varetc_path']}/dhclient_{$interface}.conf {$wanif}");
1855
	fclose($fout);
1856

    
1857
	return 0;
1858
}
1859

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

    
1863
	$wancfg = $config['interfaces'][$interface];
1864

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

    
1872
	$idle = 0;
1873

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

    
1882
	$mpdconf = <<<EOD
1883
startup:
1884
pppoeclient:
1885

    
1886
EOD;
1887

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

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

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

    
1912
EOD;
1913

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

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

    
1924
EOD;
1925
		}
1926
	}
1927

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

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

    
1949
EOD;
1950

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

    
1955
EOD;
1956
	}
1957

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

    
1962
EOD;
1963
	}
1964
	
1965
	$mpdconf .= <<<EOD
1966
	open
1967

    
1968
EOD;
1969

    
1970
	fwrite($fd, $mpdconf);
1971
	fclose($fd);
1972

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

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

    
1988
EOD;
1989

    
1990
	fwrite($fd, $mpdconf);
1991
	fclose($fd);
1992

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

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

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

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

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

    
2022
	return 0;
2023
}
2024

    
2025
function interface_pptp_configure($interface) {
2026
	global $config, $g;
2027

    
2028
	$wancfg = $config['interfaces'][$interface];
2029

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

    
2037
	$idle = 0;
2038

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

    
2047
	$mpdconf = <<<EOD
2048
startup:
2049
pptp:
2050

    
2051
EOD;
2052

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

    
2060
        $mpdconf .= <<<EOD
2061
        new -i {$realif} pptp pptp 
2062

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

    
2068
EOD;
2069

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

    
2076
EOD;
2077

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

    
2082
EOD;
2083
	}
2084

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

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

    
2103
EOD;
2104
	}
2105

    
2106
	$mpdconf .= <<<EOD
2107
	open
2108

    
2109
EOD;
2110

    
2111
	fwrite($fd, $mpdconf);
2112
	fclose($fd);
2113

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

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

    
2129
EOD;
2130

    
2131
	fwrite($fd, $mpdconf);
2132
	fclose($fd);
2133

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

    
2143
	return 0;
2144
}
2145

    
2146
function interfaces_group_setup() {
2147
	global $config;
2148

    
2149
	if (!is_array($config['ifgroups']['ifgroupentry']))
2150
		return;
2151

    
2152
	foreach ($config['ifgroups']['ifgroupentry'] as $groupar)
2153
		interface_group_setup($groupar);
2154

    
2155
	return;
2156
}
2157

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

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

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

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

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

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

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

    
2228
        /* if list */
2229
        $ifdescrs = get_configured_interface_list(false, true);
2230

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

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

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

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

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

    
2277
        return $ifdesc;
2278
}
2279

    
2280
function convert_real_interface_to_friendly_descr($interface) {
2281
        global $config;
2282

    
2283
        $ifdesc = convert_real_interface_to_friendly_interface_name("{$interface}");
2284

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

    
2290
        return $interface;
2291
}
2292

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

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

    
2306
function get_real_interface($interface = "wan") {
2307
    global $config;
2308

    
2309
	$wanif = NULL;
2310

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

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

    
2345
			if ($interface == $if || $interface == $ifdesc) {
2346

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

    
2359
			$cfg = $config['interfaces'][$if];
2360

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

    
2370
			if (empty($cfg['ipaddr'])) {
2371
				$wanif = $cfg['if'];
2372
				break;
2373
			}
2374

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

    
2414
    return $wanif;
2415
}
2416

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

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

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

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

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

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

    
2485
function link_carp_interface_to_parent($interface) {
2486
        global $config;
2487

    
2488
        if ($interface == "")
2489
                return;
2490

    
2491
        $carp_ip = get_interface_ip($interface);
2492
        if (!is_ipaddr($carp_ip))
2493
                return;
2494

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

    
2505
        return "";
2506
}
2507

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

    
2519
        if (!is_ipaddr($ip))
2520
                return;
2521

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

    
2537
        return $carp_ints;
2538
}
2539

    
2540
function link_interface_to_vips($int) {
2541
        global $config;
2542

    
2543
        if (is_array($config['virtualip']['vip']))
2544
                foreach ($config['virtualip']['vip'] as $vip)
2545
                        if($int == $vip['interface'])
2546
                                return $vip;
2547
}
2548

    
2549
/****f* interfaces/link_interface_to_bridge
2550
 * NAME
2551
 *   link_interface_to_bridge - Finds out a bridge group for an interface
2552
 * INPUTS
2553
 *   $ip
2554
 * RESULT
2555
 *   bridge[0-99]
2556
 ******/
2557
function link_interface_to_bridge($int) {
2558
        global $config;
2559

    
2560
        if (is_array($config['bridges']['bridged']))
2561
                foreach ($config['bridges']['bridged'] as $bridge)
2562
                        if(stristr($bridge['members'], "{$int}"))
2563
                                return "{$bridge['bridgeif']}";
2564
}
2565

    
2566
function link_interface_to_gre($interface) {
2567
        global $config;
2568

    
2569
        if (is_array($config['gres']['gre']))
2570
                foreach ($config['gres']['gre'] as $gre)
2571
                        if($gre['if'] == $interface)
2572
                                return "{$gre['greif']}";
2573
}
2574

    
2575
function link_interface_to_gif($interface) {
2576
        global $config;
2577

    
2578
        if (is_array($config['gifs']['gif']))
2579
                foreach ($config['gifs']['gif'] as $gif)
2580
                        if($gif['if'] == $interface)
2581
                                return "{$gif['gifif']}";
2582
}
2583

    
2584
/*
2585
 * find_interface_ip($interface): return the interface ip (first found)
2586
 */
2587
function find_interface_ip($interface, $flush = false)
2588
{
2589
	global $interface_ip_arr_cache;
2590

    
2591
	$interface = str_replace("\n", "", $interface);
2592
	
2593
	if (does_interface_exist($interface) == false)
2594
		return;
2595

    
2596
	/* Setup IP cache */
2597
	if (!isset($interface_ip_arr_cache[$interface]) or $flush) {
2598
		$interface_ip_arr_cache[$interface] = `/sbin/ifconfig {$interface} | /usr/bin/grep -w "inet" | /usr/bin/cut -d" " -f 2| /usr/bin/head -1`;
2599
		$interface_ip_arr_cache[$interface] = str_replace("\n", "", $interface_ip_arr_cache[$interface]);
2600
	}
2601

    
2602
	return $interface_ip_arr_cache[$interface];
2603
}
2604

    
2605
function find_interface_subnet($interface, $flush = false)
2606
{
2607
	global $interface_sn_arr_cache;
2608

    
2609
	$interface = str_replace("\n", "", $interface);
2610
	if (does_interface_exist($interface) == false)
2611
		return;
2612

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

    
2618
	return $interface_sn_arr_cache[$interface];
2619
}
2620

    
2621
function get_interface_ip($interface = "wan")
2622
{
2623
	$realif = get_real_interface($interface);
2624
	if (!$realif) {
2625
		if (preg_match("/^carp/i", $interface))
2626
			$realif = $interface;
2627
		else if (preg_match("/^vip/i", $interface))
2628
			$realif = $interface;
2629
		else
2630
			return null;
2631
	}
2632

    
2633
	/* Do we really come here for these interfaces ?! */
2634
	if (in_array($realif, array("pptp", "pppoe", "l2tp", "openvpn", "enc0" /* , "ppp" */)))
2635
			return "";
2636

    
2637
	$curip = find_interface_ip($realif);
2638
	if ($curip && is_ipaddr($curip) && ($curip != "0.0.0.0"))
2639
		return $curip;
2640

    
2641
	return null;
2642
}
2643

    
2644
function get_interface_subnet($interface = "wan")
2645
{
2646
	$realif = get_real_interface($interface);
2647
	if (!$realif) {
2648
                if (preg_match("/^carp/i", $interface))
2649
                        $realif = $interface;
2650
                else if (preg_match("/^vip/i", $interface))
2651
                        $realif = $interface;
2652
                else
2653
                        return null;
2654
        }
2655

    
2656
	/* Do we really come here for these interfaces ?! */
2657
	if (in_array($realif, array("pptp", "pppoe", "l2tp", "openvpn", "enc0" /* , "ppp" */)))
2658
		return "";
2659

    
2660
	$cursn = find_interface_subnet($realif);
2661
	if (!empty($cursn))
2662
		return $cursn;
2663

    
2664
	return null;
2665
}
2666

    
2667
/* return outside interfaces with a gateway */
2668
function get_interfaces_with_gateway() {
2669
	global $config;
2670

    
2671
	$ints = array();
2672

    
2673
	/* loop interfaces, check config for outbound */
2674
	foreach($config['interfaces'] as $ifdescr => $ifname) {
2675
		if($ifname['serialport']) {
2676
			$ints[] = $ifdescr;
2677
			continue;
2678
		}
2679
		switch ($ifname['ipaddr']) {
2680
			case "dhcp":
2681
			case "carpdev-dhcp":
2682
			case "pppoe":
2683
			case "pptp":
2684
			$ints[] = $ifdescr;
2685
			break;
2686
			default:
2687
			if ($ifname['pointtopoint'])
2688
				$ints[] = $ifdescr;
2689
			else if (!empty($ifname['gateway']))
2690
				$ints[] = $ifdescr;
2691
			break;
2692
		}
2693
	}
2694
	return $ints;
2695
}
2696

    
2697
/* return true if interface has a gateway */
2698
function interface_has_gateway($friendly) {
2699

    
2700
        $friendly = strtolower($friendly);
2701
        if (in_array($friendly, get_interfaces_with_gateway()))
2702
                return true;
2703

    
2704
	return false;
2705
}
2706

    
2707
/****f* interfaces/is_altq_capable
2708
 * NAME
2709
 *   is_altq_capable - Test if interface is capable of using ALTQ
2710
 * INPUTS
2711
 *   $int            - string containing interface name
2712
 * RESULT
2713
 *   boolean         - true or false
2714
 ******/
2715

    
2716
function is_altq_capable($int) {
2717
        /* Per:
2718
         * http://www.freebsd.org/cgi/man.cgi?query=altq&manpath=FreeBSD+7.2-current&format=html
2719
         * Only the following drivers have ALTQ support
2720
         */
2721
	$capable = array("age", "ale", "an", "ath", "aue", "awi", "bce",
2722
			"bfe", "bge", "dc", "de", "ed", "em", "ep", "fxp", "gem",
2723
			"hme", "ipw", "iwi", "jme", "le", "msk", "mxge", "my", "nfe",
2724
			"npe", "nve", "ral", "re", "rl", "rum", "sf", "sis", "sk",
2725
			"ste", "stge", "txp", "udav", "ural", "vge", "vr", "wi", "xl",
2726
			"ndis", "tun", "vlan", "pppoe", "pptp", "ng", "ppp");
2727

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

    
2730
        if (in_array($int_family[0], $capable))
2731
                return true;
2732
	else if (stristr($int_family, "vlan")) /* VLANs are name $parent.$vlan now */
2733
		return true;
2734
        else
2735
                return false;
2736
}
2737

    
2738
/****f* interfaces/is_interface_wireless
2739
 * NAME
2740
 *   is_interface_wireless - Returns if an interface is wireless
2741
 * RESULT
2742
 *   $tmp       - Returns if an interface is wireless
2743
 ******/
2744
function is_interface_wireless($interface) {
2745
        global $config, $g;
2746

    
2747
        $friendly = convert_real_interface_to_friendly_interface_name($interface);
2748
        if(!isset($config['interfaces'][$friendly]['wireless'])) {
2749
                if (preg_match($g['wireless_regex'], $interface)) {
2750
                        $config['interfaces'][$friendly]['wireless'] = array();
2751
                        return true;
2752
                }
2753
                unset($config['interfaces'][$friendly]['wireless']);
2754
                return false;
2755
        } else
2756
                return true;
2757
}
2758

    
2759
function get_wireless_modes($interface) {
2760
	/* return wireless modes and channels */
2761
	$wireless_modes = array();
2762

    
2763
	if(is_interface_wireless($interface)) {
2764
		$cloned_interface = get_real_interface($interface);
2765
		$wi = 1;
2766
		$ifconfig = "/sbin/ifconfig";
2767
		$awk = "/usr/bin/awk";
2768
		$chan_list = "$ifconfig $cloned_interface list chan";
2769
		$stack_list = "$awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
2770
		$format_list = "$awk '{print \$5 \" \" \$6 \",\" \$1}'";
2771

    
2772
		$interface_channels = "";
2773
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
2774
		$interface_channel_count = count($interface_channels);
2775

    
2776
		$c = 0;
2777
		while ($c < $interface_channel_count)
2778
		{
2779
			$channel_line = explode(",", $interface_channels["$c"]);
2780
			$wireless_mode = trim($channel_line[0]);
2781
			$wireless_channel = trim($channel_line[1]);
2782
			if(trim($wireless_mode) != "") {
2783
				/* if we only have 11g also set 11b channels */
2784
				if($wireless_mode == "11g") {
2785
					$wireless_modes["11b"] = array();
2786
				}
2787
				$wireless_modes["$wireless_mode"]["$c"] = $wireless_channel;
2788
			}
2789
			$c++;
2790
		}
2791
	}
2792
	return($wireless_modes);
2793
}
2794

    
2795
/****f* interfaces/get_interface_mtu
2796
 * NAME
2797
 *   get_interface_mtu - Return the mtu of an interface
2798
 * RESULT
2799
 *   $tmp       - Returns the mtu of an interface
2800
 ******/
2801
function get_interface_mtu($interface) {
2802
        $mtu = `/sbin/ifconfig {$interface} | /usr/bin/grep mtu | /usr/bin/cut -d" " -f6`;
2803
        return $mtu;
2804
}
2805

    
2806
function get_interface_mac($interface) {
2807
	$mac = array();
2808
        exec("/sbin/ifconfig {$interface} | /usr/bin/awk '/ether/ {print $2}'", $mac);
2809
        if(is_macaddr($mac[0])) {
2810
                return trim($mac[0]);
2811
        } else {
2812
                return "";
2813
        }
2814
}
2815

    
2816
/****f* pfsense-utils/generate_random_mac_address
2817
 * NAME
2818
 *   generate_random_mac - generates a random mac address
2819
 * INPUTS
2820
 *   none
2821
 * RESULT
2822
 *   $mac - a random mac address
2823
 ******/
2824
function generate_random_mac_address() {
2825
        $mac = "02";
2826
        for($x=0; $x<5; $x++)
2827
                $mac .= ":" . dechex(rand(16, 255));
2828
        return $mac;
2829
}
2830

    
2831
/****f* interfaces/is_jumbo_capable
2832
 * NAME
2833
 *   is_jumbo_capable - Test if interface is jumbo frame capable.  Useful for determining VLAN capability.
2834
 * INPUTS
2835
 *   $int             - string containing interface name
2836
 * RESULT
2837
 *   boolean          - true or false
2838
 ******/
2839
function is_jumbo_capable($int) {
2840
        global $g;
2841

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

    
2844
        if (in_array($int_family[0], $g['vlan_long_frame']))
2845
                return true;
2846
        else
2847
                return false;
2848
}
2849

    
2850
function setup_pppoe_reset_file($interface, $status) {
2851
	define("CRON_PPPOE_CMD_FILE", "/conf/pppoe{$interface}restart");
2852
	define("CRON_PPPOE_CMD", "#!/bin/sh\necho '<?php require(\"config.inc\"); require(\"interfaces.inc\"); interface_reconfigure({$interface}); ?>' | /usr/local/bin/php -q");
2853
	if ($status == true) {
2854
		if (!file_exists(CRON_PPPOE_CMD_FILE)) {
2855
			file_put_contents(CRON_PPPOE_CMD_FILE, CRON_PPPOE_CMD);
2856
			chmod(CRON_PPPOE_CMD_FILE, 0700);
2857
		}	
2858
	} else
2859
		unlink_if_exists(CRON_PPPOE_CMD_FILE);
2860
}
2861

    
2862
?>
(21-21/51)