Project

General

Profile

Download (103 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) {
107
		if (!empty($config['interfaces'][$interface])) {
108
			switch ($config['interfaces'][$interface]['ipaddr']) {
109
			case "ppp":
110
			case "pppoe":
111
			case "l2tp":
112
			case "pptp":
113
				$found = true;
114
				break;
115
			default:
116
				$found = false;
117
				break;
118
			}
119
		}
120
	}
121
	if ($found == false) {
122
		$realif = get_real_interface($interface);
123
		if (is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) {
124
			foreach ($config['ppps']['ppp'] as $pppid => $ppp) {
125
				if ($realif == $ppp['if']) {
126
					$found = true;
127
					break;
128
				}
129
			}
130
		}
131
	}
132

    
133
	if ($found == false) {
134
		$realif = get_real_interface($interface);
135
		pfSense_ngctl_detach("{$realif}:", $realif);
136
	}
137
	/* NOTE: We make sure for this on interface_ppps_configure()
138
	 *	no need to do it here agan.
139
	 *	else
140
	 *		pfSense_ngctl_attach(".", $realif);
141
	 */
142
}
143

    
144
function interfaces_loopback_configure() {
145
	if($g['booting'])
146
		echo "Configuring loopback interface...";
147
	pfSense_interface_setaddress("lo0", "127.0.0.1");
148
	interfaces_bring_up("lo0");
149
	if($g['booting'])
150
		echo "done.\n";
151
	return 0;
152
}
153

    
154
function interfaces_vlan_configure() {
155
	global $config, $g;
156
	if($g['booting'])
157
		echo "Configuring VLAN interfaces...";
158
	if (is_array($config['vlans']['vlan']) && count($config['vlans']['vlan'])) {
159
		foreach ($config['vlans']['vlan'] as $vlan) {
160
			if(empty($vlan['vlanif']))
161
				$vlan['vlanif'] = "{$vlan['if']}_vlan{$vlan['tag']}";
162
			/* XXX: Maybe we should report any errors?! */
163
			interface_vlan_configure($vlan);
164
		}
165
	}
166
	if($g['booting'])
167
		echo "done.\n";
168
}
169

    
170
function interface_vlan_configure(&$vlan) {
171
        global $config, $g;
172

    
173
	if (!is_array($vlan)) {
174
		log_error("VLAN: called with wrong options. Problems with config!");
175
		return;
176
	}
177
	$if = $vlan['if'];
178
	$vlanif  = empty($vlan['vlanif']) ? "{$if}_vlan{$vlan['tag']}" : $vlan['vlanif'];
179
	$tag = $vlan['tag'];
180

    
181
	if (empty($if)) {
182
		log_error("interface_vlan_confgure called with if undefined.");
183
		return;
184
	}
185

    
186
	/* make sure the parent interface is up */
187
	interfaces_bring_up($if);
188
	/* Since we are going to add vlan(4) try to enable all that hardware supports. */
189
	pfSense_interface_capabilities($if, IFCAP_VLAN_HWTAGGING|IFCAP_VLAN_MTU|IFCAP_VLAN_HWFILTER);
190

    
191
	if (!empty($vlanif) && does_interface_exist($vlanif)) {
192
		interface_bring_down($vlanif, true);
193
	} else {
194
		$tmpvlanif = pfSense_interface_create("vlan");
195
		pfSense_interface_rename($tmpvlanif, $vlanif);
196
		pfSense_ngctl_name("{$tmpvlanif}:", $vlanif);
197
	}
198

    
199
	pfSense_vlan_create($vlanif, $if, $tag);
200

    
201
	interfaces_bring_up($vlanif);
202

    
203
	/* invalidate interface cache */
204
	get_interface_arr(true);
205

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

    
209
	return $vlanif;
210
}
211

    
212
function interface_qinq_configure(&$vlan, $fd = NULL) {
213
        global $config, $g;
214

    
215
        if (!is_array($vlan)) {
216
                log_error("QinQ compat VLAN: called with wrong options. Problems with config!\n");
217
                return;
218
        }
219

    
220
        $qinqif = $vlan['if'];
221
        $tag = $vlan['tag'];
222
        if(empty($qinqif)) {
223
                log_error("interface_qinq_confgure called with if undefined.\n");
224
                return;
225
        }
226
	$vlanif = interface_vlan_configure($vlan);
227

    
228
        if ($fd == NULL) {
229
                $exec = true;
230
                $fd = fopen("{$g['tmp_path']}/netgraphcmd", "w");
231
        } else
232
                $exec = false;
233
        /* make sure the parent is converted to ng_vlan(4) and is up */
234
        interfaces_bring_up($qinqif);
235

    
236
        if (!empty($vlanif) && does_interface_exist($vlanif)) {
237
                fwrite($fd, "shutdown {$qinqif}qinq:\n");
238
                exec("/usr/sbin/ngctl msg {$qinqif}qinq: gettable", $result);
239
                if (empty($result)) {
240
                        fwrite($fd, "mkpeer {$qinqif}: vlan lower downstream\n");
241
                        fwrite($fd, "name {$qinqif}:lower {$vlanif}qinq\n");
242
                        fwrite($fd, "connect {$qinqif}: {$vlanif}qinq: upper nomatch\n");
243
                }
244
        } else {
245
                fwrite($fd, "mkpeer {$qinqif}: vlan lower downstream\n");
246
                fwrite($fd, "name {$qinqif}:lower {$vlanif}qinq\n");
247
                fwrite($fd, "connect {$qinqif}: {$vlanif}qinq: upper nomatch\n");
248
        }
249

    
250
        /* invalidate interface cache */
251
        get_interface_arr(true);
252

    
253
        if (!stristr($qinqif, "vlan"))
254
                mwexec("/sbin/ifconfig {$qinqif} promisc\n");
255

    
256
        $macaddr = get_interface_mac($qinqif);
257
        if (!empty($vlan['members'])) {
258
                $members = explode(" ", $vlan['members']);
259
                foreach ($members as $qtag) {
260
                        $qinq = array();
261
                        $qinq['tag'] = $qtag;
262
                        $qinq['if'] = $vlanif;
263
                        interface_qinq2_configure($qinq, $fd, $macaddr);
264
                }
265
        }
266
        if ($exec == true) {
267
                fclose($fd);
268
                mwexec("/usr/sbin/ngctl -f {$g['tmp_path']}/netgraphcmd");
269
        }
270

    
271
        interfaces_bring_up($qinqif);
272
        if (!empty($vlan['members'])) {
273
                $members = explode(" ", $vlan['members']);
274
                foreach ($members as $qif)
275
                        interfaces_bring_up("{$vlanif}_{$qif}");
276
        }
277

    
278
        return $vlanif;
279
}
280

    
281
function interfaces_qinq_configure() {
282
	global $config, $g;
283
	if($g['booting'])
284
		echo "Configuring QinQ interfaces...";
285
	if (is_array($config['qinqs']['qinqentry']) && count($config['qinqs']['qinqentry'])) {
286
		foreach ($config['qinqs']['qinqentry'] as $qinq) {
287
			/* XXX: Maybe we should report any errors?! */
288
			interface_qinq_configure($qinq);
289
		}
290
	}
291
	if($g['booting'])
292
		echo "done.\n";
293
}
294

    
295
function interface_qinq2_configure(&$qinq, $fd, $macaddr) {
296
        global $config, $g;
297

    
298
        if (!is_array($qinq)) {
299
                log_error("QinQ compat VLAN: called with wrong options. Problems with config!\n");
300
                return;
301
        }
302

    
303
        $if = $qinq['if'];
304
        $tag = $qinq['tag'];
305
        $vlanif = "{$if}_{$tag}";
306
        if(empty($if)) {
307
                log_error("interface_qinq_confgure called with if undefined.\n");
308
                return;
309
        }
310

    
311
        fwrite($fd, "shutdown {$if}h{$tag}:\n");
312
        fwrite($fd, "mkpeer {$if}qinq: eiface {$if}{$tag} ether\n");
313
        fwrite($fd, "name {$if}qinq:{$if}{$tag} {$if}h{$tag}\n");
314
        fwrite($fd, "msg {$if}qinq: addfilter { vlan={$tag} hook=\"{$if}{$tag}\" }\n");
315
        fwrite($fd, "msg {$if}h{$tag}: setifname \"{$vlanif}\"\n");
316
        fwrite($fd, "msg {$if}h{$tag}: set {$macaddr}\n");
317

    
318
        /* invalidate interface cache */
319
        get_interface_arr(true);
320

    
321
        return $vlanif;
322
}
323

    
324
function interfaces_create_wireless_clones() {
325
	global $config;
326

    
327
	if($g['booting'])
328
		echo "Creating other wireless clone interfaces...";
329
	if (is_array($config['wireless']['clone']) && count($config['wireless']['clone'])) {
330
		foreach ($config['wireless']['clone'] as $clone) {
331
			if(empty($clone['cloneif']))
332
				continue;
333
			if(does_interface_exist($clone['cloneif']))
334
				continue;
335
			/* XXX: Maybe we should report any errors?! */
336
			if(interface_wireless_clone($clone['cloneif'], $clone))
337
				if($g['booting'])
338
					echo " " . $clone['cloneif'];
339
		}
340
	}
341
	if($g['booting'])
342
		echo " done.\n";
343
}
344

    
345
function interfaces_bridge_configure() {
346
        global $config;
347

    
348
        $i = 0;
349
        if (is_array($config['bridges']['bridged']) && count($config['bridges']['bridged'])) {
350
                foreach ($config['bridges']['bridged'] as $bridge) {
351
                        if(empty($bridge['bridgeif']))
352
                                $bridge['bridgeif'] = "bridge{$i}";
353
                        /* XXX: Maybe we should report any errors?! */
354
                        interface_bridge_configure($bridge);
355
                        $i++;
356
                }
357
        }
358
}
359

    
360
function interface_bridge_configure(&$bridge) {
361
	global $config, $g;
362

    
363
	if (!is_array($bridge))
364
	        return -1;
365

    
366
	if (empty($bridge['members'])) {
367
		log_error("No members found on {$bridge['bridgeif']}");
368
		return -1;
369
	}
370

    
371
	$members = explode(',', $bridge['members']);
372
	if (!count($members))
373
		return -1;
374

    
375
	$checklist = get_configured_interface_list();
376

    
377
	if ($g['booting'] || !empty($bridge['bridgeif'])) {
378
		pfSense_interface_destroy($bridge['bridgeif']);
379
		pfSense_interface_create($bridge['bridgeif']);
380
		$bridgeif = $bridge['bridgeif'];
381
	} else
382
		$bridgeif = pfSense_interface_create("bridge");
383

    
384
	/* Calculate smaller mtu and enforce it */
385
	$smallermtu = 0;
386
	$commonrx = true;
387
	$commontx = true;
388
	foreach ($members as $member) {
389
		$realif = get_real_interface($member);
390
		$opts = pfSense_get_interface_addresses($realif);
391
		$mtu = $opts['mtu'];
392
		if (!isset($opts['encaps']['txcsum']))
393
			$commontx = false;
394
		if (!isset($opts['encaps']['rxcsum']))
395
			$commonrx = false;
396
		if (!isset($opts['encaps']['tso4']))
397
			$commontso4 = false;
398
		if (!isset($opts['encaps']['tso6']))
399
			$commontso6 = false;
400
		if (!isset($opts['encaps']['lro']))
401
			$commonlro = false;
402
		if ($smallermtu == 0 && !empty($mtu))
403
			$smallermtu = $mtu;
404
		else if (!empty($mtu) && $mtu < $smallermtu)
405
			$smallermtu = $mtu;
406
	}
407
	 
408
	/* Just in case anything is not working well */
409
	if ($smallermtu == 0)
410
		$smallermtu = 1500; 
411

    
412
	$flags = 0;
413
	if ($commonrx === false)
414
		$flags |= IFCAP_RXCSUM;
415
	if ($commontx === false)
416
		$flags |= IFCAP_TXCSUM;
417
	if ($commontso4 === false)
418
		$flags |= IFCAP_TSO4;
419
	if ($commontso6 === false)
420
		$flags |= IFCAP_TSO6;
421
	if ($commonlro === false)
422
		$flags |= IFCAP_LRO;
423
		
424
	/* Add interfaces to bridge */
425
	foreach ($members as $member) {
426
		if (!array_key_exists($member, $checklist))
427
			continue;
428
		$realif1 = get_real_interface($member);
429
		$realif =  escapeshellarg($realif1);
430
		if (!$realif) {
431
			log_error("realif not defined in interfaces bridge - up");
432
			continue;
433
		}
434
		/* make sure the parent interface is up */
435
		pfSense_interface_mtu($realif1, $smallermtu);
436
		pfSense_interface_capabilities($realif1, -$flags);
437
		interfaces_bring_up($realif1);
438
		mwexec("/sbin/ifconfig {$bridgeif} addm {$realif}");	
439
	}
440

    
441
	if (isset($bridge['enablestp'])) {
442
		/* Choose spanning tree proto */
443
		mwexec("/sbin/ifconfig {$bridgeif} proto {$bridge['proto']}");	
444
		
445
		if (!empty($bridge['stp'])) {
446
			$stpifs = explode(',', $bridge['stp']);
447
			foreach ($stpifs as $stpif) {
448
				$realif = get_real_interface($stpif);
449
				mwexec("/sbin/ifconfig {$bridgeif} stp {$realif}");
450
			}
451
		}
452
		if (!empty($bridge['maxage']))
453
			mwexec("/sbin/ifconfig {$bridgeif} maxage {$bridge['maxage']}");
454
		if (!empty($brige['fwdelay']))
455
			mwexec("/sbin/ifconfig {$bridgeif} fwddelay {$bridge['fwdelay']}");
456
		if (!empty($brige['hellotime']))
457
                        mwexec("/sbin/ifconfig {$bridgeif} hellotime {$bridge['hellotime']}");
458
		if (!empty($brige['priority']))
459
                        mwexec("/sbin/ifconfig {$bridgeif} priority {$bridge['priority']}");
460
		if (!empty($brige['holdcount']))
461
                        mwexec("/sbin/ifconfig {$bridgeif} holdcnt {$bridge['holdcnt']}");
462
		if (!empty($bridge['ifpriority'])) {
463
			$pconfig = explode(",", $bridge['ifpriority']);
464
			$ifpriority = array();
465
			foreach ($pconfig as $cfg) {
466
				$embcfg = explode(":", $cfg);
467
				foreach ($embcfg as $key => $value)
468
					$ifpriority[$key] = $value;
469
			}
470
			foreach ($ifpriority as $key => $value) {
471
				$realif = get_real_interface($key);
472
				mwexec("/sbin/ifconfig ${bridgeif} ifpriority {$realif} {$value}"); 
473
			}
474
		}
475
		if (!empty($bridge['ifpathcost'])) {
476
			$pconfig = explode(",", $bridges['ifpathcost']);
477
			$ifpathcost = array();
478
			foreach ($pconfig as $cfg) {
479
				$embcfg = explode(":", $cfg);
480
				foreach ($embcfg as $key => $value)
481
					$ifpathcost[$key] = $value;
482
			}
483
			foreach ($ifpathcost as $key => $value) {
484
                        	$realif = get_real_interface($key);
485
                        	mwexec("/sbin/ifconfig ${bridgeif} ifpathcost {$realif} {$value}");
486
                	}
487
		}
488
	}
489

    
490
	if ($bridge['maxaddr'] <> "")
491
		mwexec("/sbin/ifconfig {$bridgeif} maxaddr {$bridge['maxaddr']}");
492
        if ($bridge['timeout'] <> "")
493
                mwexec("/sbin/ifconfig {$bridgeif} timeout {$bridge['timeout']}");
494
        if ($bridge['span'] <> "") {
495
		$realif = get_real_interface($bridge['span']);
496
                mwexec("/sbin/ifconfig {$bridgeif} span {$realif}");
497
	}
498
	if (!empty($bridge['edge'])) {
499
        	$edgeifs = explode(',', $bridge['edge']);
500
        	foreach ($edgeifs as $edgeif) {
501
			$realif = get_real_interface($edgeif);
502
                	mwexec("/sbin/ifconfig {$bridgeif} edge {$realif}");
503
        	}
504
	}
505
	if (!empty($bridge['autoedge'])) {
506
        	$edgeifs = explode(',', $bridge['autoedge']);
507
        	foreach ($edgeifs as $edgeif) {
508
                	$realif = get_real_interface($edgeif);
509
                	mwexec("/sbin/ifconfig {$bridgeif} -autoedge {$realif}");
510
        	}
511
	}
512
	if (!empty($bridge['ptp'])) {
513
        	$ptpifs = explode(',', $bridge['ptp']);
514
        	foreach ($ptpifs as $ptpif) {
515
                	$realif = get_real_interface($ptpif);
516
                	mwexec("/sbin/ifconfig {$bridgeif} ptp {$realif}");
517
        	}
518
	}
519
	if (!empty($bridge['autoptp'])) {
520
        	$ptpifs = explode(',', $bridge['autoptp']);
521
        	foreach ($ptpifs as $ptpif) {
522
                	$realif = get_real_interface($ptpif);
523
                	mwexec("/sbin/ifconfig {$bridgeif} -autoptp {$realif}");
524
        	}
525
	}
526
	if (!empty($bridge['static'])) {
527
        	$stickyifs = explode(',', $bridge['static']);
528
        	foreach ($stickyifs as $stickyif) {
529
                	$realif = get_real_interface($stickyif);
530
                	mwexec("/sbin/ifconfig {$bridgeif} sticky {$realif}");
531
        	}
532
	}
533
	if (!empty($bridge['private'])) {
534
        	$privateifs = explode(',', $bridge['private']);
535
        	foreach ($privateifs as $privateif) {
536
                	$realif = get_real_interface($privateif);
537
               	 	mwexec("/sbin/ifconfig {$bridgeif} private {$realif}");
538
        	}
539
	}
540

    
541
	if($bridgeif)
542
		interfaces_bring_up($bridgeif);	
543
	else 
544
		log_error("bridgeif not defined -- could not bring interface up");
545

    
546
	return $bridgeif;
547
}
548

    
549
function interface_bridge_add_member($bridgeif, $interface) {
550

    
551
	if (!does_interface_exist($bridgeif) || !does_interface_exist($interface))
552
		return;
553

    
554
	$mtu = get_interface_mtu($brigeif);
555
	$mtum = get_interface_mtu($interface);
556
	
557
	if ($mtu != $mtum)
558
		pfSense_interface_mtu($interface, $mtu);
559

    
560
	$options = pfSense_get_interface_addresses($bridgeif);
561
	$flags = 0;
562
	if (!isset($options['encaps']['txcsum']))
563
		$flags |= IFCAP_TXCSUM;
564

    
565
	if (!isset($options['encaps']['rxcsum']))
566
		$flags |= IFCAP_RXCSUM;
567

    
568
	pfSense_interface_capabilities($interface, -$flags);
569

    
570
	interfaces_bring_up($interface);
571
	mwexec("/sbin/ifconfig {$bridgeif} addm {$interface}");
572
}
573

    
574
function interfaces_lagg_configure() 
575
{
576
        global $config, $g;
577
		if($g['booting']) 
578
			echo "Configuring LAGG interfaces...";
579
        $i = 0;
580
		if (is_array($config['laggs']['lagg']) && count($config['laggs']['lagg'])) {
581
			foreach ($config['laggs']['lagg'] as $lagg) {
582
				if(empty($lagg['laggif']))
583
					$lagg['laggif'] = "lagg{$i}";
584
				/* XXX: Maybe we should report any errors?! */
585
				interface_lagg_configure($lagg);
586
				$i++;
587
			}
588
		}
589
		if($g['booting']) 
590
			echo "done.\n";
591
}
592

    
593
function interface_lagg_configure(&$lagg) {
594
        global $config, $g;
595

    
596
        if (!is_array($lagg))
597
		return -1;
598

    
599
	$members = explode(',', $lagg['members']);
600
	if (!count($members))
601
		return -1;
602
	
603
	$checklist = get_interface_list();
604

    
605
	if ($g['booting'] || !(empty($lagg['laggif']))) {
606
		pfSense_interface_destroy($lagg['laggif']);
607
		pfSense_interface_create($lagg['laggif']);
608
                $laggif = $lagg['laggif'];
609
        } else
610
		$laggif = pfSense_interface_create("lagg");
611

    
612
	/* Calculate smaller mtu and enforce it */
613
        $smallermtu = 0;
614
        foreach ($members as $member) {
615
		$opts = pfSense_get_interface_addresses($member);
616
                $mtu = $opts['mtu'];
617
		if (!isset($opts['encaps']['txcsum']))
618
                        $commontx = false;
619
                if (!isset($opts['encaps']['rxcsum']))
620
                        $commonrx = false;
621
		if (!isset($opts['encaps']['tso4']))
622
			$commontso4 = false;
623
		if (!isset($opts['encaps']['tso6']))
624
			$commontso6 = false;
625
		if (!isset($opts['encaps']['lro']))
626
			$commonlro = false;
627
		if ($smallermtu == 0 && !empty($mtu))
628
			$smallermtu = $mtu;
629
                else if (!empty($mtu) && $mtu < $smallermtu)
630
                        $smallermtu = $mtu;
631
        }
632

    
633
	/* Just in case anything is not working well */
634
        if ($smallermtu == 0)
635
                $smallermtu = 1500;
636

    
637
	$flags = 0;
638
        if ($commonrx === false)
639
                $flags |= IFCAP_RXCSUM;
640
        if ($commontx === false)
641
                $flags |= IFCAP_TXCSUM;
642
	if ($commontso4 === false)
643
                $flags |= IFCAP_TSO4;
644
        if ($commontso6 === false)
645
                $flags |= IFCAP_TSO6;
646
        if ($commonlro === false)
647
                $flags |= IFCAP_LRO;
648

    
649
	foreach ($members as $member) {
650
		if (!array_key_exists($member, $checklist))
651
			continue;
652
		/* make sure the parent interface is up */
653
		pfSense_interface_mtu($member, $smallermtu);
654
		pfSense_interface_capabilities($member, -$flags);
655
		interfaces_bring_up($member);
656
		mwexec("/sbin/ifconfig {$laggif} laggport {$member}");
657
	}
658
	
659
	mwexec("/sbin/ifconfig {$laggif} laggproto {$lagg['proto']}");
660

    
661
	interfaces_bring_up($laggif);
662

    
663
	return $laggif;
664
}
665

    
666
function interfaces_gre_configure() {
667
        global $config;
668

    
669
        if (is_array($config['gres']['gre']) && count($config['gres']['gre'])) {
670
                foreach ($config['gres']['gre'] as $i => $gre) {
671
                        if(empty($gre['greif']))
672
                                $gre['greif'] = "gre{$i}";
673
                        /* XXX: Maybe we should report any errors?! */
674
                        interface_gre_configure($gre);
675
                }
676
        }
677
}
678

    
679
/* NOTE: $grekey is not used but useful for passing this function to array_walk. */
680
function interface_gre_configure(&$gre, $grekey = "") {
681
        global $config, $g;
682

    
683
	if (!is_array($gre))
684
		return -1;
685

    
686
	$realif = get_real_interface($gre['if']);
687
	$realifip = get_interface_ip($gre['if']);
688

    
689
	/* make sure the parent interface is up */
690
	interfaces_bring_up($realif);
691

    
692
	if ($g['booting'] || !(empty($gre['greif']))) {
693
		pfSense_interface_destroy($gre['greif']);
694
		pfSense_interface_create($gre['greif']);
695
		$greif = $gre['greif'];
696
	} else
697
		$greif = pfSense_interface_create("gre");
698

    
699
	/* Do not change the order here for more see gre(4) NOTES section. */
700
	mwexec("/sbin/ifconfig {$greif} tunnel {$realifip} {$gre['remote-addr']}");
701
	mwexec("/sbin/ifconfig {$greif} {$gre['tunnel-local-addr']} {$gre['tunnel-remote-addr']} netmask " . gen_subnet_mask($gre['tunnel-remote-net']));
702
	if (isset($gre['link0']) && $gre['link0'])
703
		pfSense_interface_flags($greif, IFF_LINK0);
704
	if (isset($gre['link1']) && $gre['link1'])
705
		pfSense_interface_flags($greif, IFF_LINK1);
706
	if (isset($gre['link2']) && $gre['link2'])
707
		pfSense_interface_flags($greif, IFF_LINK2);
708

    
709
	if($greif)
710
		interfaces_bring_up($greif);
711
	else 
712
		log_error("Could not bring greif up -- variable not defined.");
713

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

    
718
	return $greif;
719
}
720

    
721
function interfaces_gif_configure() {
722
	global $config;
723

    
724
	if (is_array($config['gifs']['gif']) && count($config['gifs']['gif'])) {
725
		foreach ($config['gifs']['gif'] as $i => $gif) {
726
			if(empty($gif['gifif']))
727
				$gre['gifif'] = "gif{$i}";
728
			/* XXX: Maybe we should report any errors?! */
729
			interface_gif_configure($gif);
730
		}
731
	}
732
}
733

    
734
/* NOTE: $gifkey is not used but useful for passing this function to array_walk. */
735
function interface_gif_configure(&$gif, $gifkey = "") {
736
	global $config, $g;
737

    
738
	if (!is_array($gif))
739
		return -1;
740

    
741
	$realif = get_real_interface($gif['if']);
742
	$realifip = get_interface_ip($gif['if']);
743

    
744
	/* make sure the parent interface is up */
745
	if($realif)
746
		interfaces_bring_up($realif);
747
	else 
748
		log_error("could not bring realif up -- variable not defined -- interface_gif_configure()");
749

    
750
	if ($g['booting'] || !(empty($gif['gifif']))) {
751
		pfSense_interface_destroy($gif['gifif']);
752
		pfSense_interface_create($gif['gifif']);
753
		$gifif = $gif['gifif'];
754
	} else
755
		$gifif = pfSense_interface_create("gif");
756

    
757
	/* Do not change the order here for more see gif(4) NOTES section. */
758
	mwexec("/sbin/ifconfig {$gifif} tunnel {$realifip} {$gif['remote-addr']}");
759
	mwexec("/sbin/ifconfig {$gifif} {$gif['tunnel-local-addr']} {$gif['tunnel-remote-addr']} netmask " . gen_subnet_mask($gif['tunnel-remote-net']));
760
	if (isset($gif['link0']) && $gif['link0'])
761
		pfSense_interface_flags($gifif, IFF_LINK0);
762
	if (isset($gif['link1']) && $gif['link1'])
763
		pfSense_interface_flags($gifif, IFF_LINK1);
764
	if($gifif)
765
		interfaces_bring_up($gifif);
766
	else
767
		log_error("could not bring gifif up -- variable not defined");
768

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

    
773
	return $gifif;
774
}
775

    
776
function interfaces_configure() {
777
	global $config, $g;
778

    
779
	/* Set up our loopback interface */
780
	interfaces_loopback_configure();
781

    
782
	/* set up LAGG virtual interfaces */
783
	interfaces_lagg_configure();
784

    
785
	/* set up VLAN virtual interfaces */
786
	interfaces_vlan_configure();
787

    
788
	interfaces_qinq_configure();
789

    
790
	$iflist = get_configured_interface_with_descr();
791
	$delayed_list = array();
792
	$bridge_list = array();
793
	
794
	/* This is needed to speedup interfaces on bootup. */
795
	$reload = false;
796
	if ($g['booting'])
797
		$reload = true;
798

    
799
	foreach($iflist as $if => $ifname) {
800
		$realif = $config['interfaces'][$if]['if'];
801
		if (strstr($realif, "bridge")) 
802
			$bridge_list[$if] = $ifname;
803
		else if (strstr($realif, "gre"))
804
			$delayed_list[$if] = $ifname;
805
		else if (strstr($realif, "gif"))
806
			$delayed_list[$if] = $ifname;
807
		else if (strstr($realif, "ovpn")) {
808
			//echo "Delaying OpenVPN interface configuration...done.\n";
809
			continue;
810
		} else {
811
			if ($g['booting'])
812
				echo "Configuring {$ifname} interface...";
813
			if($g['debug'])
814
				log_error("Configuring {$ifname}");
815
			interface_configure($if, $reload);
816
			if ($g['booting']) 
817
				echo "done.\n";
818
		}
819
	}
820

    
821
	/* create the unconfigured wireless clones */
822
	interfaces_create_wireless_clones();
823

    
824
	/* set up GRE virtual interfaces */
825
	interfaces_gre_configure();
826

    
827
	/* set up GIF virtual interfaces */
828
	interfaces_gif_configure();
829
	
830
	foreach ($delayed_list as $if => $ifname) {
831
		if ($g['booting'])
832
			echo "Configuring {$ifname} interface...";
833
        	if ($g['debug'])
834
        		log_error("Configuring {$ifname}");
835

    
836
		interface_configure($if, $reload);
837

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

    
842
	/* set up BRIDGe virtual interfaces */
843
	interfaces_bridge_configure();
844

    
845
	foreach ($bridge_list as $if => $ifname) {
846
		if ($g['booting'])
847
			echo "Configuring {$ifname} interface...";
848
		if($g['debug'])
849
			log_error("Configuring {$ifname}");
850

    
851
		interface_configure($if, $reload);
852

    
853
		if ($g['booting'])
854
			echo "done.\n";
855
	}
856

    
857
	/* bring up vip interfaces */
858
	interfaces_vips_configure();
859

    
860
	/* configure interface groups */
861
	interfaces_group_setup();
862

    
863
	if (!$g['booting']) {
864
		/* reconfigure static routes (kernel may have deleted them) */
865
		system_routing_configure();
866

    
867
		/* reload IPsec tunnels */
868
		vpn_ipsec_configure();
869

    
870
		/* reload dhcpd (interface enabled/disabled status may have changed) */
871
		services_dhcpd_configure();
872

    
873
		/* restart dnsmasq */
874
		services_dnsmasq_configure();
875

    
876
		/* reload captive portal */
877
		captiveportal_init_rules();
878
	}
879

    
880
	return 0;
881
}
882

    
883
function interface_reconfigure($interface = "wan") {
884
	interface_bring_down($interface);
885
	interface_configure($interface, true);
886
}
887

    
888
function interface_vip_bring_down($vip) {
889
	global $g;
890

    
891
	switch ($vip['mode']) {
892
	case "proxyarp":
893
		$vipif = get_real_interface($vip['interface']);
894
		if (file_exists("{$g['varrun_path']}/choparp_{$vipif}.pid"))
895
			killbypid("{$g['varrun_path']}/choparp_{$vipif}.pid");
896
		break;
897
	case "ipalias":
898
		$vipif = get_real_interface($vip['interface']);
899
		if(does_interface_exist($vipif))
900
			pfSense_interface_deladdress($vipif, $vip['subnet']);
901
		break;
902
	case "carp":
903
		$vipif = "vip" . $vip['vhid'];
904
		if(does_interface_exist($vipif)) 
905
			pfSense_interface_destroy($vipif);
906
		break;
907
	case "carpdev-dhcp":
908
		$vipif = "vip" . $vip['vhid'];
909
		if(does_interface_exist($vipif)) 
910
			pfSense_interface_destroy($vipif);
911
		break;
912
	}
913
}
914

    
915
function interface_bring_down($interface = "wan", $destroy = false) {
916
	global $config, $g;
917

    
918
	if (!isset($config['interfaces'][$interface]))
919
		return; 
920

    
921
	$ifcfg = $config['interfaces'][$interface];
922

    
923
	$realif = get_real_interface($interface);
924

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

    
975
	/* remove interface up file if it exists */
976
	unlink_if_exists("{$g['tmp_path']}/{$realif}up");
977
	unlink_if_exists("{$g['vardb_path']}/{$interface}ip");
978
	unlink_if_exists("{$g['tmp_path']}/{$realif}_router");
979
	unlink_if_exists("{$g['varetc_path']}/nameserver_{$realif}");
980
	unlink_if_exists("{$g['varetc_path']}/searchdomain_{$realif}");
981
	
982
	/* hostapd and wpa_supplicant do not need to be running when the interface is down.
983
	 * They will also use 100% CPU if running after the wireless clone gets deleted. */
984
	if (is_array($ifcfg['wireless'])) {
985
		mwexec(kill_hostapd($realif));
986
		mwexec(kill_wpasupplicant($realif));
987
	}
988

    
989
	if ($destroy == true) {
990
		if (preg_match("/^vip|^tun|^ovpn|^gif|^gre|^lagg|^bridge|vlan/i", $realif))
991
			pfSense_interface_destroy($realif);
992
	}	
993

    
994
	return;
995
}
996

    
997
function interfaces_ptpid_used($ptpid) {
998
	global $config;
999

    
1000
	if (is_array($config['ppps']['ppp']))
1001
		foreach ($config['ppps']['ppp'] as & $settings)
1002
			if ($ptpid == $settings['ptpid'])
1003
				return true;
1004

    
1005
	return false;
1006
}
1007

    
1008
function interfaces_ptpid_next() {
1009

    
1010
	$ptpid = 0;
1011
	while(interfaces_ptpid_used($ptpid))
1012
		$ptpid++;
1013

    
1014
	return $ptpid;
1015
}
1016

    
1017
function getMPDCRONSettings($pppif_) {
1018
	global $config;
1019
	$cron_cmd_file = "{$g['varetc_path']}/pppoe_restart_";
1020
	if (is_array($config['cron']['item'])) {
1021
		for ($i = 0; $i < count($config['cron']['item']); $i++) {
1022
			$item = $config['cron']['item'][$i];
1023
			if (strpos($item['command'], $cron_cmd_file.$pppif_) !== false) {
1024
				return array("ID" => $i, "ITEM" => $item);
1025
			}
1026
		}
1027
	}
1028
	return NULL;
1029
}
1030

    
1031
function handle_pppoe_reset($post_array) {
1032
	global $config, $g;
1033

    
1034
	$cron_cmd_file = "{$g['varetc_path']}/pppoe_restart_";
1035

    
1036
	$pppif = $post_array['type'].$post_array['ptpid'];
1037
	if (!is_array($config['cron']['item'])) 
1038
		$config['cron']['item'] = array(); 
1039
	$itemhash = getMPDCRONSettings($pppif);
1040
	$item = $itemhash['ITEM'];
1041
	
1042
	// reset cron items if necessary and return
1043
	if (empty($post_array['pppoe-reset-type'])) {
1044
		if (isset($item))
1045
			unset($config['cron']['item'][$itemhash['ID']]);
1046
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
1047
		return;
1048
	}
1049

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

    
1118
/*	This function can configure PPPoE, MLPPP (PPPoE), PPTP.
1119
*	It writes the mpd config file to /var/etc every time the link is opened.
1120
*/
1121

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

    
1235
		if (is_ipaddr($ppp['gateway']))
1236
			$gateway = $ppp['gateway'];
1237
		else
1238
			$gateway = "10.64.64.{$pppid}";
1239
		$ranges = "{$localip}/0 {$gateway}/0";
1240
		
1241
		if (empty($ppp['apnum']))	
1242
			$ppp['apnum'] = 1;
1243
	} else
1244
		$ranges = "0.0.0.0/0 0.0.0.0/0";
1245

    
1246
	if (isset($ppp['ondemand'])) 
1247
		$ondemand = "enable";
1248
	else
1249
		$ondemand = "disable";
1250
	if (!isset($ppp['idletimeout']))
1251
		$ppp['idletimeout'] = 0;
1252

    
1253
	if (empty($ppp['username']) && $type == "modem"){
1254
		$ppp['username'] = "user";
1255
		$ppp['password'] = "none";
1256
	}
1257
	if (empty($ppp['password']) && $type == "modem")
1258
		$passwd = "none";
1259
	else
1260
		$passwd = base64_decode($ppp['password']);
1261

    
1262
	$bandwidths = explode(',',$ppp['bandwidth']);
1263
	$mtus = explode(',',$ppp['mtu']);
1264
	$mrus = explode(',',$ppp['mru']);
1265

    
1266
	if (isset($ppp['mrru']))
1267
		$mrrus = explode(',',$ppp['mrru']);
1268

    
1269
	// Construct the mpd.conf file
1270
	$mpdconf = <<<EOD
1271
startup:
1272
	# configure the console
1273
	set console close
1274
	# configure the web server
1275
	set web close
1276

    
1277
default:
1278
{$ppp['type']}client:
1279
	create bundle static {$interface}
1280
	set iface name {$pppif}
1281

    
1282
EOD;
1283
	$setdefaultgw = false;
1284
	$founddefaultgw = false;
1285
	if (is_array($config['gateways']['gateway_item'])) {
1286
		foreach($config['gateways']['gateway_item'] as $gateway) {
1287
			if($interface == $gateway['interface'] && isset($gateway['defaultgw'])) {
1288
				$setdefaultgw = true;
1289
				break;
1290
			} else if (isset($gateway['defaultgw']) && !empty($gateway['interface'])) {
1291
				$founddefaultgw = true;
1292
				break;
1293
			}
1294
		}
1295
	}
1296
	
1297
	if (($interface == "wan" && $founddefaultgw == false) || $setdefaultgw == true){
1298
		$setdefaultgw = true;
1299
		$mpdconf .= <<<EOD
1300
	set iface route default
1301

    
1302
EOD;
1303
	}
1304
	$mpdconf .= <<<EOD
1305
	set iface {$ondemand} on-demand
1306
	set iface idle {$ppp['idletimeout']}
1307

    
1308
EOD;
1309

    
1310
	if (isset($ppp['ondemand']))
1311
		$mpdconf .= <<<EOD
1312
	set iface addrs 10.10.1.1 10.10.1.2
1313

    
1314
EOD;
1315
	
1316
	if (isset($ppp['tcpmssfix']))
1317
		$tcpmss = "disable";
1318
	else
1319
		$tcpmss = "enable";
1320
		$mpdconf .= <<<EOD
1321
	set iface {$tcpmss} tcpmssfix
1322

    
1323
EOD;
1324

    
1325
	$mpdconf .= <<<EOD
1326
	set iface up-script /usr/local/sbin/ppp-linkup
1327
	set iface down-script /usr/local/sbin/ppp-linkdown
1328
	set ipcp ranges {$ranges}
1329

    
1330
EOD;
1331
	if (isset($ppp['vjcomp']))
1332
		$mpdconf .= <<<EOD
1333
	set ipcp no vjcomp
1334

    
1335
EOD;
1336

    
1337
	if (isset($config['system']['dnsallowoverride']))
1338
		$mpdconf .= <<<EOD
1339
	set ipcp enable req-pri-dns
1340
	set ipcp enable req-sec-dns
1341

    
1342
EOD;
1343
	if (!isset($ppp['verbose_log']))
1344
		$mpdconf .= <<<EOD
1345
	#log -bund -ccp -chat -iface -ipcp -lcp -link
1346

    
1347
EOD;
1348
	foreach($ports as $pid => $port){
1349
		$port = get_real_interface($port);
1350
		$mpdconf .= <<<EOD
1351

    
1352
	create link static {$interface}_link{$pid} {$type}
1353
	set link action bundle {$interface}
1354
	set link {$multilink} multilink
1355
	set link keep-alive 10 60
1356
	set link max-redial 0
1357

    
1358
EOD;
1359
		if (isset($ppp['shortseq']))
1360
			$mpdconf .= <<<EOD
1361
	set link no shortseq
1362

    
1363
EOD;
1364

    
1365
		if (isset($ppp['acfcomp']))
1366
			$mpdconf .= <<<EOD
1367
	set link no acfcomp
1368

    
1369
EOD;
1370

    
1371
		if (isset($ppp['protocomp']))
1372
			$mpdconf .= <<<EOD
1373
	set link no protocomp
1374

    
1375
EOD;
1376

    
1377
		$mpdconf .= <<<EOD
1378
	set link disable chap pap
1379
	set link accept chap pap eap
1380
	set link disable incoming
1381

    
1382
EOD;
1383

    
1384

    
1385
		if (!empty($bandwidths[$pid]))
1386
			$mpdconf .= <<<EOD
1387
	set link bandwidth {$bandwidths[$pid]}
1388

    
1389
EOD;
1390

    
1391
		if (empty($mtus[$pid]))
1392
			$mtus[$pid] = "1492";
1393
			$mpdconf .= <<<EOD
1394
	set link mtu {$mtus[$pid]}
1395

    
1396
EOD;
1397

    
1398
		if (!empty($mrus[$pid]))
1399
			$mpdconf .= <<<EOD
1400
	set link mru {$mrus[$pid]}
1401

    
1402
EOD;
1403

    
1404
		if (!empty($mrrus[$pid]))
1405
			$mpdconf .= <<<EOD
1406
	set link mrru {$mrrus[$pid]}
1407

    
1408
EOD;
1409

    
1410
		$mpdconf .= <<<EOD
1411
	set auth authname "{$ppp['username']}"
1412
	set auth password {$passwd}
1413

    
1414
EOD;
1415
		if ($type == "modem") {
1416
			$mpdconf .= <<<EOD
1417
	set modem device {$ppp['ports']}
1418
	set modem script DialPeer
1419
	set modem idle-script Ringback
1420
	set modem watch -cd
1421
	set modem var \$DialPrefix "DT"
1422
	set modem var \$Telephone "{$ppp['phone']}"
1423

    
1424
EOD;
1425
		}
1426
		if (isset($ppp['connect-timeout']) && $type == "modem") {
1427
			$mpdconf .= <<<EOD
1428
	set modem var \$ConnectTimeout "{$ppp['connect-timeout']}"
1429

    
1430
EOD;
1431
		}
1432
		if (isset($ppp['initstr']) && $type == "modem") {
1433
			$initstr = base64_decode($ppp['initstr']);
1434
			$mpdconf .= <<<EOD
1435
	set modem var \$InitString "{$initstr}"
1436

    
1437
EOD;
1438
		}
1439
		if (isset($ppp['simpin']) && $type == "modem") {
1440
			$mpdconf .= <<<EOD
1441
	set modem var \$SimPin "{$ppp['simpin']}"
1442
	set modem var \$PinWait "{$ppp['pin-wait']}"
1443

    
1444
EOD;
1445
		}
1446
		if (isset($ppp['apn']) && $type == "modem") {
1447
			$mpdconf .= <<<EOD
1448
	set modem var \$APN "{$ppp['apn']}"
1449
	set modem var \$APNum "{$ppp['apnum']}"
1450

    
1451
EOD;
1452
		}
1453
		if (isset($ppp['provider']) && $type == "pppoe") {
1454
			$mpdconf .= <<<EOD
1455
	set pppoe service "{$ppp['provider']}"
1456

    
1457
EOD;
1458
		}
1459
		if ($type == "pppoe")
1460
			$mpdconf .= <<<EOD
1461
	set pppoe iface {$port}
1462

    
1463
EOD;
1464

    
1465
		if ($type == "pptp" || $type == "l2tp") {
1466
			$mpdconf .= <<<EOD
1467
	set {$type} self {$localips[$pid]}
1468
	set {$type} peer {$gateways[$pid]}
1469
	set {$type} disable windowing
1470

    
1471
EOD;
1472
		}
1473
		
1474
		$mpdconf .= "\topen\r\n";
1475
	} //end foreach($port)
1476

    
1477

    
1478
	/* Generate mpd.conf. If mpd_[interface].conf exists in the conf path, then link to it instead of generating a fresh conf file. */
1479
	if (file_exists("{$g['conf_path']}/mpd_{$interface}.conf"))
1480
		mwexec("/bin/ln -s {$g['conf_path']}/mpd_{$interface}.conf {$g['varetc_path']}/.");
1481
	else {
1482
		$fd = fopen("{$g['varetc_path']}/mpd_{$interface}.conf", "w");
1483
		if (!$fd) {
1484
			log_error("Error: cannot open mpd_{$interface}.conf in interface_ppps_configure().\n");
1485
			return 0;
1486
		}
1487
		// Write out mpd_ppp.conf
1488
		fwrite($fd, $mpdconf);
1489
		fclose($fd);
1490
	}
1491

    
1492
	// Create the uptime log if requested and if it doesn't exist already, or delete it if it is no longer requested.
1493
	if (isset($ppp['uptime'])) {
1494
		if (!file_exists("/conf/{$pppif}.log")) {
1495
			conf_mount_rw();
1496
			mwexec("echo /dev/null > /conf/{$pppif}.log");
1497
			conf_mount_ro();
1498
		}
1499
	} else {
1500
		if (file_exists("/conf/{$pppif}.log")) {
1501
			conf_mount_rw();
1502
			mwexec("rm -f /conf/{$pppif}.log");
1503
			conf_mount_ro();
1504
		}
1505
	}
1506

    
1507
	/* fire up mpd */
1508
	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");
1509

    
1510
	// Check for PPPoE periodic reset request 
1511
	if ($type == "pppoe") {
1512
		if (isset($ppp['pppoe-reset-type']))
1513
			setup_pppoe_reset_file($ppp['if'], $interface);
1514
		else
1515
			setup_pppoe_reset_file($ppp['if']);
1516
	}
1517

    
1518
	return 1;
1519
}
1520

    
1521
function interfaces_carp_setup() {
1522
	global $g, $config;
1523

    
1524
	$balanacing = "";
1525
	$pfsyncinterface = "";
1526
	$pfsyncenabled = "";
1527
	if(isset($config['system']['developerspew'])) {
1528
		$mt = microtime();
1529
		echo "interfaces_carp_setup() being called $mt\n";
1530
	}
1531

    
1532
	// Prepare CmdCHAIN that will be used to execute commands.
1533
	$cmdchain = new CmdCHAIN();	
1534

    
1535
	if ($g['booting']) {
1536
		echo "Configuring CARP settings...";
1537
		mute_kernel_msgs();
1538
	}
1539

    
1540
	/* suck in configuration items */
1541
	if($config['installedpackages']['carpsettings']) {
1542
		if($config['installedpackages']['carpsettings']['config']) {
1543
			foreach($config['installedpackages']['carpsettings']['config'] as $carp) {
1544
				$pfsyncenabled = $carp['pfsyncenabled'];
1545
				$balanacing = $carp['balancing'];
1546
				$pfsyncinterface = $carp['pfsyncinterface'];
1547
				$pfsyncpeerip = $carp['pfsyncpeerip'];
1548
			}
1549
		}
1550
	} else {
1551
		unset($pfsyncinterface);
1552
		unset($balanacing);
1553
		unset($pfsyncenabled);
1554
	}
1555

    
1556
	$cmdchain->add("Allow CARP", "/sbin/sysctl net.inet.carp.allow=1", true);			
1557
	if($balanacing) {
1558
		$cmdchain->add("Enable CARP ARP-balancing", "/sbin/sysctl net.inet.carp.arpbalance=1", true);
1559
		$cmdchain->add("Disallow CARP preemption", "/sbin/sysctl net.inet.carp.preempt=0", true);
1560
	} else
1561
		$cmdchain->add("Enable CARP preemption", "/sbin/sysctl net.inet.carp.preempt=1", true);		
1562

    
1563
	$cmdchain->add("Enable CARP logging", "/sbin/sysctl net.inet.carp.log=1", true);
1564
	if (!empty($pfsyncinterface))
1565
		$carp_sync_int = get_real_interface($pfsyncinterface);
1566

    
1567
	if($g['booting']) {
1568
		/*    install rules to alllow pfsync to sync up during boot
1569
		 *    carp interfaces will remain down until the bootup sequence finishes
1570
		 */
1571
		$fd = fopen("{$g['tmp_path']}/rules.boot", "w");
1572
		if ($fd) {
1573
			fwrite($fd, "pass quick proto carp all keep state\n");
1574
			fwrite($fd, "pass quick proto pfsync all\n");
1575
			fwrite($fd, "pass out quick from any to any keep state\n");
1576
			fclose($fd);
1577
			mwexec("/sbin/pfctl -f {$g['tmp_path']}/rules.boot");
1578
		} else
1579
			log_error("Could not create rules.boot file!");
1580
	}
1581

    
1582
	/* setup pfsync interface */
1583
	if($carp_sync_int and $pfsyncenabled) {
1584
		if (is_ipaddr($pfsyncpeerip))
1585
			$cmdchain->add("Bring up pfsync0 syncpeer", "/sbin/ifconfig pfsync0 syncdev {$carp_sync_int} syncpeer {$pfsyncpeerip} up", false);						
1586
		else
1587
			$cmdchain->add("Bring up pfsync0 syncdev", "/sbin/ifconfig pfsync0 syncdev {$carp_sync_int} up", false);			
1588
	} else
1589
		$cmdchain->add("Bring up pfsync0", "/sbin/ifconfig pfsync0 syncdev lo0 up", false);						
1590

    
1591
	if($config['virtualip']['vip'])
1592
		$cmdchain->add("Allow CARP.", "/sbin/sysctl net.inet.carp.allow=1", true);				
1593
	else
1594
		$cmdchain->add("Disallow CARP.", "/sbin/sysctl net.inet.carp.allow=0", true);		
1595
	
1596
	if($g['debug'])
1597
		$cmdchain->setdebug(); // optional for verbose logging
1598

    
1599
	$cmdchain->execute();
1600
	$cmdchain->clear();
1601

    
1602
	if ($g['booting']) {
1603
		unmute_kernel_msgs();
1604
		echo "done.\n";
1605
	}
1606
}
1607

    
1608
function interface_proxyarp_configure($interface = "") {
1609
	global $config, $g;
1610
	if(isset($config['system']['developerspew'])) {
1611
		$mt = microtime();
1612
		echo "interface_proxyarp_configure() being called $mt\n";
1613
	}
1614

    
1615
	/* kill any running choparp */
1616
	if (empty($interface))
1617
		killbyname("choparp");
1618
	else {
1619
		$vipif = get_real_interface($interface);
1620
		if (file_exists("{$g['varrun_path']}/choparp_{$vipif}.pid"))
1621
			killbypid("{$g['varrun_path']}/choparp_{$vipif}.pid");
1622
	}
1623

    
1624
	$paa = array();
1625
	if (!empty($config['virtualip']) && is_array($config['virtualip']['vip'])) {
1626

    
1627
		/* group by interface */
1628
		foreach ($config['virtualip']['vip'] as $vipent) {
1629
			if ($vipent['mode'] === "proxyarp") {
1630
				if ($vipent['interface'])
1631
					$proxyif = $vipent['interface'];
1632
				else
1633
					$proxyif = "wan";
1634
				
1635
				if (!empty($interface) && $interface != $proxyif)
1636
					continue;
1637

    
1638
				if (!is_array($paa[$proxyif]))
1639
					$paa[$proxyif] = array();
1640

    
1641
				$paa[$proxyif][] = $vipent;
1642
			}
1643
		}
1644
	}
1645

    
1646
	if (!empty($interface)) {
1647
		if (is_array($paa[$interface])) {
1648
			$paaifip = get_interface_ip($interface);
1649
                        if (!is_ipaddr($paaifip))
1650
                                return;
1651
                        $args = get_real_interface($interface) . " auto";
1652
                        foreach ($paa[$interface] as $paent) {
1653
                                if (isset($paent['subnet']))
1654
                                        $args .= " " . escapeshellarg("{$paent['subnet']}/{$paent['subnet_bits']}");
1655
                                else if (isset($paent['range']))
1656
                                        $args .= " " . escapeshellarg($paent['range']['from'] . "-" . $paent['range']['to']);
1657
                        }
1658
                        mwexec_bg("/usr/local/sbin/choparp " . $args);	
1659
		}
1660
	} else if (count($paa) > 0) {
1661
		foreach ($paa as $paif => $paents)  {
1662
			$paaifip = get_interface_ip($paif);
1663
			if (!is_ipaddr($paaifip))
1664
				continue;
1665
			$args = get_real_interface($paif) . " auto";
1666
			foreach ($paents as $paent) {
1667
				if (isset($paent['subnet']))
1668
					$args .= " " . escapeshellarg("{$paent['subnet']}/{$paent['subnet_bits']}");
1669
				else if (isset($paent['range']))
1670
					$args .= " " . escapeshellarg($paent['range']['from'] . "-" . $paent['range']['to']);
1671
			}
1672
			mwexec_bg("/usr/local/sbin/choparp " . $args);
1673
		}
1674
	}
1675
}
1676

    
1677
function interfaces_vips_configure($interface = "") {
1678
	global $g, $config;
1679
	if(isset($config['system']['developerspew'])) {
1680
		$mt = microtime();
1681
		echo "interfaces_vips_configure() being called $mt\n";
1682
	}
1683
	$paa = array();
1684
	if(is_array($config['virtualip']['vip'])) {
1685
		$carp_setuped = false;
1686
		$anyproxyarp = false;
1687
		foreach ($config['virtualip']['vip'] as $vip) {
1688
			switch ($vip['mode']) {
1689
			case "proxyarp":
1690
				/* nothing it is handled on interface_proxyarp_configure() */
1691
				if ($interface <> "" && $vip['interface'] <> $interface)
1692
					continue;
1693
				$anyproxyarp = true;
1694
				break;
1695
			case "ipalias":
1696
				if ($interface <> "" && $vip['interface'] <> $interface)
1697
					continue;
1698
				interface_ipalias_configure(&$vip);
1699
				break;
1700
			case "carp":
1701
				if ($interface <> "" && $vip['interface'] <> $interface)
1702
					continue;
1703
				if ($carp_setuped == false) {
1704
					interfaces_carp_setup();
1705
					$carp_setuped = true;
1706
				}
1707
				interface_carp_configure($vip);
1708
				break;
1709
			case "carpdev-dhcp":
1710
				if ($interface <> "" && $vip['interface'] <> $interface)
1711
					continue;
1712
				interface_carpdev_configure($vip);
1713
				break;
1714
			}
1715
		}
1716
		
1717
		if ($anyproxyarp == true)
1718
			interface_proxyarp_configure();
1719
	}
1720
}
1721

    
1722
function interface_ipalias_configure(&$vip) {
1723

    
1724
	if ($vip['mode'] == "ipalias") {
1725
		$if = get_real_interface($vip['interface']);
1726
		mwexec("/sbin/ifconfig " . escapeshellarg($if) . " " . $vip['subnet'] . "/" . escapeshellarg($vip['subnet_bits']) . " alias");
1727
	}
1728
}
1729

    
1730
function interface_reload_carps($cif) {
1731
	global $config;
1732

    
1733
	$carpifs = link_ip_to_carp_interface(find_interface_ip($cif));
1734
	if (empty($carpifs))
1735
		return;
1736

    
1737
	$carps = explode(" ", $carpifs);
1738
	if(is_array($config['virtualip']['vip'])) {
1739
		$viparr = &$config['virtualip']['vip'];
1740
		foreach ($viparr as $vip) {
1741
			if (in_array($vip['carpif'], $carps)) {
1742
				switch ($vip['mode']) {
1743
				case "carp":
1744
					interface_vip_bring_down($vip);
1745
					sleep(1);
1746
					interface_carp_configure($vip);
1747
					break;
1748
				case "carpdev-dhcp":
1749
					interface_vip_bring_down($vip);
1750
					sleep(1);
1751
					interface_carpdev_configure($vip);
1752
					break;
1753
				case "ipalias":
1754
					interface_vip_bring_down($vip);
1755
					sleep(1);
1756
					interface_ipalias_configure($vip);
1757
					break;
1758
				}
1759
			}
1760
		}
1761
	}
1762
}
1763

    
1764
function interface_carp_configure(&$vip) {
1765
	global $config, $g;
1766
	if(isset($config['system']['developerspew'])) {
1767
		$mt = microtime();
1768
		echo "interface_carp_configure() being called $mt\n";
1769
	}
1770

    
1771
	if ($vip['mode'] != "carp")
1772
		return;
1773

    
1774
	$vip_password = $vip['password'];
1775
	$vip_password = escapeshellarg(addslashes(str_replace(" ", "", $vip_password)));
1776
	if ($vip['password'] != "")
1777
		$password = " pass {$vip_password}";
1778

    
1779
	// set the vip interface to the vhid
1780
	$vipif = "vip{$vip['vhid']}";
1781

    
1782
	/*
1783
	 * ensure the interface containing the VIP really exists
1784
 	 * prevents a panic if the interface is missing or invalid
1785
	 */
1786
	$realif = get_real_interface($vip['interface']);
1787
	if (!does_interface_exist($realif)) {
1788
		file_notice("CARP", "Interface specified for the virtual IP address {$vip['subnet']} does not exist. Skipping this VIP.", "Firewall: Virtual IP", "");
1789
		return;
1790
	}
1791

    
1792
	/* Ensure CARP IP really exists prior to loading up. */
1793
	$ww_subnet_ip = find_interface_ip($realif);
1794
	$ww_subnet_bits = find_interface_subnet($realif);
1795
	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'])) {
1796
		file_notice("CARP", "Sorry but we could not find a matching real interface subnet for the virtual IP address {$vip['subnet']}.", "Firewall: Virtual IP", "");
1797
		return;
1798
	}
1799

    
1800
	/* create the carp interface and setup */
1801
	if (does_interface_exist($vipif)) {
1802
		pfSense_interface_flags($vipif, -IFF_UP);
1803
	} else {
1804
		$carpif = pfSense_interface_create("carp");
1805
		pfSense_interface_rename($carpif, $vipif);
1806
		pfSense_ngctl_name("{$carpif}:", $vipif);
1807
	}
1808

    
1809
	/* invalidate interface cache */
1810
	get_interface_arr(true);
1811

    
1812
	$broadcast_address = gen_subnet_max($vip['subnet'], $vip['subnet_bits']);
1813
	$advbase = "";
1814
	if (!empty($vip['advbase']))
1815
		$advbase = "advbase {$vip['advbase']}";
1816
	mwexec("/sbin/ifconfig {$vipif} {$vip['subnet']}/{$vip['subnet_bits']} vhid {$vip['vhid']} advskew {$vip['advskew']} {$advbase} {$password}");
1817

    
1818
	interfaces_bring_up($vipif);
1819
	
1820
	return $vipif;
1821
}
1822

    
1823
function interface_carpdev_configure(&$vip) {
1824
	global $g;
1825

    
1826
	if ($vip['mode'] != "carpdev-dhcp")
1827
		return;
1828

    
1829
	$vip_password = $vip['password'];
1830
	$vip_password = str_replace(" ", "", $vip_password);
1831
	if($vip['password'] != "")
1832
		$password = " pass \"" . $vip_password . "\"";
1833

    
1834
	if (empty($vip['interface']))
1835
		return;
1836

    
1837
	$vipif = "vip" . $vip['vhid'];
1838
	$realif = get_real_interface($vip['interface']);
1839
	interfaces_bring_up($realif);
1840
	/*
1841
	 * ensure the interface containing the VIP really exists
1842
	 * prevents a panic if the interface is missing or invalid
1843
	 */
1844
	if (!does_interface_exist($realif)) {
1845
		file_notice("CARP", "Interface specified for the virtual IP address {$vip['subnet']} does not exist. Skipping this VIP.", "Firewall: Virtual IP", "");
1846
		return;
1847
	}
1848

    
1849
	if (does_interface_exist($vipif)) {
1850
		interface_bring_down($vipif);
1851
	} else {
1852
		$carpdevif = exec("/sbin/ifconfig carp create");
1853
		mwexec("/sbin/ifconfig {$carpdevif} name {$vipif}");
1854
		pfSense_ngctl_name("{$carpdevif}:", $vipif);
1855
	}
1856

    
1857
	mwexec("/sbin/ifconfig {$vipif} carpdev {$realif} vhid {$vip['vhid']} advskew {$vip['advskew']} advbase {$vip['advbase']} {$password}");
1858
	interfaces_bring_up($vipif);
1859

    
1860
	/*
1861
	 * XXX: BIG HACK but carpdev needs ip services active
1862
	 *      before even starting something as dhclient.
1863
	 *      I do not know if this is a feature or a bug
1864
	 *      but better than track it make it work ;) .
1865
	 */
1866
	//$fakeiptouse = "10.254.254." . ($carp_instances_counter+1);
1867
	//$cmdchain->add("CarpDEV hack", "/sbin/ifconfig {$carpint} inet {$fakeiptouse}", false);
1868

    
1869
	/* generate dhclient_wan.conf */
1870
	$fd = fopen("{$g['varetc_path']}/dhclient_{$vipif}.conf", "w");
1871
	if ($fd) {
1872
		$dhclientconf = "";
1873

    
1874
		$dhclientconf .= <<<EOD
1875
interface "{$vipif}" {
1876
timeout 60;
1877
retry 1;
1878
select-timeout 0;
1879
initial-interval 1;
1880
script "/sbin/dhclient-script";
1881
}
1882

    
1883
EOD;
1884

    
1885
		fwrite($fd, $dhclientconf);
1886
		fclose($fd);
1887

    
1888
		/* fire up dhclient */
1889
		mwexec("/sbin/dhclient -c {$g['varetc_path']}/dhclient_{$vipif}.conf {$vipif} >{$g['tmp_path']}/{$vipif}_output 2>{$g['tmp_path']}/{$vipif}_error_output", false);
1890
	} else {
1891
		log_error("Error: cannot open dhclient_{$vipif}.conf in interfaces_carpdev_configure() for writing.\n");
1892
		mwexec("/sbin/dhclient -b {$vipif}");
1893
	}
1894

    
1895
	return $vipif;
1896
}
1897

    
1898
function interface_wireless_clone($realif, $wlcfg) {
1899
	global $config, $g;
1900
	/*   Check to see if interface has been cloned as of yet.  
1901
	 *   If it has not been cloned then go ahead and clone it.
1902
	 */
1903
	$needs_clone = false;
1904
	if(is_array($wlcfg['wireless']))
1905
		$wlcfg_mode = $wlcfg['wireless']['mode'];
1906
	else
1907
		$wlcfg_mode = $wlcfg['mode'];
1908
	switch($wlcfg_mode) {
1909
		 case "hostap":
1910
			$mode = "wlanmode hostap";
1911
			break;
1912
		 case "adhoc":
1913
			$mode = "wlanmode adhoc";
1914
			break;
1915
		 default:
1916
			$mode = "";
1917
			break;
1918
	}
1919
	$baseif = interface_get_wireless_base($wlcfg['if']);
1920
	if(does_interface_exist($realif)) {
1921
		exec("/sbin/ifconfig {$realif}", $output, $ret);
1922
		$ifconfig_str = implode($output);
1923
		if(($wlcfg_mode == "hostap") && (! preg_match("/hostap/si", $ifconfig_str))) {
1924
			log_error("Interface {$realif} changed to hostap mode");
1925
			$needs_clone = true;
1926
		}
1927
		if(($wlcfg_mode == "adhoc") && (! preg_match("/adhoc/si", $ifconfig_str))) {
1928
			log_error("Interface {$realif} changed to adhoc mode");
1929
			$needs_clone = true;
1930
		}
1931
		if(($wlcfg_mode == "bss") && (preg_match("/hostap|adhoc/si", $ifconfig_str))) {
1932
			log_error("Interface {$realif} changed to infrastructure mode");
1933
			$needs_clone = true;
1934
		}
1935
	} else {
1936
		$needs_clone = true;
1937
	}
1938

    
1939
	if($needs_clone == true) {
1940
		/* remove previous instance if it exists */
1941
		if(does_interface_exist($realif))
1942
			pfSense_interface_destroy($realif);
1943

    
1944
		log_error("Cloning new wireless interface {$realif}");
1945
		// Create the new wlan interface. FreeBSD returns the new interface name.
1946
		// example:  wlan2
1947
		exec("/sbin/ifconfig wlan create wlandev {$baseif} {$mode} bssid 2>&1", $out, $ret);
1948
		if($ret <> 0) {
1949
			log_error("Failed to clone interface {$baseif} with error code {$ret}, output {$out[0]}");
1950
			return false;
1951
		}
1952
		$newif = trim($out[0]);
1953
		// Rename the interface to {$parentnic}_wlan{$number}#: EX: ath0_wlan0
1954
		pfSense_interface_rename($newif, $realif);
1955
		// FIXME: not sure what ngctl is for. Doesn't work.
1956
		// mwexec("/usr/sbin/ngctl name {$newif}: {$realif}", false);
1957
		file_put_contents("{$g['tmp_path']}/{$realif}_oldmac", get_interface_mac($realif));
1958
	}
1959
	return true;
1960
}
1961

    
1962
function interface_sync_wireless_clones(&$ifcfg, $sync_changes = false) {
1963
	global $config, $g;
1964

    
1965
	$shared_settings = array('standard', 'turbo', 'protmode', 'txpower', 'channel',
1966
	                         'diversity', 'txantenna', 'rxantenna', 'distance',
1967
	                         'regdomain', 'regcountry', 'reglocation');
1968

    
1969
	if(!is_interface_wireless($ifcfg['if']))
1970
		return;
1971

    
1972
	$baseif = interface_get_wireless_base($ifcfg['if']);
1973

    
1974
	// Sync shared settings for assigned clones
1975
	$iflist = get_configured_interface_list(false, true);
1976
	foreach ($iflist as $if) {
1977
		if ($baseif == interface_get_wireless_base($config['interfaces'][$if]['if']) && $ifcfg['if'] != $config['interfaces'][$if]['if']) {
1978
			if (isset($config['interfaces'][$if]['wireless']['standard']) || $sync_changes) {
1979
				foreach ($shared_settings as $setting) {
1980
					if ($sync_changes) {
1981
						if (isset($ifcfg['wireless'][$setting]))
1982
							$config['interfaces'][$if]['wireless'][$setting] = $ifcfg['wireless'][$setting];
1983
						else if (isset($config['interfaces'][$if]['wireless'][$setting]))
1984
							unset($config['interfaces'][$if]['wireless'][$setting]);
1985
					} else {
1986
						if (isset($config['interfaces'][$if]['wireless'][$setting]))
1987
							$ifcfg['wireless'][$setting] = $config['interfaces'][$if]['wireless'][$setting];
1988
						else if (isset($ifcfg['wireless'][$setting]))
1989
							unset($ifcfg['wireless'][$setting]);
1990
					}
1991
				}
1992
				if (!$sync_changes)
1993
					break;
1994
			}
1995
		}
1996
	}
1997

    
1998
	// Read or write settings at shared area
1999
	if (isset($config['wireless']['interfaces'][$baseif])) {
2000
		foreach ($shared_settings as $setting) {
2001
			if ($sync_changes) {
2002
				if (isset($ifcfg['wireless'][$setting]))
2003
					$config['wireless']['interfaces'][$baseif][$setting] = $ifcfg['wireless'][$setting];
2004
				else if (isset($config['wireless']['interfaces'][$baseif][$setting]))
2005
					unset($config['wireless']['interfaces'][$baseif][$setting]);
2006
			} else if (isset($config['wireless']['interfaces'][$baseif][$setting])) {
2007
				if (isset($config['wireless']['interfaces'][$baseif][$setting]))
2008
					$ifcfg['wireless'][$setting] = $config['wireless']['interfaces'][$baseif][$setting];
2009
				else if (isset($ifcfg['wireless'][$setting]))
2010
					unset($ifcfg['wireless'][$setting]);
2011
			}
2012
		}
2013
	}
2014

    
2015
	// Sync the mode on the clone creation page with the configured mode on the interface
2016
	if (interface_is_wireless_clone($ifcfg['if'])) {
2017
		foreach ($config['wireless']['clone'] as &$clone) {
2018
			if ($clone['cloneif'] == $ifcfg['if']) {
2019
				if ($sync_changes) {
2020
					$clone['mode'] = $ifcfg['wireless']['mode'];
2021
				} else {
2022
					$ifcfg['wireless']['mode'] = $clone['mode'];
2023
				}
2024
				break;
2025
			}
2026
		}
2027
		unset($clone);
2028
	}
2029
}
2030

    
2031
function interface_wireless_configure($if, &$wl, &$wlcfg) {
2032
	global $config, $g;
2033

    
2034
	/*    open up a shell script that will be used to output the commands.
2035
	 *    since wireless is changing a lot, these series of commands are fragile
2036
     *    and will sometimes need to be verified by a operator by executing the command
2037
     *    and returning the output of the command to the developers for inspection.  please
2038
     *    do not change this routine from a shell script to individul exec commands.  -sullrich
2039
	 */
2040

    
2041
	// Remove script file
2042
	unlink_if_exists("{$g['tmp_path']}/{$if}_setup.sh");
2043

    
2044
	// Clone wireless nic if needed.
2045
	interface_wireless_clone($if, $wl);
2046

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

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

    
2054
	/* set values for /path/program */
2055
	$hostapd = "/usr/sbin/hostapd";
2056
	$wpa_supplicant = "/usr/sbin/wpa_supplicant";
2057
	$ifconfig = "/sbin/ifconfig";
2058
	$sysctl = "/sbin/sysctl";
2059
	$killall = "/usr/bin/killall";
2060

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

    
2063
	$wlcmd = array();
2064
	$wl_sysctl = array();
2065
	/* Make sure it's up */
2066
	$wlcmd[] = "up";
2067
	/* Set a/b/g standard */
2068
	$standard = str_replace(" Turbo", "", $wlcfg['standard']);
2069
	$wlcmd[] = "mode " . escapeshellarg($standard);
2070

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

    
2076
	/* Set ssid */
2077
	if($wlcfg['ssid'])
2078
		$wlcmd[] = "ssid " .escapeshellarg($wlcfg['ssid']);
2079

    
2080
	/* Set 802.11g protection mode */
2081
	$wlcmd[] = "protmode " . escapeshellarg($wlcfg['protmode']);
2082

    
2083
	/* set wireless channel value */
2084
	if(isset($wlcfg['channel'])) {
2085
		if($wlcfg['channel'] == "0") {
2086
			$wlcmd[] = "channel any";
2087
		} else {
2088
			$wlcmd[] = "channel " . escapeshellarg($wlcfg['channel']);
2089
		}
2090
	}
2091

    
2092
	/* Set antenna diversity value */
2093
	if(isset($wlcfg['diversity']))
2094
		$wl_sysctl[] = "diversity=" . escapeshellarg($wlcfg['diversity']);
2095

    
2096
	/* Set txantenna value */
2097
	if(isset($wlcfg['txantenna']))
2098
		$wl_sysctl[] = "txantenna=" . escapeshellarg($wlcfg['txantenna']);
2099

    
2100
	/* Set rxantenna value */
2101
	if(isset($wlcfg['rxantenna']))
2102
		$wl_sysctl[] = "rxantenna=" . escapeshellarg($wlcfg['rxantenna']);
2103

    
2104
	/* set Distance value */
2105
	if($wlcfg['distance'])
2106
		$distance = escapeshellarg($wlcfg['distance']);
2107

    
2108
	/* Set wireless hostap mode */
2109
	if ($wlcfg['mode'] == "hostap") {
2110
		$wlcmd[] = "mediaopt hostap";
2111
	} else {
2112
		$wlcmd[] = "-mediaopt hostap";
2113
	}
2114

    
2115
	/* Set wireless adhoc mode */
2116
	if ($wlcfg['mode'] == "adhoc") {
2117
		$wlcmd[] = "mediaopt adhoc";
2118
	} else {
2119
		$wlcmd[] = "-mediaopt adhoc";
2120
	}
2121

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

    
2124
	/* handle hide ssid option */
2125
	if(isset($wlcfg['hidessid']['enable'])) {
2126
		$wlcmd[] = "hidessid";
2127
	} else {
2128
		$wlcmd[] = "-hidessid";
2129
	}
2130

    
2131
	/* handle pureg (802.11g) only option */
2132
	if(isset($wlcfg['pureg']['enable'])) {
2133
		$wlcmd[] = "mode 11g pureg";
2134
	} else {
2135
		$wlcmd[] = "-pureg";
2136
	}
2137

    
2138
	/* handle puren (802.11n) only option */
2139
	if(isset($wlcfg['puren']['enable'])) {
2140
		$wlcmd[] = "puren";
2141
	} else {
2142
		$wlcmd[] = "-puren";
2143
	}
2144

    
2145
	/* enable apbridge option */
2146
	if(isset($wlcfg['apbridge']['enable'])) {
2147
		$wlcmd[] = "apbridge";
2148
	} else {
2149
		$wlcmd[] = "-apbridge";
2150
	}
2151

    
2152
	/* handle turbo option */
2153
	if(isset($wlcfg['turbo']['enable'])) {
2154
		$wlcmd[] = "mediaopt turbo";
2155
	} else {
2156
		$wlcmd[] = "-mediaopt turbo";
2157
	}
2158

    
2159
	/* handle txpower setting */
2160
	/* if($wlcfg['txpower'] <> "")
2161
		$wlcmd[] = "txpower " . escapeshellarg($wlcfg['txpower']);
2162
	*/
2163
	/* handle wme option */
2164
	if(isset($wlcfg['wme']['enable'])) {
2165
		$wlcmd[] = "wme";
2166
	} else {
2167
		$wlcmd[] = "-wme";
2168
	}
2169

    
2170
	/* set up wep if enabled */
2171
	$wepset = "";
2172
	if (isset($wlcfg['wep']['enable']) && is_array($wlcfg['wep']['key'])) {
2173
		switch($wlcfg['wpa']['auth_algs']) {
2174
			case "1":
2175
				$wepset .= "authmode open wepmode on ";
2176
				break;
2177
			case "2":
2178
				$wepset .= "authmode shared wepmode on ";
2179
				break;
2180
			case "3":
2181
				$wepset .= "authmode mixed wepmode on ";
2182
		}
2183
		$i = 1;
2184
		foreach ($wlcfg['wep']['key'] as $wepkey) {
2185
			$wepset .= "wepkey " . escapeshellarg("{$i}:{$wepkey['value']}") . " ";
2186
			if (isset($wepkey['txkey'])) {
2187
				$wlcmd[] = "weptxkey {$i} ";
2188
			}
2189
			$i++;
2190
		}
2191
		$wlcmd[] = $wepset;
2192
	} else {
2193
		$wlcmd[] = "authmode open wepmode off ";
2194
	}
2195

    
2196
	mwexec(kill_hostapd("{$if}"));
2197
	mwexec(kill_wpasupplicant("{$if}"));
2198

    
2199
	/* generate wpa_supplicant/hostap config if wpa is enabled */
2200
	conf_mount_rw();
2201

    
2202
	switch ($wlcfg['mode']) {
2203
		case 'bss':
2204
			if (isset($wlcfg['wpa']['enable'])) {
2205
				$wpa .= <<<EOD
2206
ctrl_interface={$g['varrun_path']}/wpa_supplicant
2207
ctrl_interface_group=0
2208
ap_scan=1
2209
#fast_reauth=1
2210
network={
2211
ssid="{$wlcfg['ssid']}"
2212
scan_ssid=1
2213
priority=5
2214
key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
2215
psk="{$wlcfg['wpa']['passphrase']}"
2216
pairwise={$wlcfg['wpa']['wpa_pairwise']}
2217
group={$wlcfg['wpa']['wpa_pairwise']}
2218
}
2219
EOD;
2220

    
2221
				$fd = fopen("{$g['varetc_path']}/wpa_supplicant_{$if}.conf", "w");
2222
				fwrite($fd, "{$wpa}");
2223
				fclose($fd);
2224
			}
2225
			break;
2226
		case 'hostap':
2227
			if($wlcfg['wpa']['passphrase']) 
2228
				$wpa_passphrase = "wpa_passphrase={$wlcfg['wpa']['passphrase']}\n";
2229
			else 
2230
				$wpa_passphrase = "";
2231
			if (isset($wlcfg['wpa']['enable'])) {
2232
				$wpa .= <<<EOD
2233
interface={$if}
2234
driver=bsd
2235
logger_syslog=-1
2236
logger_syslog_level=0
2237
logger_stdout=-1
2238
logger_stdout_level=0
2239
dump_file={$g['tmp_path']}/hostapd_{$if}.dump
2240
ctrl_interface={$g['varrun_path']}/hostapd
2241
ctrl_interface_group=wheel
2242
#accept_mac_file={$g['tmp_path']}/hostapd_{$if}.accept
2243
#deny_mac_file={$g['tmp_path']}/hostapd_{$if}.deny
2244
#macaddr_acl={$wlcfg['wpa']['macaddr_acl']}
2245
ssid={$wlcfg['ssid']}
2246
debug={$wlcfg['wpa']['debug_mode']}
2247
auth_algs={$wlcfg['wpa']['auth_algs']}
2248
wpa={$wlcfg['wpa']['wpa_mode']}
2249
wpa_key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
2250
wpa_pairwise={$wlcfg['wpa']['wpa_pairwise']}
2251
wpa_group_rekey={$wlcfg['wpa']['wpa_group_rekey']}
2252
wpa_gmk_rekey={$wlcfg['wpa']['wpa_gmk_rekey']}
2253
wpa_strict_rekey={$wlcfg['wpa']['wpa_strict_rekey']}
2254
{$wpa_passphrase}
2255

    
2256
EOD;
2257

    
2258
if (isset($wlcfg['wpa']['rsn_preauth'])) {
2259
	$wpa .= <<<EOD
2260
# Enable the next lines for preauth when roaming. Interface = wired or wireless interface talking to the AP you want to roam from/to
2261
rsn_preauth=1
2262
rsn_preauth_interfaces={$if}
2263

    
2264
EOD;
2265

    
2266
}
2267
				if($wlcfg['auth_server_addr'] && $wlcfg['auth_server_shared_secret']) {
2268
					$auth_server_port = "1812";
2269
					if($wlcfg['auth_server_port']) 
2270
						$auth_server_port = $wlcfg['auth_server_port'];
2271
					$wpa .= <<<EOD
2272

    
2273
ieee8021x=1
2274
auth_server_addr={$wlcfg['auth_server_addr']}
2275
auth_server_port={$auth_server_port}
2276
auth_server_shared_secret={$wlcfg['auth_server_shared_secret']}
2277

    
2278
EOD;
2279
				} else {
2280
					$wpa .= "ieee8021x={$wlcfg['wpa']['ieee8021x']}\n";
2281
				}
2282

    
2283
				$fd = fopen("{$g['varetc_path']}/hostapd_{$if}.conf", "w");
2284
				fwrite($fd, "{$wpa}");
2285
				fclose($fd);
2286

    
2287
			}
2288
			break;
2289
	}
2290

    
2291
	/*
2292
	 *    all variables are set, lets start up everything
2293
	 */
2294

    
2295
	$baseif = interface_get_wireless_base($if);
2296
	preg_match("/^(.*?)([0-9]*)$/", $baseif, $baseif_split);
2297
	$wl_sysctl_prefix = 'dev.' . $baseif_split[1] . '.' . $baseif_split[2];
2298

    
2299
	/* set sysctls for the wireless interface */
2300
	if (!empty($wl_sysctl)) {
2301
		fwrite($fd_set, "# sysctls for {$baseif}\n");
2302
		foreach ($wl_sysctl as $wl_sysctl_line) {
2303
			fwrite($fd_set, "{$sysctl} {$wl_sysctl_prefix}.{$wl_sysctl_line}\n");
2304
		}
2305
	}
2306

    
2307
	/* set ack timers according to users preference (if he/she has any) */
2308
	if($distance) {
2309
		fwrite($fd_set, "# Enable ATH distance settings\n");
2310
		fwrite($fd_set, "/sbin/athctrl.sh -i {$baseif} -d {$distance}\n");
2311
	}
2312

    
2313
	if (isset($wlcfg['wpa']['enable'])) {
2314
		if ($wlcfg['mode'] == "bss") {
2315
			fwrite($fd_set, "{$wpa_supplicant} -B -i {$if} -c {$g['varetc_path']}/wpa_supplicant_{$if}.conf\n");
2316
		}
2317
		if ($wlcfg['mode'] == "hostap") {
2318
			/* add line to script to restore old mac to make hostapd happy */
2319
			if (file_exists("{$g['tmp_path']}/{$if}_oldmac")) {
2320
				$if_oldmac = file_get_contents("{$g['tmp_path']}/{$if}_oldmac");
2321
				if (is_macaddr($if_oldmac))
2322
					fwrite($fd_set, "{$ifconfig} " . escapeshellarg($if) .
2323
						" link " . escapeshellarg($if_oldmac) . "\n");
2324
			}
2325

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

    
2328
			/* add line to script to restore spoofed mac after running hostapd */
2329
			if (file_exists("{$g['tmp_path']}/{$if}_oldmac")) {
2330
				if ($wl['spoofmac'])
2331
					$if_curmac = $wl['spoofmac'];
2332
				else
2333
					$if_curmac = get_interface_mac($if);
2334
				if (is_macaddr($if_curmac))
2335
					fwrite($fd_set, "{$ifconfig} " . escapeshellarg($if) .
2336
						" link " . escapeshellarg($if_curmac) . "\n");
2337
			}
2338
		}
2339
	}
2340

    
2341
	fclose($fd_set);
2342
	conf_mount_ro();
2343

    
2344
	/* Making sure regulatory settings have actually changed
2345
	 * before applying, because changing them requires bringing
2346
	 * down all wireless networks on the interface. */
2347
	exec("{$ifconfig} " . escapeshellarg($if), $output);
2348
	$ifconfig_str = implode($output);
2349
	unset($output);
2350
	$reg_changing = false;
2351

    
2352
	/* special case for the debug country code */
2353
	if ($wlcfg['regcountry'] == 'DEBUG' && !preg_match("/\sregdomain\s+DEBUG\s/si", $ifconfig_str))
2354
		$reg_changing = true;
2355
	else if ($wlcfg['regdomain'] && !preg_match("/\sregdomain\s+{$wlcfg['regdomain']}\s/si", $ifconfig_str))
2356
		$reg_changing = true;
2357
	else if ($wlcfg['regcountry'] && !preg_match("/\scountry\s+{$wlcfg['regcountry']}\s/si", $ifconfig_str))
2358
		$reg_changing = true;
2359
	else if ($wlcfg['reglocation'] == 'anywhere' && preg_match("/\s(indoor|outdoor)\s/si", $ifconfig_str))
2360
		$reg_changing = true;
2361
	else if ($wlcfg['reglocation'] && $wlcfg['reglocation'] != 'anywhere' && !preg_match("/\s{$wlcfg['reglocation']}\s/si", $ifconfig_str))
2362
		$reg_changing = true;
2363

    
2364
	if ($reg_changing) {
2365
		/* set regulatory domain */
2366
		if($wlcfg['regdomain'])
2367
			$wlregcmd[] = "regdomain " . escapeshellarg($wlcfg['regdomain']);
2368

    
2369
		/* set country */
2370
		if($wlcfg['regcountry'])
2371
			$wlregcmd[] = "country " . escapeshellarg($wlcfg['regcountry']);
2372

    
2373
		/* set location */
2374
		if($wlcfg['reglocation'])
2375
			$wlregcmd[] = escapeshellarg($wlcfg['reglocation']);
2376

    
2377
		$wlregcmd_args = implode(" ", $wlregcmd);
2378

    
2379
		/* build a complete list of the wireless clones for this interface */
2380
		$clone_list = array();
2381
		if (does_interface_exist(interface_get_wireless_clone($baseif)))
2382
			$clone_list[] = interface_get_wireless_clone($baseif);
2383
		if (is_array($config['wireless']['clone'])) {
2384
			foreach ($config['wireless']['clone'] as $clone) {
2385
				if ($clone['if'] == $baseif)
2386
					$clone_list[] = $clone['cloneif'];
2387
			}
2388
		}
2389

    
2390
		/* find which clones are up and bring them down */
2391
		$clones_up = array();
2392
		foreach ($clone_list as $clone_if) {
2393
			$clone_status = pfSense_get_interface_addresses($clone_if);
2394
			if ($clone_status['status'] == 'up') {
2395
				$clones_up[] = $clone_if;
2396
				mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " down");
2397
			}
2398
		}
2399

    
2400
		/* apply the regulatory settings */
2401
		mwexec("{$ifconfig} " . escapeshellarg($if) . " {$wlregcmd_args}");
2402

    
2403
		/* bring the clones back up that were previously up */
2404
		foreach ($clones_up as $clone_if) {
2405
			mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " up");
2406

    
2407
			/*
2408
			 * Rerun the setup script for the interface if it isn't this interface, the interface
2409
			 * is in infrastructure mode, and WPA is enabled.
2410
			 * This can be removed if wpa_supplicant stops dying when you bring the interface down.
2411
			 */
2412
			if ($clone_if != $if) {
2413
				$friendly_if = convert_real_interface_to_friendly_interface_name($clone_if);
2414
				if ( !empty($friendly_if)
2415
				    && $config['interfaces'][$friendly_if]['wireless']['mode'] == "bss"
2416
				    && isset($config['interfaces'][$friendly_if]['wireless']['wpa']['enable']) ) {
2417
					mwexec("/bin/sh {$g['tmp_path']}/{$clone_if}_setup.sh");
2418
				}
2419
			}
2420
		}
2421
	}
2422

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

    
2427
	/* configure wireless */
2428
	$wlcmd_args = implode(" ", $wlcmd);
2429
	mwexec("/sbin/ifconfig {$if} $wlcmd_args", false);
2430

    
2431
	
2432
	sleep(1);
2433
	/* execute hostapd and wpa_supplicant if required in shell */
2434
	mwexec("/bin/sh {$g['tmp_path']}/{$if}_setup.sh");
2435

    
2436
	return 0;
2437

    
2438
}
2439

    
2440
function kill_hostapd($interface) {
2441
	return "/bin/pkill -f \"hostapd .*{$interface}\"\n";
2442
}
2443

    
2444
function kill_wpasupplicant($interface) {
2445
	return "/bin/pkill -f \"wpa_supplicant .*{$interface}\"\n";
2446
}
2447

    
2448
function find_dhclient_process($interface) {
2449
	if ($interface)
2450
		$pid = `/bin/pgrep -xf "dhclient: {$interface}"`;
2451
	else
2452
		$pid = 0;
2453

    
2454
	return $pid;
2455
}
2456

    
2457
function interface_configure($interface = "wan", $reloadall = false, $linkupevent = false) {
2458
	global $config, $g;
2459
	global $interface_sn_arr_cache, $interface_ip_arr_cache;
2460

    
2461
	$wancfg = $config['interfaces'][$interface];
2462

    
2463
	$realif = get_real_interface($interface);
2464
	$realhwif = interface_translate_type_to_real($interface);
2465

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

    
2470
		switch ($wancfg['ipaddr']) {
2471
			case 'pppoe':
2472
			case 'l2tp':
2473
			case 'pptp':
2474
			case 'ppp':
2475
				break;
2476
			default:
2477
				interface_bring_down($interface);
2478
				break;
2479
		}
2480
	}
2481

    
2482
	/* wireless configuration? */
2483
	if (is_array($wancfg['wireless']))
2484
		interface_wireless_configure($realif, $wancfg, $wancfg['wireless']);
2485

    
2486
	if ($wancfg['spoofmac']) {
2487
		mwexec("/sbin/ifconfig " . escapeshellarg($realhwif) .
2488
			" link " . escapeshellarg($wancfg['spoofmac']));
2489

    
2490
                /*
2491
                 * All vlans need to spoof their parent mac address, too.  see
2492
                 * ticket #1514: http://cvstrac.pfsense.com/tktview?tn=1514,33
2493
                 */
2494
                if (is_array($config['vlans']['vlan'])) {
2495
                        foreach ($config['vlans']['vlan'] as $vlan) {
2496
                                if ($vlan['if'] == $realhwif)
2497
                                        mwexec("/sbin/ifconfig " . escapeshellarg($vlan['vlanif']) .
2498
                                                " link " . escapeshellarg($wancfg['spoofmac']));
2499
                        }
2500
                }
2501
	}  else {
2502
		$mac = get_interface_mac($realhwif);
2503
		if ($mac == "ff:ff:ff:ff:ff:ff") {
2504
			/*   this is not a valid mac address.  generate a
2505
			 *   temporary mac address so the machine can get online.
2506
			 */
2507
			echo "Generating new MAC address.";
2508
			$random_mac = generate_random_mac_address();
2509
			mwexec("/sbin/ifconfig " . escapeshellarg($realhwif) .
2510
				" link " . escapeshellarg($random_mac));
2511
			$wancfg['spoofmac'] = $random_mac;
2512
			write_config();
2513
			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");
2514
		}
2515
	}
2516

    
2517
	/* media */
2518
	if ($wancfg['media'] || $wancfg['mediaopt']) {
2519
		$cmd = "/sbin/ifconfig " . escapeshellarg($realhwif);
2520
		if ($wancfg['media'])
2521
			$cmd .= " media " . escapeshellarg($wancfg['media']);
2522
		if ($wancfg['mediaopt'])
2523
			$cmd .= " mediaopt " . escapeshellarg($wancfg['mediaopt']);
2524
		mwexec($cmd);
2525
	}
2526
	if (!empty($wancfg['mtu']))
2527
		pfSense_interface_mtu($realhwif, $wancfg['mtu']);
2528

    
2529
	$options = pfSense_get_interface_addresses($realhwif);
2530
	if (is_array($options) && isset($options['caps']['polling'])) {
2531
		if (isset($config['system']['polling']))
2532
			pfSense_interface_capabilities($realif, IFCAP_POLLING);
2533
		else
2534
			pfSense_interface_capabilities($realif, -IFCAP_POLLING);
2535
	}
2536

    
2537
	/* skip vlans for checksumming and polling */
2538
        if (!stristr($realhwif, "vlan") && is_array($options)) {
2539
		$flags = 0;
2540
		if(isset($config['system']['disablechecksumoffloading'])) {
2541
			if (isset($options['encaps']['txcsum']))
2542
				$flags |= IFCAP_TXCSUM;
2543
			if (isset($options['encaps']['rxcsum']))
2544
				$flags |= IFCAP_RXCSUM;
2545
        	} else {
2546
 			if (!isset($options['caps']['txcsum']))
2547
				$flags |= IFCAP_TXCSUM;
2548
			if (!isset($options['caps']['rxcsum']))
2549
				$flags |= IFCAP_RXCSUM;
2550
        	}
2551

    
2552
        	if(isset($config['system']['disablesegmentationoffloading'])) {
2553
                	if (isset($options['encaps']['tso4']))
2554
				$flags |= IFCAP_TSO;
2555
                	if (isset($options['encaps']['tso6']))
2556
				$flags |= IFCAP_TSO;
2557
        	} else {
2558
                	if (!isset($options['caps']['tso4']))
2559
				$flags |= IFCAP_TSO;
2560
                	if (!isset($options['caps']['tso6']))
2561
				$flags |= IFCAP_TSO;
2562
        	}
2563

    
2564
        	if(isset($config['system']['disablelargereceiveoffloading'])) {
2565
                	if (isset($options['encaps']['lro']))
2566
				$flags |= IFCAP_LRO;
2567
        	} else {
2568
                	if (!isset($options['caps']['lro']))
2569
				$flags |= IFCAP_LRO;
2570
        	}
2571

    
2572
        	/* if the NIC supports polling *AND* it is enabled in the GUI */
2573
        	if (!isset($config['system']['polling']) || !isset($options['caps']['polling'])) {
2574
			$flags |= IFCAP_POLLING;
2575
		}
2576
               	pfSense_interface_capabilities($realhwif, -$flags);
2577
	}
2578

    
2579
	/* invalidate interface/ip/sn cache */
2580
	get_interface_arr(true);
2581
	unset($interface_ip_arr_cache[$realif]);
2582
	unset($interface_sn_arr_cache[$realif]);
2583

    
2584
	switch ($wancfg['ipaddr']) {
2585
		case 'carpdev-dhcp':
2586
			interface_carpdev_dhcp_configure($interface);
2587
			break;
2588
		case 'dhcp':
2589
			interface_dhcp_configure($interface);
2590
			break;
2591
		case 'pppoe':
2592
		case 'l2tp':
2593
		case 'pptp':
2594
		case 'ppp':
2595
			interface_ppps_configure($interface);
2596
			break;
2597
		default:
2598
			if ($wancfg['ipaddr'] <> "" && $wancfg['subnet'] <> "") {
2599
				pfSense_interface_setaddress($realif, "{$wancfg['ipaddr']}/{$wancfg['subnet']}");
2600
			} else if (substr($realif, 0, 3) == "gre") {
2601
				if (is_array($config['gres']['gre'])) {
2602
					foreach ($config['gres']['gre'] as $gre)
2603
						if ($gre['greif'] == $realif)
2604
							interface_gre_configure($gre);
2605
				}
2606
			} else if (substr($realif, 0, 3) == "gif") {
2607
				 if (is_array($config['gifs']['gif'])) {
2608
					foreach ($config['gifs']['gif'] as $gif)
2609
						if($gif['gifif'] == $interface)
2610
							interface_gif_configure($gif);
2611
				}
2612
			} else if (substr($realif, 0, 4) == "ovpn") {
2613
				/* XXX: Should be done anything?! */
2614
			}
2615
			break;
2616
	}
2617

    
2618
	if(does_interface_exist($wancfg['if']))
2619
		interfaces_bring_up($wancfg['if']);
2620

    
2621
	interface_netgraph_needed($interface);
2622
 	
2623
	if (!$g['booting']) {
2624
		link_interface_to_vips($interface, "update");
2625

    
2626
		unset($gre);
2627
		$gre = link_interface_to_gre($interface);
2628
		if (!empty($gre))
2629
			array_walk($gre, 'interface_gre_configure');
2630

    
2631
		unset($gif);
2632
		$gif = link_interface_to_gif($interface);
2633
		if (!empty($gif))
2634
                       	array_walk($gif, 'interface_gif_configure');
2635

    
2636
		if ($linkupevent == false) {
2637
			unset($bridgetmp);
2638
			$bridgetmp = link_interface_to_bridge($interface);
2639
			if (!empty($bridgetmp))
2640
				interface_bridge_add_member($bridgetmp, $realif);
2641
		}
2642

    
2643
		$grouptmp = link_interface_to_group($interface);
2644
		if (!empty($grouptmp))
2645
			array_walk($grouptmp, 'interface_group_add_member');
2646

    
2647
		if ($interface == "lan")
2648
			/* make new hosts file */
2649
			system_hosts_generate();
2650

    
2651
		if ($reloadall == true) {
2652

    
2653
			/* reconfigure static routes (kernel may have deleted them) */
2654
			system_routing_configure($interface);
2655

    
2656
			/* reload ipsec tunnels */
2657
			vpn_ipsec_configure();
2658

    
2659
			/* restart dnsmasq */
2660
			services_dnsmasq_configure();
2661

    
2662
			/* update dyndns */
2663
			send_event("service reload dyndns {$interface}");
2664

    
2665
			/* reload captive portal */
2666
			captiveportal_init_rules();
2667
		}
2668
	}
2669

    
2670
	return 0;
2671
}
2672

    
2673
function interface_carpdev_dhcp_configure($interface = "wan") {
2674
	global $config, $g;
2675

    
2676
	$wancfg = $config['interfaces'][$interface];
2677
	$wanif = $wancfg['if'];
2678
	/* bring wan interface up before starting dhclient */
2679
	if($wanif)
2680
		interfaces_bring_up($wanif);
2681
	else 
2682
		log_error("Could not bring wanif up in terface_carpdev_dhcp_configure()");
2683

    
2684
	return 0;
2685
}
2686

    
2687
function interface_dhcp_configure($interface = "wan") {
2688
	global $config, $g;
2689

    
2690
	$wancfg = $config['interfaces'][$interface];
2691
	if (empty($wancfg))
2692
		$wancfg = array();
2693

    
2694
	/* generate dhclient_wan.conf */
2695
	$fd = fopen("{$g['varetc_path']}/dhclient_{$interface}.conf", "w");
2696
	if (!$fd) {
2697
		printf("Error: cannot open dhclient_{$interface}.conf in interfaces_wan_dhcp_configure() for writing.\n");
2698
		return 1;
2699
	}
2700

    
2701
	if ($wancfg['dhcphostname']) {
2702
		$dhclientconf_hostname = "send dhcp-client-identifier \"{$wancfg['dhcphostname']}\";\n";
2703
		$dhclientconf_hostname .= "\tsend host-name \"{$wancfg['dhcphostname']}\";\n";
2704
	} else {
2705
		$dhclientconf_hostname = "";
2706
	}
2707

    
2708
	$wanif = get_real_interface($interface);
2709
	if (empty($wanif)) {
2710
		log_error("Invalid interface \"{$interface}\" in interface_dhcp_configure()");
2711
		return 0;
2712
	}
2713
 	$dhclientconf = "";
2714
	
2715
	$dhclientconf .= <<<EOD
2716
interface "{$wanif}" {
2717
timeout 60;
2718
retry 1;
2719
select-timeout 0;
2720
initial-interval 1;
2721
	{$dhclientconf_hostname}
2722
	script "/sbin/dhclient-script";
2723
}
2724

    
2725
EOD;
2726

    
2727
if(is_ipaddr($wancfg['alias-address'])) {
2728
	$subnetmask = gen_subnet_mask($wancfg['alias-subnet']);
2729
	$dhclientconf .= <<<EOD
2730
alias {
2731
	interface  "{$wanif}";
2732
	fixed-address {$wancfg['alias-address']};
2733
	option subnet-mask {$subnetmask};
2734
}
2735

    
2736
EOD;
2737
}
2738
	fwrite($fd, $dhclientconf);
2739
	fclose($fd);
2740

    
2741
	/* bring wan interface up before starting dhclient */
2742
	if($wanif)
2743
		interfaces_bring_up($wanif);
2744
	else 
2745
		log_error("Could not bring up {$wanif} interface in interface_dhcp_configure()");
2746

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

    
2750
	return 0;
2751
}
2752

    
2753
function interfaces_group_setup() {
2754
	global $config;
2755

    
2756
	if (!is_array($config['ifgroups']['ifgroupentry']))
2757
		return;
2758

    
2759
	foreach ($config['ifgroups']['ifgroupentry'] as $groupar)
2760
		interface_group_setup($groupar);
2761

    
2762
	return;
2763
}
2764

    
2765
function interface_group_setup(&$groupname /* The parameter is an array */) {
2766
	global $config;
2767

    
2768
	if (!is_array($groupname))
2769
		return;
2770
	$members = explode(" ", $groupname['members']);
2771
	foreach($members as $ifs) {
2772
		$realif = get_real_interface($ifs);
2773
		if ($realif)
2774
			mwexec("/sbin/ifconfig {$realif} group {$groupname['ifname']}");
2775
	}
2776

    
2777
	return;
2778
}
2779

    
2780
function interface_group_add_member($interface, $groupname) {
2781
	$interface = get_real_interface($interface);
2782
	mwexec("/sbin/ifconfig {$interface} group {$groupname}", true);
2783
}
2784
 
2785
/* COMPAT Function */
2786
function convert_friendly_interface_to_real_interface_name($interface) {
2787
	return get_real_interface($interface);
2788
}
2789

    
2790
/* COMPAT Function */
2791
function get_real_wan_interface($interface = "wan") {
2792
	return get_real_interface($interface);
2793
}
2794

    
2795
/* COMPAT Function */
2796
function get_current_wan_address($interface = "wan") {
2797
	return get_interface_ip($interface);
2798
}
2799

    
2800
/*
2801
 * convert_real_interface_to_friendly_interface_name($interface): convert fxp0 -> wan, etc.
2802
 */
2803
function convert_real_interface_to_friendly_interface_name($interface = "wan") {
2804
        global $config;
2805

    
2806
	if (stristr($interface, "vip")) {
2807
                $index = intval(substr($interface, 3));
2808
                foreach ($config['virtualip']['vip'] as $counter => $vip) {
2809
                        if ($vip['mode'] == "carpdev-dhcp" || $vip['mode'] == "carp")  {
2810
                                if ($index == $vip['vhid'])
2811
                                        return $vip['interface'];
2812
                        }
2813
                }
2814
        }
2815

    
2816
        /* XXX: For speed reasons reference directly the interface array */
2817
	$ifdescrs = &$config['interfaces'];
2818
        //$ifdescrs = get_configured_interface_list(false, true);
2819

    
2820
        foreach ($ifdescrs as $if => $ifname) {
2821
                if ($config['interfaces'][$if]['if'] == $interface)
2822
                        return $if;
2823

    
2824
                if (stristr($interface, "_wlan0") && $config['interfaces'][$if]['if'] == interface_get_wireless_base($interface))
2825
                        return $if;
2826

    
2827
                $int = interface_translate_type_to_real($if);
2828
                if ($int == $interface)
2829
                        return $ifname;
2830
        }
2831
        return NULL;
2832
}
2833

    
2834
/* attempt to resolve interface to friendly descr */
2835
function convert_friendly_interface_to_friendly_descr($interface) {
2836
        global $config;
2837

    
2838
        switch ($interface) {
2839
        case "l2tp":
2840
        	$ifdesc = "L2TP";
2841
                break;
2842
	case "pptp":
2843
		$ifdesc = "PPTP";
2844
		break;
2845
	case "pppoe":
2846
		$ifdesc = "PPPoE";
2847
		break;
2848
	case "openvpn":
2849
		$ifdesc = "OpenVPN";
2850
		break;
2851
	case "enc0":
2852
	case "ipsec":
2853
		$ifdesc = "IPsec";
2854
		break;
2855
        default:
2856
                if (isset($config['interfaces'][$interface])) {
2857
                        if (empty($config['interfaces'][$interface]['descr']))
2858
                                $ifdesc = strtoupper($interface);
2859
                        else
2860
                                $ifdesc = strtoupper($config['interfaces'][$interface]['descr']);
2861
			break;
2862
		} else if (substr($interface, 0, 3) == "vip") {
2863
			if (is_array($config['virtualip']['vip'])) {
2864
				foreach ($config['virtualip']['vip'] as $counter => $vip) {
2865
					if ($vip['mode'] == "carpdev-dhcp" || $vip['mode'] == "carp")  {
2866
						if ($interface == "vip{$vip['vhid']}")
2867
							return "{$vip['subnet']} - {$vip['descr']}";
2868
					}
2869
				}
2870
                        }
2871
                } else {
2872
			/* if list */
2873
			$ifdescrs = get_configured_interface_with_descr(false, true);
2874
			foreach ($ifdescrs as $if => $ifname) {
2875
					if ($if == $interface || $ifname == $interface)
2876
						return $ifname;
2877
			}
2878
		}
2879
                break;
2880
        }
2881

    
2882
        return $ifdesc;
2883
}
2884

    
2885
function convert_real_interface_to_friendly_descr($interface) {
2886
        global $config;
2887

    
2888
        $ifdesc = convert_real_interface_to_friendly_interface_name("{$interface}");
2889

    
2890
        if ($ifdesc) {
2891
                $iflist = get_configured_interface_with_descr(false, true);
2892
                return $iflist[$ifdesc];
2893
        }
2894

    
2895
        return $interface;
2896
}
2897

    
2898
/*
2899
 *  interface_translate_type_to_real($interface):
2900
 *              returns the real hardware interface name for a friendly interface.  ie: wan
2901
 */
2902
function interface_translate_type_to_real($interface) {
2903
        global $config;
2904

    
2905
	if (empty($config['interfaces'][$interface]))
2906
		return $interface;
2907
	$tmpif = $config['interfaces'][$interface];
2908
	switch ($tmpif['type']) {
2909
	case "ppp":
2910
	case "pppoe":
2911
	case "pptp":
2912
	case "l2tp":
2913
		if (is_array($config['ppps']['ppp'])) {
2914
			foreach ($config['ppps']['ppp'] as $pppidx => $ppp) {
2915
				if ($tmpif['if'] == $ppp['if']) {
2916
					$interface = $ppp['ports'];
2917
					break;
2918
				}
2919
			}
2920
		}
2921
		break;
2922
	case "dhcp":
2923
	case "static":
2924
	default:
2925
		$interface = $tmpif['if'];
2926
		break;
2927
	}
2928

    
2929
	return $interface;
2930
}
2931

    
2932
function interface_is_wireless_clone($wlif) {
2933
	if(!stristr($wlif, "_wlan")) {
2934
		return false;
2935
	} else {
2936
		return true;
2937
	}
2938
}
2939

    
2940
function interface_get_wireless_base($wlif) {
2941
	if(!stristr($wlif, "_wlan")) {
2942
		return $wlif;
2943
	} else {
2944
		return substr($wlif, 0, stripos($wlif, "_wlan"));
2945
	}
2946
}
2947

    
2948
function interface_get_wireless_clone($wlif) {
2949
	if(!stristr($wlif, "_wlan")) {
2950
		return $wlif . "_wlan0";
2951
	} else {
2952
		return $wlif;
2953
	}
2954
}
2955

    
2956
function get_real_interface($interface = "wan") {
2957
    global $config;
2958

    
2959
	$wanif = NULL;
2960

    
2961
	switch ($interface) {
2962
	case "l2tp":
2963
		$wanif = "l2tp";
2964
		break;
2965
	case "pptp":
2966
		$wanif = "pptp";
2967
		break;
2968
	case "pppoe":
2969
		$wanif = "pppoe";
2970
		break;
2971
	case "openvpn":
2972
		$wanif = "openvpn";
2973
		break;
2974
	case "ipsec":
2975
	case "enc0":
2976
		$wanif = "enc0";
2977
		break;
2978
	case "ppp":
2979
		$wanif = "ppp";
2980
		break;
2981
	default:
2982
		// If a real interface was alread passed simply
2983
		// pass the real interface back.  This encourages
2984
		// the usage of this function in more cases so that
2985
		// we can combine logic for more flexibility.
2986
		if(does_interface_exist($interface)) {
2987
			$wanif = $interface;
2988
			break;
2989
		}
2990
		if (empty($config['interfaces'][$interface]))
2991
			break;
2992

    
2993
		$cfg = &$config['interfaces'][$interface];
2994

    
2995
		// Wireless cloned NIC support (FreeBSD 8+)
2996
		// interface name format: $parentnic_wlanparentnic#
2997
		// example: ath0_wlan0
2998
		if (is_interface_wireless($cfg['if'])) {
2999
			$wanif = interface_get_wireless_clone($cfg['if']);
3000
			break;
3001
		}
3002
		/*
3003
		if (empty($cfg['if'])) {
3004
			$wancfg = $cfg['if'];
3005
			break;
3006
		}
3007
		*/
3008

    
3009
		switch ($cfg['ipaddr']) {
3010
			case "carpdev-dhcp":
3011
				$viparr = &$config['virtualip']['vip'];
3012
				if(is_array($viparr))
3013
				foreach ($viparr as $counter => $vip) {
3014
					if ($vip['mode'] == "carpdev-dhcp") {
3015
						if($vip['interface'] == $interface) {
3016
							$wanif = "carp{$counter}";
3017
							break;
3018
						}
3019
					}
3020
				}
3021
				break;
3022
			case "pppoe": 
3023
			case "pptp": 
3024
			case "l2tp": 
3025
			case "ppp":
3026
				$wanif = $cfg['if'];
3027
				break;
3028
			default:
3029
				$wanif = $cfg['if'];
3030
				break;
3031
		}
3032
		break;
3033
	}
3034

    
3035
    return $wanif;
3036
}
3037

    
3038
/* Guess the physical interface by providing a IP address */
3039
function guess_interface_from_ip($ipaddress) {
3040
	if(! is_ipaddr($ipaddress)) {
3041
		return false;
3042
	}
3043
	/* create a route table we can search */
3044
	exec("netstat -rnWf inet", $output, $ret);
3045
	foreach($output as $line) {
3046
		if(preg_match("/^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\/[0-9]+[ ]+link[#]/", $line)) {
3047
			$fields = preg_split("/[ ]+/", $line);
3048
			if(ip_in_subnet($ipaddress, $fields[0])) {
3049
				return $fields[6];
3050
			}
3051
		}
3052
	}
3053
	$ret = exec_command("/sbin/route -n get {$ipaddress} | /usr/bin/awk '/interface/ { print \$2; };'");
3054
	if(empty($ret)) {
3055
        	return false;
3056
	}
3057
	return $ret;
3058
}
3059

    
3060
/*
3061
 * find_ip_interface($ip): return the interface where an ip is defined
3062
 */
3063
function find_ip_interface($ip)
3064
{
3065
        /* if list */
3066
        $ifdescrs = get_configured_interface_list();
3067

    
3068
        foreach ($ifdescrs as $ifdescr => $ifname) {
3069
		if ($ip == get_interface_ip($ifname)) {
3070
                	$int = get_real_interface($ifname);
3071
			return $int;
3072
		}
3073
        }
3074
        return false;
3075
}
3076

    
3077
/*
3078
 *   find_number_of_created_carp_interfaces: return the number of carp interfaces
3079
 */
3080
function find_number_of_created_carp_interfaces() {
3081
	return `/sbin/ifconfig | grep "carp:" | wc -l`;
3082
}
3083

    
3084
function get_all_carp_interfaces() {
3085
	$ints = str_replace("\n", " ", `ifconfig | grep "carp:" -B2 | grep ": flag" | cut -d: -f1`);
3086
	$ints = explode(" ", $ints);
3087
	return $ints;
3088
}
3089

    
3090
/*
3091
 * find_carp_interface($ip): return the carp interface where an ip is defined
3092
 */
3093
function find_carp_interface($ip) {
3094
	global $config;
3095
	if (is_array($config['virtualip']['vip'])) {
3096
		foreach ($config['virtualip']['vip'] as $vip) {
3097
			if ($vip['mode'] == "carp" || $vip['mode'] == "carpdev") {
3098
				$carp_ip = get_interface_ip($vip['interface']);
3099
				$if = `ifconfig | grep '$ip ' -B1 | head -n1 | cut -d: -f1`;
3100
				if ($if)
3101
					return $if;
3102
			}
3103
		}
3104
	}
3105
}
3106

    
3107
function link_carp_interface_to_parent($interface) {
3108
        global $config;
3109

    
3110
        if ($interface == "")
3111
                return;
3112

    
3113
        $carp_ip = get_interface_ip($interface);
3114
        if (!is_ipaddr($carp_ip))
3115
                return;
3116

    
3117
        /* if list */
3118
        $ifdescrs = get_configured_interface_list();
3119
        foreach ($ifdescrs as $ifdescr => $ifname) {
3120
                $interfaceip = get_interface_ip($ifname);
3121
                $subnet_bits = get_interface_subnet($ifname);
3122
                $subnet_ip = gen_subnet("{$interfaceip}", "{$subnet_bits}");
3123
                if(ip_in_subnet($carp_ip, "{$subnet_ip}/{$subnet_bits}"))
3124
                        return $ifname;
3125
        }
3126

    
3127
        return "";
3128
}
3129

    
3130
/****f* interfaces/link_ip_to_carp_interface
3131
 * NAME
3132
 *   link_ip_to_carp_interface - Find where a CARP interface links to.
3133
 * INPUTS
3134
 *   $ip
3135
 * RESULT
3136
 *   $carp_ints
3137
 ******/
3138
function link_ip_to_carp_interface($ip) {
3139
        global $config;
3140

    
3141
        if (!is_ipaddr($ip))
3142
                return;
3143

    
3144
        $carp_ints = "";
3145
        if (is_array($config['virtualip']['vip'])) {
3146
		$first = 0;
3147
		$carp_int = array();
3148
                foreach ($config['virtualip']['vip'] as $vip) {
3149
                        if ($vip['mode'] == "carp" || $vip['mode'] == "carpdev") {
3150
                                $carp_ip = $vip['subnet'];
3151
                                $carp_sn = $vip['subnet_bits'];
3152
                                $carp_nw = gen_subnet($carp_ip, $carp_sn);
3153
                                if (ip_in_subnet($ip, "{$carp_nw}/{$carp_sn}"))
3154
					$carp_int[] = "vip{$vip['vhid']}";
3155
                        }
3156
                }
3157
		if (!empty($carp_int))
3158
			$carp_ints = implode(" ", array_unique($carp_int));
3159
        }
3160

    
3161
        return $carp_ints;
3162
}
3163

    
3164
function link_interface_to_vlans($int, $action = "") {
3165
	global $config;
3166

    
3167
	if (empty($int))
3168
		return;
3169

    
3170
	if (is_array($config['vlans']['vlan'])) {
3171
                foreach ($config['vlans']['vlan'] as $vlan) {
3172
			if ($int == $vlan['if']) {
3173
				if ($action == "update") {
3174
					interfaces_bring_up($int);
3175
				} else if ($action == "")
3176
					return $vlan;
3177
			}
3178
		}
3179
	}
3180
}
3181

    
3182
function link_interface_to_vips($int, $action = "") {
3183
        global $config;
3184

    
3185
        if (is_array($config['virtualip']['vip'])) {
3186
		foreach ($config['virtualip']['vip'] as $vip) {
3187
			if ($int == $vip['interface']) {
3188
				if ($action == "update") {
3189
					interface_vip_bring_down($vip);
3190
					interfaces_vips_configure($int);
3191
				} else
3192
					return $vip;
3193
			}
3194
		}
3195
	}
3196
}
3197

    
3198
/****f* interfaces/link_interface_to_bridge
3199
 * NAME
3200
 *   link_interface_to_bridge - Finds out a bridge group for an interface
3201
 * INPUTS
3202
 *   $ip
3203
 * RESULT
3204
 *   bridge[0-99]
3205
 ******/
3206
function link_interface_to_bridge($int) {
3207
        global $config;
3208

    
3209
        if (is_array($config['bridges']['bridged'])) {
3210
                foreach ($config['bridges']['bridged'] as $bridge) {
3211
			if (in_array($int, explode(',', $bridge['members'])))
3212
                                return "{$bridge['bridgeif']}";
3213
		}
3214
	}
3215
}
3216

    
3217
function link_interface_to_group($int) {
3218
        global $config;
3219

    
3220
	$result = array();
3221

    
3222
        if (is_array($config['ifgroups']['ifgroupentry'])) {
3223
                foreach ($config['ifgroups']['ifgroupentry'] as $group) {
3224
			if (in_array($int, explode(" ", $group['members'])))
3225
				$result[$group['ifname']] = $int;
3226
		}
3227
	}
3228

    
3229
	return $result;
3230
}
3231

    
3232
function link_interface_to_gre($interface) {
3233
        global $config;
3234

    
3235
	$result = array();
3236

    
3237
        if (is_array($config['gres']['gre'])) {
3238
                foreach ($config['gres']['gre'] as $gre)
3239
                        if($gre['if'] == $interface)
3240
				$result[] = $gre;
3241
	}
3242

    
3243
	return $result;
3244
}
3245

    
3246
function link_interface_to_gif($interface) {
3247
        global $config;
3248

    
3249
	$result = array();
3250

    
3251
        if (is_array($config['gifs']['gif'])) {
3252
                foreach ($config['gifs']['gif'] as $gif)
3253
                        if($gif['if'] == $interface)
3254
                                $result[] = $gif;
3255
	}
3256

    
3257
	return $result;
3258
}
3259

    
3260
/*
3261
 * find_interface_ip($interface): return the interface ip (first found)
3262
 */
3263
function find_interface_ip($interface, $flush = false)
3264
{
3265
	global $interface_ip_arr_cache;
3266
	global $interface_sn_arr_cache;
3267

    
3268
	$interface = str_replace("\n", "", $interface);
3269
	
3270
	if (!does_interface_exist($interface))
3271
		return;
3272

    
3273
	/* Setup IP cache */
3274
	if (!isset($interface_ip_arr_cache[$interface]) or $flush) {
3275
		$ifinfo = pfSense_get_interface_addresses($interface);
3276
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
3277
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
3278
	}
3279

    
3280
	return $interface_ip_arr_cache[$interface];
3281
}
3282

    
3283
function find_interface_subnet($interface, $flush = false)
3284
{
3285
	global $interface_sn_arr_cache;
3286
	global $interface_ip_arr_cache;
3287

    
3288
	$interface = str_replace("\n", "", $interface);
3289
	if (does_interface_exist($interface) == false)
3290
		return;
3291

    
3292
	if (!isset($interface_sn_arr_cache[$interface]) or $flush) {
3293
		$ifinfo = pfSense_get_interface_addresses($interface);
3294
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
3295
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
3296
        }
3297

    
3298
	return $interface_sn_arr_cache[$interface];
3299
}
3300

    
3301
function ip_in_interface_alias_subnet($interface, $ipalias) {
3302
	global $config;
3303

    
3304
	if (empty($interface) || !is_ipaddr($ipalias))
3305
		return false;
3306
	if (is_array($config['virtualip']['vip'])) {
3307
                foreach ($config['virtualip']['vip'] as $vip) {
3308
                        switch ($vip['mode']) {
3309
                        case "ipalias":
3310
                                if ($vip['interface'] <> $interface)
3311
                                        break;
3312
				if (ip_in_subnet($ipalias, gen_subnet($vip['subnet'], $vip['subnet_bits']) . "/" . $vip['subnet_bits']))
3313
					return true;
3314
                                break;
3315
                        }
3316
                }
3317
	}
3318

    
3319
	return false;
3320
}
3321

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

    
3334
	$curip = find_interface_ip($realif);
3335
	if ($curip && is_ipaddr($curip) && ($curip != "0.0.0.0"))
3336
		return $curip;
3337
	else
3338
		return null;
3339
}
3340

    
3341
function get_interface_subnet($interface = "wan")
3342
{
3343
	$realif = get_real_interface($interface);
3344
	if (!$realif) {
3345
                if (preg_match("/^carp/i", $interface))
3346
                        $realif = $interface;
3347
                else if (preg_match("/^vip/i", $interface))
3348
                        $realif = $interface;
3349
                else
3350
                        return null;
3351
        }
3352

    
3353
	$cursn = find_interface_subnet($realif);
3354
	if (!empty($cursn))
3355
		return $cursn;
3356

    
3357
	return null;
3358
}
3359

    
3360
/* return outside interfaces with a gateway */
3361
function get_interfaces_with_gateway() {
3362
	global $config;
3363

    
3364
	$ints = array();
3365

    
3366
	/* loop interfaces, check config for outbound */
3367
	foreach($config['interfaces'] as $ifdescr => $ifname) {
3368
		switch ($ifname['ipaddr']) {
3369
			case "dhcp":
3370
			case "carpdev-dhcp":
3371
			case "ppp";
3372
			case "pppoe":
3373
			case "pptp":
3374
			case "l2tp":
3375
			case "ppp";
3376
				$ints[$ifdescr] = $ifdescr;
3377
			break;
3378
			default:
3379
				if (substr($ifname['if'], 0, 5) ==  "ovpnc" ||
3380
				    !empty($ifname['gateway']))
3381
					$ints[$ifdescr] = $ifdescr;
3382
			break;
3383
		}
3384
	}
3385
	return $ints;
3386
}
3387

    
3388
/* return true if interface has a gateway */
3389
function interface_has_gateway($friendly) {
3390
	global $config;
3391

    
3392
	if (!empty($config['interfaces'][$friendly])) {
3393
		$ifname = &$config['interfaces'][$friendly];
3394
		switch ($ifname['ipaddr']) {
3395
			case "dhcp":
3396
			case "carpdev-dhcp":
3397
			case "pppoe":
3398
			case "pptp":
3399
			case "l2tp":
3400
			case "ppp";
3401
				return true;
3402
			break;
3403
			default:
3404
				if (substr($ifname['if'], 0, 5) ==  "ovpnc")
3405
					return true;
3406
				if (!empty($ifname['gateway']))
3407
					return true;
3408
			break;
3409
		}
3410
	}
3411

    
3412
	return false;
3413
}
3414

    
3415
/****f* interfaces/is_altq_capable
3416
 * NAME
3417
 *   is_altq_capable - Test if interface is capable of using ALTQ
3418
 * INPUTS
3419
 *   $int            - string containing interface name
3420
 * RESULT
3421
 *   boolean         - true or false
3422
 ******/
3423

    
3424
function is_altq_capable($int) {
3425
        /* Per:
3426
         * http://www.freebsd.org/cgi/man.cgi?query=altq&manpath=FreeBSD+7.2-current&format=html
3427
         * Only the following drivers have ALTQ support
3428
         */
3429
	$capable = array("age", "ale", "an", "ath", "aue", "awi", "bce",
3430
			"bfe", "bge", "dc", "de", "ed", "em", "ep", "fxp", "gem",
3431
			"hme", "igb", "ipw", "iwi", "jme", "le", "lem", "msk", "mxge", "my", "nfe",
3432
			"npe", "nve", "ral", "re", "rl", "rum", "run", "bwn", "sf", "sis", "sk",
3433
			"ste", "stge", "txp", "udav", "ural", "vge", "vr", "wi", "xl",
3434
			"ndis", "tun", "ovpns", "ovpnc", "vlan", "pppoe", "pptp", "ng",
3435
			"l2tp", "ppp");
3436

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

    
3439
        if (in_array($int_family[0], $capable))
3440
                return true;
3441
	else if (stristr($int, "vlan")) /* VLANs are name $parent_$vlan now */
3442
		return true;
3443
	else if (stristr($int, "_wlan")) /* WLANs are name $parent_$wlan now */
3444
		return true;
3445
        else
3446
                return false;
3447
}
3448

    
3449
/****f* interfaces/is_interface_wireless
3450
 * NAME
3451
 *   is_interface_wireless - Returns if an interface is wireless
3452
 * RESULT
3453
 *   $tmp       - Returns if an interface is wireless
3454
 ******/
3455
function is_interface_wireless($interface) {
3456
        global $config, $g;
3457

    
3458
        $friendly = convert_real_interface_to_friendly_interface_name($interface);
3459
        if(!isset($config['interfaces'][$friendly]['wireless'])) {
3460
                if (preg_match($g['wireless_regex'], $interface)) {
3461
                        if (isset($config['interfaces'][$friendly]))
3462
                                $config['interfaces'][$friendly]['wireless'] = array();
3463
                        return true;
3464
                }
3465
                return false;
3466
        } else
3467
                return true;
3468
}
3469

    
3470
function get_wireless_modes($interface) {
3471
	/* return wireless modes and channels */
3472
	$wireless_modes = array();
3473

    
3474
	$wlif = interface_translate_type_to_real($interface);
3475

    
3476
	if(is_interface_wireless($wlif)) {
3477
		$cloned_interface = get_real_interface($interface);
3478
		$chan_list = "/sbin/ifconfig {$cloned_interface} list chan";
3479
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
3480
		$format_list = "/usr/bin/awk '{print \$5 \" \" \$6 \",\" \$1}'";
3481

    
3482
		$interface_channels = "";
3483
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
3484
		$interface_channel_count = count($interface_channels);
3485

    
3486
		$c = 0;
3487
		while ($c < $interface_channel_count)
3488
		{
3489
			$channel_line = explode(",", $interface_channels["$c"]);
3490
			$wireless_mode = trim($channel_line[0]);
3491
			$wireless_channel = trim($channel_line[1]);
3492
			if(trim($wireless_mode) != "") {
3493
				/* if we only have 11g also set 11b channels */
3494
				if($wireless_mode == "11g") {
3495
					if(!isset($wireless_modes["11b"]))
3496
						$wireless_modes["11b"] = array();
3497
				} else if($wireless_mode == "11g ht") {
3498
					if(!isset($wireless_modes["11b"]))
3499
						$wireless_modes["11b"] = array();
3500
					if(!isset($wireless_modes["11g"]))
3501
						$wireless_modes["11g"] = array();
3502
					$wireless_mode = "11ng";
3503
				} else if($wireless_mode == "11a ht") {
3504
					if(!isset($wireless_modes["11a"]))
3505
						$wireless_modes["11a"] = array();
3506
					$wireless_mode = "11na";
3507
				}
3508
				$wireless_modes["$wireless_mode"]["$c"] = $wireless_channel;
3509
			}
3510
			$c++;
3511
		}
3512
	}
3513
	return($wireless_modes);
3514
}
3515

    
3516
/* return channel numbers, frequency, max txpower, and max regulation txpower */
3517
function get_wireless_channel_info($interface) {
3518
	$wireless_channels = array();
3519

    
3520
	$wlif = interface_translate_type_to_real($interface);
3521

    
3522
	if(is_interface_wireless($wlif)) {
3523
		$cloned_interface = get_real_interface($interface);
3524
		$chan_list = "/sbin/ifconfig {$cloned_interface} list txpower";
3525
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
3526
		$format_list = "/usr/bin/awk '{print \$1 \",\" \$3 \" \" \$4 \",\" \$5 \",\" \$7}'";
3527

    
3528
		$interface_channels = "";
3529
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
3530

    
3531
		foreach ($interface_channels as $channel_line) {
3532
			$channel_line = explode(",", $channel_line);
3533
			if(!isset($wireless_channels[$channel_line[0]]))
3534
				$wireless_channels[$channel_line[0]] = $channel_line;
3535
		}
3536
	}
3537
	return($wireless_channels);
3538
}
3539

    
3540
/****f* interfaces/get_interface_mtu
3541
 * NAME
3542
 *   get_interface_mtu - Return the mtu of an interface
3543
 * RESULT
3544
 *   $tmp       - Returns the mtu of an interface
3545
 ******/
3546
function get_interface_mtu($interface) {
3547
        $mtu = pfSense_get_interface_addresses($interface);
3548
        return $mtu['mtu'];
3549
}
3550

    
3551
function get_interface_mac($interface) {
3552

    
3553
	$macinfo = pfSense_get_interface_addresses($interface);
3554
	return $macinfo["macaddr"];
3555
}
3556

    
3557
/****f* pfsense-utils/generate_random_mac_address
3558
 * NAME
3559
 *   generate_random_mac - generates a random mac address
3560
 * INPUTS
3561
 *   none
3562
 * RESULT
3563
 *   $mac - a random mac address
3564
 ******/
3565
function generate_random_mac_address() {
3566
        $mac = "02";
3567
        for($x=0; $x<5; $x++)
3568
                $mac .= ":" . dechex(rand(16, 255));
3569
        return $mac;
3570
}
3571

    
3572
/****f* interfaces/is_jumbo_capable
3573
 * NAME
3574
 *   is_jumbo_capable - Test if interface is jumbo frame capable.  Useful for determining VLAN capability.
3575
 * INPUTS
3576
 *   $int             - string containing interface name
3577
 * RESULT
3578
 *   boolean          - true or false
3579
 ******/
3580
function is_jumbo_capable($int) {
3581
        global $g;
3582

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

    
3585
        if (in_array($int_family[0], $g['vlan_long_frame']))
3586
                return true;
3587
        else
3588
                return false;
3589
}
3590

    
3591
function setup_pppoe_reset_file($pppif, $iface="") {
3592
	global $g;
3593
	$cron_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
3594

    
3595
	if(!empty($iface) && !empty($pppif)){
3596
		$cron_cmd = <<<EOD
3597
#!/bin/sh
3598
/usr/local/sbin/pfSctl -c 'interface reload {$iface}'
3599
/usr/bin/logger -t pppoe{$iface} "PPPoE periodic reset executed on {$iface}"
3600

    
3601
EOD;
3602

    
3603
		file_put_contents($cron_file, $cron_cmd);
3604
		chmod($cron_file, 0700);
3605
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
3606
	} else
3607
		unlink_if_exists($cron_file);
3608
}
3609

    
3610
function get_vip_descr($ipaddress) {
3611
	global $config;
3612

    
3613
	foreach ($config['virtualip']['vip'] as $vip) {
3614
		if ($vip['subnet'] == $ipaddress) {
3615
			return ($vip['descr']);
3616
		}
3617
	}
3618
	return "";
3619
}
3620

    
3621
?>
(25-25/61)