Project

General

Profile

Download (102 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:	/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/mpd5
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
	pfSense_interface_flags($interface, IFF_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 = explode(" ", trim(`/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(true);
81
	if (in_array($interface, $ints))
82
		return true;
83
	else
84
		return false;
85
}
86

    
87
function interface_netgraph_needed($interface = "wan") {
88
	global $config;
89

    
90
	$found = false;
91
	if (!empty($config['pptpd']) &&
92
		$config['pptpd']['mode'] == "server")
93
		$found = true;
94
	if ($found == false && !empty($config['l2tp']) &&
95
		$config['l2tp']['mode'] == "server")
96
		$found = true;
97
	if ($found == false && is_array($config['pppoes']['pppoe'])) {
98
		foreach ($config['pppoes']['pppoe'] as $pppoe) {
99
			if ($pppoe['mode'] != "server")
100
				continue;
101
			if ($pppoe['interface'] == $interface)
102
				$found = true;
103
				break;
104
		}
105
	}
106
	if ($found == false && !empty($config['interfaces'][$interface])) {
107
		switch ($config['interfaces'][$interface]['ipaddr']) {
108
		case "ppp":
109
		case "pppoe":
110
		case "l2tp":
111
		case "pptp":
112
			$found = true;
113
			break;
114
		default:
115
			$found = false;
116
			break;
117
		}
118
	}
119

    
120
	if ($found == false) {
121
		$realif = get_real_interface($interface);
122
		pfSense_ngctl_detach("{$realif}:", $realif);
123
	}
124
	/* NOTE: We make sure for this on interface_ppps_configure()
125
	 *	no need to do it here agan.
126
	 *	else
127
	 *		pfSense_ngctl_attach(".", $realif);
128
	 */
129
}
130

    
131
function interfaces_loopback_configure() {
132
	if($g['booting'])
133
		echo "Configuring loopback interface...";
134
	pfSense_interface_setaddress("lo0", "127.0.0.1");
135
	interfaces_bring_up("lo0");
136
	if($g['booting'])
137
		echo "done.\n";
138
	return 0;
139
}
140

    
141
function interfaces_vlan_configure() {
142
	global $config, $g;
143
	if($g['booting'])
144
		echo "Configuring VLAN interfaces...";
145
	if (is_array($config['vlans']['vlan']) && count($config['vlans']['vlan'])) {
146
		foreach ($config['vlans']['vlan'] as $vlan) {
147
			if(empty($vlan['vlanif']))
148
				$vlan['vlanif'] = "{$vlan['if']}_vlan{$vlan['tag']}";
149
			/* XXX: Maybe we should report any errors?! */
150
			interface_vlan_configure($vlan);
151
		}
152
	}
153
	if($g['booting'])
154
		echo "done.\n";
155
}
156

    
157
function interface_vlan_configure(&$vlan) {
158
        global $config, $g;
159

    
160
	if (!is_array($vlan)) {
161
		log_error("VLAN: called with wrong options. Problems with config!");
162
		return;
163
	}
164
	$if = $vlan['if'];
165
	$vlanif  = empty($vlan['vlanif']) ? "{$if}_vlan{$vlan['tag']}" : $vlan['vlanif'];
166
	$tag = $vlan['tag'];
167

    
168
	if (empty($if)) {
169
		log_error("interface_vlan_confgure called with if undefined.");
170
		return;
171
	}
172

    
173
	/* make sure the parent interface is up */
174
	interfaces_bring_up($if);
175
	/* Since we are going to add vlan(4) try to enable all that hardware supports. */
176
	pfSense_interface_capabilities($if, IFCAP_VLAN_HWTAGGING|IFCAP_VLAN_MTU|IFCAP_VLAN_HWFILTER);
177

    
178
	if (!empty($vlanif) && does_interface_exist($vlanif)) {
179
		interface_bring_down($vlanif, true);
180
	} else {
181
		$tmpvlanif = pfSense_interface_create("vlan");
182
		pfSense_interface_rename($tmpvlanif, $vlanif);
183
		pfSense_ngctl_name("{$tmpvlanif}:", $vlanif);
184
	}
185

    
186
	pfSense_vlan_create($vlanif, $if, $tag);
187

    
188
	interfaces_bring_up($vlanif);
189

    
190
	/* invalidate interface cache */
191
	get_interface_arr(true);
192

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

    
196
	return $vlanif;
197
}
198

    
199
function interface_qinq_configure(&$vlan, $fd = NULL) {
200
        global $config, $g;
201

    
202
        if (!is_array($vlan)) {
203
                log_error("QinQ compat VLAN: called with wrong options. Problems with config!\n");
204
                return;
205
        }
206

    
207
        $qinqif = $vlan['if'];
208
        $tag = $vlan['tag'];
209
        if(empty($qinqif)) {
210
                log_error("interface_qinq_confgure called with if undefined.\n");
211
                return;
212
        }
213
	$vlanif = interface_vlan_configure($vlan);
214

    
215
        if ($fd == NULL) {
216
                $exec = true;
217
                $fd = fopen("{$g['tmp_path']}/netgraphcmd", "w");
218
        } else
219
                $exec = false;
220
        /* make sure the parent is converted to ng_vlan(4) and is up */
221
        interfaces_bring_up($qinqif);
222

    
223
        if (!empty($vlanif) && does_interface_exist($vlanif)) {
224
                fwrite($fd, "shutdown {$qinqif}qinq:\n");
225
                exec("/usr/sbin/ngctl msg {$qinqif}qinq: gettable", $result);
226
                if (empty($result)) {
227
                        fwrite($fd, "mkpeer {$qinqif}: vlan lower downstream\n");
228
                        fwrite($fd, "name {$qinqif}:lower {$vlanif}qinq\n");
229
                        fwrite($fd, "connect {$qinqif}: {$vlanif}qinq: upper nomatch\n");
230
                }
231
        } else {
232
                fwrite($fd, "mkpeer {$qinqif}: vlan lower downstream\n");
233
                fwrite($fd, "name {$qinqif}:lower {$vlanif}qinq\n");
234
                fwrite($fd, "connect {$qinqif}: {$vlanif}qinq: upper nomatch\n");
235
        }
236

    
237
        /* invalidate interface cache */
238
        get_interface_arr(true);
239

    
240
        if (!stristr($qinqif, "vlan"))
241
                mwexec("/sbin/ifconfig {$qinqif} promisc\n");
242

    
243
        $macaddr = get_interface_mac($qinqif);
244
        if (!empty($vlan['members'])) {
245
                $members = explode(" ", $vlan['members']);
246
                foreach ($members as $qtag) {
247
                        $qinq = array();
248
                        $qinq['tag'] = $qtag;
249
                        $qinq['if'] = $vlanif;
250
                        interface_qinq2_configure($qinq, $fd, $macaddr);
251
                }
252
        }
253
        if ($exec == true) {
254
                fclose($fd);
255
                mwexec("/usr/sbin/ngctl -f {$g['tmp_path']}/netgraphcmd");
256
        }
257

    
258
        interfaces_bring_up($qinqif);
259
        if (!empty($vlan['members'])) {
260
                $members = explode(" ", $vlan['members']);
261
                foreach ($members as $qif)
262
                        interfaces_bring_up("{$vlanif}_{$qif}");
263
        }
264

    
265
        return $vlanif;
266
}
267

    
268
function interfaces_qinq_configure() {
269
	global $config, $g;
270
	if($g['booting'])
271
		echo "Configuring QinQ interfaces...";
272
	if (is_array($config['qinqs']['qinqentry']) && count($config['qinqs']['qinqentry'])) {
273
		foreach ($config['qinqs']['qinqentry'] as $qinq) {
274
			/* XXX: Maybe we should report any errors?! */
275
			interface_qinq_configure($qinq);
276
		}
277
	}
278
	if($g['booting'])
279
		echo "done.\n";
280
}
281

    
282
function interface_qinq2_configure(&$qinq, $fd, $macaddr) {
283
        global $config, $g;
284

    
285
        if (!is_array($qinq)) {
286
                log_error("QinQ compat VLAN: called with wrong options. Problems with config!\n");
287
                return;
288
        }
289

    
290
        $if = $qinq['if'];
291
        $tag = $qinq['tag'];
292
        $vlanif = "{$if}_{$tag}";
293
        if(empty($if)) {
294
                log_error("interface_qinq_confgure called with if undefined.\n");
295
                return;
296
        }
297

    
298
        fwrite($fd, "shutdown {$if}h{$tag}:\n");
299
        fwrite($fd, "mkpeer {$if}qinq: eiface {$if}{$tag} ether\n");
300
        fwrite($fd, "name {$if}qinq:{$if}{$tag} {$if}h{$tag}\n");
301
        fwrite($fd, "msg {$if}qinq: addfilter { vlan={$tag} hook=\"{$if}{$tag}\" }\n");
302
        fwrite($fd, "msg {$if}h{$tag}: setifname \"{$vlanif}\"\n");
303
        fwrite($fd, "msg {$if}h{$tag}: set {$macaddr}\n");
304

    
305
        /* invalidate interface cache */
306
        get_interface_arr(true);
307

    
308
        return $vlanif;
309
}
310

    
311
function interfaces_create_wireless_clones() {
312
	global $config;
313

    
314
	if($g['booting'])
315
		echo "Creating other wireless clone interfaces...";
316
	if (is_array($config['wireless']['clone']) && count($config['wireless']['clone'])) {
317
		foreach ($config['wireless']['clone'] as $clone) {
318
			if(empty($clone['cloneif']))
319
				continue;
320
			if(does_interface_exist($clone['cloneif']))
321
				continue;
322
			/* XXX: Maybe we should report any errors?! */
323
			if(interface_wireless_clone($clone['cloneif'], $clone))
324
				if($g['booting'])
325
					echo " " . $clone['cloneif'];
326
		}
327
	}
328
	if($g['booting'])
329
		echo " done.\n";
330
}
331

    
332
function interfaces_bridge_configure() {
333
        global $config;
334

    
335
        $i = 0;
336
        if (is_array($config['bridges']['bridged']) && count($config['bridges']['bridged'])) {
337
                foreach ($config['bridges']['bridged'] as $bridge) {
338
                        if(empty($bridge['bridgeif']))
339
                                $bridge['bridgeif'] = "bridge{$i}";
340
                        /* XXX: Maybe we should report any errors?! */
341
                        interface_bridge_configure($bridge);
342
                        $i++;
343
                }
344
        }
345
}
346

    
347
function interface_bridge_configure(&$bridge) {
348
	global $config, $g;
349

    
350
	if (!is_array($bridge))
351
	        return -1;
352

    
353
	if (empty($bridge['members'])) {
354
		log_error("No members found on {$bridge['bridgeif']}");
355
		return -1;
356
	}
357

    
358
	$members = explode(',', $bridge['members']);
359
	if (!count($members))
360
		return -1;
361

    
362
	$checklist = get_configured_interface_list();
363

    
364
	if ($g['booting'] || !empty($bridge['bridgeif'])) {
365
		pfSense_interface_destroy($bridge['bridgeif']);
366
		pfSense_interface_create($bridge['bridgeif']);
367
		$bridgeif = $bridge['bridgeif'];
368
	} else
369
		$bridgeif = pfSense_interface_create("bridge");
370

    
371
	/* Calculate smaller mtu and enforce it */
372
	$smallermtu = 0;
373
	$commonrx = true;
374
	$commontx = true;
375
	foreach ($members as $member) {
376
		$realif = get_real_interface($member);
377
		$opts = pfSense_get_interface_addresses($realif);
378
		$mtu = $opts['mtu'];
379
		if (!isset($opts['encaps']['txcsum']))
380
			$commontx = false;
381
		if (!isset($opts['encaps']['rxcsum']))
382
			$commonrx = false;
383
		if (!isset($opts['encaps']['tso4']))
384
			$commontso4 = false;
385
		if (!isset($opts['encaps']['tso6']))
386
			$commontso6 = false;
387
		if (!isset($opts['encaps']['lro']))
388
			$commonlro = false;
389
		if ($smallermtu == 0 && !empty($mtu))
390
			$smallermtu = $mtu;
391
		else if (!empty($mtu) && $mtu < $smallermtu)
392
			$smallermtu = $mtu;
393
	}
394
	 
395
	/* Just in case anything is not working well */
396
	if ($smallermtu == 0)
397
		$smallermtu = 1500; 
398

    
399
	$flags = 0;
400
	if ($commonrx === false)
401
		$flags |= IFCAP_RXCSUM;
402
	if ($commontx === false)
403
		$flags |= IFCAP_TXCSUM;
404
	if ($commontso4 === false)
405
		$flags |= IFCAP_TSO4;
406
	if ($commontso6 === false)
407
		$flags |= IFCAP_TSO6;
408
	if ($commonlro === false)
409
		$flags |= IFCAP_LRO;
410
		
411
	/* Add interfaces to bridge */
412
	foreach ($members as $member) {
413
		if (!array_key_exists($member, $checklist))
414
			continue;
415
		$realif1 = get_real_interface($member);
416
		$realif =  escapeshellarg($realif1);
417
		if (!$realif) {
418
			log_error("realif not defined in interfaces bridge - up");
419
			continue;
420
		}
421
		/* make sure the parent interface is up */
422
		pfSense_interface_mtu($realif1, $smallermtu);
423
		pfSense_interface_capabilities($realif1, -$flags);
424
		interfaces_bring_up($realif1);
425
		mwexec("/sbin/ifconfig {$bridgeif} addm {$realif}");	
426
	}
427

    
428
	if (isset($bridge['enablestp'])) {
429
		/* Choose spanning tree proto */
430
		mwexec("/sbin/ifconfig {$bridgeif} proto {$bridge['proto']}");	
431
		
432
		if (!empty($bridge['stp'])) {
433
			$stpifs = explode(',', $bridge['stp']);
434
			foreach ($stpifs as $stpif) {
435
				$realif = get_real_interface($stpif);
436
				mwexec("/sbin/ifconfig {$bridgeif} stp {$realif}");
437
			}
438
		}
439
		if (!empty($bridge['maxage']))
440
			mwexec("/sbin/ifconfig {$bridgeif} maxage {$bridge['maxage']}");
441
		if (!empty($brige['fwdelay']))
442
			mwexec("/sbin/ifconfig {$bridgeif} fwddelay {$bridge['fwdelay']}");
443
		if (!empty($brige['hellotime']))
444
                        mwexec("/sbin/ifconfig {$bridgeif} hellotime {$bridge['hellotime']}");
445
		if (!empty($brige['priority']))
446
                        mwexec("/sbin/ifconfig {$bridgeif} priority {$bridge['priority']}");
447
		if (!empty($brige['holdcount']))
448
                        mwexec("/sbin/ifconfig {$bridgeif} holdcnt {$bridge['holdcnt']}");
449
		if (!empty($bridge['ifpriority'])) {
450
			$pconfig = explode(",", $bridge['ifpriority']);
451
			$ifpriority = array();
452
			foreach ($pconfig as $cfg) {
453
				$embcfg = explode(":", $cfg);
454
				foreach ($embcfg as $key => $value)
455
					$ifpriority[$key] = $value;
456
			}
457
			foreach ($ifpriority as $key => $value) {
458
				$realif = get_real_interface($key);
459
				mwexec("/sbin/ifconfig ${bridgeif} ifpriority {$realif} {$value}"); 
460
			}
461
		}
462
		if (!empty($bridge['ifpathcost'])) {
463
			$pconfig = explode(",", $bridges['ifpathcost']);
464
			$ifpathcost = array();
465
			foreach ($pconfig as $cfg) {
466
				$embcfg = explode(":", $cfg);
467
				foreach ($embcfg as $key => $value)
468
					$ifpathcost[$key] = $value;
469
			}
470
			foreach ($ifpathcost as $key => $value) {
471
                        	$realif = get_real_interface($key);
472
                        	mwexec("/sbin/ifconfig ${bridgeif} ifpathcost {$realif} {$value}");
473
                	}
474
		}
475
	}
476

    
477
	if ($bridge['maxaddr'] <> "")
478
		mwexec("/sbin/ifconfig {$bridgeif} maxaddr {$bridge['maxaddr']}");
479
        if ($bridge['timeout'] <> "")
480
                mwexec("/sbin/ifconfig {$bridgeif} timeout {$bridge['timeout']}");
481
        if ($bridge['span'] <> "") {
482
		$realif = get_real_interface($bridge['span']);
483
                mwexec("/sbin/ifconfig {$bridgeif} span {$realif}");
484
	}
485
	if (!empty($bridge['edge'])) {
486
        	$edgeifs = explode(',', $bridge['edge']);
487
        	foreach ($edgeifs as $edgeif) {
488
			$realif = get_real_interface($edgeif);
489
                	mwexec("/sbin/ifconfig {$bridgeif} edge {$realif}");
490
        	}
491
	}
492
	if (!empty($bridge['autoedge'])) {
493
        	$edgeifs = explode(',', $bridge['autoedge']);
494
        	foreach ($edgeifs as $edgeif) {
495
                	$realif = get_real_interface($edgeif);
496
                	mwexec("/sbin/ifconfig {$bridgeif} -autoedge {$realif}");
497
        	}
498
	}
499
	if (!empty($bridge['ptp'])) {
500
        	$ptpifs = explode(',', $bridge['ptp']);
501
        	foreach ($ptpifs as $ptpif) {
502
                	$realif = get_real_interface($ptpif);
503
                	mwexec("/sbin/ifconfig {$bridgeif} ptp {$realif}");
504
        	}
505
	}
506
	if (!empty($bridge['autoptp'])) {
507
        	$ptpifs = explode(',', $bridge['autoptp']);
508
        	foreach ($ptpifs as $ptpif) {
509
                	$realif = get_real_interface($ptpif);
510
                	mwexec("/sbin/ifconfig {$bridgeif} -autoptp {$realif}");
511
        	}
512
	}
513
	if (!empty($bridge['static'])) {
514
        	$stickyifs = explode(',', $bridge['static']);
515
        	foreach ($stickyifs as $stickyif) {
516
                	$realif = get_real_interface($stickyif);
517
                	mwexec("/sbin/ifconfig {$bridgeif} sticky {$realif}");
518
        	}
519
	}
520
	if (!empty($bridge['private'])) {
521
        	$privateifs = explode(',', $bridge['private']);
522
        	foreach ($privateifs as $privateif) {
523
                	$realif = get_real_interface($privateif);
524
               	 	mwexec("/sbin/ifconfig {$bridgeif} private {$realif}");
525
        	}
526
	}
527

    
528
	if($bridgeif)
529
		interfaces_bring_up($bridgeif);	
530
	else 
531
		log_error("bridgeif not defined -- could not bring interface up");
532

    
533
	return $bridgeif;
534
}
535

    
536
function interface_bridge_add_member($bridgeif, $interface) {
537

    
538
	if (!does_interface_exist($bridgeif) || !does_interface_exist($interface))
539
		return;
540

    
541
	$mtu = get_interface_mtu($brigeif);
542
	$mtum = get_interface_mtu($interface);
543
	
544
	if ($mtu != $mtum)
545
		pfSense_interface_mtu($interface, $mtu);
546

    
547
	$options = pfSense_get_interface_addresses($bridgeif);
548
	$flags = 0;
549
	if (!isset($options['encaps']['txcsum']))
550
		$flags |= IFCAP_TXCSUM;
551

    
552
	if (!isset($options['encaps']['rxcsum']))
553
		$flags |= IFCAP_RXCSUM;
554

    
555
	pfSense_interface_capabilities($interface, -$flags);
556

    
557
	interfaces_bring_up($interface);
558
	mwexec("/sbin/ifconfig {$bridgeif} addm {$interface}");
559
}
560

    
561
function interfaces_lagg_configure() 
562
{
563
        global $config, $g;
564
		if($g['booting']) 
565
			echo "Configuring LAGG interfaces...";
566
        $i = 0;
567
		if (is_array($config['laggs']['lagg']) && count($config['laggs']['lagg'])) {
568
			foreach ($config['laggs']['lagg'] as $lagg) {
569
				if(empty($lagg['laggif']))
570
					$lagg['laggif'] = "lagg{$i}";
571
				/* XXX: Maybe we should report any errors?! */
572
				interface_lagg_configure($lagg);
573
				$i++;
574
			}
575
		}
576
		if($g['booting']) 
577
			echo "done.\n";
578
}
579

    
580
function interface_lagg_configure(&$lagg) {
581
        global $config, $g;
582

    
583
        if (!is_array($lagg))
584
		return -1;
585

    
586
	$members = explode(',', $lagg['members']);
587
	if (!count($members))
588
		return -1;
589
	
590
	$checklist = get_interface_list();
591

    
592
	if ($g['booting'] || !(empty($lagg['laggif']))) {
593
		pfSense_interface_destroy($lagg['laggif']);
594
		pfSense_interface_create($lagg['laggif']);
595
                $laggif = $lagg['laggif'];
596
        } else
597
		$laggif = pfSense_interface_create("lagg");
598

    
599
	/* Calculate smaller mtu and enforce it */
600
        $smallermtu = 0;
601
        foreach ($members as $member) {
602
		$opts = pfSense_get_interface_addresses($member);
603
                $mtu = $opts['mtu'];
604
		if (!isset($opts['encaps']['txcsum']))
605
                        $commontx = false;
606
                if (!isset($opts['encaps']['rxcsum']))
607
                        $commonrx = false;
608
		if (!isset($opts['encaps']['tso4']))
609
			$commontso4 = false;
610
		if (!isset($opts['encaps']['tso6']))
611
			$commontso6 = false;
612
		if (!isset($opts['encaps']['lro']))
613
			$commonlro = false;
614
		if ($smallermtu == 0 && !empty($mtu))
615
			$smallermtu = $mtu;
616
                else if (!empty($mtu) && $mtu < $smallermtu)
617
                        $smallermtu = $mtu;
618
        }
619

    
620
	/* Just in case anything is not working well */
621
        if ($smallermtu == 0)
622
                $smallermtu = 1500;
623

    
624
	$flags = 0;
625
        if ($commonrx === false)
626
                $flags |= IFCAP_RXCSUM;
627
        if ($commontx === false)
628
                $flags |= IFCAP_TXCSUM;
629
	if ($commontso4 === false)
630
                $flags |= IFCAP_TSO4;
631
        if ($commontso6 === false)
632
                $flags |= IFCAP_TSO6;
633
        if ($commonlro === false)
634
                $flags |= IFCAP_LRO;
635

    
636
	foreach ($members as $member) {
637
		if (!array_key_exists($member, $checklist))
638
			continue;
639
		/* make sure the parent interface is up */
640
		pfSense_interface_mtu($member, $smallermtu);
641
		pfSense_interface_capabilities($member, -$flags);
642
		interfaces_bring_up($member);
643
		mwexec("/sbin/ifconfig {$laggif} laggport {$member}");
644
	}
645
	
646
	mwexec("/sbin/ifconfig {$laggif} laggproto {$lagg['proto']}");
647

    
648
	interfaces_bring_up($laggif);
649

    
650
	return $laggif;
651
}
652

    
653
function interfaces_gre_configure() {
654
        global $config;
655

    
656
        if (is_array($config['gres']['gre']) && count($config['gres']['gre'])) {
657
                foreach ($config['gres']['gre'] as $i => $gre) {
658
                        if(empty($gre['greif']))
659
                                $gre['greif'] = "gre{$i}";
660
                        /* XXX: Maybe we should report any errors?! */
661
                        interface_gre_configure($gre);
662
                }
663
        }
664
}
665

    
666
/* NOTE: $grekey is not used but useful for passing this function to array_walk. */
667
function interface_gre_configure(&$gre, $grekey = "") {
668
        global $config, $g;
669

    
670
	if (!is_array($gre))
671
		return -1;
672

    
673
	$realif = get_real_interface($gre['if']);
674
	$realifip = get_interface_ip($gre['if']);
675

    
676
	/* make sure the parent interface is up */
677
	interfaces_bring_up($realif);
678

    
679
	if ($g['booting'] || !(empty($gre['greif']))) {
680
		pfSense_interface_destroy($gre['greif']);
681
		pfSense_interface_create($gre['greif']);
682
		$greif = $gre['greif'];
683
	} else
684
		$greif = pfSense_interface_create("gre");
685

    
686
	/* Do not change the order here for more see gre(4) NOTES section. */
687
	mwexec("/sbin/ifconfig {$greif} tunnel {$realifip} {$gre['remote-addr']}");
688
	mwexec("/sbin/ifconfig {$greif} {$gre['tunnel-local-addr']} {$gre['tunnel-remote-addr']} netmask " . gen_subnet_mask($gre['tunnel-remote-net']));
689
	if (isset($gre['link0']) && $gre['link0'])
690
		pfSense_interface_flags($greif, IFF_LINK0);
691
	if (isset($gre['link1']) && $gre['link1'])
692
		pfSense_interface_flags($greif, IFF_LINK1);
693
	if (isset($gre['link2']) && $gre['link2'])
694
		pfSense_interface_flags($greif, IFF_LINK2);
695

    
696
	if($greif)
697
		interfaces_bring_up($greif);
698
	else 
699
		log_error("Could not bring greif up -- variable not defined.");
700

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

    
705
	return $greif;
706
}
707

    
708
function interfaces_gif_configure() {
709
	global $config;
710

    
711
	if (is_array($config['gifs']['gif']) && count($config['gifs']['gif'])) {
712
		foreach ($config['gifs']['gif'] as $i => $gif) {
713
			if(empty($gif['gifif']))
714
				$gre['gifif'] = "gif{$i}";
715
			/* XXX: Maybe we should report any errors?! */
716
			interface_gif_configure($gif);
717
		}
718
	}
719
}
720

    
721
/* NOTE: $gifkey is not used but useful for passing this function to array_walk. */
722
function interface_gif_configure(&$gif, $gifkey = "") {
723
	global $config, $g;
724

    
725
	if (!is_array($gif))
726
		return -1;
727

    
728
	$realif = get_real_interface($gif['if']);
729
	$realifip = get_interface_ip($gif['if']);
730

    
731
	/* make sure the parent interface is up */
732
	if($realif)
733
		interfaces_bring_up($realif);
734
	else 
735
		log_error("could not bring realif up -- variable not defined -- interface_gif_configure()");
736

    
737
	if ($g['booting'] || !(empty($gif['gifif']))) {
738
		pfSense_interface_destroy($gif['gifif']);
739
		pfSense_interface_create($gif['gifif']);
740
		$gifif = $gif['gifif'];
741
	} else
742
		$gifif = pfSense_interface_create("gif");
743

    
744
	/* Do not change the order here for more see gif(4) NOTES section. */
745
	mwexec("/sbin/ifconfig {$gifif} tunnel {$realifip} {$gif['remote-addr']}");
746
	mwexec("/sbin/ifconfig {$gifif} {$gif['tunnel-local-addr']} {$gif['tunnel-remote-addr']} netmask " . gen_subnet_mask($gif['tunnel-remote-net']));
747
	if (isset($gif['link0']) && $gif['link0'])
748
		pfSense_interface_flags($gifif, IFF_LINK0);
749
	if (isset($gif['link1']) && $gif['link1'])
750
		pfSense_interface_flags($gifif, IFF_LINK1);
751
	if($gifif)
752
		interfaces_bring_up($gifif);
753
	else
754
		log_error("could not bring gifif up -- variable not defined");
755

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

    
760
	return $gifif;
761
}
762

    
763
function interfaces_configure() {
764
	global $config, $g;
765

    
766
	/* Set up our loopback interface */
767
	interfaces_loopback_configure();
768

    
769
	/* set up LAGG virtual interfaces */
770
	interfaces_lagg_configure();
771

    
772
	/* set up VLAN virtual interfaces */
773
	interfaces_vlan_configure();
774

    
775
	interfaces_qinq_configure();
776

    
777
	$iflist = get_configured_interface_with_descr();
778
	$delayed_list = array();
779
	$bridge_list = array();
780
	
781
	/* This is needed to speedup interfaces on bootup. */
782
	$reload = false;
783
	if ($g['booting'])
784
		$reload = true;
785

    
786
	foreach($iflist as $if => $ifname) {
787
		$realif = $config['interfaces'][$if]['if'];
788
		if (strstr($realif, "bridge")) 
789
			$bridge_list[$if] = $ifname;
790
		else if (strstr($realif, "gre"))
791
			$delayed_list[$if] = $ifname;
792
		else if (strstr($realif, "gif"))
793
			$delayed_list[$if] = $ifname;
794
		else if (strstr($realif, "ovpn")) {
795
			//echo "Delaying OpenVPN interface configuration...done.\n";
796
			continue;
797
		} else {
798
			if ($g['booting'])
799
				echo "Configuring {$ifname} interface...";
800
			if($g['debug'])
801
				log_error("Configuring {$ifname}");
802
			interface_configure($if, $reload);
803
			if ($g['booting']) 
804
				echo "done.\n";
805
		}
806
	}
807

    
808
	/* create the unconfigured wireless clones */
809
	interfaces_create_wireless_clones();
810

    
811
	/* set up GRE virtual interfaces */
812
	interfaces_gre_configure();
813

    
814
	/* set up GIF virtual interfaces */
815
	interfaces_gif_configure();
816
	
817
	foreach ($delayed_list as $if => $ifname) {
818
		if ($g['booting'])
819
			echo "Configuring {$ifname} interface...";
820
        	if ($g['debug'])
821
        		log_error("Configuring {$ifname}");
822

    
823
		interface_configure($if, $reload);
824

    
825
		if ($g['booting'])
826
			echo "done.\n";
827
	}
828

    
829
	/* set up BRIDGe virtual interfaces */
830
	interfaces_bridge_configure();
831

    
832
	foreach ($bridge_list as $if => $ifname) {
833
		if ($g['booting'])
834
			echo "Configuring {$ifname} interface...";
835
		if($g['debug'])
836
			log_error("Configuring {$ifname}");
837

    
838
		interface_configure($if, $reload);
839

    
840
		if ($g['booting'])
841
			echo "done.\n";
842
	}
843

    
844
	/* bring up vip interfaces */
845
	interfaces_vips_configure();
846

    
847
	/* configure interface groups */
848
	interfaces_group_setup();
849

    
850
	if (!$g['booting']) {
851
		/* reconfigure static routes (kernel may have deleted them) */
852
		system_routing_configure();
853

    
854
		/* reload IPsec tunnels */
855
		vpn_ipsec_configure();
856

    
857
		/* reload dhcpd (interface enabled/disabled status may have changed) */
858
		services_dhcpd_configure();
859

    
860
		/* restart dnsmasq */
861
		services_dnsmasq_configure();
862

    
863
		/* reload captive portal */
864
		captiveportal_init_rules();
865
	}
866

    
867
	return 0;
868
}
869

    
870
function interface_reconfigure($interface = "wan") {
871
	interface_bring_down($interface);
872
	interface_configure($interface, true);
873
}
874

    
875
function interface_vip_bring_down($vip) {
876
	global $g;
877

    
878
	switch ($vip['mode']) {
879
	case "proxyarp":
880
		$vipif = get_real_interface($vip['interface']);
881
		if (file_exists("{$g['varrun_path']}/choparp_{$vipif}.pid"))
882
			killbypid("{$g['varrun_path']}/choparp_{$vipif}.pid");
883
		break;
884
	case "ipalias":
885
		$vipif = get_real_interface($vip['interface']);
886
		if(does_interface_exist($vipif))
887
			pfSense_interface_deladdress($vipif, $vip['subnet']);
888
		break;
889
	case "carp":
890
		$vipif = "vip" . $vip['vhid'];
891
		if(does_interface_exist($vipif)) 
892
			pfSense_interface_destroy($vipif);
893
		break;
894
	case "carpdev-dhcp":
895
		$vipif = "vip" . $vip['vhid'];
896
		if(does_interface_exist($vipif)) 
897
			pfSense_interface_destroy($vipif);
898
		break;
899
	}
900
}
901

    
902
function interface_bring_down($interface = "wan", $destroy = false) {
903
	global $config, $g;
904

    
905
	if (!isset($config['interfaces'][$interface]))
906
		return; 
907

    
908
	$ifcfg = $config['interfaces'][$interface];
909

    
910
	$realif = get_real_interface($interface);
911

    
912
	switch ($ifcfg['ipaddr']) {
913
	case "ppp":
914
	case "pppoe":
915
	case "pptp":
916
	case "l2tp":
917
		if (is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) {
918
			foreach ($config['ppps']['ppp'] as $pppid => $ppp) {
919
				if ($realif == $ppp['if']) {
920
					if (file_exists("{$g['varrun_path']}/{$ppp['type']}_{$interface}.pid")) {
921
						killbypid("{$g['varrun_path']}/{$ppp['type']}_{$interface}.pid");
922
						sleep(5);
923
					}
924
					unlink_if_exists("{$g['varetc_path']}/mpd_{$interface}.conf");
925
					if (isset($ppp['ondemand']) && !$destroy)
926
						send_event("interface reconfigure {$interface}");
927
					break;
928
				}
929
			}
930
		}
931
		break;
932
	case "carpdev-dhcp":
933
		/* 
934
		 * NB: When carpdev gets enabled it would be better to be handled as all
935
		 *	   other interfaces! 
936
		 */
937
	case "dhcp":
938
		$pid = find_dhclient_process($realif);
939
		if($pid)
940
			mwexec("kill {$pid}");
941
		sleep(1);
942
		unlink_if_exists("{$g['varetc_path']}/dhclient_{$interface}.conf");
943
		if(does_interface_exist("$realif")) {
944
			mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete", true);
945
			if ($destroy == true)
946
				pfSense_interface_flags($realif, -IFF_UP);
947
			mwexec("/usr/sbin/arp -d -i {$realif} -a");
948
		}
949
		break;
950
	default:
951
		if(does_interface_exist("$realif")) {
952
			mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete", true);
953
			if ($destroy == true)
954
				pfSense_interface_flags($realif, -IFF_UP);
955
			mwexec("/usr/sbin/arp -d -i {$realif} -a");
956
		}
957
		break;
958
	}
959

    
960
	/* remove interface up file if it exists */
961
	unlink_if_exists("{$g['tmp_path']}/{$realif}up");
962
	unlink_if_exists("{$g['vardb_path']}/{$interface}ip");
963
	unlink_if_exists("{$g['tmp_path']}/{$realif}_router");
964
	unlink_if_exists("{$g['varetc_path']}/nameserver_{$realif}");
965
	unlink_if_exists("{$g['varetc_path']}/searchdomain_{$realif}");
966
	
967
	/* hostapd and wpa_supplicant do not need to be running when the interface is down.
968
	 * They will also use 100% CPU if running after the wireless clone gets deleted. */
969
	if (is_array($ifcfg['wireless'])) {
970
		mwexec(kill_hostapd($realif));
971
		mwexec(kill_wpasupplicant($realif));
972
	}
973

    
974
	if ($destroy == true) {
975
		if (preg_match("/^vip|^tun|^ovpn|^gif|^gre|^lagg|^bridge|vlan/i", $realif))
976
			pfSense_interface_destroy($realif);
977
	}	
978

    
979
	return;
980
}
981

    
982
function interfaces_ptpid_used($ptpid) {
983
	global $config;
984

    
985
	if (is_array($config['ppps']['ppp']))
986
		foreach ($config['ppps']['ppp'] as & $settings)
987
			if ($ptpid == $settings['ptpid'])
988
				return true;
989

    
990
	return false;
991
}
992

    
993
function interfaces_ptpid_next() {
994

    
995
	$ptpid = 0;
996
	while(interfaces_ptpid_used($ptpid))
997
		$ptpid++;
998

    
999
	return $ptpid;
1000
}
1001

    
1002
function getMPDCRONSettings($pppif_) {
1003
	global $config;
1004
	$cron_cmd_file = "{$g['varetc_path']}/pppoe_restart_";
1005
	if (is_array($config['cron']['item'])) {
1006
		for ($i = 0; $i < count($config['cron']['item']); $i++) {
1007
			$item = $config['cron']['item'][$i];
1008
			if (strpos($item['command'], $cron_cmd_file.$pppif_) !== false) {
1009
				return array("ID" => $i, "ITEM" => $item);
1010
			}
1011
		}
1012
	}
1013
	return NULL;
1014
}
1015

    
1016
function handle_pppoe_reset($post_array) {
1017
	global $config, $g;
1018

    
1019
	$cron_cmd_file = "{$g['varetc_path']}/pppoe_restart_";
1020

    
1021
	$pppif = $post_array['type'].$post_array['ptpid'];
1022
	if (!is_array($config['cron']['item'])) 
1023
		$config['cron']['item'] = array(); 
1024
	$itemhash = getMPDCRONSettings($pppif);
1025
	$item = $itemhash['ITEM'];
1026
	
1027
	// reset cron items if necessary and return
1028
	if (empty($post_array['pppoe-reset-type'])) {
1029
		if (isset($item))
1030
			unset($config['cron']['item'][$itemhash['ID']]);
1031
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
1032
		return;
1033
	}
1034

    
1035
	if (empty($item)) 
1036
		$item = array();
1037
	if (isset($post_array['pppoe-reset-type']) && $post_array['pppoe-reset-type'] == "custom") {
1038
		$item['minute'] = $post_array['pppoe_resetminute'];
1039
		$item['hour'] = $post_array['pppoe_resethour'];
1040
		if (isset($post_array['pppoe_resetdate']) && $post_array['pppoe_resetdate'] <> "") {
1041
			$date = explode("/", $post_array['pppoe_resetdate']);
1042
			$item['mday'] = $date[1];
1043
			$item['month'] = $date[0];
1044
		} else {
1045
			$item['mday'] = "*";
1046
			$item['month'] = "*";
1047
		}
1048
		$item['wday'] = "*";
1049
		$item['who'] = "root";
1050
		$item['command'] = $cron_cmd_file.$pppif;
1051
	} else if (isset($post_array['pppoe-reset-type']) && $post_array['pppoe-reset-type'] == "preset") {
1052
		switch ($post_array['pppoe_pr_preset_val']) {
1053
			case "monthly":
1054
				$item['minute'] = "0";
1055
				$item['hour'] = "0";
1056
				$item['mday'] = "1";
1057
				$item['month'] = "*";
1058
				$item['wday'] = "*";
1059
				$item['who'] = "root";
1060
				$item['command'] = $cron_cmd_file.$pppif;
1061
				break;
1062
	        case "weekly":
1063
				$item['minute'] = "0";
1064
				$item['hour'] = "0";
1065
				$item['mday'] = "*";
1066
				$item['month'] = "*";
1067
				$item['wday'] = "0";
1068
				$item['who'] = "root";
1069
				$item['command'] = $cron_cmd_file.$pppif;
1070
				break;
1071
			case "daily":
1072
				$item['minute'] = "0";
1073
				$item['hour'] = "0";
1074
				$item['mday'] = "*";
1075
				$item['month'] = "*";
1076
				$item['wday'] = "*";
1077
				$item['who'] = "root";
1078
				$item['command'] = $cron_cmd_file.$pppif;
1079
				break;
1080
			case "hourly":
1081
				$item['minute'] = "0";
1082
				$item['hour'] = "*";
1083
				$item['mday'] = "*";
1084
				$item['month'] = "*";
1085
				$item['wday'] = "*";
1086
				$item['who'] = "root";
1087
				$item['command'] = $cron_cmd_file.$pppif;
1088
				break;
1089
		} // end switch
1090
	} else {
1091
		/* test whether a cron item exists and unset() it if necessary */
1092
		$itemhash = getMPDCRONSettings($pppif);
1093
		$item = $itemhash['ITEM'];
1094
		if (isset($item))
1095
			unset($config['cron']['item'][$itemhash['ID']]); 
1096
	}// end if
1097
	if (isset($itemhash['ID'])) 
1098
		$config['cron']['item'][$itemhash['ID']] = $item;
1099
	else 
1100
		$config['cron']['item'][] = $item;
1101
}
1102

    
1103
/*	This function can configure PPPoE, MLPPP (PPPoE), PPTP.
1104
*	It writes the mpd config file to /var/etc every time the link is opened.
1105
*/
1106

    
1107
function interface_ppps_configure($interface) {
1108
	global $config, $g;
1109
	
1110
	// mpd5 requires a /var/spool/lock directory for PPP modem links.
1111
	if(!is_dir("/var/spool/lock")) {
1112
		exec("/bin/mkdir -p /var/spool/lock");
1113
		exec("/bin/chmod a+rw /var/spool/lock/.");
1114
	}
1115
	// mpd5 modem chat script expected in the same directory as the mpd_xxx.conf files	
1116
	if (!file_exists("{$g['varetc_path']}/mpd.script"))
1117
		mwexec("/bin/ln -s /usr/local/sbin/mpd.script {$g['varetc_path']}/.");
1118
		
1119
	$ifcfg = $config['interfaces'][$interface];
1120
	if (!isset($ifcfg['enable']))
1121
		return 0;
1122
	if (is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) {
1123
		foreach ($config['ppps']['ppp'] as $pppid => $ppp) {
1124
			if ($ifcfg['if'] == $ppp['if'])
1125
				break;
1126
		}
1127
	}
1128
	if (!$ppp || $ifcfg['if'] != $ppp['if']){
1129
		log_error("Can't find PPP config for {$ifcfg['if']} in interface_ppps_configure().");
1130
		return 0;
1131
	}
1132
	$pppif = $ifcfg['if'];
1133
	if ($ppp['type'] == "ppp")
1134
		$type = "modem";
1135
	else
1136
		$type = $ppp['type'];
1137
	$upper_type = strtoupper($ppp['type']);	
1138
	
1139
	if($g['booting']) {
1140
		$descr = isset($ifcfg['descr']) ? $ifcfg['descr'] : strtoupper($interface);
1141
		echo "starting {$pppif} link...";
1142
		// Do not re-configure the interface if we are booting and it's already been started
1143
		if(file_exists("{$g['varrun_path']}/{$ppp['type']}_{$interface}.pid"))
1144
			return 0;
1145
	}
1146
	
1147
	$ports = explode(',',$ppp['ports']);
1148
	if ($type != "modem") {
1149
		foreach ($ports as $pid => $port)
1150
			$ports[$pid] = get_real_interface($port);
1151
	}
1152
	$localips = explode(',',$ppp['localip']);
1153
	$gateways = explode(',',$ppp['gateway']);
1154
	$subnets = explode(',',$ppp['subnet']);
1155
	
1156
	/* We bring up the parent interface first because if DHCP is configured on the parent we need
1157
	to obtain an address first so we can write it in the mpd .conf file for PPTP and L2TP configs
1158
	*/
1159
	foreach($ports as $pid => $port){
1160
		switch ($ppp['type']) {
1161
			case "pppoe": 
1162
				/* Bring the parent interface up */
1163
				interfaces_bring_up($port);
1164
				pfSense_ngctl_attach(".", $port);
1165
				break;
1166
			case "pptp":
1167
			case "l2tp":
1168
				/* configure interface */
1169
				if(is_ipaddr($localips[$pid])){
1170
					// Manually configure interface IP/subnet
1171
					pfSense_interface_setaddress($port, "{$localips[$pid]}/{$subnets[$pid]}");
1172
					interfaces_bring_up($port);
1173
				} else if (empty($localips[$pid]))
1174
					$localips[$pid] = get_interface_ip($port); // try to get the interface IP from the port
1175
				
1176
				if(!is_ipaddr($localips[$pid])){
1177
					log_error("Could not get a Local IP address for PPTP/L2TP link on {$port} in interfaces_ppps_configure.");
1178
					return 0;
1179
				}
1180
				/* XXX: This needs to go away soon! [It's commented out!] */
1181
				/* Configure the gateway (remote IP ) */
1182
				if (!$g['booting'] && !is_ipaddr($gateways[$pid]) && is_hostname($gateways[$pid])) {
1183
					/* XXX: Fix later 
1184
					$gateways[$pid] = gethostbyname($gateways[$pid]);
1185
					if(!is_ipaddr($gateways[$pid])) {
1186
						log_error("Could not get a valid Gateway IP from {$port} via DNS in interfaces_ppps_configure.");
1187
						return 0;
1188
					}
1189
					*/
1190
				}
1191
				if(!is_ipaddr($gateways[$pid])){
1192
					log_error("Could not get a PPTP/L2TP Remote IP address from {$dhcp_gateway} for {$gway} in interfaces_ppps_configure.");
1193
					return 0;
1194
				}
1195
				pfSense_ngctl_attach(".", $port);
1196
				break;
1197
			case "ppp":
1198
				if (!file_exists("{$port}")) {
1199
					log_error("Device {$port} does not exist. PPP link cannot start without the modem device.");
1200
					return 0;
1201
				}
1202
				break;
1203
			default:
1204
				log_error("Unkown {$type} configured as ppp interface.");
1205
				break;
1206
		}
1207
	}
1208
	
1209
	if (is_array($ports) && count($ports) > 1)
1210
		$multilink = "enable";
1211
	else
1212
		$multilink = "disable";
1213
	
1214
	if ($type == "modem"){
1215
		if (is_ipaddr($ppp['localip']))
1216
			$localip = $ppp['localip'];
1217
		else
1218
			$localip = '0.0.0.0';
1219

    
1220
		if (is_ipaddr($ppp['gateway']))
1221
			$gateway = $ppp['gateway'];
1222
		else
1223
			$gateway = "10.64.64.{$pppid}";
1224
		$ranges = "{$localip}/0 {$gateway}/0";
1225
		
1226
		if (empty($ppp['apnum']))	
1227
			$ppp['apnum'] = 1;
1228
	} else
1229
		$ranges = "0.0.0.0/0 0.0.0.0/0";
1230

    
1231
	if (isset($ppp['ondemand'])) 
1232
		$ondemand = "enable";
1233
	else
1234
		$ondemand = "disable";
1235
	if (!isset($ppp['idletimeout']))
1236
		$ppp['idletimeout'] = 0;
1237

    
1238
	if (empty($ppp['username']) && $type == "modem"){
1239
		$ppp['username'] = "user";
1240
		$ppp['password'] = "none";
1241
	}
1242
	if (empty($ppp['password']) && $type == "modem")
1243
		$passwd = "none";
1244
	else
1245
		$passwd = base64_decode($ppp['password']);
1246

    
1247
	$bandwidths = explode(',',$ppp['bandwidth']);
1248
	$mtus = explode(',',$ppp['mtu']);
1249
	$mrus = explode(',',$ppp['mru']);
1250

    
1251
	if (isset($ppp['mrru']))
1252
		$mrrus = explode(',',$ppp['mrru']);
1253

    
1254
	// Construct the mpd.conf file
1255
	$mpdconf = <<<EOD
1256
startup:
1257
	# configure the console
1258
	set console close
1259
	# configure the web server
1260
	set web close
1261

    
1262
default:
1263
{$ppp['type']}client:
1264
	create bundle static {$interface}
1265
	set iface name {$pppif}
1266

    
1267
EOD;
1268
	$setdefaultgw = false;
1269
	$founddefaultgw = false;
1270
	if (is_array($config['gateways']['gateway_item'])) {
1271
		foreach($config['gateways']['gateway_item'] as $gateway) {
1272
			if($interface == $gateway['interface'] && isset($gateway['defaultgw'])) {
1273
				$setdefaultgw = true;
1274
				break;
1275
			} else if (isset($gateway['defaultgw']) && !empty($gateway['interface'])) {
1276
				$founddefaultgw = true;
1277
				break;
1278
			}
1279
		}
1280
	}
1281
	
1282
	if (($interface == "wan" && $founddefaultgw == false) || $setdefaultgw == true){
1283
		$setdefaultgw = true;
1284
		$mpdconf .= <<<EOD
1285
	set iface route default
1286

    
1287
EOD;
1288
	}
1289
	$mpdconf .= <<<EOD
1290
	set iface {$ondemand} on-demand
1291
	set iface idle {$ppp['idletimeout']}
1292

    
1293
EOD;
1294

    
1295
	if (isset($ppp['ondemand']))
1296
		$mpdconf .= <<<EOD
1297
	set iface addrs 10.10.1.1 10.10.1.2
1298

    
1299
EOD;
1300
	
1301
	if (isset($ppp['tcpmssfix']))
1302
		$tcpmss = "disable";
1303
	else
1304
		$tcpmss = "enable";
1305
		$mpdconf .= <<<EOD
1306
	set iface {$tcpmss} tcpmssfix
1307

    
1308
EOD;
1309

    
1310
	$mpdconf .= <<<EOD
1311
	set iface up-script /usr/local/sbin/ppp-linkup
1312
	set iface down-script /usr/local/sbin/ppp-linkdown
1313
	set ipcp ranges {$ranges}
1314

    
1315
EOD;
1316
	if (isset($ppp['vjcomp']))
1317
		$mpdconf .= <<<EOD
1318
	set ipcp no vjcomp
1319

    
1320
EOD;
1321

    
1322
	if (isset($config['system']['dnsallowoverride']))
1323
		$mpdconf .= <<<EOD
1324
	set ipcp enable req-pri-dns
1325
	set ipcp enable req-sec-dns
1326

    
1327
EOD;
1328
	if (!isset($ppp['verbose_log']))
1329
		$mpdconf .= <<<EOD
1330
	#log -bund -ccp -chat -iface -ipcp -lcp -link
1331

    
1332
EOD;
1333
	foreach($ports as $pid => $port){
1334
		$port = get_real_interface($port);
1335
		$mpdconf .= <<<EOD
1336

    
1337
	create link static {$interface}_link{$pid} {$type}
1338
	set link action bundle {$interface}
1339
	set link {$multilink} multilink
1340
	set link keep-alive 10 60
1341
	set link max-redial 0
1342

    
1343
EOD;
1344
		if (isset($ppp['shortseq']))
1345
			$mpdconf .= <<<EOD
1346
	set link no shortseq
1347

    
1348
EOD;
1349

    
1350
		if (isset($ppp['acfcomp']))
1351
			$mpdconf .= <<<EOD
1352
	set link no acfcomp
1353

    
1354
EOD;
1355

    
1356
		if (isset($ppp['protocomp']))
1357
			$mpdconf .= <<<EOD
1358
	set link no protocomp
1359

    
1360
EOD;
1361

    
1362
		$mpdconf .= <<<EOD
1363
	set link disable chap pap
1364
	set link accept chap pap eap
1365
	set link disable incoming
1366

    
1367
EOD;
1368

    
1369

    
1370
		if (!empty($bandwidths[$pid]))
1371
			$mpdconf .= <<<EOD
1372
	set link bandwidth {$bandwidths[$pid]}
1373

    
1374
EOD;
1375

    
1376
		if (empty($mtus[$pid]))
1377
			$mtus[$pid] = "1492";
1378
			$mpdconf .= <<<EOD
1379
	set link mtu {$mtus[$pid]}
1380

    
1381
EOD;
1382

    
1383
		if (!empty($mrus[$pid]))
1384
			$mpdconf .= <<<EOD
1385
	set link mru {$mrus[$pid]}
1386

    
1387
EOD;
1388

    
1389
		if (!empty($mrrus[$pid]))
1390
			$mpdconf .= <<<EOD
1391
	set link mrru {$mrrus[$pid]}
1392

    
1393
EOD;
1394

    
1395
		$mpdconf .= <<<EOD
1396
	set auth authname "{$ppp['username']}"
1397
	set auth password {$passwd}
1398

    
1399
EOD;
1400
		if ($type == "modem") {
1401
			$mpdconf .= <<<EOD
1402
	set modem device {$ppp['ports']}
1403
	set modem script DialPeer
1404
	set modem idle-script Ringback
1405
	set modem watch -cd
1406
	set modem var \$DialPrefix "DT"
1407
	set modem var \$Telephone "{$ppp['phone']}"
1408

    
1409
EOD;
1410
		}
1411
		if (isset($ppp['connect-timeout']) && $type == "modem") {
1412
			$mpdconf .= <<<EOD
1413
	set modem var \$ConnectTimeout "{$ppp['connect-timeout']}"
1414

    
1415
EOD;
1416
		}
1417
		if (isset($ppp['initstr']) && $type == "modem") {
1418
			$initstr = base64_decode($ppp['initstr']);
1419
			$mpdconf .= <<<EOD
1420
	set modem var \$InitString "{$initstr}"
1421

    
1422
EOD;
1423
		}
1424
		if (isset($ppp['simpin']) && $type == "modem") {
1425
			$mpdconf .= <<<EOD
1426
	set modem var \$SimPin "{$ppp['simpin']}"
1427
	set modem var \$PinWait "{$ppp['pin-wait']}"
1428

    
1429
EOD;
1430
		}
1431
		if (isset($ppp['apn']) && $type == "modem") {
1432
			$mpdconf .= <<<EOD
1433
	set modem var \$APN "{$ppp['apn']}"
1434
	set modem var \$APNum "{$ppp['apnum']}"
1435

    
1436
EOD;
1437
		}
1438
		if (isset($ppp['provider']) && $type == "pppoe") {
1439
			$mpdconf .= <<<EOD
1440
	set pppoe service "{$ppp['provider']}"
1441

    
1442
EOD;
1443
		}
1444
		if ($type == "pppoe")
1445
			$mpdconf .= <<<EOD
1446
	set pppoe iface {$port}
1447

    
1448
EOD;
1449

    
1450
		if ($type == "pptp" || $type == "l2tp") {
1451
			$mpdconf .= <<<EOD
1452
	set {$type} self {$localips[$pid]}
1453
	set {$type} peer {$gateways[$pid]}
1454
	set {$type} disable windowing
1455

    
1456
EOD;
1457
		}
1458
		
1459
		$mpdconf .= "\topen\r\n";
1460
	} //end foreach($port)
1461

    
1462

    
1463
	/* Generate mpd.conf. If mpd_[interface].conf exists in the conf path, then link to it instead of generating a fresh conf file. */
1464
	if (file_exists("{$g['conf_path']}/mpd_{$interface}.conf"))
1465
		mwexec("/bin/ln -s {$g['conf_path']}/mpd_{$interface}.conf {$g['varetc_path']}/.");
1466
	else {
1467
		$fd = fopen("{$g['varetc_path']}/mpd_{$interface}.conf", "w");
1468
		if (!$fd) {
1469
			log_error("Error: cannot open mpd_{$interface}.conf in interface_ppps_configure().\n");
1470
			return 0;
1471
		}
1472
		// Write out mpd_ppp.conf
1473
		fwrite($fd, $mpdconf);
1474
		fclose($fd);
1475
	}
1476

    
1477
	// Create the uptime log if requested and if it doesn't exist already, or delete it if it is no longer requested.
1478
	if (isset($ppp['uptime'])) {
1479
		if (!file_exists("/conf/{$pppif}.log")) {
1480
			conf_mount_rw();
1481
			mwexec("echo /dev/null > /conf/{$pppif}.log");
1482
			conf_mount_ro();
1483
		}
1484
	} else {
1485
		if (file_exists("/conf/{$pppif}.log")) {
1486
			conf_mount_rw();
1487
			mwexec("rm -f /conf/{$pppif}.log");
1488
			conf_mount_ro();
1489
		}
1490
	}
1491

    
1492
	/* fire up mpd */
1493
	mwexec("/usr/local/sbin/mpd5 -b -k -d {$g['varetc_path']} -f mpd_{$interface}.conf -p {$g['varrun_path']}/{$ppp['type']}_{$interface}.pid -s ppp {$ppp['type']}client");
1494

    
1495
	// Check for PPPoE periodic reset request 
1496
	if ($type == "pppoe") {
1497
		if (isset($ppp['pppoe-reset-type']))
1498
			setup_pppoe_reset_file($ppp['if'], $interface);
1499
		else
1500
			setup_pppoe_reset_file($ppp['if']);
1501
	}
1502

    
1503
	return 1;
1504
}
1505

    
1506
function interfaces_carp_setup() {
1507
	global $g, $config;
1508

    
1509
	$balanacing = "";
1510
	$pfsyncinterface = "";
1511
	$pfsyncenabled = "";
1512
	if(isset($config['system']['developerspew'])) {
1513
		$mt = microtime();
1514
		echo "interfaces_carp_setup() being called $mt\n";
1515
	}
1516

    
1517
	// Prepare CmdCHAIN that will be used to execute commands.
1518
	$cmdchain = new CmdCHAIN();	
1519

    
1520
	if ($g['booting']) {
1521
		echo "Configuring CARP settings...";
1522
		mute_kernel_msgs();
1523
	}
1524

    
1525
	/* suck in configuration items */
1526
	if($config['installedpackages']['carpsettings']) {
1527
		if($config['installedpackages']['carpsettings']['config']) {
1528
			foreach($config['installedpackages']['carpsettings']['config'] as $carp) {
1529
				$pfsyncenabled = $carp['pfsyncenabled'];
1530
				$balanacing = $carp['balancing'];
1531
				$pfsyncinterface = $carp['pfsyncinterface'];
1532
				$pfsyncpeerip = $carp['pfsyncpeerip'];
1533
			}
1534
		}
1535
	} else {
1536
		unset($pfsyncinterface);
1537
		unset($balanacing);
1538
		unset($pfsyncenabled);
1539
	}
1540

    
1541
	$cmdchain->add("Allow CARP", "/sbin/sysctl net.inet.carp.allow=1", true);			
1542
	if($balanacing) {
1543
		$cmdchain->add("Enable CARP ARP-balancing", "/sbin/sysctl net.inet.carp.arpbalance=1", true);
1544
		$cmdchain->add("Disallow CARP preemption", "/sbin/sysctl net.inet.carp.preempt=0", true);
1545
	} else
1546
		$cmdchain->add("Enable CARP preemption", "/sbin/sysctl net.inet.carp.preempt=1", true);		
1547

    
1548
	$cmdchain->add("Enable CARP logging", "/sbin/sysctl net.inet.carp.log=1", true);
1549
	if (!empty($pfsyncinterface))
1550
		$carp_sync_int = get_real_interface($pfsyncinterface);
1551

    
1552
	if($g['booting']) {
1553
		/*    install rules to alllow pfsync to sync up during boot
1554
		 *    carp interfaces will remain down until the bootup sequence finishes
1555
		 */
1556
		$fd = fopen("{$g['tmp_path']}/rules.boot", "w");
1557
		if ($fd) {
1558
			fwrite($fd, "pass quick proto carp all keep state\n");
1559
			fwrite($fd, "pass quick proto pfsync all\n");
1560
			fwrite($fd, "pass out quick from any to any keep state\n");
1561
			fclose($fd);
1562
			mwexec("/sbin/pfctl -f {$g['tmp_path']}/rules.boot");
1563
		} else
1564
			log_error("Could not create rules.boot file!");
1565
	}
1566

    
1567
	/* setup pfsync interface */
1568
	if($carp_sync_int and $pfsyncenabled) {
1569
		if (is_ipaddr($pfsyncpeerip))
1570
			$cmdchain->add("Bring up pfsync0 syncpeer", "/sbin/ifconfig pfsync0 syncdev {$carp_sync_int} syncpeer {$pfsyncpeerip} up", false);						
1571
		else
1572
			$cmdchain->add("Bring up pfsync0 syncdev", "/sbin/ifconfig pfsync0 syncdev {$carp_sync_int} up", false);			
1573
	} else
1574
		$cmdchain->add("Bring up pfsync0", "/sbin/ifconfig pfsync0 syncdev lo0 up", false);						
1575

    
1576
	if($config['virtualip']['vip'])
1577
		$cmdchain->add("Allow CARP.", "/sbin/sysctl net.inet.carp.allow=1", true);				
1578
	else
1579
		$cmdchain->add("Disallow CARP.", "/sbin/sysctl net.inet.carp.allow=0", true);		
1580
	
1581
	if($g['debug'])
1582
		$cmdchain->setdebug(); // optional for verbose logging
1583

    
1584
	$cmdchain->execute();
1585
	$cmdchain->clear();
1586

    
1587
	if ($g['booting']) {
1588
		unmute_kernel_msgs();
1589
		echo "done.\n";
1590
	}
1591
}
1592

    
1593
function interface_proxyarp_configure($interface = "") {
1594
	global $config, $g;
1595
	if(isset($config['system']['developerspew'])) {
1596
		$mt = microtime();
1597
		echo "interface_proxyarp_configure() being called $mt\n";
1598
	}
1599

    
1600
	/* kill any running choparp */
1601
	if (empty($interface))
1602
		killbyname("choparp");
1603
	else {
1604
		$vipif = get_real_interface($interface);
1605
		if (file_exists("{$g['varrun_path']}/choparp_{$vipif}.pid"))
1606
			killbypid("{$g['varrun_path']}/choparp_{$vipif}.pid");
1607
	}
1608

    
1609
	$paa = array();
1610
	if (!empty($config['virtualip']) && is_array($config['virtualip']['vip'])) {
1611

    
1612
		/* group by interface */
1613
		foreach ($config['virtualip']['vip'] as $vipent) {
1614
			if ($vipent['mode'] === "proxyarp") {
1615
				if ($vipent['interface'])
1616
					$proxyif = $vipent['interface'];
1617
				else
1618
					$proxyif = "wan";
1619
				
1620
				if (!empty($interface) && $interface != $proxyif)
1621
					continue;
1622

    
1623
				if (!is_array($paa[$proxyif]))
1624
					$paa[$proxyif] = array();
1625

    
1626
				$paa[$proxyif][] = $vipent;
1627
			}
1628
		}
1629
	}
1630

    
1631
	if (!empty($interface)) {
1632
		if (is_array($paa[$interface])) {
1633
			$paaifip = get_interface_ip($interface);
1634
                        if (!is_ipaddr($paaifip))
1635
                                return;
1636
                        $args = get_real_interface($interface) . " auto";
1637
                        foreach ($paa[$interface] as $paent) {
1638
                                if (isset($paent['subnet']))
1639
                                        $args .= " " . escapeshellarg("{$paent['subnet']}/{$paent['subnet_bits']}");
1640
                                else if (isset($paent['range']))
1641
                                        $args .= " " . escapeshellarg($paent['range']['from'] . "-" . $paent['range']['to']);
1642
                        }
1643
                        mwexec_bg("/usr/local/sbin/choparp " . $args);	
1644
		}
1645
	} else if (count($paa) > 0) {
1646
		foreach ($paa as $paif => $paents)  {
1647
			$paaifip = get_interface_ip($paif);
1648
			if (!is_ipaddr($paaifip))
1649
				continue;
1650
			$args = get_real_interface($paif) . " auto";
1651
			foreach ($paents as $paent) {
1652
				if (isset($paent['subnet']))
1653
					$args .= " " . escapeshellarg("{$paent['subnet']}/{$paent['subnet_bits']}");
1654
				else if (isset($paent['range']))
1655
					$args .= " " . escapeshellarg($paent['range']['from'] . "-" . $paent['range']['to']);
1656
			}
1657
			mwexec_bg("/usr/local/sbin/choparp " . $args);
1658
		}
1659
	}
1660
}
1661

    
1662
function interfaces_vips_configure($interface = "") {
1663
	global $g, $config;
1664
	if(isset($config['system']['developerspew'])) {
1665
		$mt = microtime();
1666
		echo "interfaces_vips_configure() being called $mt\n";
1667
	}
1668
	$paa = array();
1669
	if(is_array($config['virtualip']['vip'])) {
1670
		$carp_setuped = false;
1671
		$anyproxyarp = false;
1672
		foreach ($config['virtualip']['vip'] as $vip) {
1673
			switch ($vip['mode']) {
1674
			case "proxyarp":
1675
				/* nothing it is handled on interface_proxyarp_configure() */
1676
				if ($interface <> "" && $vip['interface'] <> $interface)
1677
					continue;
1678
				$anyproxyarp = true;
1679
				break;
1680
			case "ipalias":
1681
				if ($interface <> "" && $vip['interface'] <> $interface)
1682
					continue;
1683
				interface_ipalias_configure(&$vip);
1684
				break;
1685
			case "carp":
1686
				if ($interface <> "" && $vip['interface'] <> $interface)
1687
					continue;
1688
				if ($carp_setuped == false) {
1689
					interfaces_carp_setup();
1690
					$carp_setuped = true;
1691
				}
1692
				interface_carp_configure($vip);
1693
				break;
1694
			case "carpdev-dhcp":
1695
				if ($interface <> "" && $vip['interface'] <> $interface)
1696
					continue;
1697
				interface_carpdev_configure($vip);
1698
				break;
1699
			}
1700
		}
1701
		
1702
		if ($anyproxyarp == true)
1703
			interface_proxyarp_configure();
1704
	}
1705
}
1706

    
1707
function interface_ipalias_configure(&$vip) {
1708

    
1709
	if ($vip['mode'] == "ipalias") {
1710
		$if = get_real_interface($vip['interface']);
1711
		mwexec("/sbin/ifconfig " . escapeshellarg($if) . " " . $vip['subnet'] . "/" . escapeshellarg($vip['subnet_bits']) . " alias");
1712
	}
1713
}
1714

    
1715
function interface_reload_carps($cif) {
1716
	global $config;
1717

    
1718
	$carpifs = link_ip_to_carp_interface(find_interface_ip($cif));
1719
	if (empty($carpifs))
1720
		return;
1721

    
1722
	$carps = explode(" ", $carpifs);
1723
	if(is_array($config['virtualip']['vip'])) {
1724
		$viparr = &$config['virtualip']['vip'];
1725
		foreach ($viparr as $vip) {
1726
			if (in_array($vip['carpif'], $carps)) {
1727
				switch ($vip['mode']) {
1728
				case "carp":
1729
					interface_vip_bring_down($vip);
1730
					sleep(1);
1731
					interface_carp_configure($vip);
1732
					break;
1733
				case "carpdev-dhcp":
1734
					interface_vip_bring_down($vip);
1735
					sleep(1);
1736
					interface_carpdev_configure($vip);
1737
					break;
1738
				case "ipalias":
1739
					interface_vip_bring_down($vip);
1740
					sleep(1);
1741
					interface_ipalias_configure($vip);
1742
					break;
1743
				}
1744
			}
1745
		}
1746
	}
1747
}
1748

    
1749
function interface_carp_configure(&$vip) {
1750
	global $config, $g;
1751
	if(isset($config['system']['developerspew'])) {
1752
		$mt = microtime();
1753
		echo "interface_carp_configure() being called $mt\n";
1754
	}
1755

    
1756
	if ($vip['mode'] != "carp")
1757
		return;
1758

    
1759
	$vip_password = $vip['password'];
1760
	$vip_password = escapeshellarg(addslashes(str_replace(" ", "", $vip_password)));
1761
	if ($vip['password'] != "")
1762
		$password = " pass {$vip_password}";
1763

    
1764
	// set the vip interface to the vhid
1765
	$vipif = "vip{$vip['vhid']}";
1766

    
1767
	/*
1768
	 * ensure the interface containing the VIP really exists
1769
 	 * prevents a panic if the interface is missing or invalid
1770
	 */
1771
	$realif = get_real_interface($vip['interface']);
1772
	if (!does_interface_exist($realif)) {
1773
		file_notice("CARP", "Interface specified for the virtual IP address {$vip['subnet']} does not exist. Skipping this VIP.", "Firewall: Virtual IP", "");
1774
		return;
1775
	}
1776

    
1777
	/* Ensure CARP IP really exists prior to loading up. */
1778
	$ww_subnet_ip = find_interface_ip($realif);
1779
	$ww_subnet_bits = find_interface_subnet($realif);
1780
	if (!ip_in_subnet($vip['subnet'], gen_subnet($ww_subnet_ip, $ww_subnet_bits) . "/" . $ww_subnet_bits) && !ip_in_interface_alias_subnet($vip['interface'], $vip['subnet'])) {
1781
		file_notice("CARP", "Sorry but we could not find a matching real interface subnet for the virtual IP address {$vip['subnet']}.", "Firewall: Virtual IP", "");
1782
		return;
1783
	}
1784

    
1785
	/* create the carp interface and setup */
1786
	if (does_interface_exist($vipif)) {
1787
		pfSense_interface_flags($vipif, -IFF_UP);
1788
	} else {
1789
		$carpif = pfSense_interface_create("carp");
1790
		pfSense_interface_rename($carpif, $vipif);
1791
		pfSense_ngctl_name("{$carpif}:", $vipif);
1792
	}
1793

    
1794
	/* invalidate interface cache */
1795
	get_interface_arr(true);
1796

    
1797
	$broadcast_address = gen_subnet_max($vip['subnet'], $vip['subnet_bits']);
1798
	mwexec("/sbin/ifconfig {$vipif} {$vip['subnet']}/{$vip['subnet_bits']} vhid {$vip['vhid']} advskew {$vip['advskew']} advbase {$vip['advbase']} {$password}");
1799

    
1800
	interfaces_bring_up($vipif);
1801
	
1802
	return $vipif;
1803
}
1804

    
1805
function interface_carpdev_configure(&$vip) {
1806
	global $g;
1807

    
1808
	if ($vip['mode'] != "carpdev-dhcp")
1809
		return;
1810

    
1811
	$vip_password = $vip['password'];
1812
	$vip_password = str_replace(" ", "", $vip_password);
1813
	if($vip['password'] != "")
1814
		$password = " pass \"" . $vip_password . "\"";
1815

    
1816
	if (empty($vip['interface']))
1817
		return;
1818

    
1819
	$vipif = "vip" . $vip['vhid'];
1820
	$realif = get_real_interface($vip['interface']);
1821
	interfaces_bring_up($realif);
1822
	/*
1823
	 * ensure the interface containing the VIP really exists
1824
	 * prevents a panic if the interface is missing or invalid
1825
	 */
1826
	if (!does_interface_exist($realif)) {
1827
		file_notice("CARP", "Interface specified for the virtual IP address {$vip['subnet']} does not exist. Skipping this VIP.", "Firewall: Virtual IP", "");
1828
		return;
1829
	}
1830

    
1831
	if (does_interface_exist($vipif)) {
1832
		interface_bring_down($vipif);
1833
	} else {
1834
		$carpdevif = exec("/sbin/ifconfig carp create");
1835
		mwexec("/sbin/ifconfig {$carpdevif} name {$vipif}");
1836
		pfSense_ngctl_name("{$carpdevif}:", $vipif);
1837
	}
1838

    
1839
	mwexec("/sbin/ifconfig {$vipif} carpdev {$realif} vhid {$vip['vhid']} advskew {$vip['advskew']} advbase {$vip['advbase']} {$password}");
1840
	interfaces_bring_up($vipif);
1841

    
1842
	/*
1843
	 * XXX: BIG HACK but carpdev needs ip services active
1844
	 *      before even starting something as dhclient.
1845
	 *      I do not know if this is a feature or a bug
1846
	 *      but better than track it make it work ;) .
1847
	 */
1848
	//$fakeiptouse = "10.254.254." . ($carp_instances_counter+1);
1849
	//$cmdchain->add("CarpDEV hack", "/sbin/ifconfig {$carpint} inet {$fakeiptouse}", false);
1850

    
1851
	/* generate dhclient_wan.conf */
1852
	$fd = fopen("{$g['varetc_path']}/dhclient_{$vipif}.conf", "w");
1853
	if ($fd) {
1854
		$dhclientconf = "";
1855

    
1856
		$dhclientconf .= <<<EOD
1857
interface "{$vipif}" {
1858
timeout 60;
1859
retry 1;
1860
select-timeout 0;
1861
initial-interval 1;
1862
script "/sbin/dhclient-script";
1863
}
1864

    
1865
EOD;
1866

    
1867
		fwrite($fd, $dhclientconf);
1868
		fclose($fd);
1869

    
1870
		/* fire up dhclient */
1871
		mwexec("/sbin/dhclient -c {$g['varetc_path']}/dhclient_{$vipif}.conf {$vipif} >{$g['tmp_path']}/{$vipif}_output 2>{$g['tmp_path']}/{$vipif}_error_output", false);
1872
	} else {
1873
		log_error("Error: cannot open dhclient_{$vipif}.conf in interfaces_carpdev_configure() for writing.\n");
1874
		mwexec("/sbin/dhclient -b {$vipif}");
1875
	}
1876

    
1877
	return $vipif;
1878
}
1879

    
1880
function interface_wireless_clone($realif, $wlcfg) {
1881
	global $config, $g;
1882
	/*   Check to see if interface has been cloned as of yet.  
1883
	 *   If it has not been cloned then go ahead and clone it.
1884
	 */
1885
	$needs_clone = false;
1886
	if(is_array($wlcfg['wireless']))
1887
		$wlcfg_mode = $wlcfg['wireless']['mode'];
1888
	else
1889
		$wlcfg_mode = $wlcfg['mode'];
1890
	switch($wlcfg_mode) {
1891
		 case "hostap":
1892
			$mode = "wlanmode hostap";
1893
			break;
1894
		 case "adhoc":
1895
			$mode = "wlanmode adhoc";
1896
			break;
1897
		 default:
1898
			$mode = "";
1899
			break;
1900
	}
1901
	$baseif = interface_get_wireless_base($wlcfg['if']);
1902
	if(does_interface_exist($realif)) {
1903
		exec("/sbin/ifconfig {$realif}", $output, $ret);
1904
		$ifconfig_str = implode($output);
1905
		if(($wlcfg_mode == "hostap") && (! preg_match("/hostap/si", $ifconfig_str))) {
1906
			log_error("Interface {$realif} changed to hostap mode");
1907
			$needs_clone = true;
1908
		}
1909
		if(($wlcfg_mode == "adhoc") && (! preg_match("/adhoc/si", $ifconfig_str))) {
1910
			log_error("Interface {$realif} changed to adhoc mode");
1911
			$needs_clone = true;
1912
		}
1913
		if(($wlcfg_mode == "bss") && (preg_match("/hostap|adhoc/si", $ifconfig_str))) {
1914
			log_error("Interface {$realif} changed to infrastructure mode");
1915
			$needs_clone = true;
1916
		}
1917
	} else {
1918
		$needs_clone = true;
1919
	}
1920

    
1921
	if($needs_clone == true) {
1922
		/* remove previous instance if it exists */
1923
		if(does_interface_exist($realif))
1924
			pfSense_interface_destroy($realif);
1925

    
1926
		log_error("Cloning new wireless interface {$realif}");
1927
		// Create the new wlan interface. FreeBSD returns the new interface name.
1928
		// example:  wlan2
1929
		exec("/sbin/ifconfig wlan create wlandev {$baseif} {$mode} bssid 2>&1", $out, $ret);
1930
		if($ret <> 0) {
1931
			log_error("Failed to clone interface {$baseif} with error code {$ret}, output {$out[0]}");
1932
			return false;
1933
		}
1934
		$newif = trim($out[0]);
1935
		// Rename the interface to {$parentnic}_wlan{$number}#: EX: ath0_wlan0
1936
		pfSense_interface_rename($newif, $realif);
1937
		// FIXME: not sure what ngctl is for. Doesn't work.
1938
		// mwexec("/usr/sbin/ngctl name {$newif}: {$realif}", false);
1939
		file_put_contents("{$g['tmp_path']}/{$realif}_oldmac", get_interface_mac($realif));
1940
	}
1941
	return true;
1942
}
1943

    
1944
function interface_sync_wireless_clones(&$ifcfg, $sync_changes = false) {
1945
	global $config, $g;
1946

    
1947
	$shared_settings = array('standard', 'turbo', 'protmode', 'txpower', 'channel',
1948
	                         'diversity', 'txantenna', 'rxantenna', 'distance',
1949
	                         'regdomain', 'regcountry', 'reglocation');
1950

    
1951
	if(!is_interface_wireless($ifcfg['if']))
1952
		return;
1953

    
1954
	$baseif = interface_get_wireless_base($ifcfg['if']);
1955

    
1956
	// Sync shared settings for assigned clones
1957
	$iflist = get_configured_interface_list(false, true);
1958
	foreach ($iflist as $if) {
1959
		if ($baseif == interface_get_wireless_base($config['interfaces'][$if]['if']) && $ifcfg['if'] != $config['interfaces'][$if]['if']) {
1960
			if (isset($config['interfaces'][$if]['wireless']['standard']) || $sync_changes) {
1961
				foreach ($shared_settings as $setting) {
1962
					if ($sync_changes) {
1963
						if (isset($ifcfg['wireless'][$setting]))
1964
							$config['interfaces'][$if]['wireless'][$setting] = $ifcfg['wireless'][$setting];
1965
						else if (isset($config['interfaces'][$if]['wireless'][$setting]))
1966
							unset($config['interfaces'][$if]['wireless'][$setting]);
1967
					} else {
1968
						if (isset($config['interfaces'][$if]['wireless'][$setting]))
1969
							$ifcfg['wireless'][$setting] = $config['interfaces'][$if]['wireless'][$setting];
1970
						else if (isset($ifcfg['wireless'][$setting]))
1971
							unset($ifcfg['wireless'][$setting]);
1972
					}
1973
				}
1974
				if (!$sync_changes)
1975
					break;
1976
			}
1977
		}
1978
	}
1979

    
1980
	// Read or write settings at shared area
1981
	if (isset($config['wireless']['interfaces'][$baseif])) {
1982
		foreach ($shared_settings as $setting) {
1983
			if ($sync_changes) {
1984
				if (isset($ifcfg['wireless'][$setting]))
1985
					$config['wireless']['interfaces'][$baseif][$setting] = $ifcfg['wireless'][$setting];
1986
				else if (isset($config['wireless']['interfaces'][$baseif][$setting]))
1987
					unset($config['wireless']['interfaces'][$baseif][$setting]);
1988
			} else if (isset($config['wireless']['interfaces'][$baseif][$setting])) {
1989
				if (isset($config['wireless']['interfaces'][$baseif][$setting]))
1990
					$ifcfg['wireless'][$setting] = $config['wireless']['interfaces'][$baseif][$setting];
1991
				else if (isset($ifcfg['wireless'][$setting]))
1992
					unset($ifcfg['wireless'][$setting]);
1993
			}
1994
		}
1995
	}
1996

    
1997
	// Sync the mode on the clone creation page with the configured mode on the interface
1998
	if (interface_is_wireless_clone($ifcfg['if'])) {
1999
		foreach ($config['wireless']['clone'] as &$clone) {
2000
			if ($clone['cloneif'] == $ifcfg['if']) {
2001
				if ($sync_changes) {
2002
					$clone['mode'] = $ifcfg['wireless']['mode'];
2003
				} else {
2004
					$ifcfg['wireless']['mode'] = $clone['mode'];
2005
				}
2006
				break;
2007
			}
2008
		}
2009
		unset($clone);
2010
	}
2011
}
2012

    
2013
function interface_wireless_configure($if, &$wl, &$wlcfg) {
2014
	global $config, $g;
2015

    
2016
	/*    open up a shell script that will be used to output the commands.
2017
	 *    since wireless is changing a lot, these series of commands are fragile
2018
     *    and will sometimes need to be verified by a operator by executing the command
2019
     *    and returning the output of the command to the developers for inspection.  please
2020
     *    do not change this routine from a shell script to individul exec commands.  -sullrich
2021
	 */
2022

    
2023
	// Remove script file
2024
	unlink_if_exists("{$g['tmp_path']}/{$if}_setup.sh");
2025

    
2026
	// Clone wireless nic if needed.
2027
	interface_wireless_clone($if, $wl);
2028

    
2029
	// Reject inadvertent changes to shared settings in case the interface hasn't been configured.
2030
	interface_sync_wireless_clones($wl, false);
2031

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

    
2036
	/* set values for /path/program */
2037
	$hostapd = "/usr/sbin/hostapd";
2038
	$wpa_supplicant = "/usr/sbin/wpa_supplicant";
2039
	$ifconfig = "/sbin/ifconfig";
2040
	$sysctl = "/sbin/sysctl";
2041
	$killall = "/usr/bin/killall";
2042

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

    
2045
	$wlcmd = array();
2046
	$wl_sysctl = array();
2047
	/* Make sure it's up */
2048
	$wlcmd[] = "up";
2049
	/* Set a/b/g standard */
2050
	$standard = str_replace(" Turbo", "", $wlcfg['standard']);
2051
	$wlcmd[] = "mode " . escapeshellarg($standard);
2052

    
2053
	/* XXX: Disable ampdu for now on mwl when running in 11n mode
2054
	 * to prevent massive packet loss under certain conditions. */
2055
	if(preg_match("/^mwl/i", $if) && ($standard == "11ng" || $standard == "11na"))
2056
		$wlcmd[] = "-ampdu";
2057

    
2058
	/* Set ssid */
2059
	if($wlcfg['ssid'])
2060
		$wlcmd[] = "ssid " .escapeshellarg($wlcfg['ssid']);
2061

    
2062
	/* Set 802.11g protection mode */
2063
	$wlcmd[] = "protmode " . escapeshellarg($wlcfg['protmode']);
2064

    
2065
	/* set wireless channel value */
2066
	if(isset($wlcfg['channel'])) {
2067
		if($wlcfg['channel'] == "0") {
2068
			$wlcmd[] = "channel any";
2069
		} else {
2070
			$wlcmd[] = "channel " . escapeshellarg($wlcfg['channel']);
2071
		}
2072
	}
2073

    
2074
	/* Set antenna diversity value */
2075
	if(isset($wlcfg['diversity']))
2076
		$wl_sysctl[] = "diversity=" . escapeshellarg($wlcfg['diversity']);
2077

    
2078
	/* Set txantenna value */
2079
	if(isset($wlcfg['txantenna']))
2080
		$wl_sysctl[] = "txantenna=" . escapeshellarg($wlcfg['txantenna']);
2081

    
2082
	/* Set rxantenna value */
2083
	if(isset($wlcfg['rxantenna']))
2084
		$wl_sysctl[] = "rxantenna=" . escapeshellarg($wlcfg['rxantenna']);
2085

    
2086
	/* set Distance value */
2087
	if($wlcfg['distance'])
2088
		$distance = escapeshellarg($wlcfg['distance']);
2089

    
2090
	/* Set wireless hostap mode */
2091
	if ($wlcfg['mode'] == "hostap") {
2092
		$wlcmd[] = "mediaopt hostap";
2093
	} else {
2094
		$wlcmd[] = "-mediaopt hostap";
2095
	}
2096

    
2097
	/* Set wireless adhoc mode */
2098
	if ($wlcfg['mode'] == "adhoc") {
2099
		$wlcmd[] = "mediaopt adhoc";
2100
	} else {
2101
		$wlcmd[] = "-mediaopt adhoc";
2102
	}
2103

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

    
2106
	/* handle hide ssid option */
2107
	if(isset($wlcfg['hidessid']['enable'])) {
2108
		$wlcmd[] = "hidessid";
2109
	} else {
2110
		$wlcmd[] = "-hidessid";
2111
	}
2112

    
2113
	/* handle pureg (802.11g) only option */
2114
	if(isset($wlcfg['pureg']['enable'])) {
2115
		$wlcmd[] = "mode 11g pureg";
2116
	} else {
2117
		$wlcmd[] = "-pureg";
2118
	}
2119

    
2120
	/* handle puren (802.11n) only option */
2121
	if(isset($wlcfg['puren']['enable'])) {
2122
		$wlcmd[] = "puren";
2123
	} else {
2124
		$wlcmd[] = "-puren";
2125
	}
2126

    
2127
	/* enable apbridge option */
2128
	if(isset($wlcfg['apbridge']['enable'])) {
2129
		$wlcmd[] = "apbridge";
2130
	} else {
2131
		$wlcmd[] = "-apbridge";
2132
	}
2133

    
2134
	/* handle turbo option */
2135
	if(isset($wlcfg['turbo']['enable'])) {
2136
		$wlcmd[] = "mediaopt turbo";
2137
	} else {
2138
		$wlcmd[] = "-mediaopt turbo";
2139
	}
2140

    
2141
	/* handle txpower setting */
2142
	/* if($wlcfg['txpower'] <> "")
2143
		$wlcmd[] = "txpower " . escapeshellarg($wlcfg['txpower']);
2144
	*/
2145
	/* handle wme option */
2146
	if(isset($wlcfg['wme']['enable'])) {
2147
		$wlcmd[] = "wme";
2148
	} else {
2149
		$wlcmd[] = "-wme";
2150
	}
2151

    
2152
	/* set up wep if enabled */
2153
	$wepset = "";
2154
	if (isset($wlcfg['wep']['enable']) && is_array($wlcfg['wep']['key'])) {
2155
		switch($wlcfg['wpa']['auth_algs']) {
2156
			case "1":
2157
				$wepset .= "authmode open wepmode on ";
2158
				break;
2159
			case "2":
2160
				$wepset .= "authmode shared wepmode on ";
2161
				break;
2162
			case "3":
2163
				$wepset .= "authmode mixed wepmode on ";
2164
		}
2165
		$i = 1;
2166
		foreach ($wlcfg['wep']['key'] as $wepkey) {
2167
			$wepset .= "wepkey " . escapeshellarg("{$i}:{$wepkey['value']}") . " ";
2168
			if (isset($wepkey['txkey'])) {
2169
				$wlcmd[] = "weptxkey {$i} ";
2170
			}
2171
			$i++;
2172
		}
2173
		$wlcmd[] = $wepset;
2174
	} else {
2175
		$wlcmd[] = "authmode open wepmode off ";
2176
	}
2177

    
2178
	mwexec(kill_hostapd("{$if}"));
2179
	mwexec(kill_wpasupplicant("{$if}"));
2180

    
2181
	/* generate wpa_supplicant/hostap config if wpa is enabled */
2182
	conf_mount_rw();
2183

    
2184
	switch ($wlcfg['mode']) {
2185
		case 'bss':
2186
			if (isset($wlcfg['wpa']['enable'])) {
2187
				$wpa .= <<<EOD
2188
ctrl_interface={$g['varrun_path']}/wpa_supplicant
2189
ctrl_interface_group=0
2190
ap_scan=1
2191
#fast_reauth=1
2192
network={
2193
ssid="{$wlcfg['ssid']}"
2194
scan_ssid=1
2195
priority=5
2196
key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
2197
psk="{$wlcfg['wpa']['passphrase']}"
2198
pairwise={$wlcfg['wpa']['wpa_pairwise']}
2199
group={$wlcfg['wpa']['wpa_pairwise']}
2200
}
2201
EOD;
2202

    
2203
				$fd = fopen("{$g['varetc_path']}/wpa_supplicant_{$if}.conf", "w");
2204
				fwrite($fd, "{$wpa}");
2205
				fclose($fd);
2206
			}
2207
			break;
2208
		case 'hostap':
2209
			if($wlcfg['wpa']['passphrase']) 
2210
				$wpa_passphrase = "wpa_passphrase={$wlcfg['wpa']['passphrase']}\n";
2211
			else 
2212
				$wpa_passphrase = "";
2213
			if (isset($wlcfg['wpa']['enable'])) {
2214
				$wpa .= <<<EOD
2215
interface={$if}
2216
driver=bsd
2217
logger_syslog=-1
2218
logger_syslog_level=0
2219
logger_stdout=-1
2220
logger_stdout_level=0
2221
dump_file={$g['tmp_path']}/hostapd_{$if}.dump
2222
ctrl_interface={$g['varrun_path']}/hostapd
2223
ctrl_interface_group=wheel
2224
#accept_mac_file={$g['tmp_path']}/hostapd_{$if}.accept
2225
#deny_mac_file={$g['tmp_path']}/hostapd_{$if}.deny
2226
#macaddr_acl={$wlcfg['wpa']['macaddr_acl']}
2227
ssid={$wlcfg['ssid']}
2228
debug={$wlcfg['wpa']['debug_mode']}
2229
auth_algs={$wlcfg['wpa']['auth_algs']}
2230
wpa={$wlcfg['wpa']['wpa_mode']}
2231
wpa_key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
2232
wpa_pairwise={$wlcfg['wpa']['wpa_pairwise']}
2233
wpa_group_rekey={$wlcfg['wpa']['wpa_group_rekey']}
2234
wpa_gmk_rekey={$wlcfg['wpa']['wpa_gmk_rekey']}
2235
wpa_strict_rekey={$wlcfg['wpa']['wpa_strict_rekey']}
2236
{$wpa_passphrase}
2237

    
2238
EOD;
2239

    
2240
if (isset($wlcfg['wpa']['rsn_preauth'])) {
2241
	$wpa .= <<<EOD
2242
# Enable the next lines for preauth when roaming. Interface = wired or wireless interface talking to the AP you want to roam from/to
2243
rsn_preauth=1
2244
rsn_preauth_interfaces={$if}
2245

    
2246
EOD;
2247

    
2248
}
2249
				if($wlcfg['auth_server_addr'] && $wlcfg['auth_server_shared_secret']) {
2250
					$auth_server_port = "1812";
2251
					if($wlcfg['auth_server_port']) 
2252
						$auth_server_port = $wlcfg['auth_server_port'];
2253
					$wpa .= <<<EOD
2254

    
2255
ieee8021x=1
2256
auth_server_addr={$wlcfg['auth_server_addr']}
2257
auth_server_port={$auth_server_port}
2258
auth_server_shared_secret={$wlcfg['auth_server_shared_secret']}
2259

    
2260
EOD;
2261
				} else {
2262
					$wpa .= "ieee8021x={$wlcfg['wpa']['ieee8021x']}\n";
2263
				}
2264

    
2265
				$fd = fopen("{$g['varetc_path']}/hostapd_{$if}.conf", "w");
2266
				fwrite($fd, "{$wpa}");
2267
				fclose($fd);
2268

    
2269
			}
2270
			break;
2271
	}
2272

    
2273
	/*
2274
	 *    all variables are set, lets start up everything
2275
	 */
2276

    
2277
	$baseif = interface_get_wireless_base($if);
2278
	preg_match("/^(.*?)([0-9]*)$/", $baseif, $baseif_split);
2279
	$wl_sysctl_prefix = 'dev.' . $baseif_split[1] . '.' . $baseif_split[2];
2280

    
2281
	/* set sysctls for the wireless interface */
2282
	if (!empty($wl_sysctl)) {
2283
		fwrite($fd_set, "# sysctls for {$baseif}\n");
2284
		foreach ($wl_sysctl as $wl_sysctl_line) {
2285
			fwrite($fd_set, "{$sysctl} {$wl_sysctl_prefix}.{$wl_sysctl_line}\n");
2286
		}
2287
	}
2288

    
2289
	/* set ack timers according to users preference (if he/she has any) */
2290
	if($distance) {
2291
		fwrite($fd_set, "# Enable ATH distance settings\n");
2292
		fwrite($fd_set, "/sbin/athctrl.sh -i {$baseif} -d {$distance}\n");
2293
	}
2294

    
2295
	if (isset($wlcfg['wpa']['enable'])) {
2296
		if ($wlcfg['mode'] == "bss") {
2297
			fwrite($fd_set, "{$wpa_supplicant} -B -i {$if} -c {$g['varetc_path']}/wpa_supplicant_{$if}.conf\n");
2298
		}
2299
		if ($wlcfg['mode'] == "hostap") {
2300
			/* add line to script to restore old mac to make hostapd happy */
2301
			if (file_exists("{$g['tmp_path']}/{$if}_oldmac")) {
2302
				$if_oldmac = file_get_contents("{$g['tmp_path']}/{$if}_oldmac");
2303
				if (is_macaddr($if_oldmac))
2304
					fwrite($fd_set, "{$ifconfig} " . escapeshellarg($if) .
2305
						" link " . escapeshellarg($if_oldmac) . "\n");
2306
			}
2307

    
2308
			fwrite($fd_set, "{$hostapd} -B {$g['varetc_path']}/hostapd_{$if}.conf\n");
2309

    
2310
			/* add line to script to restore spoofed mac after running hostapd */
2311
			if (file_exists("{$g['tmp_path']}/{$if}_oldmac")) {
2312
				if ($wl['spoofmac'])
2313
					$if_curmac = $wl['spoofmac'];
2314
				else
2315
					$if_curmac = get_interface_mac($if);
2316
				if (is_macaddr($if_curmac))
2317
					fwrite($fd_set, "{$ifconfig} " . escapeshellarg($if) .
2318
						" link " . escapeshellarg($if_curmac) . "\n");
2319
			}
2320
		}
2321
	}
2322

    
2323
	fclose($fd_set);
2324
	conf_mount_ro();
2325

    
2326
	/* Making sure regulatory settings have actually changed
2327
	 * before applying, because changing them requires bringing
2328
	 * down all wireless networks on the interface. */
2329
	exec("{$ifconfig} " . escapeshellarg($if), $output);
2330
	$ifconfig_str = implode($output);
2331
	unset($output);
2332
	$reg_changing = false;
2333

    
2334
	/* special case for the debug country code */
2335
	if ($wlcfg['regcountry'] == 'DEBUG' && !preg_match("/\sregdomain\s+DEBUG\s/si", $ifconfig_str))
2336
		$reg_changing = true;
2337
	else if ($wlcfg['regdomain'] && !preg_match("/\sregdomain\s+{$wlcfg['regdomain']}\s/si", $ifconfig_str))
2338
		$reg_changing = true;
2339
	else if ($wlcfg['regcountry'] && !preg_match("/\scountry\s+{$wlcfg['regcountry']}\s/si", $ifconfig_str))
2340
		$reg_changing = true;
2341
	else if ($wlcfg['reglocation'] == 'anywhere' && preg_match("/\s(indoor|outdoor)\s/si", $ifconfig_str))
2342
		$reg_changing = true;
2343
	else if ($wlcfg['reglocation'] && $wlcfg['reglocation'] != 'anywhere' && !preg_match("/\s{$wlcfg['reglocation']}\s/si", $ifconfig_str))
2344
		$reg_changing = true;
2345

    
2346
	if ($reg_changing) {
2347
		/* set regulatory domain */
2348
		if($wlcfg['regdomain'])
2349
			$wlregcmd[] = "regdomain " . escapeshellarg($wlcfg['regdomain']);
2350

    
2351
		/* set country */
2352
		if($wlcfg['regcountry'])
2353
			$wlregcmd[] = "country " . escapeshellarg($wlcfg['regcountry']);
2354

    
2355
		/* set location */
2356
		if($wlcfg['reglocation'])
2357
			$wlregcmd[] = escapeshellarg($wlcfg['reglocation']);
2358

    
2359
		$wlregcmd_args = implode(" ", $wlregcmd);
2360

    
2361
		/* build a complete list of the wireless clones for this interface */
2362
		$clone_list = array();
2363
		if (does_interface_exist(interface_get_wireless_clone($baseif)))
2364
			$clone_list[] = interface_get_wireless_clone($baseif);
2365
		if (is_array($config['wireless']['clone'])) {
2366
			foreach ($config['wireless']['clone'] as $clone) {
2367
				if ($clone['if'] == $baseif)
2368
					$clone_list[] = $clone['cloneif'];
2369
			}
2370
		}
2371

    
2372
		/* find which clones are up and bring them down */
2373
		$clones_up = array();
2374
		foreach ($clone_list as $clone_if) {
2375
			$clone_status = pfSense_get_interface_addresses($clone_if);
2376
			if ($clone_status['status'] == 'up') {
2377
				$clones_up[] = $clone_if;
2378
				mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " down");
2379
			}
2380
		}
2381

    
2382
		/* apply the regulatory settings */
2383
		mwexec("{$ifconfig} " . escapeshellarg($if) . " {$wlregcmd_args}");
2384

    
2385
		/* bring the clones back up that were previously up */
2386
		foreach ($clones_up as $clone_if) {
2387
			mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " up");
2388

    
2389
			/*
2390
			 * Rerun the setup script for the interface if it isn't this interface, the interface
2391
			 * is in infrastructure mode, and WPA is enabled.
2392
			 * This can be removed if wpa_supplicant stops dying when you bring the interface down.
2393
			 */
2394
			if ($clone_if != $if) {
2395
				$friendly_if = convert_real_interface_to_friendly_interface_name($clone_if);
2396
				if ( !empty($friendly_if)
2397
				    && $config['interfaces'][$friendly_if]['wireless']['mode'] == "bss"
2398
				    && isset($config['interfaces'][$friendly_if]['wireless']['wpa']['enable']) ) {
2399
					mwexec("/bin/sh {$g['tmp_path']}/{$clone_if}_setup.sh");
2400
				}
2401
			}
2402
		}
2403
	}
2404

    
2405
	/* The mode must be specified in a separate command before ifconfig
2406
	 * will allow the mode and channel at the same time in the next. */
2407
	mwexec("/sbin/ifconfig {$if} mode " . escapeshellarg($standard));
2408

    
2409
	/* configure wireless */
2410
	$wlcmd_args = implode(" ", $wlcmd);
2411
	mwexec("/sbin/ifconfig {$if} $wlcmd_args", false);
2412

    
2413
	
2414
	sleep(1);
2415
	/* execute hostapd and wpa_supplicant if required in shell */
2416
	mwexec("/bin/sh {$g['tmp_path']}/{$if}_setup.sh");
2417

    
2418
	return 0;
2419

    
2420
}
2421

    
2422
function kill_hostapd($interface) {
2423
	return "/bin/pkill -f \"hostapd .*{$interface}\"\n";
2424
}
2425

    
2426
function kill_wpasupplicant($interface) {
2427
	return "/bin/pkill -f \"wpa_supplicant .*{$interface}\"\n";
2428
}
2429

    
2430
function find_dhclient_process($interface) {
2431
	if ($interface)
2432
		$pid = `/bin/pgrep -xf "dhclient: {$interface}"`;
2433
	else
2434
		$pid = 0;
2435

    
2436
	return $pid;
2437
}
2438

    
2439
function interface_configure($interface = "wan", $reloadall = false, $linkupevent = false) {
2440
	global $config, $g;
2441
	global $interface_sn_arr_cache, $interface_ip_arr_cache;
2442

    
2443
	$wancfg = $config['interfaces'][$interface];
2444

    
2445
	$realif = get_real_interface($interface);
2446
	$realhwif = interface_translate_type_to_real($interface);
2447

    
2448
	if (!$g['booting']) {
2449
		/* remove all IPv4 addresses */
2450
		while (mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " -alias", true) == 0);
2451

    
2452
		switch ($wancfg['ipaddr']) {
2453
			case 'pppoe':
2454
			case 'l2tp':
2455
			case 'pptp':
2456
			case 'ppp':
2457
				interface_bring_down($interface, true);
2458
				break;
2459
			default:
2460
				interface_bring_down($interface);
2461
				break;
2462
		}
2463
	}
2464

    
2465
	/* wireless configuration? */
2466
	if (is_array($wancfg['wireless']))
2467
		interface_wireless_configure($realif, $wancfg, $wancfg['wireless']);
2468

    
2469
	if ($wancfg['spoofmac']) {
2470
		mwexec("/sbin/ifconfig " . escapeshellarg($realhwif) .
2471
			" link " . escapeshellarg($wancfg['spoofmac']));
2472

    
2473
                /*
2474
                 * All vlans need to spoof their parent mac address, too.  see
2475
                 * ticket #1514: http://cvstrac.pfsense.com/tktview?tn=1514,33
2476
                 */
2477
                if (is_array($config['vlans']['vlan'])) {
2478
                        foreach ($config['vlans']['vlan'] as $vlan) {
2479
                                if ($vlan['if'] == $realhwif)
2480
                                        mwexec("/sbin/ifconfig " . escapeshellarg($vlan['vlanif']) .
2481
                                                " link " . escapeshellarg($wancfg['spoofmac']));
2482
                        }
2483
                }
2484
	}  else {
2485
		$mac = get_interface_mac($realhwif);
2486
		if ($mac == "ff:ff:ff:ff:ff:ff") {
2487
			/*   this is not a valid mac address.  generate a
2488
			 *   temporary mac address so the machine can get online.
2489
			 */
2490
			echo "Generating new MAC address.";
2491
			$random_mac = generate_random_mac_address();
2492
			mwexec("/sbin/ifconfig " . escapeshellarg($realhwif) .
2493
				" link " . escapeshellarg($random_mac));
2494
			$wancfg['spoofmac'] = $random_mac;
2495
			write_config();
2496
			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");
2497
		}
2498
	}
2499

    
2500
	/* media */
2501
	if ($wancfg['media'] || $wancfg['mediaopt']) {
2502
		$cmd = "/sbin/ifconfig " . escapeshellarg($realhwif);
2503
		if ($wancfg['media'])
2504
			$cmd .= " media " . escapeshellarg($wancfg['media']);
2505
		if ($wancfg['mediaopt'])
2506
			$cmd .= " mediaopt " . escapeshellarg($wancfg['mediaopt']);
2507
		mwexec($cmd);
2508
	}
2509
	if (!empty($wancfg['mtu']))
2510
		pfSense_interface_mtu($realhwif, $wancfg['mtu']);
2511

    
2512
	$options = pfSense_get_interface_addresses($realhwif);
2513
	if (is_array($options) && isset($options['caps']['polling'])) {
2514
		if (isset($config['system']['polling']))
2515
			pfSense_interface_capabilities($realif, IFCAP_POLLING);
2516
		else
2517
			pfSense_interface_capabilities($realif, -IFCAP_POLLING);
2518
	}
2519

    
2520
	/* skip vlans for checksumming and polling */
2521
        if (!stristr($realhwif, "vlan") && is_array($options)) {
2522
		$flags = 0;
2523
		if(isset($config['system']['disablechecksumoffloading'])) {
2524
			if (isset($options['encaps']['txcsum']))
2525
				$flags |= IFCAP_TXCSUM;
2526
			if (isset($options['encaps']['rxcsum']))
2527
				$flags |= IFCAP_RXCSUM;
2528
        	} else {
2529
 			if (!isset($options['caps']['txcsum']))
2530
				$flags |= IFCAP_TXCSUM;
2531
			if (!isset($options['caps']['rxcsum']))
2532
				$flags |= IFCAP_RXCSUM;
2533
        	}
2534

    
2535
        	if(isset($config['system']['disablesegmentationoffloading'])) {
2536
                	if (isset($options['encaps']['tso4']))
2537
				$flags |= IFCAP_TSO;
2538
                	if (isset($options['encaps']['tso6']))
2539
				$flags |= IFCAP_TSO;
2540
        	} else {
2541
                	if (!isset($options['caps']['tso4']))
2542
				$flags |= IFCAP_TSO;
2543
                	if (!isset($options['caps']['tso6']))
2544
				$flags |= IFCAP_TSO;
2545
        	}
2546

    
2547
        	if(isset($config['system']['disablelargereceiveoffloading'])) {
2548
                	if (isset($options['encaps']['lro']))
2549
				$flags |= IFCAP_LRO;
2550
        	} else {
2551
                	if (!isset($options['caps']['lro']))
2552
				$flags |= IFCAP_LRO;
2553
        	}
2554

    
2555
        	/* if the NIC supports polling *AND* it is enabled in the GUI */
2556
        	if (!isset($config['system']['polling']) || !isset($options['caps']['polling'])) {
2557
			$flags |= IFCAP_POLLING;
2558
		}
2559
               	pfSense_interface_capabilities($realhwif, -$flags);
2560
	}
2561

    
2562
	/* invalidate interface/ip/sn cache */
2563
	get_interface_arr(true);
2564
	unset($interface_ip_arr_cache[$realif]);
2565
	unset($interface_sn_arr_cache[$realif]);
2566

    
2567
	switch ($wancfg['ipaddr']) {
2568
		case 'carpdev-dhcp':
2569
			interface_carpdev_dhcp_configure($interface);
2570
			break;
2571
		case 'dhcp':
2572
			interface_dhcp_configure($interface);
2573
			break;
2574
		case 'pppoe':
2575
		case 'l2tp':
2576
		case 'pptp':
2577
		case 'ppp':
2578
			interface_ppps_configure($interface);
2579
			break;
2580
		default:
2581
			if ($wancfg['ipaddr'] <> "" && $wancfg['subnet'] <> "") {
2582
				pfSense_interface_setaddress($realif, "{$wancfg['ipaddr']}/{$wancfg['subnet']}");
2583
			} else if (substr($realif, 0, 3) == "gre") {
2584
				if (is_array($config['gres']['gre'])) {
2585
					foreach ($config['gres']['gre'] as $gre)
2586
						if ($gre['greif'] == $realif)
2587
							interface_gre_configure($gre);
2588
				}
2589
			} else if (substr($realif, 0, 3) == "gif") {
2590
				 if (is_array($config['gifs']['gif'])) {
2591
					foreach ($config['gifs']['gif'] as $gif)
2592
						if($gif['gifif'] == $interface)
2593
							interface_gif_configure($gif);
2594
				}
2595
			} else if (substr($realif, 0, 4) == "ovpn") {
2596
				/* XXX: Should be done anything?! */
2597
			}
2598
			break;
2599
	}
2600

    
2601
	if(does_interface_exist($wancfg['if']))
2602
		interfaces_bring_up($wancfg['if']);
2603

    
2604
	interface_netgraph_needed($interface);
2605
 	
2606
	if (!$g['booting']) {
2607
		link_interface_to_vips($interface, "update");
2608

    
2609
		unset($gre);
2610
		$gre = link_interface_to_gre($interface);
2611
		if (!empty($gre))
2612
			array_walk($gre, 'interface_gre_configure');
2613

    
2614
		unset($gif);
2615
		$gif = link_interface_to_gif($interface);
2616
		if (!empty($gif))
2617
                       	array_walk($gif, 'interface_gif_configure');
2618

    
2619
		if ($linkupevent == false) {
2620
			unset($bridgetmp);
2621
			$bridgetmp = link_interface_to_bridge($interface);
2622
			if (!empty($bridgetmp))
2623
				interface_bridge_add_member($bridgetmp, $realif);
2624
		}
2625

    
2626
		$grouptmp = link_interface_to_group($interface);
2627
		if (!empty($grouptmp))
2628
			array_walk($grouptmp, 'interface_group_add_member');
2629

    
2630
		if ($interface == "lan")
2631
			/* make new hosts file */
2632
			system_hosts_generate();
2633

    
2634
		if ($reloadall == true) {
2635

    
2636
			/* reconfigure static routes (kernel may have deleted them) */
2637
			system_routing_configure($interface);
2638

    
2639
			/* reload ipsec tunnels */
2640
			vpn_ipsec_configure();
2641

    
2642
			/* restart dnsmasq */
2643
			services_dnsmasq_configure();
2644

    
2645
			/* update dyndns */
2646
			send_event("service reload dyndns {$interface}");
2647

    
2648
			/* reload captive portal */
2649
			captiveportal_init_rules();
2650
		}
2651
	}
2652

    
2653
	return 0;
2654
}
2655

    
2656
function interface_carpdev_dhcp_configure($interface = "wan") {
2657
	global $config, $g;
2658

    
2659
	$wancfg = $config['interfaces'][$interface];
2660
	$wanif = $wancfg['if'];
2661
	/* bring wan interface up before starting dhclient */
2662
	if($wanif)
2663
		interfaces_bring_up($wanif);
2664
	else 
2665
		log_error("Could not bring wanif up in terface_carpdev_dhcp_configure()");
2666

    
2667
	return 0;
2668
}
2669

    
2670
function interface_dhcp_configure($interface = "wan") {
2671
	global $config, $g;
2672

    
2673
	$wancfg = $config['interfaces'][$interface];
2674
	if (empty($wancfg))
2675
		$wancfg = array();
2676

    
2677
	/* generate dhclient_wan.conf */
2678
	$fd = fopen("{$g['varetc_path']}/dhclient_{$interface}.conf", "w");
2679
	if (!$fd) {
2680
		printf("Error: cannot open dhclient_{$interface}.conf in interfaces_wan_dhcp_configure() for writing.\n");
2681
		return 1;
2682
	}
2683

    
2684
	if ($wancfg['dhcphostname']) {
2685
		$dhclientconf_hostname = "send dhcp-client-identifier \"{$wancfg['dhcphostname']}\";\n";
2686
		$dhclientconf_hostname .= "\tsend host-name \"{$wancfg['dhcphostname']}\";\n";
2687
	} else {
2688
		$dhclientconf_hostname = "";
2689
	}
2690

    
2691
	$wanif = get_real_interface($interface);
2692
	if (empty($wanif)) {
2693
		log_error("Invalid interface \"{$interface}\" in interface_dhcp_configure()");
2694
		return 0;
2695
	}
2696
 	$dhclientconf = "";
2697
	
2698
	$dhclientconf .= <<<EOD
2699
interface "{$wanif}" {
2700
timeout 60;
2701
retry 1;
2702
select-timeout 0;
2703
initial-interval 1;
2704
	{$dhclientconf_hostname}
2705
	script "/sbin/dhclient-script";
2706
}
2707

    
2708
EOD;
2709

    
2710
if(is_ipaddr($wancfg['alias-address'])) {
2711
	$subnetmask = gen_subnet_mask($wancfg['alias-subnet']);
2712
	$dhclientconf .= <<<EOD
2713
alias {
2714
	interface  "{$wanif}";
2715
	fixed-address {$wancfg['alias-address']};
2716
	option subnet-mask {$subnetmask};
2717
}
2718

    
2719
EOD;
2720
}
2721
	fwrite($fd, $dhclientconf);
2722
	fclose($fd);
2723

    
2724
	/* bring wan interface up before starting dhclient */
2725
	if($wanif)
2726
		interfaces_bring_up($wanif);
2727
	else 
2728
		log_error("Could not bring up {$wanif} interface in interface_dhcp_configure()");
2729

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

    
2733
	return 0;
2734
}
2735

    
2736
function interfaces_group_setup() {
2737
	global $config;
2738

    
2739
	if (!is_array($config['ifgroups']['ifgroupentry']))
2740
		return;
2741

    
2742
	foreach ($config['ifgroups']['ifgroupentry'] as $groupar)
2743
		interface_group_setup($groupar);
2744

    
2745
	return;
2746
}
2747

    
2748
function interface_group_setup(&$groupname /* The parameter is an array */) {
2749
	global $config;
2750

    
2751
	if (!is_array($groupname))
2752
		return;
2753
	$members = explode(" ", $groupname['members']);
2754
	foreach($members as $ifs) {
2755
		$realif = get_real_interface($ifs);
2756
		if ($realif)
2757
			mwexec("/sbin/ifconfig {$realif} group {$groupname['ifname']}");
2758
	}
2759

    
2760
	return;
2761
}
2762

    
2763
function interface_group_add_member($interface, $groupname) {
2764
	$interface = get_real_interface($interface);
2765
	mwexec("/sbin/ifconfig {$interface} group {$groupname}", true);
2766
}
2767
 
2768
/* COMPAT Function */
2769
function convert_friendly_interface_to_real_interface_name($interface) {
2770
	return get_real_interface($interface);
2771
}
2772

    
2773
/* COMPAT Function */
2774
function get_real_wan_interface($interface = "wan") {
2775
	return get_real_interface($interface);
2776
}
2777

    
2778
/* COMPAT Function */
2779
function get_current_wan_address($interface = "wan") {
2780
	return get_interface_ip($interface);
2781
}
2782

    
2783
/*
2784
 * convert_real_interface_to_friendly_interface_name($interface): convert fxp0 -> wan, etc.
2785
 */
2786
function convert_real_interface_to_friendly_interface_name($interface = "wan") {
2787
        global $config;
2788

    
2789
	if (stristr($interface, "vip")) {
2790
                $index = intval(substr($interface, 3));
2791
                foreach ($config['virtualip']['vip'] as $counter => $vip) {
2792
                        if ($vip['mode'] == "carpdev-dhcp" || $vip['mode'] == "carp")  {
2793
                                if ($index == $vip['vhid'])
2794
                                        return $vip['interface'];
2795
                        }
2796
                }
2797
        }
2798

    
2799
        /* XXX: For speed reasons reference directly the interface array */
2800
	$ifdescrs = &$config['interfaces'];
2801
        //$ifdescrs = get_configured_interface_list(false, true);
2802

    
2803
        foreach ($ifdescrs as $if => $ifname) {
2804
                if ($config['interfaces'][$if]['if'] == $interface)
2805
                        return $if;
2806

    
2807
                if (stristr($interface, "_wlan0") && $config['interfaces'][$if]['if'] == interface_get_wireless_base($interface))
2808
                        return $if;
2809

    
2810
                $int = interface_translate_type_to_real($if);
2811
                if ($int == $interface)
2812
                        return $ifname;
2813
        }
2814
        return NULL;
2815
}
2816

    
2817
/* attempt to resolve interface to friendly descr */
2818
function convert_friendly_interface_to_friendly_descr($interface) {
2819
        global $config;
2820

    
2821
        switch ($interface) {
2822
        case "l2tp":
2823
        	$ifdesc = "L2TP";
2824
                break;
2825
	case "pptp":
2826
		$ifdesc = "PPTP";
2827
		break;
2828
	case "pppoe":
2829
		$ifdesc = "PPPoE";
2830
		break;
2831
	case "openvpn":
2832
		$ifdesc = "OpenVPN";
2833
		break;
2834
	case "enc0":
2835
	case "ipsec":
2836
		$ifdesc = "IPsec";
2837
		break;
2838
        default:
2839
                if (isset($config['interfaces'][$interface])) {
2840
                        if (empty($config['interfaces'][$interface]['descr']))
2841
                                $ifdesc = strtoupper($interface);
2842
                        else
2843
                                $ifdesc = strtoupper($config['interfaces'][$interface]['descr']);
2844
			break;
2845
		} else if (substr($interface, 0, 3) == "vip") {
2846
			if (is_array($config['virtualip']['vip'])) {
2847
				foreach ($config['virtualip']['vip'] as $counter => $vip) {
2848
					if ($vip['mode'] == "carpdev-dhcp" || $vip['mode'] == "carp")  {
2849
						if ($interface == "vip{$vip['vhid']}")
2850
							return "{$vip['subnet']} - {$vip['descr']}";
2851
					}
2852
				}
2853
                        }
2854
                } else {
2855
			/* if list */
2856
			$ifdescrs = get_configured_interface_with_descr(false, true);
2857
			foreach ($ifdescrs as $if => $ifname) {
2858
					if ($if == $interface || $ifname == $interface)
2859
						return $ifname;
2860
			}
2861
		}
2862
                break;
2863
        }
2864

    
2865
        return $ifdesc;
2866
}
2867

    
2868
function convert_real_interface_to_friendly_descr($interface) {
2869
        global $config;
2870

    
2871
        $ifdesc = convert_real_interface_to_friendly_interface_name("{$interface}");
2872

    
2873
        if ($ifdesc) {
2874
                $iflist = get_configured_interface_with_descr(false, true);
2875
                return $iflist[$ifdesc];
2876
        }
2877

    
2878
        return $interface;
2879
}
2880

    
2881
/*
2882
 *  interface_translate_type_to_real($interface):
2883
 *              returns the real hardware interface name for a friendly interface.  ie: wan
2884
 */
2885
function interface_translate_type_to_real($interface) {
2886
        global $config;
2887

    
2888
	if (empty($config['interfaces'][$interface]))
2889
		return $interface;
2890
	$tmpif = $config['interfaces'][$interface];
2891
	switch ($tmpif['type']) {
2892
	case "ppp":
2893
	case "pppoe":
2894
	case "pptp":
2895
	case "l2tp":
2896
		if (is_array($config['ppps']['ppp'])) {
2897
			foreach ($config['ppps']['ppp'] as $pppidx => $ppp) {
2898
				if ($tmpif['if'] == $ppp['if']) {
2899
					$interface = $ppp['ports'];
2900
					break;
2901
				}
2902
			}
2903
		}
2904
		break;
2905
	case "dhcp":
2906
	case "static":
2907
	default:
2908
		$interface = $tmpif['if'];
2909
		break;
2910
	}
2911

    
2912
	return $interface;
2913
}
2914

    
2915
function interface_is_wireless_clone($wlif) {
2916
	if(!stristr($wlif, "_wlan")) {
2917
		return false;
2918
	} else {
2919
		return true;
2920
	}
2921
}
2922

    
2923
function interface_get_wireless_base($wlif) {
2924
	if(!stristr($wlif, "_wlan")) {
2925
		return $wlif;
2926
	} else {
2927
		return substr($wlif, 0, stripos($wlif, "_wlan"));
2928
	}
2929
}
2930

    
2931
function interface_get_wireless_clone($wlif) {
2932
	if(!stristr($wlif, "_wlan")) {
2933
		return $wlif . "_wlan0";
2934
	} else {
2935
		return $wlif;
2936
	}
2937
}
2938

    
2939
function get_real_interface($interface = "wan") {
2940
    global $config;
2941

    
2942
	$wanif = NULL;
2943

    
2944
	switch ($interface) {
2945
	case "l2tp":
2946
		$wanif = "l2tp";
2947
		break;
2948
	case "pptp":
2949
		$wanif = "pptp";
2950
		break;
2951
	case "pppoe":
2952
		$wanif = "pppoe";
2953
		break;
2954
	case "openvpn":
2955
		$wanif = "openvpn";
2956
		break;
2957
	case "ipsec":
2958
	case "enc0":
2959
		$wanif = "enc0";
2960
		break;
2961
	case "ppp":
2962
		$wanif = "ppp";
2963
		break;
2964
	default:
2965
		// If a real interface was alread passed simply
2966
		// pass the real interface back.  This encourages
2967
		// the usage of this function in more cases so that
2968
		// we can combine logic for more flexibility.
2969
		if(does_interface_exist($interface)) {
2970
			$wanif = $interface;
2971
			break;
2972
		}
2973
		if (empty($config['interfaces'][$interface]))
2974
			break;
2975

    
2976
		$cfg = &$config['interfaces'][$interface];
2977

    
2978
		// Wireless cloned NIC support (FreeBSD 8+)
2979
		// interface name format: $parentnic_wlanparentnic#
2980
		// example: ath0_wlan0
2981
		if (is_interface_wireless($cfg['if'])) {
2982
			$wanif = interface_get_wireless_clone($cfg['if']);
2983
			break;
2984
		}
2985
		/*
2986
		if (empty($cfg['if'])) {
2987
			$wancfg = $cfg['if'];
2988
			break;
2989
		}
2990
		*/
2991

    
2992
		switch ($cfg['ipaddr']) {
2993
			case "carpdev-dhcp":
2994
				$viparr = &$config['virtualip']['vip'];
2995
				if(is_array($viparr))
2996
				foreach ($viparr as $counter => $vip) {
2997
					if ($vip['mode'] == "carpdev-dhcp") {
2998
						if($vip['interface'] == $interface) {
2999
							$wanif = "carp{$counter}";
3000
							break;
3001
						}
3002
					}
3003
				}
3004
				break;
3005
			case "pppoe": 
3006
			case "pptp": 
3007
			case "l2tp": 
3008
			case "ppp":
3009
				$wanif = $cfg['if'];
3010
				break;
3011
			default:
3012
				$wanif = $cfg['if'];
3013
				break;
3014
		}
3015
		break;
3016
	}
3017

    
3018
    return $wanif;
3019
}
3020

    
3021
/* Guess the physical interface by providing a IP address */
3022
function guess_interface_from_ip($ipaddress) {
3023
	if(! is_ipaddr($ipaddress)) {
3024
		return false;
3025
	}
3026
	/* create a route table we can search */
3027
	exec("netstat -rnWf inet", $output, $ret);
3028
	foreach($output as $line) {
3029
		if(preg_match("/^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\/[0-9]+[ ]+link[#]/", $line)) {
3030
			$fields = preg_split("/[ ]+/", $line);
3031
			if(ip_in_subnet($ipaddress, $fields[0])) {
3032
				return $fields[6];
3033
			}
3034
		}
3035
	}
3036
	$ret = exec_command("/sbin/route -n get {$ipaddress} | /usr/bin/awk '/interface/ { print \$2; };'");
3037
	if(empty($ret)) {
3038
        	return false;
3039
	}
3040
	return $ret;
3041
}
3042

    
3043
/*
3044
 * find_ip_interface($ip): return the interface where an ip is defined
3045
 */
3046
function find_ip_interface($ip)
3047
{
3048
        /* if list */
3049
        $ifdescrs = get_configured_interface_list();
3050

    
3051
        foreach ($ifdescrs as $ifdescr => $ifname) {
3052
		if ($ip == get_interface_ip($ifname)) {
3053
                	$int = get_real_interface($ifname);
3054
			return $int;
3055
		}
3056
        }
3057
        return false;
3058
}
3059

    
3060
/*
3061
 *   find_number_of_created_carp_interfaces: return the number of carp interfaces
3062
 */
3063
function find_number_of_created_carp_interfaces() {
3064
	return `/sbin/ifconfig | grep "carp:" | wc -l`;
3065
}
3066

    
3067
function get_all_carp_interfaces() {
3068
	$ints = str_replace("\n", " ", `ifconfig | grep "carp:" -B2 | grep ": flag" | cut -d: -f1`);
3069
	$ints = explode(" ", $ints);
3070
	return $ints;
3071
}
3072

    
3073
/*
3074
 * find_carp_interface($ip): return the carp interface where an ip is defined
3075
 */
3076
function find_carp_interface($ip) {
3077
	global $config;
3078
	if (is_array($config['virtualip']['vip'])) {
3079
		foreach ($config['virtualip']['vip'] as $vip) {
3080
			if ($vip['mode'] == "carp" || $vip['mode'] == "carpdev") {
3081
				$carp_ip = get_interface_ip($vip['interface']);
3082
				$if = `ifconfig | grep '$ip ' -B1 | head -n1 | cut -d: -f1`;
3083
				if ($if)
3084
					return $if;
3085
			}
3086
		}
3087
	}
3088
}
3089

    
3090
function link_carp_interface_to_parent($interface) {
3091
        global $config;
3092

    
3093
        if ($interface == "")
3094
                return;
3095

    
3096
        $carp_ip = get_interface_ip($interface);
3097
        if (!is_ipaddr($carp_ip))
3098
                return;
3099

    
3100
        /* if list */
3101
        $ifdescrs = get_configured_interface_list();
3102
        foreach ($ifdescrs as $ifdescr => $ifname) {
3103
                $interfaceip = get_interface_ip($ifname);
3104
                $subnet_bits = get_interface_subnet($ifname);
3105
                $subnet_ip = gen_subnet("{$interfaceip}", "{$subnet_bits}");
3106
                if(ip_in_subnet($carp_ip, "{$subnet_ip}/{$subnet_bits}"))
3107
                        return $ifname;
3108
        }
3109

    
3110
        return "";
3111
}
3112

    
3113
/****f* interfaces/link_ip_to_carp_interface
3114
 * NAME
3115
 *   link_ip_to_carp_interface - Find where a CARP interface links to.
3116
 * INPUTS
3117
 *   $ip
3118
 * RESULT
3119
 *   $carp_ints
3120
 ******/
3121
function link_ip_to_carp_interface($ip) {
3122
        global $config;
3123

    
3124
        if (!is_ipaddr($ip))
3125
                return;
3126

    
3127
        $carp_ints = "";
3128
        if (is_array($config['virtualip']['vip'])) {
3129
		$first = 0;
3130
		$carp_int = array();
3131
                foreach ($config['virtualip']['vip'] as $vip) {
3132
                        if ($vip['mode'] == "carp" || $vip['mode'] == "carpdev") {
3133
                                $carp_ip = $vip['subnet'];
3134
                                $carp_sn = $vip['subnet_bits'];
3135
                                $carp_nw = gen_subnet($carp_ip, $carp_sn);
3136
                                if (ip_in_subnet($ip, "{$carp_nw}/{$carp_sn}"))
3137
					$carp_int[] = "vip{$vip['vhid']}";
3138
                        }
3139
                }
3140
		if (!empty($carp_int))
3141
			$carp_ints = implode(" ", array_unique($carp_int));
3142
        }
3143

    
3144
        return $carp_ints;
3145
}
3146

    
3147
function link_interface_to_vlans($int, $action = "") {
3148
	global $config;
3149

    
3150
	if (empty($int))
3151
		return;
3152

    
3153
	if (is_array($config['vlans']['vlan'])) {
3154
                foreach ($config['vlans']['vlan'] as $vlan) {
3155
			if ($int == $vlan['if']) {
3156
				if ($action == "update") {
3157
					interfaces_bring_up($int);
3158
				} else if ($action == "")
3159
					return $vlan;
3160
			}
3161
		}
3162
	}
3163
}
3164

    
3165
function link_interface_to_vips($int, $action = "") {
3166
        global $config;
3167

    
3168
        if (is_array($config['virtualip']['vip'])) {
3169
		foreach ($config['virtualip']['vip'] as $vip) {
3170
			if ($int == $vip['interface']) {
3171
				if ($action == "update") {
3172
					interface_vip_bring_down($vip);
3173
					interfaces_vips_configure($int);
3174
				} else
3175
					return $vip;
3176
			}
3177
		}
3178
	}
3179
}
3180

    
3181
/****f* interfaces/link_interface_to_bridge
3182
 * NAME
3183
 *   link_interface_to_bridge - Finds out a bridge group for an interface
3184
 * INPUTS
3185
 *   $ip
3186
 * RESULT
3187
 *   bridge[0-99]
3188
 ******/
3189
function link_interface_to_bridge($int) {
3190
        global $config;
3191

    
3192
        if (is_array($config['bridges']['bridged'])) {
3193
                foreach ($config['bridges']['bridged'] as $bridge) {
3194
			if (in_array($int, explode(',', $bridge['members'])))
3195
                                return "{$bridge['bridgeif']}";
3196
		}
3197
	}
3198
}
3199

    
3200
function link_interface_to_group($int) {
3201
        global $config;
3202

    
3203
	$result = array();
3204

    
3205
        if (is_array($config['ifgroups']['ifgroupentry'])) {
3206
                foreach ($config['ifgroups']['ifgroupentry'] as $group) {
3207
			if (in_array($int, explode(" ", $group['members'])))
3208
				$result[$group['ifname']] = $int;
3209
		}
3210
	}
3211

    
3212
	return $result;
3213
}
3214

    
3215
function link_interface_to_gre($interface) {
3216
        global $config;
3217

    
3218
	$result = array();
3219

    
3220
        if (is_array($config['gres']['gre'])) {
3221
                foreach ($config['gres']['gre'] as $gre)
3222
                        if($gre['if'] == $interface)
3223
				$result[] = $gre;
3224
	}
3225

    
3226
	return $result;
3227
}
3228

    
3229
function link_interface_to_gif($interface) {
3230
        global $config;
3231

    
3232
	$result = array();
3233

    
3234
        if (is_array($config['gifs']['gif'])) {
3235
                foreach ($config['gifs']['gif'] as $gif)
3236
                        if($gif['if'] == $interface)
3237
                                $result[] = $gif;
3238
	}
3239

    
3240
	return $result;
3241
}
3242

    
3243
/*
3244
 * find_interface_ip($interface): return the interface ip (first found)
3245
 */
3246
function find_interface_ip($interface, $flush = false)
3247
{
3248
	global $interface_ip_arr_cache;
3249
	global $interface_sn_arr_cache;
3250

    
3251
	$interface = str_replace("\n", "", $interface);
3252
	
3253
	if (!does_interface_exist($interface))
3254
		return;
3255

    
3256
	/* Setup IP cache */
3257
	if (!isset($interface_ip_arr_cache[$interface]) or $flush) {
3258
		$ifinfo = pfSense_get_interface_addresses($interface);
3259
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
3260
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
3261
	}
3262

    
3263
	return $interface_ip_arr_cache[$interface];
3264
}
3265

    
3266
function find_interface_subnet($interface, $flush = false)
3267
{
3268
	global $interface_sn_arr_cache;
3269
	global $interface_ip_arr_cache;
3270

    
3271
	$interface = str_replace("\n", "", $interface);
3272
	if (does_interface_exist($interface) == false)
3273
		return;
3274

    
3275
	if (!isset($interface_sn_arr_cache[$interface]) or $flush) {
3276
		$ifinfo = pfSense_get_interface_addresses($interface);
3277
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
3278
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
3279
        }
3280

    
3281
	return $interface_sn_arr_cache[$interface];
3282
}
3283

    
3284
function ip_in_interface_alias_subnet($interface, $ipalias) {
3285
	global $config;
3286

    
3287
	if (empty($interface) || !is_ipaddr($ipalias))
3288
		return false;
3289
	if (is_array($config['virtualip']['vip'])) {
3290
                foreach ($config['virtualip']['vip'] as $vip) {
3291
                        switch ($vip['mode']) {
3292
                        case "ipalias":
3293
                                if ($vip['interface'] <> $interface)
3294
                                        break;
3295
				if (ip_in_subnet($ipalias, gen_subnet($vip['subnet'], $vip['subnet_bits']) . "/" . $vip['subnet_bits']))
3296
					return true;
3297
                                break;
3298
                        }
3299
                }
3300
	}
3301

    
3302
	return false;
3303
}
3304

    
3305
function get_interface_ip($interface = "wan")
3306
{
3307
	$realif = get_real_interface($interface);
3308
	if (!$realif) {
3309
		if (preg_match("/^carp/i", $interface))
3310
			$realif = $interface;
3311
		else if (preg_match("/^vip/i", $interface))
3312
			$realif = $interface;
3313
		else
3314
			return null;
3315
	}
3316

    
3317
	$curip = find_interface_ip($realif);
3318
	if ($curip && is_ipaddr($curip) && ($curip != "0.0.0.0"))
3319
		return $curip;
3320
	else
3321
		return null;
3322
}
3323

    
3324
function get_interface_subnet($interface = "wan")
3325
{
3326
	$realif = get_real_interface($interface);
3327
	if (!$realif) {
3328
                if (preg_match("/^carp/i", $interface))
3329
                        $realif = $interface;
3330
                else if (preg_match("/^vip/i", $interface))
3331
                        $realif = $interface;
3332
                else
3333
                        return null;
3334
        }
3335

    
3336
	$cursn = find_interface_subnet($realif);
3337
	if (!empty($cursn))
3338
		return $cursn;
3339

    
3340
	return null;
3341
}
3342

    
3343
/* return outside interfaces with a gateway */
3344
function get_interfaces_with_gateway() {
3345
	global $config;
3346

    
3347
	$ints = array();
3348

    
3349
	/* loop interfaces, check config for outbound */
3350
	foreach($config['interfaces'] as $ifdescr => $ifname) {
3351
		switch ($ifname['ipaddr']) {
3352
			case "dhcp":
3353
			case "carpdev-dhcp":
3354
			case "ppp";
3355
			case "pppoe":
3356
			case "pptp":
3357
			case "l2tp":
3358
			case "ppp";
3359
				$ints[$ifdescr] = $ifdescr;
3360
			break;
3361
			default:
3362
				if (substr($ifname['if'], 0, 5) ==  "ovpnc" ||
3363
				    !empty($ifname['gateway']))
3364
					$ints[$ifdescr] = $ifdescr;
3365
			break;
3366
		}
3367
	}
3368
	return $ints;
3369
}
3370

    
3371
/* return true if interface has a gateway */
3372
function interface_has_gateway($friendly) {
3373
	global $config;
3374

    
3375
	if (!empty($config['interfaces'][$friendly])) {
3376
		$ifname = &$config['interfaces'][$friendly];
3377
		switch ($ifname['ipaddr']) {
3378
			case "dhcp":
3379
			case "carpdev-dhcp":
3380
			case "pppoe":
3381
			case "pptp":
3382
			case "l2tp":
3383
			case "ppp";
3384
				return true;
3385
			break;
3386
			default:
3387
				if (substr($ifname['if'], 0, 5) ==  "ovpnc")
3388
					return true;
3389
				if (!empty($ifname['gateway']))
3390
					return true;
3391
			break;
3392
		}
3393
	}
3394

    
3395
	return false;
3396
}
3397

    
3398
/****f* interfaces/is_altq_capable
3399
 * NAME
3400
 *   is_altq_capable - Test if interface is capable of using ALTQ
3401
 * INPUTS
3402
 *   $int            - string containing interface name
3403
 * RESULT
3404
 *   boolean         - true or false
3405
 ******/
3406

    
3407
function is_altq_capable($int) {
3408
        /* Per:
3409
         * http://www.freebsd.org/cgi/man.cgi?query=altq&manpath=FreeBSD+7.2-current&format=html
3410
         * Only the following drivers have ALTQ support
3411
         */
3412
	$capable = array("age", "ale", "an", "ath", "aue", "awi", "bce",
3413
			"bfe", "bge", "dc", "de", "ed", "em", "ep", "fxp", "gem",
3414
			"hme", "igb", "ipw", "iwi", "jme", "le", "lem", "msk", "mxge", "my", "nfe",
3415
			"npe", "nve", "ral", "re", "rl", "rum", "run", "bwn", "sf", "sis", "sk",
3416
			"ste", "stge", "txp", "udav", "ural", "vge", "vr", "wi", "xl",
3417
			"ndis", "tun", "ovpns", "ovpnc", "vlan", "pppoe", "pptp", "ng",
3418
			"l2tp", "ppp");
3419

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

    
3422
        if (in_array($int_family[0], $capable))
3423
                return true;
3424
	else if (stristr($int, "vlan")) /* VLANs are name $parent_$vlan now */
3425
		return true;
3426
	else if (stristr($int, "_wlan")) /* WLANs are name $parent_$wlan now */
3427
		return true;
3428
        else
3429
                return false;
3430
}
3431

    
3432
/****f* interfaces/is_interface_wireless
3433
 * NAME
3434
 *   is_interface_wireless - Returns if an interface is wireless
3435
 * RESULT
3436
 *   $tmp       - Returns if an interface is wireless
3437
 ******/
3438
function is_interface_wireless($interface) {
3439
        global $config, $g;
3440

    
3441
        $friendly = convert_real_interface_to_friendly_interface_name($interface);
3442
        if(!isset($config['interfaces'][$friendly]['wireless'])) {
3443
                if (preg_match($g['wireless_regex'], $interface)) {
3444
                        if (isset($config['interfaces'][$friendly]))
3445
                                $config['interfaces'][$friendly]['wireless'] = array();
3446
                        return true;
3447
                }
3448
                return false;
3449
        } else
3450
                return true;
3451
}
3452

    
3453
function get_wireless_modes($interface) {
3454
	/* return wireless modes and channels */
3455
	$wireless_modes = array();
3456

    
3457
	$wlif = interface_translate_type_to_real($interface);
3458

    
3459
	if(is_interface_wireless($wlif)) {
3460
		$cloned_interface = get_real_interface($interface);
3461
		$chan_list = "/sbin/ifconfig {$cloned_interface} list chan";
3462
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
3463
		$format_list = "/usr/bin/awk '{print \$5 \" \" \$6 \",\" \$1}'";
3464

    
3465
		$interface_channels = "";
3466
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
3467
		$interface_channel_count = count($interface_channels);
3468

    
3469
		$c = 0;
3470
		while ($c < $interface_channel_count)
3471
		{
3472
			$channel_line = explode(",", $interface_channels["$c"]);
3473
			$wireless_mode = trim($channel_line[0]);
3474
			$wireless_channel = trim($channel_line[1]);
3475
			if(trim($wireless_mode) != "") {
3476
				/* if we only have 11g also set 11b channels */
3477
				if($wireless_mode == "11g") {
3478
					if(!isset($wireless_modes["11b"]))
3479
						$wireless_modes["11b"] = array();
3480
				} else if($wireless_mode == "11g ht") {
3481
					if(!isset($wireless_modes["11b"]))
3482
						$wireless_modes["11b"] = array();
3483
					if(!isset($wireless_modes["11g"]))
3484
						$wireless_modes["11g"] = array();
3485
					$wireless_mode = "11ng";
3486
				} else if($wireless_mode == "11a ht") {
3487
					if(!isset($wireless_modes["11a"]))
3488
						$wireless_modes["11a"] = array();
3489
					$wireless_mode = "11na";
3490
				}
3491
				$wireless_modes["$wireless_mode"]["$c"] = $wireless_channel;
3492
			}
3493
			$c++;
3494
		}
3495
	}
3496
	return($wireless_modes);
3497
}
3498

    
3499
/* return channel numbers, frequency, max txpower, and max regulation txpower */
3500
function get_wireless_channel_info($interface) {
3501
	$wireless_channels = array();
3502

    
3503
	$wlif = interface_translate_type_to_real($interface);
3504

    
3505
	if(is_interface_wireless($wlif)) {
3506
		$cloned_interface = get_real_interface($interface);
3507
		$chan_list = "/sbin/ifconfig {$cloned_interface} list txpower";
3508
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
3509
		$format_list = "/usr/bin/awk '{print \$1 \",\" \$3 \" \" \$4 \",\" \$5 \",\" \$7}'";
3510

    
3511
		$interface_channels = "";
3512
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
3513

    
3514
		foreach ($interface_channels as $channel_line) {
3515
			$channel_line = explode(",", $channel_line);
3516
			if(!isset($wireless_channels[$channel_line[0]]))
3517
				$wireless_channels[$channel_line[0]] = $channel_line;
3518
		}
3519
	}
3520
	return($wireless_channels);
3521
}
3522

    
3523
/****f* interfaces/get_interface_mtu
3524
 * NAME
3525
 *   get_interface_mtu - Return the mtu of an interface
3526
 * RESULT
3527
 *   $tmp       - Returns the mtu of an interface
3528
 ******/
3529
function get_interface_mtu($interface) {
3530
        $mtu = pfSense_get_interface_addresses($interface);
3531
        return $mtu['mtu'];
3532
}
3533

    
3534
function get_interface_mac($interface) {
3535

    
3536
	$macinfo = pfSense_get_interface_addresses($interface);
3537
	return $macinfo["macaddr"];
3538
}
3539

    
3540
/****f* pfsense-utils/generate_random_mac_address
3541
 * NAME
3542
 *   generate_random_mac - generates a random mac address
3543
 * INPUTS
3544
 *   none
3545
 * RESULT
3546
 *   $mac - a random mac address
3547
 ******/
3548
function generate_random_mac_address() {
3549
        $mac = "02";
3550
        for($x=0; $x<5; $x++)
3551
                $mac .= ":" . dechex(rand(16, 255));
3552
        return $mac;
3553
}
3554

    
3555
/****f* interfaces/is_jumbo_capable
3556
 * NAME
3557
 *   is_jumbo_capable - Test if interface is jumbo frame capable.  Useful for determining VLAN capability.
3558
 * INPUTS
3559
 *   $int             - string containing interface name
3560
 * RESULT
3561
 *   boolean          - true or false
3562
 ******/
3563
function is_jumbo_capable($int) {
3564
        global $g;
3565

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

    
3568
        if (in_array($int_family[0], $g['vlan_long_frame']))
3569
                return true;
3570
        else
3571
                return false;
3572
}
3573

    
3574
function setup_pppoe_reset_file($pppif, $iface="") {
3575
	global $g;
3576
	$cron_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
3577

    
3578
	if(!empty($iface) && !empty($pppif)){
3579
		$cron_cmd = <<<EOD
3580
#!/bin/sh
3581
/usr/local/sbin/pfSctl -c 'interface reload {$iface}'
3582
/usr/bin/logger -t pppoe{$iface} "PPPoE periodic reset executed on {$iface}"
3583

    
3584
EOD;
3585

    
3586
		file_put_contents($cron_file, $cron_cmd);
3587
		chmod($cron_file, 0700);
3588
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
3589
	} else
3590
		unlink_if_exists($cron_file);
3591
}
3592

    
3593
function get_vip_descr($ipaddress) {
3594
	global $config;
3595

    
3596
	foreach ($config['virtualip']['vip'] as $vip) {
3597
		if ($vip['subnet'] == $ipaddress) {
3598
			return ($vip['descr']);
3599
		}
3600
	}
3601
	return "";
3602
}
3603

    
3604
?>
(22-22/54)