Project

General

Profile

Download (83.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
		$realif1 = get_real_interface($member);
342
		$realif =  escapeshellarg($realif1);
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($realif1);
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 interface_bridge_add_member($bridgeif, $interface) {
460

    
461
	if (!does_interface_exist($bridgeif) || !does_interface_exist($interface))
462
		return;
463

    
464
	$mtu = get_interface_mtu($brigeif);
465
	$mtum = get_interface_mtu($interface);
466
	
467
	if ($mtu != $mtum)
468
		mwexec("/sbin/ifconfig {$interface} mtu {$mtu}");
469

    
470
	interfaces_bring_up($interface);
471
	mwexec("/sbin/ifconfig {$bridgeif} addm {$interface}");
472
}
473

    
474
function interfaces_lagg_configure() 
475
{
476
        global $config, $g;
477
		if($g['booting']) 
478
			echo "Configuring LAGG interfaces...";
479
        $i = 0;
480
		if (is_array($config['laggs']['lagg']) && count($config['laggs']['lagg'])) {
481
			foreach ($config['laggs']['lagg'] as $lagg) {
482
				if(empty($lagg['laggif']))
483
					$lagg['laggif'] = "lagg{$i}";
484
				/* XXX: Maybe we should report any errors?! */
485
				interface_lagg_configure($lagg);
486
				$i++;
487
			}
488
		}
489
		if($g['booting']) 
490
			echo "done.\n";
491
}
492

    
493
function interface_lagg_configure(&$lagg) {
494
        global $config, $g;
495

    
496
        if (!is_array($lagg))
497
		return -1;
498

    
499
	$members = explode(',', $lagg['members']);
500
	if (!count($members))
501
		return -1;
502
	
503
	$checklist = get_interface_list();
504

    
505
	if ($g['booting'] || !(empty($lagg['laggif']))) {
506
                mwexec("/sbin/ifconfig {$lagg['laggif']} destroy");
507
                mwexec("/sbin/ifconfig {$lagg['laggif']} create");
508
                $laggif = $lagg['laggif'];
509
        } else
510
                $laggif = exec("/sbin/ifconfig lagg create");
511

    
512
	/* Calculate smaller mtu and enforce it */
513
        $smallermtu = 0;
514
        foreach ($members as $member) {
515
                $mtu = get_interface_mtu($member);
516
		if ($smallermtu == 0 && !empty($mtu))
517
			$smallermtu = $mtu;
518
                else if (!empty($mtu) && $mtu < $smallermtu)
519
                        $smallermtu = $mtu;
520
        }
521

    
522
	/* Just in case anything is not working well */
523
        if ($smallermtu == 0)
524
                $smallermtu = 1500;
525

    
526
	foreach ($members as $member) {
527
		if (!array_key_exists($member, $checklist))
528
			continue;
529
		/* make sure the parent interface is up */
530
		mwexec("/sbin/ifconfig {$member} mtu {$smallermtu}");
531
		interfaces_bring_up($member);
532
		mwexec("/sbin/ifconfig {$laggif} laggport {$member}");
533
	}
534
	
535
	mwexec("/sbin/ifconfig {$laggif} laggproto {$lagg['proto']}");
536

    
537
	interfaces_bring_up($laggif);
538

    
539
	return $laggif;
540
}
541

    
542
function interfaces_gre_configure() {
543
        global $config;
544

    
545
        $i = 0;
546
        if (is_array($config['gres']['gre']) && count($config['gres']['gre'])) {
547
                foreach ($config['gres']['gre'] as $gre) {
548
                        if(empty($gre['greif']))
549
                                $gre['greif'] = "gre{$i}";
550
                        /* XXX: Maybe we should report any errors?! */
551
                        interface_gre_configure($gre);
552
                        $i++;
553
                }
554
        }
555
}
556

    
557
function interface_gre_configure(&$gre) {
558
        global $config, $g;
559

    
560
	if (!is_array($gre))
561
		return -1;
562

    
563
	$realif = get_real_interface($gre['if']);
564
	$realifip = get_interface_ip($gre['if']);
565

    
566
	/* make sure the parent interface is up */
567
	interfaces_bring_up($realif);
568

    
569
	if ($g['booting'] || !(empty($gre['greif']))) {
570
		mwexec("/sbin/ifconfig {$gre['greif']} destroy");
571
		mwexec("/sbin/ifconfig {$gre['greif']} create");
572
		$greif = $gre['greif'];
573
	} else {
574
		$greif = exec("/sbin/ifconfig gre create");
575
	}
576

    
577
	/* Do not change the order here for more see gre(4) NOTES section. */
578
	mwexec("/sbin/ifconfig {$greif} tunnel {$realifip} {$gre['remote-addr']}");
579
	mwexec("/sbin/ifconfig {$greif} {$gre['tunnel-local-addr']} {$gre['tunnel-remote-addr']} netmask " . gen_subnet_mask($gre['tunnel-remote-net']));
580
	if (isset($gre['link0']) && $gre['link0'])
581
		mwexec("/sbin/ifconfig {$greif} link0");
582
	if (isset($gre['link1']) && $gre['link1'])
583
		mwexec("/sbin/ifconfig {$greif} link1");
584
	if (isset($gre['link2']) && $gre['link2'])
585
		mwexec("/sbin/ifconfig {$greif} link2");
586

    
587
	if($greif)
588
		interfaces_bring_up($greif);
589
	else 
590
		log_error("Could not bring greif up -- variable not defined.");
591

    
592
	if (isset($gre['link1']) && $gre['link1'])
593
		mwexec("/sbin/route add {$gre['tunnel-remote-addr']}/{$gre['tunnel-remote-net']} {$gre['tunnel-local-addr']}");
594
	file_put_contents("{$g['tmp_path']}/{$greif}_router", $gre['tunnel-remote-addr']);
595

    
596
	return $greif;
597
}
598

    
599
function interfaces_gif_configure() {
600
	global $config;
601
	$i = 0;
602
	if (is_array($config['gifs']['gif']) && count($config['gifs']['gif'])) {
603
		foreach ($config['gifs']['gif'] as $gif) {
604
			if(empty($gif['gifif']))
605
				$gre['gifif'] = "gif{$i}";
606
			/* XXX: Maybe we should report any errors?! */
607
			interface_gif_configure($gif);
608
			$i++;
609
		}
610
	}
611
}
612

    
613
function interface_gif_configure(&$gif) {
614
	global $config, $g;
615

    
616
	if (!is_array($gif))
617
		return -1;
618

    
619
	$realif = get_real_interface($gif['if']);
620
	$realifip = get_interface_ip($gif['if']);
621

    
622
	/* make sure the parent interface is up */
623
	if($realif)
624
		interfaces_bring_up($realif);
625
	else 
626
		log_error("could not bring realif up -- variable not defined -- interface_gif_configure()");
627

    
628
	if ($g['booting'] || !(empty($gif['gifif']))) {
629
		mwexec("/sbin/ifconfig {$gif['gifif']} destroy");
630
		mwexec("/sbin/ifconfig {$gif['gifif']} create");
631
		$gifif = $gif['gifif'];
632
	} else
633
		$gifif = exec("/sbin/ifconfig gif create");
634

    
635
	/* Do not change the order here for more see gif(4) NOTES section. */
636
	mwexec("/sbin/ifconfig {$gifif} tunnel {$realifip} {$gif['remote-addr']}");
637
	mwexec("/sbin/ifconfig {$gifif} {$gif['tunnel-local-addr']} {$gif['tunnel-remote-addr']} netmask " . gen_subnet_mask($gif['tunnel-remote-net']));
638
	if (isset($gif['link0']) && $gif['link0'])
639
		mwexec("/sbin/ifconfig {$gifif} link0");
640
	if (isset($gif['link1']) && $gif['link1'])
641
		mwexec("/sbin/ifconfig {$gifif} link1");
642
	if($gifif)
643
		interfaces_bring_up($gifif);
644
	else
645
		log_error("could not bring gifif up -- variable not defined");
646

    
647
	/* XXX: Needed?! */
648
	//mwexec("/sbin/route add {$gif['tunnel-remote-addr']}/{$gif['tunnel-remote-net']} -iface {$gifif}");
649
	file_put_contents("{$g['tmp_path']}/{$gifif}_router", $gif['tunnel-remote-addr']);
650

    
651
	return $gifif;
652
}
653

    
654
function interfaces_configure() {
655
	global $config, $g;
656

    
657
	/* Set up our loopback interface */
658
	interfaces_loopback_configure();
659

    
660
	/* set up LAGG virtual interfaces */
661
	interfaces_lagg_configure();
662

    
663
	/* set up VLAN virtual interfaces */
664
	interfaces_vlan_configure();
665

    
666
	interfaces_qinq_configure();
667

    
668
	/* Set up PPP interfaces */
669
	interfaces_ppp_configure();
670

    
671
	$iflist = get_configured_interface_with_descr();
672
	$delayed_list = array();
673
	$bridge_list = array();
674
	
675
	foreach($iflist as $if => $ifname) {
676
		$realif = $config['interfaces'][$if]['if'];
677
		if(is_array($realif['pppoe']) && isset($realif['pppoe']['pppoe-reset-type']))
678
			setup_pppoe_reset_file($if, true);
679
		else 
680
			setup_pppoe_reset_file($if, false);
681
		if (strstr($realif, "bridge")) 
682
			$bridge_list[$if] = $ifname;
683
		else if (strstr($realif, "gre"))
684
			$delayed_list[$if] = $ifname;
685
		else if (strstr($realif, "gif"))
686
			$delayed_list[$if] = $ifname;
687
		else {
688
			if ($g['booting'])
689
				echo "Configuring {$ifname} interface...";
690
			if($g['debug'])
691
				log_error("Configuring {$ifname}");
692
			interface_configure($if, true);
693
			if ($g['booting']) 
694
				echo "done.\n";
695
		}
696
	}
697

    
698
	/* set up GRE virtual interfaces */
699
	interfaces_gre_configure();
700

    
701
	/* set up GIF virtual interfaces */
702
	interfaces_gif_configure();
703
	
704
	foreach ($delayed_list as $if => $ifname) {
705
		if ($g['booting'])
706
			echo "Configuring {$ifname} interface...";
707
        	if ($g['debug'])
708
        		log_error("Configuring {$ifname}");
709

    
710
		interface_configure($if, true);
711

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

    
716
	/* set up BRIDGe virtual interfaces */
717
	interfaces_bridge_configure();
718

    
719
	foreach ($bridge_list as $if => $ifname) {
720
		if ($g['booting'])
721
			echo "Configuring {$ifname} interface...";
722
		if($g['debug'])
723
			log_error("Configuring {$ifname}");
724

    
725
		interface_configure($if, true);
726

    
727
		if ($g['booting'])
728
			echo "done.\n";
729
	}
730

    
731
	/* bring up vip interfaces */
732
	interfaces_vips_configure();
733

    
734
	/* configure interface groups */
735
	interfaces_group_setup();
736

    
737
	if (!$g['booting']) {
738
		/* reconfigure static routes (kernel may have deleted them) */
739
		system_routing_configure();
740

    
741
		/* reload IPsec tunnels */
742
		vpn_ipsec_configure();
743

    
744
		/* reload dhcpd (interface enabled/disabled status may have changed) */
745
		services_dhcpd_configure();
746

    
747
		/* restart dnsmasq */
748
		services_dnsmasq_configure();
749

    
750
		/* reload captive portal */
751
		captiveportal_configure();
752

    
753
		/* set the reload filter dity flag */
754
		filter_configure();
755
	}
756

    
757
	return 0;
758
}
759

    
760
function interface_reconfigure($interface = "wan") {
761
	interface_bring_down($interface);
762
	interface_configure($interface);
763
}
764

    
765
function interface_vip_bring_down(&$vip) {
766
	switch ($vip['mode']) {
767
	case "proxyarp":
768
		interface_proxyarp_configure();
769
		break;
770
	case "ipalias":
771
		$vipif = get_real_interface($vip['interface']);
772
		if(does_interface_exist($vipif))
773
			mwexec("/sbin/ifconfig {$vipif} delete {$vip['subnet']}");
774
		break;
775
	case "carp":
776
		$vipif = "vip" . $vip['vhid'];
777
		if(does_interface_exist($vipif)) 
778
			mwexec("/sbin/ifconfig {$vipif} destroy");
779
		break;
780
	case "carpdev-dhcp":
781
		$vipif = "vip" . $vip['vhid'];
782
		if(does_interface_exist($vipif)) 
783
			mwexec("/sbin/ifconfig {$vipif} destroy");
784
		break;
785
	}
786
}
787

    
788
function interface_bring_down($interface = "wan", $destroy = false) {
789
	global $config, $g;
790

    
791
	if (!isset($config['interfaces'][$interface]))
792
		return; 
793

    
794
	$ifcfg = $config['interfaces'][$interface];
795

    
796
	$realif = get_real_interface($interface);
797

    
798

    
799
	/* remove interface up file if it exists */
800
	unlink_if_exists("{$g['tmp_path']}/{$realif}up");
801
	unlink_if_exists("{$g['vardb_path']}/{$interface}ip");
802
	unlink_if_exists("{$g['tmp_path']}/{$realif}_router");
803
	
804
	interface_ppp_bring_down($realif);
805

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

    
845
	if ($destroy == true) {
846
		if (preg_match("/^tun|^ppp|^ovpn|^gif|^gre|^lagg|^bridge|vlan/i", $realif))
847
			mwexec("/sbin/ifconfig {$realif} destroy");
848
	}	
849

    
850
	return;
851
}
852

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

    
871
function interface_ppp_configure($ifcfg,$edit=false) {
872
	global $config, $g;
873
	
874
	/* Remove  the /dev/ from the device name. */
875
	$orig_dev = $ifcfg;
876

    
877
	// ppp (userland) requires a /var/spool/lock directory
878
	if(!is_dir("/var/spool/lock")) {
879
		exec("mkdir -p /var/spool/lock");
880
		exec("chmod a+rw /var/spool/lock/.");
881
	}
882
	if ($edit){
883
		// Construct the ppp.conf file
884
		$peerfile .= "default:\n";
885
		$peerfile .= " set log Phase Chat LCP IPCP CCP tun command\n";
886
		$peerfile .= " ident user-ppp VERSION (built COMPILATIONDATE)\n";
887
		$peerfile .= " set dial \"ABORT BUSY ABORT NO\\\sCARRIER TIMEOUT 5 \\\n";
888
		$peerfile .= " 		\\\"\\\" AT OK-AT-OK ATE1Q0 OK \\\dATDT\\\T TIMEOUT 40 CONNECT\"\n";
889
		$peerfile .= " enable dns\n";
890
		$peerfile .= " nat enable yes\n";
891
		$peerfile .= " set reconnect {$ifcfg['connect-max-attempts']} 5\n";
892
		$peerfile .= " allow users root\n\n";
893
	
894
		// Loop variables
895
    		$i = 0;
896
		$startingip = 1;
897

    
898
		// Start ppp.linkup file
899
		$rclinkup = "default:\n";
900
		// Start ppp.linkdown file
901
		$rclinkdown = "default:\n";
902

    
903
 	   	if (is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) {
904
			foreach ($config['ppps']['ppp'] as $ppp) {
905
				$dev = substr($ppp['port'], 5);
906
				$realif  = $ppp['port'];
907
				$peerfile .= "{$dev}:\n";
908
				$peerfile .= " set device {$realif}\n";
909
				if($ppp['dialcmd']) {
910
					$peerfile .= " set dial " . base64_decode($ppp['dialcmd']) . "\n";
911
				} else
912
					$peerfile .= " set dial \"\"\n";
913
				$peerfile .= " set speed {$ppp['linespeed']}\n";
914
				if (isset($ppp['defaultgw']))
915
					$peerfile .= " add default HISADDR\n";
916
				$peerfile .= " set timeout 0\n";
917
				$peerfile .= " enable dns\n";
918
				$endingip = $startingip+1;
919
				if($ppp['localip'] && $ppp['gateway'])
920
					$peerfile .= " set ifaddr {$ppp['localip']}/0 {$ppp['gateway']}/0 255.255.255.0 0.0.0.0\n";
921
				if(!$ppp['localip'] && $ppp['gateway'])
922
					$peerfile .= " set ifaddr 10.0.0.{$startingip}/0 {$ppp['gateway']}/0 255.255.255.0 0.0.0.0\n";
923
				if($ppp['localip'] and !$ppp['gateway'])
924
					$peerfile .= " set ifaddr {$ppp['localip']}/0 10.0.0.{$endingip}/0 255.255.255.0 0.0.0.0\n";
925
				if(!$ppp['localip'] and !$ppp['gateway'])	
926
					$peerfile .= " set ifaddr 10.0.0.{$startingip}/0 10.0.0.{$endingip}/0 255.255.255.0 0.0.0.0\n";
927
				//$peerfile .= " iface name ppp_{$orig_dev}\n";
928
				$peerfile .= " set phone \"{$ppp['phone']}\"\n";
929
				$peerfile .= " set authname \"{$ppp['username']}\"\n";
930
				$peerfile .= " set authkey \"{$ppp['password']}\"\n";
931
				// Add a local socket for the daemon so we can query it later
932
				$peerfile .= " set server /var/run/{$dev}.sock \"\" 0177\n";
933
				$peerfile .= "\n";
934
				$i++;
935
				$startingip++;
936
				$rclinkup .= "{$dev}:\n";
937
				$rclinkup .= "	! sh -c \"/etc/rc.conf_mount_rw\"\n";
938
 				$rclinkup .= "	! sh -c \"/bin/echo `date -j +%Y.%m.%d-%H:%M:%S` 00:00:00 >> /conf/ppp-up.{$dev}.log\"\n";
939
				$rclinkup .= "	! sh -c \"/sbin/ppp-script HISADDR INTERFACE DNS0 DNS1\"\n";
940
				$rclinkup .= "	! sh -c \"/etc/rc.linkup INTERFACE start\"\n";
941
				$rclinkup .= "	! sh -c \"/etc/rc.conf_mount_ro\"\n";
942
				$rclinkup.= "	! sh -c \"/etc/rc.filter_configure_sync\"\n";
943
				// Link down file
944
				$rclinkdown .= "{$dev}:\n";
945
				$rclinkdown .= "	! sh -c \"/etc/rc.conf_mount_rw\"\n";
946
				$rclinkdown .= "	! sh -c \"/bin/echo `date -j +%Y.%m.%d-%H:%M:%S` UPTIME >> /conf/ppp-up.{$dev}.log\"\n";
947
				$rclinkdown .= "	! sh -c \"/etc/rc.conf_mount_ro\"\n";
948
				$rclinkdown .= "	! sh -c \"/bin/rm -f /var/run/{$dev}.if\"\n";
949
			}	
950
    		}
951

    
952
		// Write out configuration for ppp.conf
953
		file_put_contents("/etc/ppp/ppp.conf", $peerfile);
954

    
955
		// Write out linkup file
956
		file_put_contents("/etc/ppp/ppp.linkup", $rclinkup);
957
		file_put_contents("/etc/ppp/ppp.linkdown", $rclinkdown);
958
		// Make executable
959
		exec("chmod a+rx /etc/ppp/ppp.linkup");
960
		exec("chmod a+rx /etc/ppp/ppp.linkdown");
961
	}
962
	// Launch specified ppp instance
963
	if( (!$edit || $g['booting']) && file_exists("/dev/{$orig_dev}")){
964
		$running = `ps awux | grep ppp | grep -v grep | grep $orig_dev`;
965
		if(!$running)
966
			mwexec_bg("/usr/sbin/ppp -background {$orig_dev}");
967
	}
968
}
969

    
970
function interface_ppp_bring_down($if) {
971
	if(file_exists("/var/run/{$if}.pid")) {
972
		$pid = trim(file_get_contents("/var/run/{$if}.pid"));
973
		mwexec("kill -QUIT {$pid}");
974
	}
975
}
976

    
977
function interfaces_carp_setup() {
978
	global $g, $config;
979

    
980
	$balanacing = "";
981
	$pfsyncinterface = "";
982
	$pfsyncenabled = "";
983
	if(isset($config['system']['developerspew'])) {
984
		$mt = microtime();
985
		echo "interfaces_carp_setup() being called $mt\n";
986
	}
987

    
988
	// Prepare CmdCHAIN that will be used to execute commands.
989
	$cmdchain = new CmdCHAIN();	
990

    
991
	if ($g['booting']) {
992
		echo "Configuring CARP settings...";
993
		mute_kernel_msgs();
994
	}
995

    
996
	/* suck in configuration items */
997
	if($config['installedpackages']['carpsettings']) {
998
		if($config['installedpackages']['carpsettings']['config']) {
999
			foreach($config['installedpackages']['carpsettings']['config'] as $carp) {
1000
				$pfsyncenabled = $carp['pfsyncenabled'];
1001
				$balanacing = $carp['balancing'];
1002
				$pfsyncinterface = $carp['pfsyncinterface'];
1003
				$pfsyncpeerip = $carp['pfsyncpeerip'];
1004
			}
1005
		}
1006
	} else {
1007
		unset($pfsyncinterface);
1008
		unset($balanacing);
1009
		unset($pfsyncenabled);
1010
	}
1011

    
1012
	$cmdchain->add("Allow CARP", "/sbin/sysctl net.inet.carp.allow=1", true);			
1013
	if($balanacing) {
1014
		$cmdchain->add("Enable CARP ARP-balancing", "/sbin/sysctl net.inet.carp.arpbalance=1", true);
1015
		$cmdchain->add("Disallow CARP preemption", "/sbin/sysctl net.inet.carp.preempt=0", true);
1016
	} else
1017
		$cmdchain->add("Enable CARP preemption", "/sbin/sysctl net.inet.carp.preempt=1", true);		
1018

    
1019
	$cmdchain->add("Enable CARP logging", "/sbin/sysctl net.inet.carp.log=2", true);
1020
	if (!empty($pfsyncinterface))
1021
		$carp_sync_int = get_real_interface($pfsyncinterface);
1022

    
1023
	if($g['booting']) {
1024
		/*    install rules to alllow pfsync to sync up during boot
1025
		 *    carp interfaces will remain down until the bootup sequence finishes
1026
		 */
1027
		$fd = fopen("{$g['tmp_path']}/rules.boot", "w");
1028
		if ($fd) {
1029
			fwrite($fd, "pass quick proto carp all keep state\n");
1030
			fwrite($fd, "pass quick proto pfsync all\n");
1031
			fwrite($fd, "pass out quick from any to any keep state\n");
1032
			fclose($fd);
1033
			mwexec("/sbin/pfctl -f {$g['tmp_path']}/rules.boot");
1034
		} else
1035
			log_error("Could not create rules.boot file!");
1036
	}
1037

    
1038
	/* setup pfsync interface */
1039
	if($carp_sync_int and $pfsyncenabled) {
1040
		if (is_ipaddr($pfsyncpeerip))
1041
			$cmdchain->add("Bring up pfsync0 syncpeer", "/sbin/ifconfig pfsync0 syncdev {$carp_sync_int} syncpeer {$pfsyncpeerip} up", false);						
1042
		else
1043
			$cmdchain->add("Bring up pfsync0 syncdev", "/sbin/ifconfig pfsync0 syncdev {$carp_sync_int} up", false);			
1044
	} else
1045
		$cmdchain->add("Bring up pfsync0", "/sbin/ifconfig pfsync0 syncdev lo0 up", false);						
1046

    
1047
	if($config['virtualip']['vip'])
1048
		$cmdchain->add("Allow CARP.", "/sbin/sysctl net.inet.carp.allow=1", true);				
1049
	else
1050
		$cmdchain->add("Disallow CARP.", "/sbin/sysctl net.inet.carp.allow=0", true);		
1051
	
1052
	if($g['debug'])
1053
		$cmdchain->setdebug(); // optional for verbose logging
1054

    
1055
	$cmdchain->execute();
1056
	$cmdchain->clear();
1057

    
1058
	if ($g['booting']) {
1059
		unmute_kernel_msgs();
1060
		echo "done.\n";
1061
	}
1062
}
1063

    
1064
function interface_proxyarp_configure() {
1065
	global $config, $g;
1066
	if(isset($config['system']['developerspew'])) {
1067
		$mt = microtime();
1068
		echo "interface_proxyarp_configure() being called $mt\n";
1069
	}
1070

    
1071
	/* kill any running choparp */
1072
	killbyname("choparp");
1073

    
1074
	if (isset($config['virtualip']) && is_array($config['virtualip']['vip'])) {
1075
		$paa = array();
1076

    
1077
		/* group by interface */
1078
		foreach ($config['virtualip']['vip'] as $vipent) {
1079
			if ($vipent['mode'] === "proxyarp") {
1080
				if ($vipent['interface'])
1081
					$proxyif = $vipent['interface'];
1082
				else
1083
					$proxyif = "wan";
1084

    
1085
				if (!is_array($paa[$if]))
1086
					$paa[$proxyif] = array();
1087

    
1088
				$paa[$proxyif][] = $vipent;
1089
			}
1090
	}
1091

    
1092
	if (count($paa))
1093
		foreach ($paa as $paif => $paents) {
1094
			$paaifip = get_interface_ip($paif);
1095
			if (!(is_ipaddr($paaifip)))
1096
				continue;
1097
			$args = get_real_interface($paif) . " auto";
1098
			foreach ($paents as $paent) {
1099

    
1100
				if (isset($paent['subnet']))
1101
					$args .= " " . escapeshellarg("{$paent['subnet']}/{$paent['subnet_bits']}");
1102
				else if (isset($paent['range']))
1103
					$args .= " " . escapeshellarg($paent['range']['from'] . "-" .
1104
					$paent['range']['to']);
1105
			}
1106
			mwexec_bg("/usr/local/sbin/choparp " . $args);
1107
		}
1108
	}
1109

    
1110
}
1111

    
1112
function interfaces_vips_configure($interface = "") {
1113
	global $g, $config;
1114
	if(isset($config['system']['developerspew'])) {
1115
		$mt = microtime();
1116
		echo "interfaces_vips_configure() being called $mt\n";
1117
	}
1118
	$paa = array();
1119
	if(is_array($config['virtualip']['vip'])) {
1120
		$carp_setuped = false;
1121
		$anyproxyarp = false;
1122
		foreach ($config['virtualip']['vip'] as $vip) {
1123
			switch ($vip['mode']) {
1124
			case "proxyarp":
1125
				/* nothing it is handled on interface_proxyarp_configure() */
1126
				if ($interface <> "" && $vip['interface'] <> $interface)
1127
					continue;
1128
				$anyproxyarp = true;
1129
				break;
1130
			case "ipalias":
1131
				if ($interface <> "" && $vip['interface'] <> $interface)
1132
					continue;
1133
				interface_ipalias_configure(&$vip);
1134
				break;
1135
			case "carp":
1136
				if ($interface <> "" && $vip['interface'] <> $interface)
1137
					continue;
1138
				if ($carp_setuped == false) {
1139
					interfaces_carp_setup();
1140
					$carp_setuped = true;
1141
				}
1142
				interface_carp_configure($vip);
1143
				break;
1144
			case "carpdev-dhcp":
1145
				if ($interface <> "" && $vip['interface'] <> $interface)
1146
					continue;
1147
				interface_carpdev_configure($vip);
1148
				break;
1149
			}
1150
		}
1151
		
1152
		if ($anyproxyarp == true)
1153
			interface_proxyarp_configure();
1154
	}
1155
}
1156

    
1157
function interface_ipalias_configure(&$vip) {
1158

    
1159
	if ($vip['mode'] == "ipalias") {
1160
		$if = get_real_interface($vip['interface']);
1161
		mwexec("/sbin/ifconfig " . escapeshellarg($if) . " " . $vip['subnet'] . "/" . escapeshellarg($vip['subnet_bits']) . " alias");
1162
	}
1163
}
1164

    
1165
function interface_reload_carps($cif) {
1166
	global $config;
1167

    
1168
	$carpifs = link_ip_to_carp_interface(find_interface_ip($cif));
1169
	if (empty($carpifs))
1170
		return;
1171

    
1172
	$carps = explode(" ", $carpifs);
1173
	if(is_array($config['virtualip']['vip'])) {
1174
		$viparr = &$config['virtualip']['vip'];
1175
		foreach ($viparr as $vip) {
1176
			if (in_array($vip['carpif'], $carps)) {
1177
				switch ($vip['mode']) {
1178
					case "carp":
1179
					interface_vip_bring_down($vip);
1180
					sleep(1);
1181
					interface_carp_configure($vip);
1182
					break;
1183
					case "carpdev-dhcp":
1184
					interface_vip_bring_down($vip);
1185
					sleep(1);
1186
					interface_carpdev_configure($vip);
1187
					break;
1188
				}
1189
			}
1190
		}
1191
	}
1192
}
1193

    
1194
function interface_carp_configure(&$vip) {
1195
	global $config, $g;
1196
	if(isset($config['system']['developerspew'])) {
1197
		$mt = microtime();
1198
		echo "interface_carp_configure() being called $mt\n";
1199
	}
1200

    
1201
	if ($vip['mode'] != "carp")
1202
		return;
1203

    
1204
	$vip_password = $vip['password'];
1205
	$vip_password = escapeshellarg(addslashes(str_replace(" ", "", $vip_password)));
1206
	if ($vip['password'] != "")
1207
		$password = " pass {$vip_password}";
1208

    
1209
	// set the vip interface to the vhid
1210
	$vipif = "vip{$vip['vhid']}";
1211

    
1212
	$interface = interface_translate_type_to_real($vip['interface']);
1213
	/*
1214
	 * ensure the interface containing the VIP really exists
1215
 	 * prevents a panic if the interface is missing or invalid
1216
	 */
1217
	$realif = get_real_interface($vip['interface']);
1218
	if (!does_interface_exist($realif)) {
1219
		file_notice("CARP", "Interface specified for the virtual IP address {$vip['subnet']} does not exist. Skipping this VIP.", "Firewall: Virtual IP", "");
1220
		return;
1221
	}
1222

    
1223
	/* ensure CARP IP really exists prior to loading up */
1224
	/* XXX: this can be bound to only the interface choosen in the carp creation. Not yet since upgrade is needed! */
1225
	$found = false;
1226
	$iflist = get_configured_interface_list();
1227
	foreach($iflist as $if) {
1228
		$ww_subnet_ip = get_interface_ip($if);
1229
		$ww_subnet_bits = get_interface_subnet($if);
1230
		if (ip_in_subnet($vip['subnet'], gen_subnet($ww_subnet_ip, $ww_subnet_bits) . "/" . $ww_subnet_bits)) {
1231
			$found = true;
1232
			break;
1233
		}
1234
	}
1235
	if($found == false) {
1236
		file_notice("CARP", "Sorry but we could not find a matching real interface subnet for the virtual IP address {$vip['subnet']}.", "Firewall: Virtual IP", "");
1237
		return;
1238
	}
1239

    
1240
	/* invalidate interface cache */
1241
	get_interface_arr(true);
1242

    
1243
	/* create the carp interface and setup */
1244
	if (does_interface_exist($vipif)) {
1245
		interface_bring_down($vipif);
1246
	} else {
1247
		$carpif = exec("/sbin/ifconfig carp create");
1248
		mwexec("/sbin/ifconfig {$carpif} name {$vipif}");
1249
		mwexec("/usr/sbin/ngctl name {$carpif}: {$vipif}");
1250
	}
1251

    
1252
	/* invalidate interface cache */
1253
	get_interface_arr(true);
1254

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

    
1258
	interfaces_bring_up($vipif);
1259
	
1260
	return $vipif;
1261
}
1262

    
1263
function interface_carpdev_configure(&$vip) {
1264
	global $g;
1265

    
1266
	if ($vip['mode'] != "carpdev-dhcp")
1267
		return;
1268

    
1269
	$vip_password = $vip['password'];
1270
	$vip_password = str_replace(" ", "", $vip_password);
1271
	if($vip['password'] != "")
1272
		$password = " pass \"" . $vip_password . "\"";
1273

    
1274
	log_error("Found carpdev interface {$vip['interface']} on top of interface {$interface}");
1275
	if (empty($vip['interface']))
1276
		return;
1277

    
1278
	$vipif = "vip" . $vip['vhid'];
1279
	$realif = interface_translate_type_to_real($vip['interface']);
1280
	interfaces_bring_up($realif);
1281
	/*
1282
	 * ensure the interface containing the VIP really exists
1283
	 * prevents a panic if the interface is missing or invalid
1284
	 */
1285
	if (!does_interface_exist($realif)) {
1286
		file_notice("CARP", "Interface specified for the virtual IP address {$vip['subnet']} does not exist. Skipping this VIP.", "Firewall: Virtual IP", "");
1287
		return;
1288
	}
1289

    
1290
	if (does_interface_exist($vipif)) {
1291
		interface_bring_down($vipif);
1292
	} else {
1293
		$carpdevif = exec("/sbin/ifconfig carp create");
1294
		mwexec("/sbin/ifconfig {$carpdevif} name {$vipif}");
1295
		mwexec("/usr/sbin/ngctl name {$carpdevif}: {$vipif}");
1296
	}
1297

    
1298
	mwexec("/sbin/ifconfig {$vipif} carpdev {$realif} vhid {$vip['vhid']} advskew {$vip['advskew']} {$password}");
1299
	interfaces_bring_up($vipif);
1300

    
1301
	/*
1302
	 * XXX: BIG HACK but carpdev needs ip services active
1303
	 *      before even starting something as dhclient.
1304
	 *      I do not know if this is a feature or a bug
1305
	 *      but better than track it make it work ;) .
1306
	 */
1307
	//$fakeiptouse = "10.254.254." . ($carp_instances_counter+1);
1308
	//$cmdchain->add("CarpDEV hack", "/sbin/ifconfig {$carpint} inet {$fakeiptouse}", false);
1309

    
1310
	/* generate dhclient_wan.conf */
1311
	$fd = fopen("{$g['varetc_path']}/dhclient_{$vipif}.conf", "w");
1312
	if ($fd) {
1313
		$dhclientconf = "";
1314

    
1315
		$dhclientconf .= <<<EOD
1316
interface "{$vipif}" {
1317
timeout 60;
1318
retry 1;
1319
select-timeout 0;
1320
initial-interval 1;
1321
script "/sbin/dhclient-script";
1322
}
1323

    
1324
EOD;
1325

    
1326
		fwrite($fd, $dhclientconf);
1327
		fclose($fd);
1328

    
1329
		/* fire up dhclient */
1330
		mwexec("/sbin/dhclient -c {$g['varetc_path']}/dhclient_{$vipif}.conf {$vipif} > {$g['tmp_path']}/{$vipif}_output > {$g['tmp_path']}/{$vipif}_error_output", false);
1331
	} else {
1332
		log_error("Error: cannot open dhclient_{$vipif}.conf in interfaces_carpdev_configure() for writing.\n");
1333
		mwexec("/sbin/dhclient -b {$vipif}");
1334
	}
1335

    
1336
	return $vipif;
1337
}
1338

    
1339
function interface_wireless_clone($realif, $wlcfg) {
1340
	global $config, $g;
1341
	/*   Check to see if interface has been cloned as of yet.  
1342
	 *   If it has not been cloned then go ahead and clone it.
1343
	 */
1344
	$needs_clone = false;
1345
	switch($wlcfg['wireless']['mode']) {
1346
		 case "hostap":
1347
			$mode = "wlanmode hostap";
1348
			break;
1349
		 case "adhoc":
1350
			$mode = "wlanmode adhoc";
1351
			break;
1352
		 default:
1353
			$mode = "";
1354
			break;
1355
	}
1356
	if(does_interface_exist($realif)) {
1357
		exec("/sbin/ifconfig {$realif}", $output, $ret);
1358
		$ifconfig_str = implode($output);
1359
		if(($wlcfg['wireless']['mode'] == "hostap") && (! preg_match("/hostap/si", $ifconfig_str))) {
1360
			log_error("Interface {$wlcfg['if']}_wlan{$interface_num} changed to hostap mode");
1361
			$needs_clone = true;
1362
		}
1363
		if(($wlcfg['wireless']['mode'] == "adhoc") && (! preg_match("/adhoc/si", $ifconfig_str))) {
1364
			log_error("Interface {$wlcfg['if']}_wlan{$interface_num} changed to adhoc mode");
1365
			$needs_clone = true;
1366
		}
1367
		if(($wlcfg['wireless']['mode'] == "bss") && (preg_match("/hostap|adhoc/si", $ifconfig_str))) {
1368
			log_error("Interface {$wlcfg['if']}_wlan{$interface_num} changed to infrastructure mode");
1369
			$needs_clone = true;
1370
		}
1371
	} else {
1372
		$needs_clone = true;
1373
	}
1374

    
1375
	if($needs_clone == true) {
1376
		/* remove previous instance if it exists */
1377
		if(does_interface_exist($realif))
1378
			mwexec("/sbin/ifconfig {$realif} destroy");			
1379

    
1380
		log_error("Cloning new wireless interface {$realif}");
1381
		// Create the new wlan interface. FreeBSD returns the new interface name.
1382
		// example:  wlan2
1383
		exec("/sbin/ifconfig wlan create wlandev {$wlcfg['if']} {$mode} 2>&1", $out, $ret);
1384
		if($ret <> 0) {
1385
			log_error("Failed to clone interface {$wlcfg['if']} with error code {$ret}, output {$out[0]}");
1386
		}
1387
		$newif = trim($out[0]);
1388
		// Rename the interface to {$parentnic}_wlan{$number}#: EX: ath0_wlan0
1389
		mwexec("/sbin/ifconfig {$newif} name {$realif} 2>&1", false);
1390
		// FIXME: not sure what ngctl is for. Doesn't work.
1391
		// mwexec("/usr/sbin/ngctl name {$newif}: {$wlcfg['if']}_wlan{$interface_num}", false);
1392
	}
1393
}
1394

    
1395
function interface_wireless_configure($if, &$wl, &$wlcfg) {
1396
	global $config, $g;
1397

    
1398
	/*    open up a shell script that will be used to output the commands.
1399
	 *    since wireless is changing a lot, these series of commands are fragile
1400
     *    and will sometimes need to be verified by a operator by executing the command
1401
     *    and returning the output of the command to the developers for inspection.  please
1402
     *    do not change this routine from a shell script to individul exec commands.  -sullrich
1403
	 */
1404

    
1405
	// Remove script file
1406
	unlink_if_exists("{$g['tmp_path']}/{$if}_setup.sh");
1407

    
1408
	// Clone wireless nic if needed.
1409
	interface_wireless_clone($if, $wl);
1410

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

    
1415
	/* set values for /path/program */
1416
	$hostapd = "/usr/sbin/hostapd";
1417
	$wpa_supplicant = "/usr/sbin/wpa_supplicant";
1418
	$ifconfig = "/sbin/ifconfig";
1419
	$killall = "/usr/bin/killall";
1420

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

    
1423
	$wlcmd = array();
1424
	/* Make sure it's up */
1425
	$wlcmd[] = "up";
1426
	/* Set a/b/g standard */
1427
	$wlcmd[] = "mode " . escapeshellarg($wlcfg['standard']);
1428

    
1429
	/* Set ssid */
1430
	if($wlcfg['ssid'])
1431
		$wlcmd[] = "ssid " .escapeshellarg($wlcfg['ssid']);
1432

    
1433
	/* Set 802.11g protection mode */
1434
	$wlcmd[] = "protmode " . escapeshellarg($wlcfg['protmode']);
1435

    
1436
	/* set wireless channel value */
1437
	if(isset($wlcfg['channel'])) {
1438
		if($wlcfg['channel'] == "0") {
1439
			$wlcmd[] = "channel any";
1440
		} else {
1441
			$wlcmd[] = "channel " . escapeshellarg($wlcfg['channel']);
1442
		}
1443
	}
1444

    
1445
	/* set Distance value */
1446
	if($wlcfg['distance'])
1447
		$distance = escapeshellarg($wlcfg['distance']);
1448

    
1449
	/* Set wireless hostap mode */
1450
	if ($wlcfg['mode'] == "hostap") {
1451
		$wlcmd[] = "mediaopt hostap";
1452
	} else {
1453
		$wlcmd[] = "-mediaopt hostap";
1454
	}
1455

    
1456
	/* Set wireless adhoc mode */
1457
	if ($wlcfg['mode'] == "adhoc") {
1458
		$wlcmd[] = "mediaopt adhoc";
1459
	} else {
1460
		$wlcmd[] = "-mediaopt adhoc";
1461
	}
1462

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

    
1465
	/* handle hide ssid option */
1466
	if(isset($wlcfg['hidessid']['enable'])) {
1467
		$wlcmd[] = "hidessid";
1468
	} else {
1469
		$wlcmd[] = "-hidessid";
1470
	}
1471

    
1472
	/* handle pureg (802.11g) only option */
1473
	if(isset($wlcfg['pureg']['enable'])) {
1474
		$wlcmd[] = "mode 11g pureg";
1475
	} else {
1476
		$wlcmd[] = "-pureg";
1477
	}
1478

    
1479
	/* enable apbridge option */
1480
	if(isset($wlcfg['apbridge']['enable'])) {
1481
		$wlcmd[] = "apbridge";
1482
	} else {
1483
		$wlcmd[] = "-apbridge";
1484
	}
1485

    
1486
	/* handle turbo option */
1487
	if(isset($wlcfg['turbo']['enable'])) {
1488
		$wlcmd[] = "mediaopt turbo";
1489
	} else {
1490
		$wlcmd[] = "-mediaopt turbo";
1491
	}
1492

    
1493
	/* handle txpower setting */
1494
	/* if($wlcfg['txpower'] <> "")
1495
		$wlcmd[] = "txpower " . escapeshellarg($wlcfg['txpower']);
1496
	*/
1497
	/* handle wme option */
1498
	if(isset($wlcfg['wme']['enable'])) {
1499
		$wlcmd[] = "wme";
1500
	} else {
1501
		$wlcmd[] = "-wme";
1502
	}
1503

    
1504
	/* set up wep if enabled */
1505
	$wepset = "";
1506
	if (isset($wlcfg['wep']['enable']) && is_array($wlcfg['wep']['key'])) {
1507
		switch($wlcfg['wpa']['auth_algs']) {
1508
			case "1":
1509
				$wepset .= "authmode open wepmode on ";
1510
				break;
1511
			case "2":
1512
				$wepset .= "authmode shared wepmode on ";
1513
				break;
1514
			case "3":
1515
				$wepset .= "authmode mixed wepmode on ";
1516
		}
1517
		$i = 1;
1518
		foreach ($wlcfg['wep']['key'] as $wepkey) {
1519
			$wepset .= "wepkey " . escapeshellarg("{$i}:{$wepkey['value']}") . " ";
1520
			if (isset($wepkey['txkey'])) {
1521
				$wlcmd[] = "weptxkey {$i} ";
1522
			}
1523
			$i++;
1524
		}
1525
		$wlcmd[] = $wepset;
1526
	} else {
1527
		$wlcmd[] = "authmode open wepmode off ";
1528
	}
1529

    
1530
	/* generate wpa_supplicant/hostap config if wpa is enabled */
1531
	conf_mount_rw();
1532

    
1533
	switch ($wlcfg['mode']) {
1534
		case 'bss':
1535
			if (isset($wlcfg['wpa']['enable'])) {
1536
				$wpa .= <<<EOD
1537
ctrl_interface={$g['varrun_path']}/wpa_supplicant
1538
ctrl_interface_group=0
1539
ap_scan=1
1540
#fast_reauth=1
1541
network={
1542
ssid="{$wlcfg['ssid']}"
1543
scan_ssid=1
1544
priority=5
1545
key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
1546
psk="{$wlcfg['wpa']['passphrase']}"
1547
pairwise={$wlcfg['wpa']['wpa_pairwise']}
1548
group={$wlcfg['wpa']['wpa_pairwise']}
1549
}
1550
EOD;
1551

    
1552
				$fd = fopen("{$g['varetc_path']}/wpa_supplicant_{$if}.conf", "w");
1553
				fwrite($fd, "{$wpa}");
1554
				fclose($fd);
1555

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

    
1590
				$fd = fopen("{$g['varetc_path']}/hostapd_{$if}.conf", "w");
1591
				fwrite($fd, "{$wpa}");
1592
				fclose($fd);
1593

    
1594
			}
1595
			mwexec(kill_hostapd("{$if}"));
1596
			break;
1597
		case 'adhoc':
1598
			mwexec(kill_hostapd("{$if}"));
1599
			mwexec(kill_wpasupplicant("{$if}"));
1600
			break;
1601
	}
1602

    
1603
	/*
1604
	 *    all variables are set, lets start up everything
1605
	 */
1606

    
1607
	/* set ack timers according to users preference (if he/she has any) */
1608
	if($distance) {
1609
		fwrite($fd_set, "# Enable ATH distance settings\n");
1610
		fwrite($fd_set, "/sbin/athctrl.sh -i {$if} -d {$distance}\n");
1611
	}
1612

    
1613
	$standard_no_turbo = str_replace(" Turbo", "", $standard);
1614

    
1615
	if (isset($wlcfg['wpa']['enable'])) {
1616
		if ($wlcfg['mode'] == "bss") {
1617
			fwrite($fd_set, "{$wpa_supplicant} -B -i {$if} -c {$g['varetc_path']}/wpa_supplicant_{$if}.conf\n");
1618
		}
1619
		if ($wlcfg['mode'] == "hostap") {
1620
			fwrite($fd_set, "{$hostapd} -B {$g['varetc_path']}/hostapd_{$if}.conf\n");
1621
		}
1622
	}
1623

    
1624
	fclose($fd_set);
1625
	conf_mount_ro();
1626

    
1627
	/* configure wireless */
1628
	$wlcmd_args = implode(" ", $wlcmd);
1629
	mwexec("/sbin/ifconfig {$if} $wlcmd_args", false);
1630

    
1631
	
1632
	sleep(1);
1633
	/* execute hostapd and wpa_supplicant if required in shell */
1634
	mwexec("/bin/sh {$g['tmp_path']}/{$if}_setup.sh");
1635

    
1636
	return 0;
1637

    
1638
}
1639

    
1640
function kill_hostapd($interface) {
1641
	return "/bin/ps awwuxx | grep hostapd | grep $interface | awk '{ print \$2 }' | xargs kill\n";
1642
}
1643

    
1644
function kill_wpasupplicant($interface) {
1645
	return "/bin/ps awwuxx | grep wpa_supplicant | grep $interface | awk '{ print \$2 }' | xargs kill\n";
1646
}
1647

    
1648
function find_dhclient_process($interface) {
1649
	if($interface)
1650
		$pid = `ps awwwux | grep dhclient | grep -v grep | grep {$interface} | awk '{ print \$2 }'`;
1651
	return $pid;
1652
}
1653

    
1654
function interface_configure($interface = "wan", $reloadall = false) {
1655
	global $config, $g;
1656
	global $interface_sn_arr_cache, $interface_ip_arr_cache;
1657

    
1658
	$wancfg = $config['interfaces'][$interface];
1659

    
1660
	$realif = get_real_interface($interface);
1661

    
1662
	if (!$g['booting']) {
1663
		/* remove all IPv4 addresses */
1664
		while (mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " -alias", true) == 0);
1665
			interface_bring_down($interface);
1666
	}
1667

    
1668
	/* wireless configuration? */
1669
	if (is_array($wancfg['wireless']))
1670
		interface_wireless_configure($realif, $wancfg, $wancfg['wireless']);
1671

    
1672
	if ($wancfg['spoofmac']) {
1673
		mwexec("/sbin/ifconfig " . escapeshellarg($realif) .
1674
			" link " . escapeshellarg($wancfg['spoofmac']));
1675
	}  else {
1676
		$mac = get_interface_mac(get_real_interface(get_real_interface($wancfg['if'])));
1677
		if($mac == "ff:ff:ff:ff:ff:ff") {
1678
			/*   this is not a valid mac address.  generate a
1679
			 *   temporary mac address so the machine can get online.
1680
			 */
1681
			echo "Generating new MAC address.";
1682
			$random_mac = generate_random_mac_address();
1683
			mwexec("/sbin/ifconfig " . escapeshellarg(get_real_interface($wancfg['if'])) .
1684
				" link " . escapeshellarg($random_mac));
1685
			$wancfg['spoofmac'] = $random_mac;
1686
			write_config();
1687
			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");
1688
		}
1689
	}
1690

    
1691
	/* media */
1692
	if ($wancfg['media'] || $wancfg['mediaopt']) {
1693
		$cmd = "/sbin/ifconfig " . escapeshellarg(get_real_interface($wancfg['if']));
1694
		if ($wancfg['media'])
1695
			$cmd .= " media " . escapeshellarg($wancfg['media']);
1696
		if ($wancfg['mediaopt'])
1697
			$cmd .= " mediaopt " . escapeshellarg($wancfg['mediaopt']);
1698
		mwexec($cmd);
1699
	}
1700

    
1701
	/* invalidate interface/ip/sn cache */
1702
	get_interface_arr(true);
1703
	unset($interface_ip_arr_cache[$realif]);
1704
	unset($interface_sn_arr_cache[$realif]);
1705

    
1706
	switch ($wancfg['ipaddr']) {
1707

    
1708
		case 'carpdev-dhcp':
1709
			interface_carpdev_dhcp_configure($interface);
1710
			break;
1711
		case 'dhcp':
1712
			interface_dhcp_configure($interface);
1713
			break;
1714

    
1715
		case 'pppoe':
1716
			interface_pppoe_configure($interface);
1717
			break;
1718

    
1719
		case 'pptp':
1720
			interface_pptp_configure($interface);
1721
			break;
1722

    
1723
		default:
1724
			if ($wancfg['ipaddr'] <> "" && $wancfg['subnet'] <> "") {
1725
				if (isset($wancfg['ispointtopoint']) && $wancfg['pointtopoint']) {
1726
					mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " " .
1727
						escapeshellarg($wancfg['ipaddr'] . "/" . $wancfg['subnet']) .
1728
						" " . escapeshellarg($wancfg['pointtopoint']) . " up");
1729
				} else {
1730
					if($wancfg['ipaddr'] && $wancfg['subnet'])
1731
						mwexec("/sbin/ifconfig " . escapeshellarg($realif) .
1732
							" " . escapeshellarg($wancfg['ipaddr'] . "/" . 
1733
							$wancfg['subnet']));
1734
				}
1735
			}
1736

    
1737
			if (is_ipaddr($wancfg['gateway']))
1738
				file_put_contents("{$g['tmp_path']}/{$realif}_router", $wancfg['gateway']);
1739
	}
1740

    
1741
	if(does_interface_exist($wancfg['if']))
1742
		interfaces_bring_up($wancfg['if']);
1743
 	
1744
	interface_reload_carps($realif);
1745
	
1746
	if($wancfg['serialport'])
1747
		interface_ppp_configure($wancfg['serialport']);
1748
	
1749
	if (!$g['booting']) {
1750
		if (link_interface_to_gre($interface)) {
1751
			foreach ($config['gres']['gre'] as $gre)
1752
				if ($gre['if'] == $interface)
1753
					interface_gre_configure($gre);
1754
		}
1755
		if (link_interface_to_gif($interface)) {
1756
                	foreach ($config['gifs']['gif'] as $gif)
1757
				if ($gif['if'] == $interface)
1758
                        		interface_gif_configure($gif);
1759
        	}
1760
		if (link_interface_to_bridge($interface)) {
1761
			foreach ($config['bridges']['bridged'] as $bridge)
1762
				if (stristr($bridge['members'], "{$interface}"))
1763
					interface_bridge_add_member($bridge['bridgeif'], $realif);
1764
		}
1765

    
1766
		link_interface_to_vips($interface, "update");
1767

    
1768
		if ($interface == "lan")
1769
			/* make new hosts file */
1770
			system_hosts_generate();
1771

    
1772
		if ($reloadall == true) {
1773

    
1774
			/* reconfigure static routes (kernel may have deleted them) */
1775
			system_routing_configure();
1776

    
1777
			/* reload ipsec tunnels */
1778
			vpn_ipsec_configure();
1779

    
1780
			/* update dyndns */
1781
			services_dyndns_configure($interface);
1782

    
1783
			/* force DNS update */
1784
			services_dnsupdate_process($interface);
1785

    
1786
			/* restart dnsmasq */
1787
			services_dnsmasq_configure();
1788

    
1789
			/* reload captive portal */
1790
			captiveportal_configure();
1791

    
1792
			/* set the reload filter dity flag */
1793
			filter_configure();
1794
		}
1795
	}
1796

    
1797
	unmute_kernel_msgs();
1798

    
1799
	return 0;
1800
}
1801

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

    
1805
	$wancfg = $config['interfaces'][$interface];
1806
	$wanif = $wancfg['if'];
1807
	/* bring wan interface up before starting dhclient */
1808
	if($wanif)
1809
		interfaces_bring_up($wanif);
1810
	else 
1811
		log_error("Could not bring wanif up in terface_carpdev_dhcp_configure()");
1812

    
1813
	return 0;
1814
}
1815

    
1816
function interface_dhcp_configure($interface = "wan") {
1817
	global $config, $g;
1818

    
1819
	$wancfg = $config['interfaces'][$interface];
1820

    
1821
	/* generate dhclient_wan.conf */
1822
	$fd = fopen("{$g['varetc_path']}/dhclient_{$interface}.conf", "w");
1823
	if (!$fd) {
1824
		printf("Error: cannot open dhclient_{$interface}.conf in interfaces_wan_dhcp_configure() for writing.\n");
1825
		return 1;
1826
	}
1827

    
1828
	if ($wancfg['dhcphostname']) {
1829
		$dhclientconf_hostname = "send dhcp-client-identifier \"{$wancfg['dhcphostname']}\";\n";
1830
		$dhclientconf_hostname .= "\tsend host-name \"{$wancfg['dhcphostname']}\";\n";
1831
	} else {
1832
		$dhclientconf_hostname = "";
1833
	}
1834

    
1835
	$wanif = get_real_interface($interface);
1836

    
1837
 	$dhclientconf = "";
1838
	
1839
	$dhclientconf .= <<<EOD
1840
interface "{$wanif}" {
1841
timeout 60;
1842
retry 1;
1843
select-timeout 0;
1844
initial-interval 1;
1845
	{$dhclientconf_hostname}
1846
	script "/sbin/dhclient-script";
1847
}
1848

    
1849
EOD;
1850

    
1851
if(is_ipaddr($wancfg['alias-address'])) {
1852
	$subnetmask = gen_subnet_mask($wancfg['alias-subnet']);
1853
	$dhclientconf .= <<<EOD
1854
alias {
1855
	interface  "{$wanif}";
1856
	fixed-address {$wancfg['alias-address']};
1857
	option subnet-mask {$subnetmask};
1858
}
1859

    
1860
EOD;
1861
}
1862
	fwrite($fd, $dhclientconf);
1863
	fclose($fd);
1864

    
1865
	$realwanif = $wancfg['if'];
1866

    
1867
	/* bring wan interface up before starting dhclient */
1868
	if($realwanif)
1869
		interfaces_bring_up($realwanif);
1870
	else 
1871
		log_error("Could not bring realwanif up in interface_dhcp_configure()");
1872

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

    
1876
	return 0;
1877
}
1878

    
1879
function interface_pppoe_configure($interface = "wan") {
1880
	global $config, $g;
1881

    
1882
	$wancfg = $config['interfaces'][$interface];
1883

    
1884
	/* generate mpd.conf */
1885
	$fd = fopen("{$g['varetc_path']}/mpd_{$interface}.conf", "w");
1886
	if (!$fd) {
1887
		printf("Error: cannot open mpd_{$interface}.conf in interface_pppoe_configure().\n");
1888
		return 1;
1889
	}
1890

    
1891
	$idle = 0;
1892

    
1893
	if (isset($wancfg['ondemand'])) {
1894
		$ondemand = "enable";
1895
		if ($wancfg['timeout'])
1896
			$idle = $wancfg['timeout'];
1897
	} else {
1898
		$ondemand = "disable";
1899
	}
1900

    
1901
	$mpdconf = <<<EOD
1902
startup:
1903
pppoeclient:
1904

    
1905
EOD;
1906

    
1907
	if ($interface == "wan")
1908
		$realif = "pppoe0";
1909
	else {
1910
		// Here code assumes only that strings of form "opt#" will be passed.
1911
		$realif = "pppoe" . substr($interface, 3); 
1912
	}
1913
	
1914
	$mpdconf .= <<<EOD
1915
	new -i {$realif} pppoeclient pppoeclient
1916

    
1917
EOD;
1918
	if ($interface == "wan")
1919
		$mpdconf .= <<<EOD
1920
	set iface route default
1921

    
1922
EOD;
1923
	
1924
	$mpdconf .= <<<EOD
1925
	set iface {$ondemand} on-demand
1926
	set iface idle {$idle}
1927
	set iface enable tcpmssfix
1928
	set iface up-script /usr/local/sbin/ppp-linkup
1929
	set iface down-script /usr/local/sbin/ppp-linkdown
1930

    
1931
EOD;
1932

    
1933
	if (isset($wancfg['ondemand'])) {
1934
		if (isset($wancfg['local-ip']) && isset($wancfg['remote-ip'])) {
1935
			$mpdconf .= <<<EOD
1936
	set iface addrs {$wancfg['local-ip']} {$wancfg['remote-ip']}
1937

    
1938
EOD;
1939
		} else {
1940
			$mpdconf .= <<<EOD
1941
	set iface addrs 192.0.2.112 192.0.2.113
1942

    
1943
EOD;
1944
		}
1945
	}
1946

    
1947
	$mpdconf .= <<<EOD
1948
	set bundle disable multilink
1949
	set auth authname "{$wancfg['pppoe_username']}"
1950
	set auth password "{$wancfg['pppoe_password']}"
1951
	set link keep-alive 10 60
1952
	set link max-redial 0
1953
	set link no acfcomp protocomp
1954
	set link disable pap chap
1955
	set link accept chap
1956
	
1957
EOD;
1958
	if (empty($wancfg['mtu']))
1959
		$mpdmtu = "1492";
1960
	else 
1961
		$mpdmtu = "{$wancfg['mtu']}";
1962

    
1963
	$mpdconf .= <<<EOD
1964
	set link mtu {$mpdmtu}
1965
	set ipcp yes vjcomp
1966
	set ipcp ranges 0.0.0.0/0 0.0.0.0/0
1967

    
1968
EOD;
1969

    
1970
	if (isset($config['system']['dnsallowoverride'])) {
1971
		$mpdconf .= <<<EOD
1972
	set ipcp enable req-pri-dns
1973

    
1974
EOD;
1975
	}
1976

    
1977
	if (!isset($wancfg['dnsnosec']) && isset($config['system']['dnsallowoverride'])) {
1978
			$mpdconf .= <<<EOD
1979
	set ipcp enable req-sec-dns
1980

    
1981
EOD;
1982
	}
1983
	
1984
	$mpdconf .= <<<EOD
1985
	open
1986

    
1987
EOD;
1988

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

    
1992
	/* generate mpd.links */
1993
	$fd = fopen("{$g['varetc_path']}/mpd_{$interface}.links", "w");
1994
	if (!$fd) {
1995
		printf("Error: cannot open mpd_{$interface}.links in interface_pppoe_configure().\n");
1996
		return 1;
1997
	}
1998

    
1999
	$mpdconf = <<<EOD
2000
pppoeclient:
2001
	set link type pppoe
2002
	set pppoe iface {$wancfg['if']}
2003
	set pppoe service "{$wancfg['provider']}"
2004
	set pppoe enable originate
2005
	set pppoe disable incoming
2006

    
2007
EOD;
2008

    
2009
	fwrite($fd, $mpdconf);
2010
	fclose($fd);
2011

    
2012
	if(file_exists("{$g['varrun_path']}/pppoe_{$interface}.pid") and $g['booting']) {
2013
		/* if we are booting and mpd has already been started then don't start again. */
2014
	} else {
2015
		/* if mpd is active, lets take it down */
2016
		if(file_exists("{$g['varrun_path']}/pppoe_{$interface}.pid")) {
2017
			killbypid("{$g['varrun_path']}/pppoe_{$interface}.pid");
2018
			sleep(3);
2019
		}
2020

    
2021
		/* Bring the parent interface up */
2022
		if($wancfg['if'])
2023
			interfaces_bring_up($wancfg['if']);
2024
		else 
2025
			log_error("Could not bring wancfg['if'] up in interface_pppoe_configure()");
2026

    
2027
		/* fire up mpd */
2028
		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");
2029
	}
2030

    
2031
	/* sleep until wan is up - or 30 seconds, whichever comes first */
2032
	for ($count = 0; $count < 30; $count++) {
2033
		if(file_exists("{$g['tmp_path']}/{$realif}up")) {
2034
			break;
2035
		}
2036
		sleep(1);
2037
	}
2038

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

    
2041
	return 0;
2042
}
2043

    
2044
function interface_pptp_configure($interface) {
2045
	global $config, $g;
2046

    
2047
	$wancfg = $config['interfaces'][$interface];
2048

    
2049
	/* generate mpd.conf */
2050
	$fd = fopen("{$g['varetc_path']}/mpd_{$interface}.conf", "w");
2051
	if (!$fd) {
2052
		printf("Error: cannot open mpd_{$interface}.conf in interface_pptp_configure().\n");
2053
		return 1;
2054
	}
2055

    
2056
	$idle = 0;
2057

    
2058
	if (isset($wancfg['ondemand'])) {
2059
		$ondemand = "enable";
2060
		if ($wancfg['timeout'])
2061
			$idle = $wancfg['timeout'];
2062
	} else {
2063
		$ondemand = "disable";
2064
	}
2065

    
2066
	$mpdconf = <<<EOD
2067
startup:
2068
pptp:
2069

    
2070
EOD;
2071

    
2072
        if ($interface == "wan")
2073
                $realif = "pptp0";
2074
        else {
2075
                // Here code assumes only that strings of form "opt#" will be passed.
2076
                $realif = "pptp" . substr($interface, 3);
2077
	}
2078

    
2079
        $mpdconf .= <<<EOD
2080
        new -i {$realif} pptp pptp 
2081

    
2082
EOD;
2083
        if ($interface == "wan")
2084
                $mpdconf .= <<<EOD
2085
        set iface route default
2086

    
2087
EOD;
2088

    
2089
        $mpdconf .= <<<EOD
2090
	set iface {$ondemand} on-demand
2091
	set iface idle {$idle}
2092
	set iface up-script /usr/local/sbin/ppp-linkup
2093
	set iface down-script /usr/local/sbin/ppp-linkdown
2094

    
2095
EOD;
2096

    
2097
	if (isset($wanfg['ondemand'])) {
2098
		$mpdconf .= <<<EOD
2099
	set iface addrs 10.0.0.1 10.0.0.2
2100

    
2101
EOD;
2102
	}
2103

    
2104
	$mpdconf .= <<<EOD
2105
	set bundle disable multilink
2106
	set auth authname "{$wancfg['pptp_username']}"
2107
	set auth password "{$wancfg['pptp_password']}"
2108
	set bundle no noretry
2109
	set link keep-alive 10 60
2110
	set link max-redial 0
2111
	set link no acfcomp protocomp
2112
	set link disable pap chap
2113
	set link accept chap
2114
	set ipcp no vjcomp
2115
	set ipcp ranges 0.0.0.0/0 0.0.0.0/0
2116

    
2117
EOD;
2118
	if (isset($config['system']['dnsallowoverride'])) {
2119
		$mpdconf .= <<<EOD
2120
	set ipcp enable req-pri-dns
2121

    
2122
EOD;
2123
	}
2124

    
2125
	$mpdconf .= <<<EOD
2126
	open
2127

    
2128
EOD;
2129

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

    
2133
	/* generate mpd.links */
2134
	$fd = fopen("{$g['varetc_path']}/mpd_{$interface}.links", "w");
2135
	if (!$fd) {
2136
		printf("Error: cannot open mpd_{$interface}.links in interface_pptp_configure().\n");
2137
		return 1;
2138
	}
2139

    
2140
	$mpdconf = <<<EOD
2141
pptp:
2142
	set link type pptp
2143
	set pptp enable originate outcall
2144
	set pptp disable windowing
2145
	set pptp self {$wancfg['local']}
2146
	set pptp peer {$wancfg['remote']}
2147

    
2148
EOD;
2149

    
2150
	fwrite($fd, $mpdconf);
2151
	fclose($fd);
2152

    
2153
	/* configure interface */
2154
	if($wancfg['if'])
2155
		mwexec("/sbin/ifconfig " . escapeshellarg($wancfg['if']) . " " .
2156
			escapeshellarg($wancfg['local'] . "/" . $wancfg['subnet']) . " up");
2157
	else 
2158
		log_error("Could not bring interface wancfg['if'] up in interface_pptp_configure()");
2159
	/* fire up mpd */
2160
	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");
2161

    
2162
	return 0;
2163
}
2164

    
2165
function interfaces_group_setup() {
2166
	global $config;
2167

    
2168
	if (!is_array($config['ifgroups']['ifgroupentry']))
2169
		return;
2170

    
2171
	foreach ($config['ifgroups']['ifgroupentry'] as $groupar)
2172
		interface_group_setup($groupar);
2173

    
2174
	return;
2175
}
2176

    
2177
function interface_group_setup(&$groupname /* The parameter is an array */) {
2178
	global $config;
2179

    
2180
	if (!is_array($groupname))
2181
		return;
2182
	$members = explode(" ", $groupname['members']);
2183
	foreach($members as $ifs) {
2184
		$realif = get_real_interface($ifs);
2185
		if ($realif)
2186
			mwexec("/sbin/ifconfig {$realif} group {$groupname['ifname']}");
2187
	}
2188

    
2189
	return;
2190
}
2191
 
2192
/* COMPAT Function */
2193
function convert_friendly_interface_to_real_interface_name($interface) {
2194
	return get_real_interface($interface);
2195
}
2196

    
2197
/* COMPAT Function */
2198
function get_real_wan_interface($interface = "wan") {
2199
	return get_real_interface($interface);
2200
}
2201

    
2202
/* COMPAT Function */
2203
function get_current_wan_address($interface = "wan") {
2204
	return get_interface_ip($interface);
2205
}
2206

    
2207
/*
2208
 * convert_real_interface_to_friendly_interface_name($interface): convert fxp0 -> wan, etc.
2209
 */
2210
function convert_real_interface_to_friendly_interface_name($interface = "wan") {
2211
        global $config;
2212

    
2213
        if (stristr($interface, "pppoe")) {
2214
                $index = substr($interface, 5);
2215
                if (intval($index) > 0)
2216
                        return "opt{$index}";
2217
                else
2218
                        return "wan";
2219
        } else if (stristr($interface, "pptp")) {
2220
                $index = substr($interface, 4);
2221
                if (intval($index) > 0)
2222
                        return "opt{$index}";
2223
                else
2224
                        return "wan";
2225
	} else if (stristr($interface, "vip")) {
2226
                $index = substr($interface, 3);
2227
                $counter = 0;
2228
                foreach ($config['virtualip']['vip'] as $vip) {
2229
                        if ($vip['mode'] == "carpdev-dhcp" || $vip['mode'] == "carp")  {
2230
                                if (intval($index) == $counter)
2231
                                        return $vip['interface'];
2232
                                $counter++;
2233
                        }
2234
                }
2235
        } else if (stristr($interface, "carp")) {
2236
                $index = substr($interface, 4);
2237
                $counter = 0;
2238
                foreach ($config['virtualip']['vip'] as $vip) {
2239
                        if ($vip['mode'] == "carpdev-dhcp" || $vip['mode'] == "carp")  {
2240
                                if (intval($index) == $counter)
2241
                                        return $vip['interface'];
2242
                                $counter++;
2243
                        }
2244
                }
2245
        }
2246

    
2247
        /* if list */
2248
        $ifdescrs = get_configured_interface_list(false, true);
2249

    
2250
        foreach ($ifdescrs as $if => $ifname) {
2251
                if($config['interfaces'][$if]['if'] == $interface)
2252
                        return $ifname;
2253

    
2254
                /* XXX: ermal - The 3 lines below are totally bogus code. */
2255
                $int = interface_translate_type_to_real($if);
2256
                if($ifname == $interface)
2257
                        return $ifname;
2258

    
2259
                if($int == $interface)
2260
                        return $ifname;
2261
        }
2262
        return NULL;
2263
}
2264

    
2265
/* attempt to resolve interface to friendly descr */
2266
function convert_friendly_interface_to_friendly_descr($interface) {
2267
        global $config;
2268

    
2269
        switch ($interface) {
2270
                case "l2tp":
2271
                                $ifdesc = "L2TP";
2272
                                break;
2273
                case "pptp":
2274
                                $ifdesc = "pptp";
2275
                                break;
2276
                case "pppoe":
2277
                                $ifdesc = "pppoe";
2278
                                break;
2279
                case "openvpn":
2280
                                $ifdesc = "OpenVPN";
2281
                                break;
2282
                case "enc0":
2283
                        case "ipsec":
2284
                                $ifdesc = "IPsec";
2285
                                break;
2286
        default:
2287
                /* if list */
2288
                $ifdescrs = get_configured_interface_with_descr(false, true);
2289
                foreach ($ifdescrs as $if => $ifname) {
2290
                                if ($if == $interface || $ifname == $interface)
2291
                                        return $ifname;
2292
                }
2293
                break;
2294
        }
2295

    
2296
        return $ifdesc;
2297
}
2298

    
2299
function convert_real_interface_to_friendly_descr($interface) {
2300
        global $config;
2301

    
2302
        $ifdesc = convert_real_interface_to_friendly_interface_name("{$interface}");
2303

    
2304
        if ($ifdesc) {
2305
                $iflist = get_configured_interface_with_descr(false, true);
2306
                return $iflist[$ifdesc];
2307
        }
2308

    
2309
        return $interface;
2310
}
2311

    
2312
/*
2313
 *  interface_translate_type_to_real($interface):
2314
 *              returns the real hardware interface name for a friendly interface.  ie: wan
2315
 */
2316
function interface_translate_type_to_real($interface) {
2317
        global $config;
2318

    
2319
        if ($config['interfaces'][$interface]['if'] <> "")
2320
                return $config['interfaces'][$interface]['if'];
2321
        else
2322
		return $interface;
2323
}
2324

    
2325
function get_real_interface($interface = "wan") {
2326
    global $config;
2327

    
2328
	$wanif = NULL;
2329

    
2330
	switch ($interface) {
2331
	case "l2tp":
2332
		$wanif = "l2tp";
2333
		break;
2334
	case "pptp":
2335
		$wanif = "pptp";
2336
		break;
2337
	case "pppoe":
2338
		$wanif = "pppoe";
2339
		break;
2340
	case "openvpn":
2341
		$wanif = "openvpn";
2342
		break;
2343
	case "ipsec":
2344
	case "enc0":
2345
		$wanif = "enc0";
2346
		break;
2347
	case "ppp":
2348
		$wanif = "ppp";
2349
		break;
2350
	default:
2351
		$iflist = get_configured_interface_with_descr(false, true);
2352

    
2353
		foreach ($iflist as $if => $ifdesc) {
2354
			// If a real interface was alread passed simply
2355
			// pass the real interface back.  This encourages
2356
			// the usage of this function in more cases so that
2357
			// we can combine logic for more flexibility.
2358
			if($config['interfaces'][$if]['if'] == $interface) {
2359
				if(does_interface_exist($interface)) {
2360
					$wanif = $interface;
2361
					break;
2362
				}
2363
			}
2364

    
2365
			if ($interface == $if || $interface == $ifdesc) {
2366

    
2367
			// PPP Support
2368
			if($config['interfaces'][$if]['serialport']) {
2369
				$dev = $config['interfaces'][$if]['serialport'];
2370
				if(file_exists("/var/run/{$dev}.if")) {
2371
					$wanif = trim(file_get_contents("/var/run/{$dev}.if"));
2372
				} else
2373
					$wanif = "Not connected";
2374

    
2375
				break;
2376
			}
2377

    
2378
			$cfg = $config['interfaces'][$if];
2379

    
2380
			// Wireless cloned NIC support (FreeBSD 8+)
2381
			// interface name format: $parentnic_wlanparentnic#
2382
			// example: ath0_wlan0
2383
			if(is_interface_wireless($cfg['if'])) {
2384
				if ($interface == "wan")
2385
					$interface_num = 0;
2386
				else
2387
					$interface_num = substr($interface, 3);
2388
				$wanif = $cfg['if'] . "_wlan" . $interface_num;
2389
				break;
2390
			}
2391

    
2392
			if (empty($cfg['ipaddr'])) {
2393
				$wanif = $cfg['if'];
2394
				break;
2395
			}
2396

    
2397
			switch ($cfg['ipaddr']) {
2398
				case "carpdev-dhcp":
2399
					$viparr = &$config['virtualip']['vip'];
2400
					$counter = 0;
2401
					if(is_array($viparr))
2402
					foreach ($viparr as $vip) {
2403
						if ($vip['mode'] == "carpdev-dhcp") {
2404
							if($vip['interface'] == $if) {
2405
								$wanif =  "carp{$counter}";
2406
								break;
2407
							}
2408
							$counter++;
2409
						} else if ($vip['mode'] = "carp") 
2410
							$counter++;
2411
					}
2412
					break;
2413
				case "pppoe": 
2414
					if ($if == "wan")
2415
						$wanif = "pppoe0";
2416
					else
2417
						$wanif = "pppoe" . substr($if,3);
2418
					break;
2419
				case "pptp": 
2420
					if ($if == "wan")
2421
						$wanif = "pptp0";
2422
					else
2423
						$wanif = "pptp" . substr($if, 3);
2424
					break;
2425
				default:
2426
					$wanif = $cfg['if'];
2427
					break;
2428
				}
2429
			
2430
				break;
2431
			}
2432
		}
2433
		break;
2434
	}
2435

    
2436
    return $wanif;
2437
}
2438

    
2439
/* Guess the physical interface by providing a IP address */
2440
function guess_interface_from_ip($ipaddress) {
2441
	if(! is_ipaddr($ipaddress)) {
2442
		return false;
2443
	}
2444
	/* create a route table we can search */
2445
	exec("netstat -rnW", $output, $ret);
2446
	foreach($output as $line) {
2447
		if(preg_match("/^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\/[0-9]+[ ]+link[#]/", $line)) {
2448
			$fields = preg_split("/[ ]+/", $line);
2449
			if(ip_in_subnet($ipaddress, $fields[0])) {
2450
				return $fields[6];
2451
			}
2452
		}
2453
	}
2454
	$ret = exec_command("/sbin/route -n get {$ipaddress} | /usr/bin/awk '/interface/ { print \$2; };'");
2455
	if(empty($ret)) {
2456
        	return false;
2457
	}
2458
	return $ret;
2459
}
2460

    
2461
/*
2462
 * find_ip_interface($ip): return the interface where an ip is defined
2463
 */
2464
function find_ip_interface($ip)
2465
{
2466
        /* if list */
2467
        $ifdescrs = get_configured_interface_list();
2468

    
2469
        foreach ($ifdescrs as $ifdescr => $ifname) {
2470
		if ($ip == get_interface_ip($ifname)) {
2471
                	$int = get_real_interface($ifname);
2472
			return $int;
2473
		}
2474
        }
2475
        return false;
2476
}
2477

    
2478
/*
2479
 *   find_number_of_created_carp_interfaces: return the number of carp interfaces
2480
 */
2481
function find_number_of_created_carp_interfaces() {
2482
	return `/sbin/ifconfig | grep "carp:" | wc -l`;
2483
}
2484

    
2485
function get_all_carp_interfaces() {
2486
	$ints = str_replace("\n", " ", `ifconfig | grep "carp:" -B2 | grep ": flag" | cut -d: -f1`);
2487
	return $ints;
2488
}
2489

    
2490
/*
2491
 * find_carp_interface($ip): return the carp interface where an ip is defined
2492
 */
2493
function find_carp_interface($ip) {
2494
	global $config;
2495
	if (is_array($config['virtualip']['vip'])) {
2496
		foreach ($config['virtualip']['vip'] as $vip) {
2497
			if ($vip['mode'] == "carp" || $vip['mode'] == "carpdev") {
2498
				$carp_ip = get_interface_ip($vip['interface']);
2499
				$if = `ifconfig | grep '$ip' -B1 | head -n1 | cut -d: -f1`;
2500
				if ($if)
2501
					return $if;
2502
			}
2503
		}
2504
	}
2505
}
2506

    
2507
function link_carp_interface_to_parent($interface) {
2508
        global $config;
2509

    
2510
        if ($interface == "")
2511
                return;
2512

    
2513
        $carp_ip = get_interface_ip($interface);
2514
        if (!is_ipaddr($carp_ip))
2515
                return;
2516

    
2517
        /* if list */
2518
        $ifdescrs = get_configured_interface_list();
2519
        foreach ($ifdescrs as $ifdescr => $ifname) {
2520
                $interfaceip = get_interface_ip($ifname);
2521
                $subnet_bits = get_interface_subnet($ifname);
2522
                $subnet_ip = gen_subnet("{$interfaceip}", "{$subnet_bits}");
2523
                if(ip_in_subnet($carp_ip, "{$subnet_ip}/{$subnet_bits}"))
2524
                        return $ifname;
2525
        }
2526

    
2527
        return "";
2528
}
2529

    
2530
/****f* interfaces/link_ip_to_carp_interface
2531
 * NAME
2532
 *   link_ip_to_carp_interface - Find where a CARP interface links to.
2533
 * INPUTS
2534
 *   $ip
2535
 * RESULT
2536
 *   $carp_ints
2537
 ******/
2538
function link_ip_to_carp_interface($ip) {
2539
        global $config;
2540

    
2541
        if (!is_ipaddr($ip))
2542
                return;
2543

    
2544
        $carp_ints = "";
2545
        if (is_array($config['virtualip']['vip'])) {
2546
                foreach ($config['virtualip']['vip'] as $vip) {
2547
                        if ($vip['mode'] == "carp" || $vip['mode'] == "carpdev") {
2548
                                $carp_ip = $vip['subnet'];
2549
                                $carp_sn = $vip['subnet_bits'];
2550
                                $carp_nw = gen_subnet($carp_ip, $carp_sn);
2551
                                if (ip_in_subnet($ip, "{$carp_nw}/{$carp_sn}")) {
2552
                                        if (!stristr($carp_ints, $carp_int))
2553
                                                $carp_ints .= " {$carp_int}";
2554
                                }
2555
                        }
2556
                }
2557
        }
2558

    
2559
        return $carp_ints;
2560
}
2561

    
2562
function link_interface_to_vlans($int, $action = "") {
2563
	global $config;
2564

    
2565
	if (empty($int))
2566
		return;
2567

    
2568
	$real_if = get_real_interface($int);
2569
	if (is_array($config['vlans']['vlan'])) {
2570
                foreach ($config['vlans']['vlan'] as $vlan) {
2571
			if ($real_int == $vlan['if']) {
2572
				if ($action == "update") {
2573
					foreach ($config['interfaces'] as $ifname => $ifcfg) {
2574
						if ($ifcfg['if'] == $vlan['vlanif'])
2575
							interface_vlan_configure($vlan);
2576
							interface_configure($ifname);
2577
					}
2578
				} else if ($action == "")
2579
					return $vlan;
2580
			}
2581
		}
2582
	}
2583
}
2584

    
2585
function link_interface_to_vips($int, $action = "") {
2586
        global $config;
2587

    
2588
        if (is_array($config['virtualip']['vip']))
2589
                foreach ($config['virtualip']['vip'] as $vip)
2590
                        if ($int == $vip['interface']) {
2591
				if ($action == "update")
2592
					interfaces_vips_configure($int);
2593
				else
2594
                                	return $vip;
2595
			}
2596
}
2597

    
2598
/****f* interfaces/link_interface_to_bridge
2599
 * NAME
2600
 *   link_interface_to_bridge - Finds out a bridge group for an interface
2601
 * INPUTS
2602
 *   $ip
2603
 * RESULT
2604
 *   bridge[0-99]
2605
 ******/
2606
function link_interface_to_bridge($int) {
2607
        global $config;
2608

    
2609
        if (is_array($config['bridges']['bridged']))
2610
                foreach ($config['bridges']['bridged'] as $bridge)
2611
                        if(stristr($bridge['members'], "{$int}"))
2612
                                return "{$bridge['bridgeif']}";
2613
}
2614

    
2615
function link_interface_to_gre($interface) {
2616
        global $config;
2617

    
2618
        if (is_array($config['gres']['gre']))
2619
                foreach ($config['gres']['gre'] as $gre)
2620
                        if($gre['if'] == $interface)
2621
                                return "{$gre['greif']}";
2622
}
2623

    
2624
function link_interface_to_gif($interface) {
2625
        global $config;
2626

    
2627
        if (is_array($config['gifs']['gif']))
2628
                foreach ($config['gifs']['gif'] as $gif)
2629
                        if($gif['if'] == $interface)
2630
                                return "{$gif['gifif']}";
2631
}
2632

    
2633
/*
2634
 * find_interface_ip($interface): return the interface ip (first found)
2635
 */
2636
function find_interface_ip($interface, $flush = false)
2637
{
2638
	global $interface_ip_arr_cache;
2639

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

    
2645
	/* Setup IP cache */
2646
	if (!isset($interface_ip_arr_cache[$interface]) or $flush) {
2647
		$ifinfo = pfSense_get_interface_addresses($interface);
2648
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
2649
	}
2650

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

    
2654
function find_interface_subnet($interface, $flush = false)
2655
{
2656
	global $interface_sn_arr_cache;
2657

    
2658
	$interface = str_replace("\n", "", $interface);
2659
	if (does_interface_exist($interface) == false)
2660
		return;
2661

    
2662
	if (!isset($interface_sn_arr_cache[$interface]) or $flush) {
2663
		if (preg_match("/^tun|^ppp|^pptp|^pppoe|^ovpn|^gif|^gre/i", $interface))
2664
			$interface_sn_arr_cache[$interface] = `/sbin/ifconfig {$interface} | /usr/bin/grep -w "inet" | /usr/bin/cut -d" " -f 6 | /usr/bin/head -1`;
2665
		else
2666
			$interface_sn_arr_cache[$interface] = `/sbin/ifconfig {$interface} | /usr/bin/grep -w "inet" | /usr/bin/cut -d" " -f 4 | /usr/bin/head -1`;
2667
		$interface_sn_arr_cache[$interface] = strlen(str_replace("0", "", base_convert(str_replace("\n", "", $interface_sn_arr_cache[$interface]),16, 2)));
2668
        }
2669

    
2670
	return $interface_sn_arr_cache[$interface];
2671
}
2672

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

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

    
2689
	$curip = find_interface_ip($realif);
2690
	if ($curip && is_ipaddr($curip) && ($curip != "0.0.0.0"))
2691
		return $curip;
2692

    
2693
	return null;
2694
}
2695

    
2696
function get_interface_subnet($interface = "wan")
2697
{
2698
	$realif = get_real_interface($interface);
2699
	if (!$realif) {
2700
                if (preg_match("/^carp/i", $interface))
2701
                        $realif = $interface;
2702
                else if (preg_match("/^vip/i", $interface))
2703
                        $realif = $interface;
2704
                else
2705
                        return null;
2706
        }
2707

    
2708
	/* Do we really come here for these interfaces ?! */
2709
	if (in_array($realif, array("pptp", "pppoe", "l2tp", "openvpn", "enc0" /* , "ppp" */)))
2710
		return "";
2711

    
2712
	$cursn = find_interface_subnet($realif);
2713
	if (!empty($cursn))
2714
		return $cursn;
2715

    
2716
	return null;
2717
}
2718

    
2719
/* return outside interfaces with a gateway */
2720
function get_interfaces_with_gateway() {
2721
	global $config;
2722

    
2723
	$ints = array();
2724

    
2725
	/* loop interfaces, check config for outbound */
2726
	foreach($config['interfaces'] as $ifdescr => $ifname) {
2727
		if($ifname['serialport']) {
2728
			$ints[] = $ifdescr;
2729
			continue;
2730
		}
2731
		switch ($ifname['ipaddr']) {
2732
			case "dhcp":
2733
			case "carpdev-dhcp":
2734
			case "pppoe":
2735
			case "pptp":
2736
			$ints[] = $ifdescr;
2737
			break;
2738
			default:
2739
			if ($ifname['pointtopoint'])
2740
				$ints[] = $ifdescr;
2741
			else if (!empty($ifname['gateway']))
2742
				$ints[] = $ifdescr;
2743
			break;
2744
		}
2745
	}
2746
	return $ints;
2747
}
2748

    
2749
/* return true if interface has a gateway */
2750
function interface_has_gateway($friendly) {
2751

    
2752
        $friendly = strtolower($friendly);
2753
        if (in_array($friendly, get_interfaces_with_gateway()))
2754
                return true;
2755

    
2756
	return false;
2757
}
2758

    
2759
/****f* interfaces/is_altq_capable
2760
 * NAME
2761
 *   is_altq_capable - Test if interface is capable of using ALTQ
2762
 * INPUTS
2763
 *   $int            - string containing interface name
2764
 * RESULT
2765
 *   boolean         - true or false
2766
 ******/
2767

    
2768
function is_altq_capable($int) {
2769
        /* Per:
2770
         * http://www.freebsd.org/cgi/man.cgi?query=altq&manpath=FreeBSD+7.2-current&format=html
2771
         * Only the following drivers have ALTQ support
2772
         */
2773
	$capable = array("age", "ale", "an", "ath", "aue", "awi", "bce",
2774
			"bfe", "bge", "dc", "de", "ed", "em", "ep", "fxp", "gem",
2775
			"hme", "ipw", "iwi", "jme", "le", "msk", "mxge", "my", "nfe",
2776
			"npe", "nve", "ral", "re", "rl", "rum", "sf", "sis", "sk",
2777
			"ste", "stge", "txp", "udav", "ural", "vge", "vr", "wi", "xl",
2778
			"ndis", "tun", "ovpns", "ovpnc", "vlan", "pppoe", "pptp", "ng", "ppp");
2779

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

    
2782
        if (in_array($int_family[0], $capable))
2783
                return true;
2784
	else if (stristr($int_family, "vlan")) /* VLANs are name $parent.$vlan now */
2785
		return true;
2786
        else
2787
                return false;
2788
}
2789

    
2790
/****f* interfaces/is_interface_ppp
2791
 * NAME
2792
 *   is_interface_ppp - Returns if an interface is ppp
2793
 * RESULT
2794
 *   $tmp       - Returns if an interface is ppp
2795
 ******/
2796
function is_interface_ppp($interface) {
2797
	global $config, $g;
2798

    
2799
	$friendly = convert_real_interface_to_friendly_interface_name($interface);
2800
	if(isset($config['interfaces'][$friendly]['serialport'])) 
2801
		return true;
2802

    
2803
	return false;
2804
}
2805

    
2806
/****f* interfaces/is_interface_wireless
2807
 * NAME
2808
 *   is_interface_wireless - Returns if an interface is wireless
2809
 * RESULT
2810
 *   $tmp       - Returns if an interface is wireless
2811
 ******/
2812
function is_interface_wireless($interface) {
2813
        global $config, $g;
2814

    
2815
        $friendly = convert_real_interface_to_friendly_interface_name($interface);
2816
        if(!isset($config['interfaces'][$friendly]['wireless'])) {
2817
                if (preg_match($g['wireless_regex'], $interface)) {
2818
                        $config['interfaces'][$friendly]['wireless'] = array();
2819
                        return true;
2820
                }
2821
                unset($config['interfaces'][$friendly]['wireless']);
2822
                return false;
2823
        } else
2824
                return true;
2825
}
2826

    
2827
function get_wireless_modes($interface) {
2828
	/* return wireless modes and channels */
2829
	$wireless_modes = array();
2830

    
2831
	$wlif = interface_translate_type_to_real($interface);
2832

    
2833
	if(is_interface_wireless($wlif)) {
2834
		$cloned_interface = get_real_interface($interface);
2835
		$wi = 1;
2836
		$chan_list = "/sbin/ifconfig {$cloned_interface} list chan";
2837
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
2838
		$format_list = "/usr/bin/awk '{print \$5 \" \" \$6 \",\" \$1}'";
2839

    
2840
		$interface_channels = "";
2841
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
2842
		$interface_channel_count = count($interface_channels);
2843

    
2844
		$c = 0;
2845
		while ($c < $interface_channel_count)
2846
		{
2847
			$channel_line = explode(",", $interface_channels["$c"]);
2848
			$wireless_mode = trim($channel_line[0]);
2849
			$wireless_channel = trim($channel_line[1]);
2850
			if(trim($wireless_mode) != "") {
2851
				/* if we only have 11g also set 11b channels */
2852
				if($wireless_mode == "11g") {
2853
					$wireless_modes["11b"] = array();
2854
				}
2855
				$wireless_modes["$wireless_mode"]["$c"] = $wireless_channel;
2856
			}
2857
			$c++;
2858
		}
2859
	}
2860
	return($wireless_modes);
2861
}
2862

    
2863
/****f* interfaces/get_interface_mtu
2864
 * NAME
2865
 *   get_interface_mtu - Return the mtu of an interface
2866
 * RESULT
2867
 *   $tmp       - Returns the mtu of an interface
2868
 ******/
2869
function get_interface_mtu($interface) {
2870
        $mtu = `/sbin/ifconfig {$interface} | /usr/bin/grep mtu | /usr/bin/cut -d" " -f6`;
2871
        return $mtu;
2872
}
2873

    
2874
function get_interface_mac($interface) {
2875

    
2876
	$macinfo = pfSense_get_interface_addresses($interface);
2877
	return $macinfo["macaddr"];
2878
}
2879

    
2880
/****f* pfsense-utils/generate_random_mac_address
2881
 * NAME
2882
 *   generate_random_mac - generates a random mac address
2883
 * INPUTS
2884
 *   none
2885
 * RESULT
2886
 *   $mac - a random mac address
2887
 ******/
2888
function generate_random_mac_address() {
2889
        $mac = "02";
2890
        for($x=0; $x<5; $x++)
2891
                $mac .= ":" . dechex(rand(16, 255));
2892
        return $mac;
2893
}
2894

    
2895
/****f* interfaces/is_jumbo_capable
2896
 * NAME
2897
 *   is_jumbo_capable - Test if interface is jumbo frame capable.  Useful for determining VLAN capability.
2898
 * INPUTS
2899
 *   $int             - string containing interface name
2900
 * RESULT
2901
 *   boolean          - true or false
2902
 ******/
2903
function is_jumbo_capable($int) {
2904
        global $g;
2905

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

    
2908
        if (in_array($int_family[0], $g['vlan_long_frame']))
2909
                return true;
2910
        else
2911
                return false;
2912
}
2913

    
2914
function setup_pppoe_reset_file($interface, $status) {
2915
	define("CRON_PPPOE_CMD_FILE", "/conf/pppoe{$interface}restart");
2916
	define("CRON_PPPOE_CMD", "#!/bin/sh\necho '<?php require(\"config.inc\"); require(\"interfaces.inc\"); interface_reconfigure({$interface}); ?>' | /usr/local/bin/php -q");
2917
	if ($status == true) {
2918
		if (!file_exists(CRON_PPPOE_CMD_FILE)) {
2919
			file_put_contents(CRON_PPPOE_CMD_FILE, CRON_PPPOE_CMD);
2920
			chmod(CRON_PPPOE_CMD_FILE, 0700);
2921
		}	
2922
	} else
2923
		unlink_if_exists(CRON_PPPOE_CMD_FILE);
2924
}
2925

    
2926
?>
(21-21/50)