Project

General

Profile

Download (115 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_BUILDER_BINARIES:	/usr/local/sbin/dhcp6c
41
	pfSense_MODULE:	interfaces
42

    
43
*/
44

    
45
/* include all configuration functions */
46
require_once("globals.inc");
47
require_once("cmd_chain.inc");
48

    
49
function interfaces_bring_up($interface) {
50
	if(!$interface) {
51
		log_error("interfaces_bring_up() was called but no variable defined.");
52
		log_error( "Backtrace: " . debug_backtrace() );
53
		return;
54
	}
55
	pfSense_interface_flags($interface, IFF_UP);
56
}
57

    
58
/*
59
 * Return the interface array
60
 */
61
function get_interface_arr($flush = false) {
62
        global $interface_arr_cache;
63

    
64
        /* If the cache doesn't exist, build it */
65
        if (!isset($interface_arr_cache) or $flush)
66
                $interface_arr_cache = explode(" ", trim(`/sbin/ifconfig -l`));
67

    
68
        return $interface_arr_cache;
69
}
70

    
71
/*
72
 * does_interface_exist($interface): return true or false if a interface is
73
 * detected.
74
 */
75
function does_interface_exist($interface) {
76
	global $config;
77
	
78
	if(!$interface)
79
		return false;
80

    
81
	$ints = get_interface_arr(true);
82
	if (in_array($interface, $ints))
83
		return true;
84
	else
85
		return false;
86
}
87

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

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

    
127
/* This if block doesn't do anything. It can be deleted.
128
PPP interfaces are found above in the previous if ($found == false) block.
129
This block of code is only entered for OPTx interfaces that are configured for PPPoE modem access, so $realif != $ppp['if']
130

    
131
				if ($realif == $ppp['if']) {
132
					$found = true;
133
					break;
134
				}
135
*/			
136
				$ports = explode(',',$ppp['ports']);
137
				foreach($ports as $pid => $port){
138
					$port = get_real_interface($port);
139
					if ($realif == $port) {
140
						$found = true;
141
						break;
142
					}
143
					/* Find the parent interfaces of the vlans in the MLPPP configs 
144
					* there should be only one element in the array here 
145
					* -- this could be better . . . */
146
					$parent_if = get_parent_interface($port);
147
					if ($realif == $parent_if[0]) {
148
						$found = true;
149
						break;
150
					}
151
				}
152
			}
153
		}
154
	}
155
	
156
	if ($found == false) {
157
		$realif = get_real_interface($interface);
158
		pfSense_ngctl_detach("{$realif}:", $realif);
159
	}
160
	/* NOTE: We make sure for this on interface_ppps_configure()
161
	 *	no need to do it here agan.
162
	 *	else
163
	 *		pfSense_ngctl_attach(".", $realif);
164
	 */
165
}
166

    
167
function interfaces_loopback_configure() {
168
	if($g['booting'])
169
		echo "Configuring loopback interface...";
170
	pfSense_interface_setaddress("lo0", "127.0.0.1");
171
	interfaces_bring_up("lo0");
172
	if($g['booting'])
173
		echo "done.\n";
174
	return 0;
175
}
176

    
177
function interfaces_vlan_configure() {
178
	global $config, $g;
179
	if($g['booting'])
180
		echo "Configuring VLAN interfaces...";
181
	if (is_array($config['vlans']['vlan']) && count($config['vlans']['vlan'])) {
182
		foreach ($config['vlans']['vlan'] as $vlan) {
183
			if(empty($vlan['vlanif']))
184
				$vlan['vlanif'] = "{$vlan['if']}_vlan{$vlan['tag']}";
185
			/* XXX: Maybe we should report any errors?! */
186
			interface_vlan_configure($vlan);
187
		}
188
	}
189
	if($g['booting'])
190
		echo "done.\n";
191
}
192

    
193
function interface_vlan_configure(&$vlan) {
194
        global $config, $g;
195

    
196
	if (!is_array($vlan)) {
197
		log_error("VLAN: called with wrong options. Problems with config!");
198
		return;
199
	}
200
	$if = $vlan['if'];
201
	$vlanif  = empty($vlan['vlanif']) ? "{$if}_vlan{$vlan['tag']}" : $vlan['vlanif'];
202
	$tag = $vlan['tag'];
203

    
204
	if (empty($if)) {
205
		log_error("interface_vlan_confgure called with if undefined.");
206
		return;
207
	}
208

    
209
	/* make sure the parent interface is up */
210
	interfaces_bring_up($if);
211
	/* Since we are going to add vlan(4) try to enable all that hardware supports. */
212
	pfSense_interface_capabilities($if, IFCAP_VLAN_HWTAGGING|IFCAP_VLAN_MTU|IFCAP_VLAN_HWFILTER);
213

    
214
	if (!empty($vlanif) && does_interface_exist($vlanif)) {
215
		interface_bring_down($vlanif, true);
216
	} else {
217
		$tmpvlanif = pfSense_interface_create("vlan");
218
		pfSense_interface_rename($tmpvlanif, $vlanif);
219
		pfSense_ngctl_name("{$tmpvlanif}:", $vlanif);
220
	}
221

    
222
	pfSense_vlan_create($vlanif, $if, $tag);
223

    
224
	interfaces_bring_up($vlanif);
225

    
226
	/* invalidate interface cache */
227
	get_interface_arr(true);
228

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

    
232
	return $vlanif;
233
}
234

    
235
function interface_qinq_configure(&$vlan, $fd = NULL) {
236
        global $config, $g;
237

    
238
        if (!is_array($vlan)) {
239
                log_error("QinQ compat VLAN: called with wrong options. Problems with config!\n");
240
                return;
241
        }
242

    
243
        $qinqif = $vlan['if'];
244
        $tag = $vlan['tag'];
245
        if(empty($qinqif)) {
246
                log_error("interface_qinq_confgure called with if undefined.\n");
247
                return;
248
        }
249
	$vlanif = interface_vlan_configure($vlan);
250

    
251
        if ($fd == NULL) {
252
                $exec = true;
253
                $fd = fopen("{$g['tmp_path']}/netgraphcmd", "w");
254
        } else
255
                $exec = false;
256
        /* make sure the parent is converted to ng_vlan(4) and is up */
257
        interfaces_bring_up($qinqif);
258

    
259
	pfSense_ngctl_attach(".", $qinqif);
260
        if (!empty($vlanif) && does_interface_exist($vlanif)) {
261
                fwrite($fd, "shutdown {$qinqif}qinq:\n");
262
                exec("/usr/sbin/ngctl msg {$qinqif}qinq: gettable", $result);
263
                if (empty($result)) {
264
                        fwrite($fd, "mkpeer {$qinqif}: vlan lower downstream\n");
265
                        fwrite($fd, "name {$qinqif}:lower {$vlanif}qinq\n");
266
                        fwrite($fd, "connect {$qinqif}: {$vlanif}qinq: upper nomatch\n");
267
                }
268
        } else {
269
                fwrite($fd, "mkpeer {$qinqif}: vlan lower downstream\n");
270
                fwrite($fd, "name {$qinqif}:lower {$vlanif}qinq\n");
271
                fwrite($fd, "connect {$qinqif}: {$vlanif}qinq: upper nomatch\n");
272
        }
273

    
274
        /* invalidate interface cache */
275
        get_interface_arr(true);
276

    
277
        if (!stristr($qinqif, "vlan"))
278
                mwexec("/sbin/ifconfig {$qinqif} promisc\n");
279

    
280
        $macaddr = get_interface_mac($qinqif);
281
        if (!empty($vlan['members'])) {
282
                $members = explode(" ", $vlan['members']);
283
                foreach ($members as $qtag) {
284
                        $qinq = array();
285
                        $qinq['tag'] = $qtag;
286
                        $qinq['if'] = $vlanif;
287
                        interface_qinq2_configure($qinq, $fd, $macaddr);
288
                }
289
        }
290
        if ($exec == true) {
291
                fclose($fd);
292
                mwexec("/usr/sbin/ngctl -f {$g['tmp_path']}/netgraphcmd");
293
        }
294

    
295
        interfaces_bring_up($qinqif);
296
        if (!empty($vlan['members'])) {
297
                $members = explode(" ", $vlan['members']);
298
                foreach ($members as $qif)
299
                        interfaces_bring_up("{$vlanif}_{$qif}");
300
        }
301

    
302
        return $vlanif;
303
}
304

    
305
function interfaces_qinq_configure() {
306
	global $config, $g;
307
	if($g['booting'])
308
		echo "Configuring QinQ interfaces...";
309
	if (is_array($config['qinqs']['qinqentry']) && count($config['qinqs']['qinqentry'])) {
310
		foreach ($config['qinqs']['qinqentry'] as $qinq) {
311
			/* XXX: Maybe we should report any errors?! */
312
			interface_qinq_configure($qinq);
313
		}
314
	}
315
	if($g['booting'])
316
		echo "done.\n";
317
}
318

    
319
function interface_qinq2_configure(&$qinq, $fd, $macaddr) {
320
        global $config, $g;
321

    
322
        if (!is_array($qinq)) {
323
                log_error("QinQ compat VLAN: called with wrong options. Problems with config!\n");
324
                return;
325
        }
326

    
327
        $if = $qinq['if'];
328
        $tag = $qinq['tag'];
329
        $vlanif = "{$if}_{$tag}";
330
        if(empty($if)) {
331
                log_error("interface_qinq_confgure called with if undefined.\n");
332
                return;
333
        }
334

    
335
        fwrite($fd, "shutdown {$if}h{$tag}:\n");
336
        fwrite($fd, "mkpeer {$if}qinq: eiface {$if}{$tag} ether\n");
337
        fwrite($fd, "name {$if}qinq:{$if}{$tag} {$if}h{$tag}\n");
338
        fwrite($fd, "msg {$if}qinq: addfilter { vlan={$tag} hook=\"{$if}{$tag}\" }\n");
339
        fwrite($fd, "msg {$if}h{$tag}: setifname \"{$vlanif}\"\n");
340
        fwrite($fd, "msg {$if}h{$tag}: set {$macaddr}\n");
341

    
342
        /* invalidate interface cache */
343
        get_interface_arr(true);
344

    
345
        return $vlanif;
346
}
347

    
348
function interfaces_create_wireless_clones() {
349
	global $config;
350

    
351
	if($g['booting'])
352
		echo "Creating other wireless clone interfaces...";
353
	if (is_array($config['wireless']['clone']) && count($config['wireless']['clone'])) {
354
		foreach ($config['wireless']['clone'] as $clone) {
355
			if(empty($clone['cloneif']))
356
				continue;
357
			if(does_interface_exist($clone['cloneif']))
358
				continue;
359
			/* XXX: Maybe we should report any errors?! */
360
			if(interface_wireless_clone($clone['cloneif'], $clone))
361
				if($g['booting'])
362
					echo " " . $clone['cloneif'];
363
		}
364
	}
365
	if($g['booting'])
366
		echo " done.\n";
367
}
368

    
369
function interfaces_bridge_configure($checkmember = 0) {
370
        global $config;
371

    
372
        $i = 0;
373
        if (is_array($config['bridges']['bridged']) && count($config['bridges']['bridged'])) {
374
                foreach ($config['bridges']['bridged'] as $bridge) {
375
                        if(empty($bridge['bridgeif']))
376
                                $bridge['bridgeif'] = "bridge{$i}";
377
			if ($checkmember == 1 && (strstr($bridge['members'], "gif") || strstr($bridge['members'], "gre")))
378
				continue;
379
			if ($checkmember == 2 && !strstr($bridge['members'], "gif") && !strstr($bridge['members'], "gre"))
380
				continue;
381
                        /* XXX: Maybe we should report any errors?! */
382
                        interface_bridge_configure($bridge);
383
                        $i++;
384
                }
385
        }
386
}
387

    
388
function interface_bridge_configure(&$bridge) {
389
	global $config, $g;
390

    
391
	if (!is_array($bridge))
392
	        return -1;
393

    
394
	if (empty($bridge['members'])) {
395
		log_error("No members found on {$bridge['bridgeif']}");
396
		return -1;
397
	}
398

    
399
	$members = explode(',', $bridge['members']);
400
	if (!count($members))
401
		return -1;
402

    
403
	$checklist = get_configured_interface_list();
404

    
405
	if ($g['booting'] || !empty($bridge['bridgeif'])) {
406
		pfSense_interface_destroy($bridge['bridgeif']);
407
		pfSense_interface_create($bridge['bridgeif']);
408
		$bridgeif = $bridge['bridgeif'];
409
	} else
410
		$bridgeif = pfSense_interface_create("bridge");
411

    
412
	/* Calculate smaller mtu and enforce it */
413
	$smallermtu = 0;
414
	$commonrx = true;
415
	$commontx = true;
416
	foreach ($members as $member) {
417
		$realif = get_real_interface($member);
418
		$opts = pfSense_get_interface_addresses($realif);
419
		$mtu = $opts['mtu'];
420
		if (!isset($opts['encaps']['txcsum']))
421
			$commontx = false;
422
		if (!isset($opts['encaps']['rxcsum']))
423
			$commonrx = false;
424
		if (!isset($opts['encaps']['tso4']))
425
			$commontso4 = false;
426
		if (!isset($opts['encaps']['tso6']))
427
			$commontso6 = false;
428
		if (!isset($opts['encaps']['lro']))
429
			$commonlro = false;
430
		if ($smallermtu == 0 && !empty($mtu))
431
			$smallermtu = $mtu;
432
		else if (!empty($mtu) && $mtu < $smallermtu)
433
			$smallermtu = $mtu;
434
	}
435
	 
436
	/* Just in case anything is not working well */
437
	if ($smallermtu == 0)
438
		$smallermtu = 1500; 
439

    
440
	$flags = 0;
441
	if ($commonrx === false)
442
		$flags |= IFCAP_RXCSUM;
443
	if ($commontx === false)
444
		$flags |= IFCAP_TXCSUM;
445
	if ($commontso4 === false)
446
		$flags |= IFCAP_TSO4;
447
	if ($commontso6 === false)
448
		$flags |= IFCAP_TSO6;
449
	if ($commonlro === false)
450
		$flags |= IFCAP_LRO;
451
		
452
	/* Add interfaces to bridge */
453
	foreach ($members as $member) {
454
		if (!array_key_exists($member, $checklist))
455
			continue;
456
		$realif1 = get_real_interface($member);
457
		$realif =  escapeshellarg($realif1);
458
		if (!$realif) {
459
			log_error("realif not defined in interfaces bridge - up");
460
			continue;
461
		}
462
		/* make sure the parent interface is up */
463
		pfSense_interface_mtu($realif1, $smallermtu);
464
		pfSense_interface_capabilities($realif1, -$flags);
465
		interfaces_bring_up($realif1);
466
		mwexec("/sbin/ifconfig {$bridgeif} addm {$realif}");	
467
	}
468

    
469
	if (isset($bridge['enablestp'])) {
470
		/* Choose spanning tree proto */
471
		mwexec("/sbin/ifconfig {$bridgeif} proto {$bridge['proto']}");	
472
		
473
		if (!empty($bridge['stp'])) {
474
			$stpifs = explode(',', $bridge['stp']);
475
			foreach ($stpifs as $stpif) {
476
				$realif = get_real_interface($stpif);
477
				mwexec("/sbin/ifconfig {$bridgeif} stp {$realif}");
478
			}
479
		}
480
		if (!empty($bridge['maxage']))
481
			mwexec("/sbin/ifconfig {$bridgeif} maxage {$bridge['maxage']}");
482
		if (!empty($brige['fwdelay']))
483
			mwexec("/sbin/ifconfig {$bridgeif} fwddelay {$bridge['fwdelay']}");
484
		if (!empty($brige['hellotime']))
485
                        mwexec("/sbin/ifconfig {$bridgeif} hellotime {$bridge['hellotime']}");
486
		if (!empty($brige['priority']))
487
                        mwexec("/sbin/ifconfig {$bridgeif} priority {$bridge['priority']}");
488
		if (!empty($brige['holdcount']))
489
                        mwexec("/sbin/ifconfig {$bridgeif} holdcnt {$bridge['holdcnt']}");
490
		if (!empty($bridge['ifpriority'])) {
491
			$pconfig = explode(",", $bridge['ifpriority']);
492
			$ifpriority = array();
493
			foreach ($pconfig as $cfg) {
494
				$embcfg = explode(":", $cfg);
495
				foreach ($embcfg as $key => $value)
496
					$ifpriority[$key] = $value;
497
			}
498
			foreach ($ifpriority as $key => $value) {
499
				$realif = get_real_interface($key);
500
				mwexec("/sbin/ifconfig ${bridgeif} ifpriority {$realif} {$value}"); 
501
			}
502
		}
503
		if (!empty($bridge['ifpathcost'])) {
504
			$pconfig = explode(",", $bridges['ifpathcost']);
505
			$ifpathcost = array();
506
			foreach ($pconfig as $cfg) {
507
				$embcfg = explode(":", $cfg);
508
				foreach ($embcfg as $key => $value)
509
					$ifpathcost[$key] = $value;
510
			}
511
			foreach ($ifpathcost as $key => $value) {
512
                        	$realif = get_real_interface($key);
513
                        	mwexec("/sbin/ifconfig ${bridgeif} ifpathcost {$realif} {$value}");
514
                	}
515
		}
516
	}
517

    
518
	if ($bridge['maxaddr'] <> "")
519
		mwexec("/sbin/ifconfig {$bridgeif} maxaddr {$bridge['maxaddr']}");
520
        if ($bridge['timeout'] <> "")
521
                mwexec("/sbin/ifconfig {$bridgeif} timeout {$bridge['timeout']}");
522
        if ($bridge['span'] <> "") {
523
		$realif = get_real_interface($bridge['span']);
524
                mwexec("/sbin/ifconfig {$bridgeif} span {$realif}");
525
	}
526
	if (!empty($bridge['edge'])) {
527
        	$edgeifs = explode(',', $bridge['edge']);
528
        	foreach ($edgeifs as $edgeif) {
529
			$realif = get_real_interface($edgeif);
530
                	mwexec("/sbin/ifconfig {$bridgeif} edge {$realif}");
531
        	}
532
	}
533
	if (!empty($bridge['autoedge'])) {
534
        	$edgeifs = explode(',', $bridge['autoedge']);
535
        	foreach ($edgeifs as $edgeif) {
536
                	$realif = get_real_interface($edgeif);
537
                	mwexec("/sbin/ifconfig {$bridgeif} -autoedge {$realif}");
538
        	}
539
	}
540
	if (!empty($bridge['ptp'])) {
541
        	$ptpifs = explode(',', $bridge['ptp']);
542
        	foreach ($ptpifs as $ptpif) {
543
                	$realif = get_real_interface($ptpif);
544
                	mwexec("/sbin/ifconfig {$bridgeif} ptp {$realif}");
545
        	}
546
	}
547
	if (!empty($bridge['autoptp'])) {
548
        	$ptpifs = explode(',', $bridge['autoptp']);
549
        	foreach ($ptpifs as $ptpif) {
550
                	$realif = get_real_interface($ptpif);
551
                	mwexec("/sbin/ifconfig {$bridgeif} -autoptp {$realif}");
552
        	}
553
	}
554
	if (!empty($bridge['static'])) {
555
        	$stickyifs = explode(',', $bridge['static']);
556
        	foreach ($stickyifs as $stickyif) {
557
                	$realif = get_real_interface($stickyif);
558
                	mwexec("/sbin/ifconfig {$bridgeif} sticky {$realif}");
559
        	}
560
	}
561
	if (!empty($bridge['private'])) {
562
        	$privateifs = explode(',', $bridge['private']);
563
        	foreach ($privateifs as $privateif) {
564
                	$realif = get_real_interface($privateif);
565
               	 	mwexec("/sbin/ifconfig {$bridgeif} private {$realif}");
566
        	}
567
	}
568

    
569
	if($bridgeif)
570
		interfaces_bring_up($bridgeif);	
571
	else 
572
		log_error("bridgeif not defined -- could not bring interface up");
573

    
574
	return $bridgeif;
575
}
576

    
577
function interface_bridge_add_member($bridgeif, $interface) {
578

    
579
	if (!does_interface_exist($bridgeif) || !does_interface_exist($interface))
580
		return;
581

    
582
	$mtu = get_interface_mtu($brigeif);
583
	$mtum = get_interface_mtu($interface);
584
	
585
	if ($mtu != $mtum)
586
		pfSense_interface_mtu($interface, $mtu);
587

    
588
	$options = pfSense_get_interface_addresses($bridgeif);
589
	$flags = 0;
590
	if (!isset($options['encaps']['txcsum']))
591
		$flags |= IFCAP_TXCSUM;
592

    
593
	if (!isset($options['encaps']['rxcsum']))
594
		$flags |= IFCAP_RXCSUM;
595

    
596
	pfSense_interface_capabilities($interface, -$flags);
597

    
598
	interfaces_bring_up($interface);
599
	mwexec("/sbin/ifconfig {$bridgeif} addm {$interface}");
600
}
601

    
602
function interfaces_lagg_configure() 
603
{
604
        global $config, $g;
605
		if($g['booting']) 
606
			echo "Configuring LAGG interfaces...";
607
        $i = 0;
608
		if (is_array($config['laggs']['lagg']) && count($config['laggs']['lagg'])) {
609
			foreach ($config['laggs']['lagg'] as $lagg) {
610
				if(empty($lagg['laggif']))
611
					$lagg['laggif'] = "lagg{$i}";
612
				/* XXX: Maybe we should report any errors?! */
613
				interface_lagg_configure($lagg);
614
				$i++;
615
			}
616
		}
617
		if($g['booting']) 
618
			echo "done.\n";
619
}
620

    
621
function interface_lagg_configure(&$lagg) {
622
        global $config, $g;
623

    
624
        if (!is_array($lagg))
625
		return -1;
626

    
627
	$members = explode(',', $lagg['members']);
628
	if (!count($members))
629
		return -1;
630
	
631
	$checklist = get_interface_list();
632

    
633
	if ($g['booting'] || !(empty($lagg['laggif']))) {
634
		pfSense_interface_destroy($lagg['laggif']);
635
		pfSense_interface_create($lagg['laggif']);
636
                $laggif = $lagg['laggif'];
637
        } else
638
		$laggif = pfSense_interface_create("lagg");
639

    
640
	/* Calculate smaller mtu and enforce it */
641
        $smallermtu = 0;
642
        foreach ($members as $member) {
643
		$opts = pfSense_get_interface_addresses($member);
644
                $mtu = $opts['mtu'];
645
		if (!isset($opts['encaps']['txcsum']))
646
                        $commontx = false;
647
                if (!isset($opts['encaps']['rxcsum']))
648
                        $commonrx = false;
649
		if (!isset($opts['encaps']['tso4']))
650
			$commontso4 = false;
651
		if (!isset($opts['encaps']['tso6']))
652
			$commontso6 = false;
653
		if (!isset($opts['encaps']['lro']))
654
			$commonlro = false;
655
		if ($smallermtu == 0 && !empty($mtu))
656
			$smallermtu = $mtu;
657
                else if (!empty($mtu) && $mtu < $smallermtu)
658
                        $smallermtu = $mtu;
659
        }
660

    
661
	/* Just in case anything is not working well */
662
        if ($smallermtu == 0)
663
                $smallermtu = 1500;
664

    
665
	$flags = 0;
666
        if ($commonrx === false)
667
                $flags |= IFCAP_RXCSUM;
668
        if ($commontx === false)
669
                $flags |= IFCAP_TXCSUM;
670
	if ($commontso4 === false)
671
                $flags |= IFCAP_TSO4;
672
        if ($commontso6 === false)
673
                $flags |= IFCAP_TSO6;
674
        if ($commonlro === false)
675
                $flags |= IFCAP_LRO;
676

    
677
	foreach ($members as $member) {
678
		if (!array_key_exists($member, $checklist))
679
			continue;
680
		/* make sure the parent interface is up */
681
		pfSense_interface_mtu($member, $smallermtu);
682
		pfSense_interface_capabilities($member, -$flags);
683
		interfaces_bring_up($member);
684
		mwexec("/sbin/ifconfig {$laggif} laggport {$member}");
685
	}
686
	
687
	mwexec("/sbin/ifconfig {$laggif} laggproto {$lagg['proto']}");
688

    
689
	interfaces_bring_up($laggif);
690

    
691
	return $laggif;
692
}
693

    
694
function interfaces_gre_configure($checkparent = 0) {
695
        global $config;
696

    
697
        if (is_array($config['gres']['gre']) && count($config['gres']['gre'])) {
698
                foreach ($config['gres']['gre'] as $i => $gre) {
699
                        if(empty($gre['greif']))
700
                                $gre['greif'] = "gre{$i}";
701
			if ($checkparent == 1 && strstr($gre['if'], "vip"))
702
				continue;
703
			if ($checkparent == 2 && !strstr($gre['if'], "vip"))
704
				continue;
705
                        /* XXX: Maybe we should report any errors?! */
706
                        interface_gre_configure($gre);
707
                }
708
        }
709
}
710

    
711
/* NOTE: $grekey is not used but useful for passing this function to array_walk. */
712
function interface_gre_configure(&$gre, $grekey = "") {
713
        global $config, $g;
714

    
715
	if (!is_array($gre))
716
		return -1;
717

    
718
	$realif = get_real_interface($gre['if']);
719
	$realifip = get_interface_ip($gre['if']);
720

    
721
	/* make sure the parent interface is up */
722
	interfaces_bring_up($realif);
723

    
724
	if ($g['booting'] || !(empty($gre['greif']))) {
725
		pfSense_interface_destroy($gre['greif']);
726
		pfSense_interface_create($gre['greif']);
727
		$greif = $gre['greif'];
728
	} else
729
		$greif = pfSense_interface_create("gre");
730

    
731
	/* Do not change the order here for more see gre(4) NOTES section. */
732
	mwexec("/sbin/ifconfig {$greif} tunnel {$realifip} {$gre['remote-addr']}");
733
	mwexec("/sbin/ifconfig {$greif} {$gre['tunnel-local-addr']} {$gre['tunnel-remote-addr']} netmask " . gen_subnet_mask($gre['tunnel-remote-net']));
734
	if (isset($gre['link0']) && $gre['link0'])
735
		pfSense_interface_flags($greif, IFF_LINK0);
736
	if (isset($gre['link1']) && $gre['link1'])
737
		pfSense_interface_flags($greif, IFF_LINK1);
738
	if (isset($gre['link2']) && $gre['link2'])
739
		pfSense_interface_flags($greif, IFF_LINK2);
740

    
741
	if($greif)
742
		interfaces_bring_up($greif);
743
	else 
744
		log_error("Could not bring greif up -- variable not defined.");
745

    
746
	if (isset($gre['link1']) && $gre['link1'])
747
		mwexec("/sbin/route add {$gre['tunnel-remote-addr']}/{$gre['tunnel-remote-net']} {$gre['tunnel-local-addr']}");
748
	if(is_ipaddrv4($gre['tunnel-remote-addr']))
749
		file_put_contents("{$g['tmp_path']}/{$greif}_router", $gre['tunnel-remote-addr']);
750
	if(is_ipaddrv6($gre['tunnel-remote-addr']))
751
		file_put_contents("{$g['tmp_path']}/{$greif}_routerv6", $gre['tunnel-remote-addr']);
752

    
753
	return $greif;
754
}
755

    
756
function interfaces_gif_configure($checkparent = 0) {
757
	global $config;
758

    
759
	if (is_array($config['gifs']['gif']) && count($config['gifs']['gif'])) {
760
		foreach ($config['gifs']['gif'] as $i => $gif) {
761
			if(empty($gif['gifif']))
762
				$gre['gifif'] = "gif{$i}";
763
			if ($checkparent == 1 && strstr($gif['if'], "vip"))
764
				continue;
765
			if ($checkparent == 2 && !strstr($gif['if'], "vip"))
766
				continue;
767
			/* XXX: Maybe we should report any errors?! */
768
			interface_gif_configure($gif);
769
		}
770
	}
771
}
772

    
773
/* NOTE: $gifkey is not used but useful for passing this function to array_walk. */
774
function interface_gif_configure(&$gif, $gifkey = "") {
775
	global $config, $g;
776

    
777
	if (!is_array($gif))
778
		return -1;
779

    
780
	$realif = get_real_interface($gif['if']);
781
	$realifip = get_interface_ip($gif['if']);
782

    
783
	/* make sure the parent interface is up */
784
	if($realif)
785
		interfaces_bring_up($realif);
786
	else 
787
		log_error("could not bring realif up -- variable not defined -- interface_gif_configure()");
788

    
789
	if ($g['booting'] || !(empty($gif['gifif']))) {
790
		pfSense_interface_destroy($gif['gifif']);
791
		pfSense_interface_create($gif['gifif']);
792
		$gifif = $gif['gifif'];
793
	} else
794
		$gifif = pfSense_interface_create("gif");
795

    
796
	/* Do not change the order here for more see gif(4) NOTES section. */
797
	mwexec("/sbin/ifconfig {$gifif} tunnel {$realifip} {$gif['remote-addr']}");
798
	if((is_ipaddrv6($gif['tunnel-local-addr'])) || (is_ipaddrv6($gif['tunnel-remote-addr']))) {
799
		mwexec("/sbin/ifconfig {$gifif} inet6 {$gif['tunnel-local-addr']} {$gif['tunnel-remote-addr']} prefixlen {$gif['tunnel-remote-net']} ");
800
	} else {
801
		mwexec("/sbin/ifconfig {$gifif} {$gif['tunnel-local-addr']} {$gif['tunnel-remote-addr']} netmask " . gen_subnet_mask($gif['tunnel-remote-net']));
802
	}
803
	if (isset($gif['link0']) && $gif['link0'])
804
		pfSense_interface_flags($gifif, IFF_LINK0);
805
	if (isset($gif['link1']) && $gif['link1'])
806
		pfSense_interface_flags($gifif, IFF_LINK1);
807
	if($gifif)
808
		interfaces_bring_up($gifif);
809
	else
810
		log_error("could not bring gifif up -- variable not defined");
811

    
812
	/* XXX: Needed?! Let them use the defined gateways instead */
813
	//mwexec("/sbin/route add {$gif['tunnel-remote-addr']}/{$gif['tunnel-remote-net']} -iface {$gifif}");
814

    
815
	if(is_ipaddrv4($gif['tunnel-remote-addr']))
816
		file_put_contents("{$g['tmp_path']}/{$gifif}_router", $gif['tunnel-remote-addr']);
817
	if(is_ipaddrv6($gif['tunnel-remote-addr']))
818
		file_put_contents("{$g['tmp_path']}/{$gifif}_routerv6", $gif['tunnel-remote-addr']);
819

    
820
	return $gifif;
821
}
822

    
823
function interfaces_configure() {
824
	global $config, $g;
825

    
826
	/* Set up our loopback interface */
827
	interfaces_loopback_configure();
828

    
829
	/* set up LAGG virtual interfaces */
830
	interfaces_lagg_configure();
831

    
832
	/* set up VLAN virtual interfaces */
833
	interfaces_vlan_configure();
834

    
835
	interfaces_qinq_configure();
836

    
837
	$iflist = get_configured_interface_with_descr();
838
	$delayed_list = array();
839
	$bridge_list = array();
840
	
841
	/* This is needed to speedup interfaces on bootup. */
842
	$reload = false;
843
	if ($g['booting'])
844
		$reload = true;
845

    
846
	foreach($iflist as $if => $ifname) {
847
		$realif = $config['interfaces'][$if]['if'];
848
		if (strstr($realif, "bridge")) 
849
			$bridge_list[$if] = $ifname;
850
		else if (strstr($realif, "gre"))
851
			$delayed_list[$if] = $ifname;
852
		else if (strstr($realif, "gif"))
853
			$delayed_list[$if] = $ifname;
854
		else if (strstr($realif, "ovpn")) {
855
			//echo "Delaying OpenVPN interface configuration...done.\n";
856
			continue;
857
		} else {
858
			if ($g['booting'])
859
				echo "Configuring {$ifname} interface...";
860
			if($g['debug'])
861
				log_error("Configuring {$ifname}");
862
			interface_configure($if, $reload);
863
			if ($g['booting']) 
864
				echo "done.\n";
865
		}
866
	}
867

    
868
	/* create the unconfigured wireless clones */
869
	interfaces_create_wireless_clones();
870

    
871
	/*
872
	 * NOTE: The following function parameter consists of
873
	 *	1 - Do not load gre/gif/bridge with parent/member as vip
874
	 *	2 - Do load gre/gif/bridge with parent/member as vip
875
	 */
876

    
877
	/* set up GRE virtual interfaces */
878
	interfaces_gre_configure(1);
879

    
880
	/* set up GIF virtual interfaces */
881
	interfaces_gif_configure(1);
882

    
883
	/* set up BRIDGe virtual interfaces */
884
	interfaces_bridge_configure(1);
885

    
886
	/* bring up vip interfaces */
887
	interfaces_vips_configure();
888

    
889
	/* set up GRE virtual interfaces */
890
	interfaces_gre_configure(2);
891

    
892
	/* set up GIF virtual interfaces */
893
	interfaces_gif_configure(2);
894

    
895
	foreach ($delayed_list as $if => $ifname) {
896
		if ($g['booting'])
897
			echo "Configuring {$ifname} interface...";
898
        	if ($g['debug'])
899
        		log_error("Configuring {$ifname}");
900

    
901
		interface_configure($if, $reload);
902

    
903
		if ($g['booting'])
904
			echo "done.\n";
905
	}
906

    
907
	/* set up BRIDGe virtual interfaces */
908
	interfaces_bridge_configure(2);
909

    
910
	foreach ($bridge_list as $if => $ifname) {
911
		if ($g['booting'])
912
			echo "Configuring {$ifname} interface...";
913
		if($g['debug'])
914
			log_error("Configuring {$ifname}");
915

    
916
		interface_configure($if, $reload);
917

    
918
		if ($g['booting'])
919
			echo "done.\n";
920
	}
921

    
922
	/* configure interface groups */
923
	interfaces_group_setup();
924

    
925
	if (!$g['booting']) {
926
		/* reconfigure static routes (kernel may have deleted them) */
927
		system_routing_configure();
928

    
929
		/* reload IPsec tunnels */
930
		vpn_ipsec_configure();
931

    
932
		/* reload dhcpd (interface enabled/disabled status may have changed) */
933
		services_dhcpd_configure();
934

    
935
		/* restart dnsmasq */
936
		services_dnsmasq_configure();
937

    
938
		/* reload captive portal */
939
		captiveportal_init_rules();
940
	}
941

    
942
	return 0;
943
}
944

    
945
function interface_reconfigure($interface = "wan") {
946
	interface_bring_down($interface);
947
	interface_configure($interface, true);
948
}
949

    
950
function interface_vip_bring_down($vip) {
951
	global $g;
952

    
953
	switch ($vip['mode']) {
954
	case "proxyarp":
955
		$vipif = get_real_interface($vip['interface']);
956
		if (file_exists("{$g['varrun_path']}/choparp_{$vipif}.pid"))
957
			killbypid("{$g['varrun_path']}/choparp_{$vipif}.pid");
958
		break;
959
	case "ipalias":
960
		$vipif = get_real_interface($vip['interface']);
961
		if(does_interface_exist($vipif))
962
			pfSense_interface_deladdress($vipif, $vip['subnet']);
963
		break;
964
	case "carp":
965
		$vipif = "vip" . $vip['vhid'];
966
		if(does_interface_exist($vipif)) 
967
			pfSense_interface_destroy($vipif);
968
		break;
969
	case "carpdev-dhcp":
970
		$vipif = "vip" . $vip['vhid'];
971
		if(does_interface_exist($vipif)) 
972
			pfSense_interface_destroy($vipif);
973
		break;
974
	}
975
}
976

    
977
function interface_bring_down($interface = "wan", $destroy = false) {
978
	global $config, $g;
979

    
980
	if (!isset($config['interfaces'][$interface]))
981
		return; 
982

    
983
	$ifcfg = $config['interfaces'][$interface];
984

    
985
	$realif = get_real_interface($interface);
986

    
987
	switch ($ifcfg['ipaddr']) {
988
	case "ppp":
989
	case "pppoe":
990
	case "pptp":
991
	case "l2tp":
992
		if (is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) {
993
			foreach ($config['ppps']['ppp'] as $pppid => $ppp) {
994
				if ($realif == $ppp['if']) {
995
					if (isset($ppp['ondemand']) && !$destroy){
996
						send_event("interface reconfigure {$interface}");
997
						break;
998
					}
999
					if (file_exists("{$g['varrun_path']}/{$ppp['type']}_{$interface}.pid")) {
1000
						killbypid("{$g['varrun_path']}/{$ppp['type']}_{$interface}.pid");
1001
						sleep(2);
1002
					}
1003
					unlink_if_exists("{$g['varetc_path']}/mpd_{$interface}.conf");
1004
					break;
1005
				}
1006
			}
1007
		}
1008
		break;
1009
	case "carpdev-dhcp":
1010
		/* 
1011
		 * NB: When carpdev gets enabled it would be better to be handled as all
1012
		 *	   other interfaces! 
1013
		 */
1014
	case "dhcp":
1015
		$pid = find_dhclient_process($realif);
1016
		if($pid)
1017
			mwexec("/bin/kill {$pid}");
1018
		$pidv6 = find_dhcp6c_process($realif);
1019
		if($pidv6)
1020
			mwexec("/bin/kill {$pidv6}");
1021
		sleep(1);
1022
		unlink_if_exists("{$g['varetc_path']}/dhclient_{$interface}.conf");
1023
		unlink_if_exists("{$g['varetc_path']}/dhcp6c_{$interface}.conf");
1024
		if(does_interface_exist("$realif")) {
1025
			mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete", true);
1026
			if ($destroy == true)
1027
				pfSense_interface_flags($realif, -IFF_UP);
1028
			mwexec("/usr/sbin/arp -d -i {$realif} -a");
1029
		}
1030
		break;
1031
	default:
1032
		if(does_interface_exist("$realif")) {
1033
			mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete", true);
1034
			if ($destroy == true)
1035
				pfSense_interface_flags($realif, -IFF_UP);
1036
			mwexec("/usr/sbin/arp -d -i {$realif} -a");
1037
		}
1038
		break;
1039
	}
1040

    
1041
	/* remove interface up file if it exists */
1042
	unlink_if_exists("{$g['tmp_path']}/{$realif}up");
1043
	unlink_if_exists("{$g['vardb_path']}/{$interface}ip");
1044
	unlink_if_exists("{$g['vardb_path']}/{$interface}ipv6");
1045
	unlink_if_exists("{$g['tmp_path']}/{$realif}_router");
1046
	unlink_if_exists("{$g['tmp_path']}/{$realif}_routerv6");
1047
	unlink_if_exists("{$g['varetc_path']}/nameserver_{$realif}");
1048
	unlink_if_exists("{$g['varetc_path']}/searchdomain_{$realif}");
1049
	
1050
	/* hostapd and wpa_supplicant do not need to be running when the interface is down.
1051
	 * They will also use 100% CPU if running after the wireless clone gets deleted. */
1052
	if (is_array($ifcfg['wireless'])) {
1053
		mwexec(kill_hostapd($realif));
1054
		mwexec(kill_wpasupplicant($realif));
1055
	}
1056

    
1057
	if ($destroy == true) {
1058
		if (preg_match("/^vip|^tun|^ovpn|^gif|^gre|^lagg|^bridge|vlan/i", $realif))
1059
			pfSense_interface_destroy($realif);
1060
	}	
1061

    
1062
	return;
1063
}
1064

    
1065
function interfaces_ptpid_used($ptpid) {
1066
	global $config;
1067

    
1068
	if (is_array($config['ppps']['ppp']))
1069
		foreach ($config['ppps']['ppp'] as & $settings)
1070
			if ($ptpid == $settings['ptpid'])
1071
				return true;
1072

    
1073
	return false;
1074
}
1075

    
1076
function interfaces_ptpid_next() {
1077

    
1078
	$ptpid = 0;
1079
	while(interfaces_ptpid_used($ptpid))
1080
		$ptpid++;
1081

    
1082
	return $ptpid;
1083
}
1084

    
1085
function getMPDCRONSettings($pppif_) {
1086
	global $config;
1087
	$cron_cmd_file = "{$g['varetc_path']}/pppoe_restart_";
1088
	if (is_array($config['cron']['item'])) {
1089
		for ($i = 0; $i < count($config['cron']['item']); $i++) {
1090
			$item = $config['cron']['item'][$i];
1091
			if (strpos($item['command'], $cron_cmd_file.$pppif_) !== false) {
1092
				return array("ID" => $i, "ITEM" => $item);
1093
			}
1094
		}
1095
	}
1096
	return NULL;
1097
}
1098

    
1099
function handle_pppoe_reset($post_array) {
1100
	global $config, $g;
1101

    
1102
	$cron_cmd_file = "{$g['varetc_path']}/pppoe_restart_";
1103

    
1104
	$pppif = $post_array['type'].$post_array['ptpid'];
1105
	if (!is_array($config['cron']['item'])) 
1106
		$config['cron']['item'] = array(); 
1107
	$itemhash = getMPDCRONSettings($pppif);
1108
	$item = $itemhash['ITEM'];
1109
	
1110
	// reset cron items if necessary and return
1111
	if (empty($post_array['pppoe-reset-type'])) {
1112
		if (isset($item))
1113
			unset($config['cron']['item'][$itemhash['ID']]);
1114
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
1115
		return;
1116
	}
1117

    
1118
	if (empty($item)) 
1119
		$item = array();
1120
	if (isset($post_array['pppoe-reset-type']) && $post_array['pppoe-reset-type'] == "custom") {
1121
		$item['minute'] = $post_array['pppoe_resetminute'];
1122
		$item['hour'] = $post_array['pppoe_resethour'];
1123
		if (isset($post_array['pppoe_resetdate']) && $post_array['pppoe_resetdate'] <> "") {
1124
			$date = explode("/", $post_array['pppoe_resetdate']);
1125
			$item['mday'] = $date[1];
1126
			$item['month'] = $date[0];
1127
		} else {
1128
			$item['mday'] = "*";
1129
			$item['month'] = "*";
1130
		}
1131
		$item['wday'] = "*";
1132
		$item['who'] = "root";
1133
		$item['command'] = $cron_cmd_file.$pppif;
1134
	} else if (isset($post_array['pppoe-reset-type']) && $post_array['pppoe-reset-type'] == "preset") {
1135
		switch ($post_array['pppoe_pr_preset_val']) {
1136
			case "monthly":
1137
				$item['minute'] = "0";
1138
				$item['hour'] = "0";
1139
				$item['mday'] = "1";
1140
				$item['month'] = "*";
1141
				$item['wday'] = "*";
1142
				$item['who'] = "root";
1143
				$item['command'] = $cron_cmd_file.$pppif;
1144
				break;
1145
	        case "weekly":
1146
				$item['minute'] = "0";
1147
				$item['hour'] = "0";
1148
				$item['mday'] = "*";
1149
				$item['month'] = "*";
1150
				$item['wday'] = "0";
1151
				$item['who'] = "root";
1152
				$item['command'] = $cron_cmd_file.$pppif;
1153
				break;
1154
			case "daily":
1155
				$item['minute'] = "0";
1156
				$item['hour'] = "0";
1157
				$item['mday'] = "*";
1158
				$item['month'] = "*";
1159
				$item['wday'] = "*";
1160
				$item['who'] = "root";
1161
				$item['command'] = $cron_cmd_file.$pppif;
1162
				break;
1163
			case "hourly":
1164
				$item['minute'] = "0";
1165
				$item['hour'] = "*";
1166
				$item['mday'] = "*";
1167
				$item['month'] = "*";
1168
				$item['wday'] = "*";
1169
				$item['who'] = "root";
1170
				$item['command'] = $cron_cmd_file.$pppif;
1171
				break;
1172
		} // end switch
1173
	} else {
1174
		/* test whether a cron item exists and unset() it if necessary */
1175
		$itemhash = getMPDCRONSettings($pppif);
1176
		$item = $itemhash['ITEM'];
1177
		if (isset($item))
1178
			unset($config['cron']['item'][$itemhash['ID']]); 
1179
	}// end if
1180
	if (isset($itemhash['ID'])) 
1181
		$config['cron']['item'][$itemhash['ID']] = $item;
1182
	else 
1183
		$config['cron']['item'][] = $item;
1184
}
1185

    
1186
/*	This function can configure PPPoE, MLPPP (PPPoE), PPTP.
1187
*	It writes the mpd config file to /var/etc every time the link is opened.
1188
*/
1189

    
1190
function interface_ppps_configure($interface) {
1191
	global $config, $g;
1192

    
1193
	/* Return for unassigned interfaces. This is a minimum requirement. */
1194
	if (empty($config['interfaces'][$interface]))
1195
		return 0;
1196
	$ifcfg = $config['interfaces'][$interface];
1197
	if (!isset($ifcfg['enable']))
1198
		return 0;
1199

    
1200
	// mpd5 requires a /var/spool/lock directory for PPP modem links.
1201
	if(!is_dir("/var/spool/lock")) {
1202
		exec("/bin/mkdir -p /var/spool/lock");
1203
		exec("/bin/chmod a+rw /var/spool/lock/.");
1204
	}
1205
	// mpd5 modem chat script expected in the same directory as the mpd_xxx.conf files	
1206
	if (!file_exists("{$g['varetc_path']}/mpd.script"))
1207
		mwexec("/bin/ln -s /usr/local/sbin/mpd.script {$g['varetc_path']}/.");
1208

    
1209
	if (is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) {
1210
		foreach ($config['ppps']['ppp'] as $pppid => $ppp) {
1211
			if ($ifcfg['if'] == $ppp['if'])
1212
				break;
1213
		}
1214
	}
1215
	if (!$ppp || $ifcfg['if'] != $ppp['if']){
1216
		log_error("Can't find PPP config for {$ifcfg['if']} in interface_ppps_configure().");
1217
		return 0;
1218
	}
1219
	$pppif = $ifcfg['if'];
1220
	if ($ppp['type'] == "ppp")
1221
		$type = "modem";
1222
	else
1223
		$type = $ppp['type'];
1224
	$upper_type = strtoupper($ppp['type']);	
1225

    
1226
	if($g['booting']) {
1227
		$descr = isset($ifcfg['descr']) ? $ifcfg['descr'] : strtoupper($interface);
1228
		echo "starting {$pppif} link...";
1229
		// Do not re-configure the interface if we are booting and it's already been started
1230
		if(file_exists("{$g['varrun_path']}/{$ppp['type']}_{$interface}.pid"))
1231
			return 0;
1232
	}
1233

    
1234
	$ports = explode(',',$ppp['ports']);
1235
	if ($type != "modem") {
1236
		foreach ($ports as $pid => $port)
1237
			$ports[$pid] = get_real_interface($port);
1238
	}
1239
	$localips = explode(',',$ppp['localip']);
1240
	$gateways = explode(',',$ppp['gateway']);
1241
	$subnets = explode(',',$ppp['subnet']);
1242

    
1243
	/* We bring up the parent interface first because if DHCP is configured on the parent we need
1244
	 * to obtain an address first so we can write it in the mpd .conf file for PPTP and L2TP configs
1245
	 */
1246
	foreach($ports as $pid => $port){
1247
		switch ($ppp['type']) {
1248
			case "pppoe": 
1249
				/* Bring the parent interface up */
1250
				interfaces_bring_up($port);
1251
				pfSense_ngctl_attach(".", $port);
1252
				break;
1253
			case "pptp":
1254
			case "l2tp":
1255
				/* configure interface */
1256
				if(is_ipaddr($localips[$pid])){
1257
					// Manually configure interface IP/subnet
1258
					pfSense_interface_setaddress($port, "{$localips[$pid]}/{$subnets[$pid]}");
1259
					interfaces_bring_up($port);
1260
				} else if (empty($localips[$pid]))
1261
					$localips[$pid] = get_interface_ip($port); // try to get the interface IP from the port
1262
				
1263
				if(!is_ipaddr($localips[$pid])){
1264
					log_error("Could not get a Local IP address for PPTP/L2TP link on {$port} in interfaces_ppps_configure. Using 0.0.0.0 ip!");
1265
					$localips[$pid] = "0.0.0.0";
1266
				}
1267
				/* XXX: This needs to go away soon! [It's commented out!] */
1268
				/* Configure the gateway (remote IP ) */
1269
				if (!$g['booting'] && !is_ipaddr($gateways[$pid]) && is_hostname($gateways[$pid])) {
1270
					/* XXX: Fix later 
1271
					$gateways[$pid] = gethostbyname($gateways[$pid]);
1272
					if(!is_ipaddr($gateways[$pid])) {
1273
						log_error("Could not get a valid Gateway IP from {$port} via DNS in interfaces_ppps_configure.");
1274
						return 0;
1275
					}
1276
					*/
1277
				}
1278
				if(!is_ipaddr($gateways[$pid])){
1279
					log_error("Could not get a PPTP/L2TP Remote IP address from {$dhcp_gateway} for {$gway} in interfaces_ppps_configure.");
1280
					return 0;
1281
				}
1282
				pfSense_ngctl_attach(".", $port);
1283
				break;
1284
			case "ppp":
1285
				if (!file_exists("{$port}")) {
1286
					log_error("Device {$port} does not exist. PPP link cannot start without the modem device.");
1287
					return 0;
1288
				}
1289
				break;
1290
			default:
1291
				log_error("Unkown {$type} configured as ppp interface.");
1292
				break;
1293
		}
1294
	}
1295
	
1296
	if (is_array($ports) && count($ports) > 1)
1297
		$multilink = "enable";
1298
	else
1299
		$multilink = "disable";
1300
	
1301
	if ($type == "modem"){
1302
		if (is_ipaddr($ppp['localip']))
1303
			$localip = $ppp['localip'];
1304
		else
1305
			$localip = '0.0.0.0';
1306

    
1307
		if (is_ipaddr($ppp['gateway']))
1308
			$gateway = $ppp['gateway'];
1309
		else
1310
			$gateway = "10.64.64.{$pppid}";
1311
		$ranges = "{$localip}/0 {$gateway}/0";
1312
		
1313
		if (empty($ppp['apnum']))	
1314
			$ppp['apnum'] = 1;
1315
	} else
1316
		$ranges = "0.0.0.0/0 0.0.0.0/0";
1317

    
1318
	if (isset($ppp['ondemand'])) 
1319
		$ondemand = "enable";
1320
	else
1321
		$ondemand = "disable";
1322
	if (!isset($ppp['idletimeout']))
1323
		$ppp['idletimeout'] = 0;
1324

    
1325
	if (empty($ppp['username']) && $type == "modem"){
1326
		$ppp['username'] = "user";
1327
		$ppp['password'] = "none";
1328
	}
1329
	if (empty($ppp['password']) && $type == "modem")
1330
		$passwd = "none";
1331
	else
1332
		$passwd = base64_decode($ppp['password']);
1333

    
1334
	$bandwidths = explode(',',$ppp['bandwidth']);
1335
	$mtus = explode(',',$ppp['mtu']);
1336
	$mrus = explode(',',$ppp['mru']);
1337

    
1338
	if (isset($ppp['mrru']))
1339
		$mrrus = explode(',',$ppp['mrru']);
1340

    
1341
	// Construct the mpd.conf file
1342
	$mpdconf = <<<EOD
1343
startup:
1344
	# configure the console
1345
	set console close
1346
	# configure the web server
1347
	set web close
1348

    
1349
default:
1350
{$ppp['type']}client:
1351
	create bundle static {$interface}
1352
	set bundle enable ipv6cp
1353
	set iface name {$pppif}
1354

    
1355
EOD;
1356
	$setdefaultgw = false;
1357
	$founddefaultgw = false;
1358
	if (is_array($config['gateways']['gateway_item'])) {
1359
		foreach($config['gateways']['gateway_item'] as $gateway) {
1360
			if($interface == $gateway['interface'] && isset($gateway['defaultgw'])) {
1361
				$setdefaultgw = true;
1362
				break;
1363
			} else if (isset($gateway['defaultgw']) && !empty($gateway['interface'])) {
1364
				$founddefaultgw = true;
1365
				break;
1366
			}
1367
		}
1368
	}
1369
	
1370
	if (($interface == "wan" && $founddefaultgw == false) || $setdefaultgw == true){
1371
		$setdefaultgw = true;
1372
		$mpdconf .= <<<EOD
1373
	set iface route default
1374

    
1375
EOD;
1376
	}
1377
	$mpdconf .= <<<EOD
1378
	set iface {$ondemand} on-demand
1379
	set iface idle {$ppp['idletimeout']}
1380

    
1381
EOD;
1382

    
1383
	if (isset($ppp['ondemand']))
1384
		$mpdconf .= <<<EOD
1385
	set iface addrs 10.10.1.1 10.10.1.2
1386

    
1387
EOD;
1388
	
1389
	if (isset($ppp['tcpmssfix']))
1390
		$tcpmss = "disable";
1391
	else
1392
		$tcpmss = "enable";
1393
		$mpdconf .= <<<EOD
1394
	set iface {$tcpmss} tcpmssfix
1395

    
1396
EOD;
1397

    
1398
	$mpdconf .= <<<EOD
1399
	set iface up-script /usr/local/sbin/ppp-linkup
1400
	set iface down-script /usr/local/sbin/ppp-linkdown
1401
	set ipcp ranges {$ranges}
1402

    
1403
EOD;
1404
	if (isset($ppp['vjcomp']))
1405
		$mpdconf .= <<<EOD
1406
	set ipcp no vjcomp
1407

    
1408
EOD;
1409

    
1410
	if (isset($config['system']['dnsallowoverride']))
1411
		$mpdconf .= <<<EOD
1412
	set ipcp enable req-pri-dns
1413
	set ipcp enable req-sec-dns
1414

    
1415
EOD;
1416
	if (!isset($ppp['verbose_log']))
1417
		$mpdconf .= <<<EOD
1418
	#log -bund -ccp -chat -iface -ipcp -lcp -link
1419

    
1420
EOD;
1421
	foreach($ports as $pid => $port){
1422
		$port = get_real_interface($port);
1423
		$mpdconf .= <<<EOD
1424

    
1425
	create link static {$interface}_link{$pid} {$type}
1426
	set link action bundle {$interface}
1427
	set link {$multilink} multilink
1428
	set link keep-alive 10 60
1429
	set link max-redial 0
1430

    
1431
EOD;
1432
		if (isset($ppp['shortseq']))
1433
			$mpdconf .= <<<EOD
1434
	set link no shortseq
1435

    
1436
EOD;
1437

    
1438
		if (isset($ppp['acfcomp']))
1439
			$mpdconf .= <<<EOD
1440
	set link no acfcomp
1441

    
1442
EOD;
1443

    
1444
		if (isset($ppp['protocomp']))
1445
			$mpdconf .= <<<EOD
1446
	set link no protocomp
1447

    
1448
EOD;
1449

    
1450
		$mpdconf .= <<<EOD
1451
	set link disable chap pap
1452
	set link accept chap pap eap
1453
	set link disable incoming
1454

    
1455
EOD;
1456

    
1457

    
1458
		if (!empty($bandwidths[$pid]))
1459
			$mpdconf .= <<<EOD
1460
	set link bandwidth {$bandwidths[$pid]}
1461

    
1462
EOD;
1463

    
1464
		if (empty($mtus[$pid]))
1465
			$mtus[$pid] = "1492";
1466
			$mpdconf .= <<<EOD
1467
	set link mtu {$mtus[$pid]}
1468

    
1469
EOD;
1470

    
1471
		if (!empty($mrus[$pid]))
1472
			$mpdconf .= <<<EOD
1473
	set link mru {$mrus[$pid]}
1474

    
1475
EOD;
1476

    
1477
		if (!empty($mrrus[$pid]))
1478
			$mpdconf .= <<<EOD
1479
	set link mrru {$mrrus[$pid]}
1480

    
1481
EOD;
1482

    
1483
		$mpdconf .= <<<EOD
1484
	set auth authname "{$ppp['username']}"
1485
	set auth password {$passwd}
1486

    
1487
EOD;
1488
		if ($type == "modem") {
1489
			$mpdconf .= <<<EOD
1490
	set modem device {$ppp['ports']}
1491
	set modem script DialPeer
1492
	set modem idle-script Ringback
1493
	set modem watch -cd
1494
	set modem var \$DialPrefix "DT"
1495
	set modem var \$Telephone "{$ppp['phone']}"
1496

    
1497
EOD;
1498
		}
1499
		if (isset($ppp['connect-timeout']) && $type == "modem") {
1500
			$mpdconf .= <<<EOD
1501
	set modem var \$ConnectTimeout "{$ppp['connect-timeout']}"
1502

    
1503
EOD;
1504
		}
1505
		if (isset($ppp['initstr']) && $type == "modem") {
1506
			$initstr = base64_decode($ppp['initstr']);
1507
			$mpdconf .= <<<EOD
1508
	set modem var \$InitString "{$initstr}"
1509

    
1510
EOD;
1511
		}
1512
		if (isset($ppp['simpin']) && $type == "modem") {
1513
			$mpdconf .= <<<EOD
1514
	set modem var \$SimPin "{$ppp['simpin']}"
1515
	set modem var \$PinWait "{$ppp['pin-wait']}"
1516

    
1517
EOD;
1518
		}
1519
		if (isset($ppp['apn']) && $type == "modem") {
1520
			$mpdconf .= <<<EOD
1521
	set modem var \$APN "{$ppp['apn']}"
1522
	set modem var \$APNum "{$ppp['apnum']}"
1523

    
1524
EOD;
1525
		}
1526
		if (isset($ppp['provider']) && $type == "pppoe") {
1527
			$mpdconf .= <<<EOD
1528
	set pppoe service "{$ppp['provider']}"
1529

    
1530
EOD;
1531
		}
1532
		if ($type == "pppoe")
1533
			$mpdconf .= <<<EOD
1534
	set pppoe iface {$port}
1535

    
1536
EOD;
1537

    
1538
		if ($type == "pptp" || $type == "l2tp") {
1539
			$mpdconf .= <<<EOD
1540
	set {$type} self {$localips[$pid]}
1541
	set {$type} peer {$gateways[$pid]}
1542

    
1543
EOD;
1544
		}
1545
		
1546
		$mpdconf .= "\topen\r\n";
1547
	} //end foreach($port)
1548

    
1549

    
1550
	/* Generate mpd.conf. If mpd_[interface].conf exists in the conf path, then link to it instead of generating a fresh conf file. */
1551
	if (file_exists("{$g['conf_path']}/mpd_{$interface}.conf"))
1552
		mwexec("/bin/ln -s {$g['conf_path']}/mpd_{$interface}.conf {$g['varetc_path']}/.");
1553
	else {
1554
		$fd = fopen("{$g['varetc_path']}/mpd_{$interface}.conf", "w");
1555
		if (!$fd) {
1556
			log_error("Error: cannot open mpd_{$interface}.conf in interface_ppps_configure().\n");
1557
			return 0;
1558
		}
1559
		// Write out mpd_ppp.conf
1560
		fwrite($fd, $mpdconf);
1561
		fclose($fd);
1562
	}
1563

    
1564
	// Create the uptime log if requested and if it doesn't exist already, or delete it if it is no longer requested.
1565
	if (isset($ppp['uptime'])) {
1566
		if (!file_exists("/conf/{$pppif}.log")) {
1567
			conf_mount_rw();
1568
			mwexec("echo /dev/null > /conf/{$pppif}.log");
1569
			conf_mount_ro();
1570
		}
1571
	} else {
1572
		if (file_exists("/conf/{$pppif}.log")) {
1573
			conf_mount_rw();
1574
			mwexec("rm -f /conf/{$pppif}.log");
1575
			conf_mount_ro();
1576
		}
1577
	}
1578

    
1579
	/* fire up mpd */
1580
	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");
1581

    
1582
	// Check for PPPoE periodic reset request 
1583
	if ($type == "pppoe") {
1584
		if (isset($ppp['pppoe-reset-type']))
1585
			setup_pppoe_reset_file($ppp['if'], $interface);
1586
		else
1587
			setup_pppoe_reset_file($ppp['if']);
1588
	}
1589

    
1590
	return 1;
1591
}
1592

    
1593
function interfaces_carp_setup() {
1594
	global $g, $config;
1595

    
1596
	$balanacing = "";
1597
	$pfsyncinterface = "";
1598
	$pfsyncenabled = "";
1599
	if(isset($config['system']['developerspew'])) {
1600
		$mt = microtime();
1601
		echo "interfaces_carp_setup() being called $mt\n";
1602
	}
1603

    
1604
	// Prepare CmdCHAIN that will be used to execute commands.
1605
	$cmdchain = new CmdCHAIN();	
1606

    
1607
	if ($g['booting']) {
1608
		echo "Configuring CARP settings...";
1609
		mute_kernel_msgs();
1610
	}
1611

    
1612
	/* suck in configuration items */
1613
	if($config['installedpackages']['carpsettings']) {
1614
		if($config['installedpackages']['carpsettings']['config']) {
1615
			foreach($config['installedpackages']['carpsettings']['config'] as $carp) {
1616
				$pfsyncenabled = $carp['pfsyncenabled'];
1617
				$balanacing = $carp['balancing'];
1618
				$pfsyncinterface = $carp['pfsyncinterface'];
1619
				$pfsyncpeerip = $carp['pfsyncpeerip'];
1620
			}
1621
		}
1622
	} else {
1623
		unset($pfsyncinterface);
1624
		unset($balanacing);
1625
		unset($pfsyncenabled);
1626
	}
1627

    
1628
	if($balanacing) {
1629
		$cmdchain->add("Enable CARP ARP-balancing", "/sbin/sysctl net.inet.carp.arpbalance=1", true);
1630
		$cmdchain->add("Disallow CARP preemption", "/sbin/sysctl net.inet.carp.preempt=0", true);
1631
	} else
1632
		$cmdchain->add("Enable CARP preemption", "/sbin/sysctl net.inet.carp.preempt=1", true);		
1633

    
1634
	$cmdchain->add("Enable CARP logging", "/sbin/sysctl net.inet.carp.log=1", true);
1635
	if (!empty($pfsyncinterface))
1636
		$carp_sync_int = get_real_interface($pfsyncinterface);
1637

    
1638
	if($g['booting']) {
1639
		/*    install rules to alllow pfsync to sync up during boot
1640
		 *    carp interfaces will remain down until the bootup sequence finishes
1641
		 */
1642
		$fd = fopen("{$g['tmp_path']}/rules.boot", "w");
1643
		if ($fd) {
1644
			fwrite($fd, "block quick proto carp \n");
1645
			fwrite($fd, "block quick proto pfsync \n");
1646
			fwrite($fd, "pass out quick from any to any keep state\n");
1647
			fclose($fd);
1648
			mwexec("/sbin/pfctl -f {$g['tmp_path']}/rules.boot");
1649
		} else
1650
			log_error("Could not create rules.boot file!");
1651
	}
1652

    
1653
	/* setup pfsync interface */
1654
	if($carp_sync_int and $pfsyncenabled) {
1655
		if (is_ipaddr($pfsyncpeerip))
1656
			$cmdchain->add("Bring up pfsync0 syncpeer", "/sbin/ifconfig pfsync0 syncdev {$carp_sync_int} syncpeer {$pfsyncpeerip} up", false);						
1657
		else
1658
			$cmdchain->add("Bring up pfsync0 syncdev", "/sbin/ifconfig pfsync0 syncdev {$carp_sync_int} up", false);			
1659
	} else
1660
		$cmdchain->add("Bring up pfsync0", "/sbin/ifconfig pfsync0 syncdev lo0 up", false);						
1661

    
1662
	if($config['virtualip']['vip'])
1663
		$cmdchain->add("Allow CARP.", "/sbin/sysctl net.inet.carp.allow=1", true);				
1664
	else
1665
		$cmdchain->add("Disallow CARP.", "/sbin/sysctl net.inet.carp.allow=0", true);		
1666
	
1667
	if($g['debug'])
1668
		$cmdchain->setdebug(); // optional for verbose logging
1669

    
1670
	$cmdchain->execute();
1671
	$cmdchain->clear();
1672

    
1673
	if ($g['booting']) {
1674
		unmute_kernel_msgs();
1675
		echo "done.\n";
1676
	}
1677
}
1678

    
1679
function interface_proxyarp_configure($interface = "") {
1680
	global $config, $g;
1681
	if(isset($config['system']['developerspew'])) {
1682
		$mt = microtime();
1683
		echo "interface_proxyarp_configure() being called $mt\n";
1684
	}
1685

    
1686
	/* kill any running choparp */
1687
	if (empty($interface))
1688
		killbyname("choparp");
1689
	else {
1690
		$vipif = get_real_interface($interface);
1691
		if (file_exists("{$g['varrun_path']}/choparp_{$vipif}.pid"))
1692
			killbypid("{$g['varrun_path']}/choparp_{$vipif}.pid");
1693
	}
1694

    
1695
	$paa = array();
1696
	if (!empty($config['virtualip']) && is_array($config['virtualip']['vip'])) {
1697

    
1698
		/* group by interface */
1699
		foreach ($config['virtualip']['vip'] as $vipent) {
1700
			if ($vipent['mode'] === "proxyarp") {
1701
				if ($vipent['interface'])
1702
					$proxyif = $vipent['interface'];
1703
				else
1704
					$proxyif = "wan";
1705
				
1706
				if (!empty($interface) && $interface != $proxyif)
1707
					continue;
1708

    
1709
				if (!is_array($paa[$proxyif]))
1710
					$paa[$proxyif] = array();
1711

    
1712
				$paa[$proxyif][] = $vipent;
1713
			}
1714
		}
1715
	}
1716

    
1717
	if (!empty($interface)) {
1718
		if (is_array($paa[$interface])) {
1719
			$paaifip = get_interface_ip($interface);
1720
                        if (!is_ipaddr($paaifip))
1721
                                return;
1722
                        $args = get_real_interface($interface) . " auto";
1723
                        foreach ($paa[$interface] as $paent) {
1724
                                if (isset($paent['subnet']))
1725
                                        $args .= " " . escapeshellarg("{$paent['subnet']}/{$paent['subnet_bits']}");
1726
                                else if (isset($paent['range']))
1727
                                        $args .= " " . escapeshellarg($paent['range']['from'] . "-" . $paent['range']['to']);
1728
                        }
1729
                        mwexec_bg("/usr/local/sbin/choparp " . $args);	
1730
		}
1731
	} else if (count($paa) > 0) {
1732
		foreach ($paa as $paif => $paents)  {
1733
			$paaifip = get_interface_ip($paif);
1734
			if (!is_ipaddr($paaifip))
1735
				continue;
1736
			$args = get_real_interface($paif) . " auto";
1737
			foreach ($paents as $paent) {
1738
				if (isset($paent['subnet']))
1739
					$args .= " " . escapeshellarg("{$paent['subnet']}/{$paent['subnet_bits']}");
1740
				else if (isset($paent['range']))
1741
					$args .= " " . escapeshellarg($paent['range']['from'] . "-" . $paent['range']['to']);
1742
			}
1743
			mwexec_bg("/usr/local/sbin/choparp " . $args);
1744
		}
1745
	}
1746
}
1747

    
1748
function interfaces_vips_configure($interface = "") {
1749
	global $g, $config;
1750
	if(isset($config['system']['developerspew'])) {
1751
		$mt = microtime();
1752
		echo "interfaces_vips_configure() being called $mt\n";
1753
	}
1754
	$paa = array();
1755
	if(is_array($config['virtualip']['vip'])) {
1756
		$carp_setuped = false;
1757
		$anyproxyarp = false;
1758
		foreach ($config['virtualip']['vip'] as $vip) {
1759
			switch ($vip['mode']) {
1760
			case "proxyarp":
1761
				/* nothing it is handled on interface_proxyarp_configure() */
1762
				if ($interface <> "" && $vip['interface'] <> $interface)
1763
					continue;
1764
				$anyproxyarp = true;
1765
				break;
1766
			case "ipalias":
1767
				if ($interface <> "" && $vip['interface'] <> $interface)
1768
					continue;
1769
				interface_ipalias_configure(&$vip);
1770
				break;
1771
			case "carp":
1772
				if ($interface <> "" && $vip['interface'] <> $interface)
1773
					continue;
1774
				if ($carp_setuped == false)
1775
					$carp_setuped = true;
1776
				interface_carp_configure($vip);
1777
				break;
1778
			case "carpdev-dhcp":
1779
				if ($interface <> "" && $vip['interface'] <> $interface)
1780
					continue;
1781
				interface_carpdev_configure($vip);
1782
				break;
1783
			}
1784
		}
1785
		if ($carp_setuped == true)
1786
			interfaces_carp_setup();
1787
		if ($anyproxyarp == true)
1788
			interface_proxyarp_configure();
1789
	}
1790
}
1791

    
1792
function interface_ipalias_configure(&$vip) {
1793

    
1794
	if ($vip['mode'] == "ipalias") {
1795
		$if = get_real_interface($vip['interface']);
1796
		mwexec("/sbin/ifconfig " . escapeshellarg($if) . " " . $vip['subnet'] . "/" . escapeshellarg($vip['subnet_bits']) . " alias");
1797
	}
1798
}
1799

    
1800
function interface_reload_carps($cif) {
1801
	global $config;
1802

    
1803
	$carpifs = link_ip_to_carp_interface(find_interface_ip($cif));
1804
	if (empty($carpifs))
1805
		return;
1806

    
1807
	$carps = explode(" ", $carpifs);
1808
	if(is_array($config['virtualip']['vip'])) {
1809
		$viparr = &$config['virtualip']['vip'];
1810
		foreach ($viparr as $vip) {
1811
			if (in_array($vip['carpif'], $carps)) {
1812
				switch ($vip['mode']) {
1813
				case "carp":
1814
					interface_vip_bring_down($vip);
1815
					sleep(1);
1816
					interface_carp_configure($vip);
1817
					break;
1818
				case "carpdev-dhcp":
1819
					interface_vip_bring_down($vip);
1820
					sleep(1);
1821
					interface_carpdev_configure($vip);
1822
					break;
1823
				case "ipalias":
1824
					interface_vip_bring_down($vip);
1825
					sleep(1);
1826
					interface_ipalias_configure($vip);
1827
					break;
1828
				}
1829
			}
1830
		}
1831
	}
1832
}
1833

    
1834
function interface_carp_configure(&$vip) {
1835
	global $config, $g;
1836
	if(isset($config['system']['developerspew'])) {
1837
		$mt = microtime();
1838
		echo "interface_carp_configure() being called $mt\n";
1839
	}
1840

    
1841
	if ($vip['mode'] != "carp")
1842
		return;
1843

    
1844
	$vip_password = $vip['password'];
1845
	$vip_password = escapeshellarg(addslashes(str_replace(" ", "", $vip_password)));
1846
	if ($vip['password'] != "")
1847
		$password = " pass {$vip_password}";
1848

    
1849
	// set the vip interface to the vhid
1850
	$vipif = "vip{$vip['vhid']}";
1851

    
1852
	/*
1853
	 * ensure the interface containing the VIP really exists
1854
 	 * prevents a panic if the interface is missing or invalid
1855
	 */
1856
	$realif = get_real_interface($vip['interface']);
1857
	if (!does_interface_exist($realif)) {
1858
		file_notice("CARP", "Interface specified for the virtual IP address {$vip['subnet']} does not exist. Skipping this VIP.", "Firewall: Virtual IP", "");
1859
		return;
1860
	}
1861

    
1862
	if(is_ipaddrv4($vip['subnet'])) {
1863
		/* Ensure CARP IP really exists prior to loading up. */
1864
		$ww_subnet_ip = find_interface_ip($realif);
1865
		$ww_subnet_bits = find_interface_subnet($realif);
1866
		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'])) {
1867
			file_notice("CARP", "Sorry but we could not find a matching real interface subnet for the virtual IP address {$vip['subnet']}.", "Firewall: Virtual IP", "");
1868
			return;
1869
		}
1870
	}
1871
	if(is_ipaddrv6($vip['subnet'])) {
1872
		/* Ensure CARP IP really exists prior to loading up. */
1873
		$ww_subnet_ip = find_interface_ipv6($realif);
1874
		$ww_subnet_bits = find_interface_subnetv6($realif);
1875
		if (!ip_in_subnet($vip['subnet'], gen_subnetv6($ww_subnet_ip, $ww_subnet_bits) . "/" . $ww_subnet_bits) && !ip_in_interface_alias_subnet($vip['interface'], $vip['subnet'])) {
1876
			file_notice("CARP", "Sorry but we could not find a matching real interface subnet for the virtual IPv6 address {$vip['subnet']}.", "Firewall: Virtual IP", "");
1877
			return;
1878
		}
1879
	}
1880

    
1881
	/* create the carp interface and setup */
1882
	if (does_interface_exist($vipif)) {
1883
		pfSense_interface_flags($vipif, -IFF_UP);
1884
	} else {
1885
		$carpif = pfSense_interface_create("carp");
1886
		pfSense_interface_rename($carpif, $vipif);
1887
		pfSense_ngctl_name("{$carpif}:", $vipif);
1888
	}
1889

    
1890
	/* invalidate interface cache */
1891
	get_interface_arr(true);
1892

    
1893
	$advbase = "";
1894
	if (!empty($vip['advbase']))
1895
		$advbase = "advbase {$vip['advbase']}";
1896

    
1897
	if(is_ipaddrv4($vip['subnet'])) {
1898
		$broadcast_address = gen_subnet_max($vip['subnet'], $vip['subnet_bits']);
1899
		mwexec("/sbin/ifconfig {$vipif} {$vip['subnet']}/{$vip['subnet_bits']} vhid {$vip['vhid']} advskew {$vip['advskew']} {$advbase} {$password}");
1900
	}
1901
	if(is_ipaddrv6($vip['subnet'])) {
1902
		$broadcast_address = gen_subnet_max($vip['subnet'], $vip['subnet_bits']);
1903
		mwexec("/sbin/ifconfig {$vipif} inet6 {$vip['subnet']} prefixlen {$vip['subnet_bits']} vhid {$vip['vhid']} advskew {$vip['advskew']} {$advbase} {$password}");
1904
	}
1905

    
1906
	interfaces_bring_up($vipif);
1907
	
1908
	return $vipif;
1909
}
1910

    
1911
function interface_carpdev_configure(&$vip) {
1912
	global $g;
1913

    
1914
	if ($vip['mode'] != "carpdev-dhcp")
1915
		return;
1916

    
1917
	$vip_password = $vip['password'];
1918
	$vip_password = str_replace(" ", "", $vip_password);
1919
	if($vip['password'] != "")
1920
		$password = " pass \"" . $vip_password . "\"";
1921

    
1922
	if (empty($vip['interface']))
1923
		return;
1924

    
1925
	$vipif = "vip" . $vip['vhid'];
1926
	$realif = get_real_interface($vip['interface']);
1927
	interfaces_bring_up($realif);
1928
	/*
1929
	 * ensure the interface containing the VIP really exists
1930
	 * prevents a panic if the interface is missing or invalid
1931
	 */
1932
	if (!does_interface_exist($realif)) {
1933
		file_notice("CARP", "Interface specified for the virtual IP address {$vip['subnet']} does not exist. Skipping this VIP.", "Firewall: Virtual IP", "");
1934
		return;
1935
	}
1936

    
1937
	if (does_interface_exist($vipif)) {
1938
		interface_bring_down($vipif);
1939
	} else {
1940
		$carpdevif = exec("/sbin/ifconfig carp create");
1941
		mwexec("/sbin/ifconfig {$carpdevif} name {$vipif}");
1942
		pfSense_ngctl_name("{$carpdevif}:", $vipif);
1943
	}
1944

    
1945
	mwexec("/sbin/ifconfig {$vipif} carpdev {$realif} vhid {$vip['vhid']} advskew {$vip['advskew']} advbase {$vip['advbase']} {$password}");
1946
	interfaces_bring_up($vipif);
1947

    
1948
	/*
1949
	 * XXX: BIG HACK but carpdev needs ip services active
1950
	 *      before even starting something as dhclient.
1951
	 *      I do not know if this is a feature or a bug
1952
	 *      but better than track it make it work ;) .
1953
	 */
1954
	//$fakeiptouse = "10.254.254." . ($carp_instances_counter+1);
1955
	//$cmdchain->add("CarpDEV hack", "/sbin/ifconfig {$carpint} inet {$fakeiptouse}", false);
1956

    
1957
	/* generate dhclient_wan.conf */
1958
	$fd = fopen("{$g['varetc_path']}/dhclient_{$vipif}.conf", "w");
1959
	if ($fd) {
1960
		$dhclientconf = "";
1961

    
1962
		$dhclientconf .= <<<EOD
1963
interface "{$vipif}" {
1964
timeout 60;
1965
retry 1;
1966
select-timeout 0;
1967
initial-interval 1;
1968
script "/sbin/dhclient-script";
1969
}
1970

    
1971
EOD;
1972

    
1973
		fwrite($fd, $dhclientconf);
1974
		fclose($fd);
1975

    
1976
		/* fire up dhclient */
1977
		mwexec("/sbin/dhclient -c {$g['varetc_path']}/dhclient_{$vipif}.conf {$vipif} >{$g['tmp_path']}/{$vipif}_output 2>{$g['tmp_path']}/{$vipif}_error_output", false);
1978
	} else {
1979
		log_error("Error: cannot open dhclient_{$vipif}.conf in interfaces_carpdev_configure() for writing.\n");
1980
		mwexec("/sbin/dhclient -b {$vipif}");
1981
	}
1982

    
1983
	return $vipif;
1984
}
1985

    
1986
function interface_wireless_clone($realif, $wlcfg) {
1987
	global $config, $g;
1988
	/*   Check to see if interface has been cloned as of yet.  
1989
	 *   If it has not been cloned then go ahead and clone it.
1990
	 */
1991
	$needs_clone = false;
1992
	if(is_array($wlcfg['wireless']))
1993
		$wlcfg_mode = $wlcfg['wireless']['mode'];
1994
	else
1995
		$wlcfg_mode = $wlcfg['mode'];
1996
	switch($wlcfg_mode) {
1997
		 case "hostap":
1998
			$mode = "wlanmode hostap";
1999
			break;
2000
		 case "adhoc":
2001
			$mode = "wlanmode adhoc";
2002
			break;
2003
		 default:
2004
			$mode = "";
2005
			break;
2006
	}
2007
	$baseif = interface_get_wireless_base($wlcfg['if']);
2008
	if(does_interface_exist($realif)) {
2009
		exec("/sbin/ifconfig {$realif}", $output, $ret);
2010
		$ifconfig_str = implode($output);
2011
		if(($wlcfg_mode == "hostap") && (! preg_match("/hostap/si", $ifconfig_str))) {
2012
			log_error("Interface {$realif} changed to hostap mode");
2013
			$needs_clone = true;
2014
		}
2015
		if(($wlcfg_mode == "adhoc") && (! preg_match("/adhoc/si", $ifconfig_str))) {
2016
			log_error("Interface {$realif} changed to adhoc mode");
2017
			$needs_clone = true;
2018
		}
2019
		if(($wlcfg_mode == "bss") && (preg_match("/hostap|adhoc/si", $ifconfig_str))) {
2020
			log_error("Interface {$realif} changed to infrastructure mode");
2021
			$needs_clone = true;
2022
		}
2023
	} else {
2024
		$needs_clone = true;
2025
	}
2026

    
2027
	if($needs_clone == true) {
2028
		/* remove previous instance if it exists */
2029
		if(does_interface_exist($realif))
2030
			pfSense_interface_destroy($realif);
2031

    
2032
		log_error("Cloning new wireless interface {$realif}");
2033
		// Create the new wlan interface. FreeBSD returns the new interface name.
2034
		// example:  wlan2
2035
		exec("/sbin/ifconfig wlan create wlandev {$baseif} {$mode} bssid 2>&1", $out, $ret);
2036
		if($ret <> 0) {
2037
			log_error("Failed to clone interface {$baseif} with error code {$ret}, output {$out[0]}");
2038
			return false;
2039
		}
2040
		$newif = trim($out[0]);
2041
		// Rename the interface to {$parentnic}_wlan{$number}#: EX: ath0_wlan0
2042
		pfSense_interface_rename($newif, $realif);
2043
		// FIXME: not sure what ngctl is for. Doesn't work.
2044
		// mwexec("/usr/sbin/ngctl name {$newif}: {$realif}", false);
2045
		file_put_contents("{$g['tmp_path']}/{$realif}_oldmac", get_interface_mac($realif));
2046
	}
2047
	return true;
2048
}
2049

    
2050
function interface_sync_wireless_clones(&$ifcfg, $sync_changes = false) {
2051
	global $config, $g;
2052

    
2053
	$shared_settings = array('standard', 'turbo', 'protmode', 'txpower', 'channel',
2054
	                         'diversity', 'txantenna', 'rxantenna', 'distance',
2055
	                         'regdomain', 'regcountry', 'reglocation');
2056

    
2057
	if(!is_interface_wireless($ifcfg['if']))
2058
		return;
2059

    
2060
	$baseif = interface_get_wireless_base($ifcfg['if']);
2061

    
2062
	// Sync shared settings for assigned clones
2063
	$iflist = get_configured_interface_list(false, true);
2064
	foreach ($iflist as $if) {
2065
		if ($baseif == interface_get_wireless_base($config['interfaces'][$if]['if']) && $ifcfg['if'] != $config['interfaces'][$if]['if']) {
2066
			if (isset($config['interfaces'][$if]['wireless']['standard']) || $sync_changes) {
2067
				foreach ($shared_settings as $setting) {
2068
					if ($sync_changes) {
2069
						if (isset($ifcfg['wireless'][$setting]))
2070
							$config['interfaces'][$if]['wireless'][$setting] = $ifcfg['wireless'][$setting];
2071
						else if (isset($config['interfaces'][$if]['wireless'][$setting]))
2072
							unset($config['interfaces'][$if]['wireless'][$setting]);
2073
					} else {
2074
						if (isset($config['interfaces'][$if]['wireless'][$setting]))
2075
							$ifcfg['wireless'][$setting] = $config['interfaces'][$if]['wireless'][$setting];
2076
						else if (isset($ifcfg['wireless'][$setting]))
2077
							unset($ifcfg['wireless'][$setting]);
2078
					}
2079
				}
2080
				if (!$sync_changes)
2081
					break;
2082
			}
2083
		}
2084
	}
2085

    
2086
	// Read or write settings at shared area
2087
	if (isset($config['wireless']['interfaces'][$baseif])) {
2088
		foreach ($shared_settings as $setting) {
2089
			if ($sync_changes) {
2090
				if (isset($ifcfg['wireless'][$setting]))
2091
					$config['wireless']['interfaces'][$baseif][$setting] = $ifcfg['wireless'][$setting];
2092
				else if (isset($config['wireless']['interfaces'][$baseif][$setting]))
2093
					unset($config['wireless']['interfaces'][$baseif][$setting]);
2094
			} else if (isset($config['wireless']['interfaces'][$baseif][$setting])) {
2095
				if (isset($config['wireless']['interfaces'][$baseif][$setting]))
2096
					$ifcfg['wireless'][$setting] = $config['wireless']['interfaces'][$baseif][$setting];
2097
				else if (isset($ifcfg['wireless'][$setting]))
2098
					unset($ifcfg['wireless'][$setting]);
2099
			}
2100
		}
2101
	}
2102

    
2103
	// Sync the mode on the clone creation page with the configured mode on the interface
2104
	if (interface_is_wireless_clone($ifcfg['if'])) {
2105
		foreach ($config['wireless']['clone'] as &$clone) {
2106
			if ($clone['cloneif'] == $ifcfg['if']) {
2107
				if ($sync_changes) {
2108
					$clone['mode'] = $ifcfg['wireless']['mode'];
2109
				} else {
2110
					$ifcfg['wireless']['mode'] = $clone['mode'];
2111
				}
2112
				break;
2113
			}
2114
		}
2115
		unset($clone);
2116
	}
2117
}
2118

    
2119
function interface_wireless_configure($if, &$wl, &$wlcfg) {
2120
	global $config, $g;
2121

    
2122
	/*    open up a shell script that will be used to output the commands.
2123
	 *    since wireless is changing a lot, these series of commands are fragile
2124
     *    and will sometimes need to be verified by a operator by executing the command
2125
     *    and returning the output of the command to the developers for inspection.  please
2126
     *    do not change this routine from a shell script to individul exec commands.  -sullrich
2127
	 */
2128

    
2129
	// Remove script file
2130
	unlink_if_exists("{$g['tmp_path']}/{$if}_setup.sh");
2131

    
2132
	// Clone wireless nic if needed.
2133
	interface_wireless_clone($if, $wl);
2134

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

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

    
2142
	/* set values for /path/program */
2143
	$hostapd = "/usr/sbin/hostapd";
2144
	$wpa_supplicant = "/usr/sbin/wpa_supplicant";
2145
	$ifconfig = "/sbin/ifconfig";
2146
	$sysctl = "/sbin/sysctl";
2147
	$killall = "/usr/bin/killall";
2148

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

    
2151
	$wlcmd = array();
2152
	$wl_sysctl = array();
2153
	/* Make sure it's up */
2154
	$wlcmd[] = "up";
2155
	/* Set a/b/g standard */
2156
	$standard = str_replace(" Turbo", "", $wlcfg['standard']);
2157
	$wlcmd[] = "mode " . escapeshellarg($standard);
2158

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

    
2164
	/* Set ssid */
2165
	if($wlcfg['ssid'])
2166
		$wlcmd[] = "ssid " .escapeshellarg($wlcfg['ssid']);
2167

    
2168
	/* Set 802.11g protection mode */
2169
	$wlcmd[] = "protmode " . escapeshellarg($wlcfg['protmode']);
2170

    
2171
	/* set wireless channel value */
2172
	if(isset($wlcfg['channel'])) {
2173
		if($wlcfg['channel'] == "0") {
2174
			$wlcmd[] = "channel any";
2175
		} else {
2176
			$wlcmd[] = "channel " . escapeshellarg($wlcfg['channel']);
2177
		}
2178
	}
2179

    
2180
	/* Set antenna diversity value */
2181
	if(isset($wlcfg['diversity']))
2182
		$wl_sysctl[] = "diversity=" . escapeshellarg($wlcfg['diversity']);
2183

    
2184
	/* Set txantenna value */
2185
	if(isset($wlcfg['txantenna']))
2186
		$wl_sysctl[] = "txantenna=" . escapeshellarg($wlcfg['txantenna']);
2187

    
2188
	/* Set rxantenna value */
2189
	if(isset($wlcfg['rxantenna']))
2190
		$wl_sysctl[] = "rxantenna=" . escapeshellarg($wlcfg['rxantenna']);
2191

    
2192
	/* set Distance value */
2193
	if($wlcfg['distance'])
2194
		$distance = escapeshellarg($wlcfg['distance']);
2195

    
2196
	/* Set wireless hostap mode */
2197
	if ($wlcfg['mode'] == "hostap") {
2198
		$wlcmd[] = "mediaopt hostap";
2199
	} else {
2200
		$wlcmd[] = "-mediaopt hostap";
2201
	}
2202

    
2203
	/* Set wireless adhoc mode */
2204
	if ($wlcfg['mode'] == "adhoc") {
2205
		$wlcmd[] = "mediaopt adhoc";
2206
	} else {
2207
		$wlcmd[] = "-mediaopt adhoc";
2208
	}
2209

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

    
2212
	/* handle hide ssid option */
2213
	if(isset($wlcfg['hidessid']['enable'])) {
2214
		$wlcmd[] = "hidessid";
2215
	} else {
2216
		$wlcmd[] = "-hidessid";
2217
	}
2218

    
2219
	/* handle pureg (802.11g) only option */
2220
	if(isset($wlcfg['pureg']['enable'])) {
2221
		$wlcmd[] = "mode 11g pureg";
2222
	} else {
2223
		$wlcmd[] = "-pureg";
2224
	}
2225

    
2226
	/* handle puren (802.11n) only option */
2227
	if(isset($wlcfg['puren']['enable'])) {
2228
		$wlcmd[] = "puren";
2229
	} else {
2230
		$wlcmd[] = "-puren";
2231
	}
2232

    
2233
	/* enable apbridge option */
2234
	if(isset($wlcfg['apbridge']['enable'])) {
2235
		$wlcmd[] = "apbridge";
2236
	} else {
2237
		$wlcmd[] = "-apbridge";
2238
	}
2239

    
2240
	/* handle turbo option */
2241
	if(isset($wlcfg['turbo']['enable'])) {
2242
		$wlcmd[] = "mediaopt turbo";
2243
	} else {
2244
		$wlcmd[] = "-mediaopt turbo";
2245
	}
2246

    
2247
	/* handle txpower setting */
2248
	/* if($wlcfg['txpower'] <> "")
2249
		$wlcmd[] = "txpower " . escapeshellarg($wlcfg['txpower']);
2250
	*/
2251
	/* handle wme option */
2252
	if(isset($wlcfg['wme']['enable'])) {
2253
		$wlcmd[] = "wme";
2254
	} else {
2255
		$wlcmd[] = "-wme";
2256
	}
2257

    
2258
	/* set up wep if enabled */
2259
	$wepset = "";
2260
	if (isset($wlcfg['wep']['enable']) && is_array($wlcfg['wep']['key'])) {
2261
		switch($wlcfg['wpa']['auth_algs']) {
2262
			case "1":
2263
				$wepset .= "authmode open wepmode on ";
2264
				break;
2265
			case "2":
2266
				$wepset .= "authmode shared wepmode on ";
2267
				break;
2268
			case "3":
2269
				$wepset .= "authmode mixed wepmode on ";
2270
		}
2271
		$i = 1;
2272
		foreach ($wlcfg['wep']['key'] as $wepkey) {
2273
			$wepset .= "wepkey " . escapeshellarg("{$i}:{$wepkey['value']}") . " ";
2274
			if (isset($wepkey['txkey'])) {
2275
				$wlcmd[] = "weptxkey {$i} ";
2276
			}
2277
			$i++;
2278
		}
2279
		$wlcmd[] = $wepset;
2280
	} else {
2281
		$wlcmd[] = "authmode open wepmode off ";
2282
	}
2283

    
2284
	mwexec(kill_hostapd("{$if}"));
2285
	mwexec(kill_wpasupplicant("{$if}"));
2286

    
2287
	/* generate wpa_supplicant/hostap config if wpa is enabled */
2288
	conf_mount_rw();
2289

    
2290
	switch ($wlcfg['mode']) {
2291
		case 'bss':
2292
			if (isset($wlcfg['wpa']['enable'])) {
2293
				$wpa .= <<<EOD
2294
ctrl_interface={$g['varrun_path']}/wpa_supplicant
2295
ctrl_interface_group=0
2296
ap_scan=1
2297
#fast_reauth=1
2298
network={
2299
ssid="{$wlcfg['ssid']}"
2300
scan_ssid=1
2301
priority=5
2302
key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
2303
psk="{$wlcfg['wpa']['passphrase']}"
2304
pairwise={$wlcfg['wpa']['wpa_pairwise']}
2305
group={$wlcfg['wpa']['wpa_pairwise']}
2306
}
2307
EOD;
2308

    
2309
				$fd = fopen("{$g['varetc_path']}/wpa_supplicant_{$if}.conf", "w");
2310
				fwrite($fd, "{$wpa}");
2311
				fclose($fd);
2312
			}
2313
			break;
2314
		case 'hostap':
2315
			if($wlcfg['wpa']['passphrase']) 
2316
				$wpa_passphrase = "wpa_passphrase={$wlcfg['wpa']['passphrase']}\n";
2317
			else 
2318
				$wpa_passphrase = "";
2319
			if (isset($wlcfg['wpa']['enable'])) {
2320
				$wpa .= <<<EOD
2321
interface={$if}
2322
driver=bsd
2323
logger_syslog=-1
2324
logger_syslog_level=0
2325
logger_stdout=-1
2326
logger_stdout_level=0
2327
dump_file={$g['tmp_path']}/hostapd_{$if}.dump
2328
ctrl_interface={$g['varrun_path']}/hostapd
2329
ctrl_interface_group=wheel
2330
#accept_mac_file={$g['tmp_path']}/hostapd_{$if}.accept
2331
#deny_mac_file={$g['tmp_path']}/hostapd_{$if}.deny
2332
#macaddr_acl={$wlcfg['wpa']['macaddr_acl']}
2333
ssid={$wlcfg['ssid']}
2334
debug={$wlcfg['wpa']['debug_mode']}
2335
auth_algs={$wlcfg['wpa']['auth_algs']}
2336
wpa={$wlcfg['wpa']['wpa_mode']}
2337
wpa_key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
2338
wpa_pairwise={$wlcfg['wpa']['wpa_pairwise']}
2339
wpa_group_rekey={$wlcfg['wpa']['wpa_group_rekey']}
2340
wpa_gmk_rekey={$wlcfg['wpa']['wpa_gmk_rekey']}
2341
wpa_strict_rekey={$wlcfg['wpa']['wpa_strict_rekey']}
2342
{$wpa_passphrase}
2343

    
2344
EOD;
2345

    
2346
if (isset($wlcfg['wpa']['rsn_preauth'])) {
2347
	$wpa .= <<<EOD
2348
# Enable the next lines for preauth when roaming. Interface = wired or wireless interface talking to the AP you want to roam from/to
2349
rsn_preauth=1
2350
rsn_preauth_interfaces={$if}
2351

    
2352
EOD;
2353

    
2354
}
2355
				if($wlcfg['auth_server_addr'] && $wlcfg['auth_server_shared_secret']) {
2356
					$auth_server_port = "1812";
2357
					if($wlcfg['auth_server_port']) 
2358
						$auth_server_port = $wlcfg['auth_server_port'];
2359
					$wpa .= <<<EOD
2360

    
2361
ieee8021x=1
2362
auth_server_addr={$wlcfg['auth_server_addr']}
2363
auth_server_port={$auth_server_port}
2364
auth_server_shared_secret={$wlcfg['auth_server_shared_secret']}
2365

    
2366
EOD;
2367
				} else {
2368
					$wpa .= "ieee8021x={$wlcfg['wpa']['ieee8021x']}\n";
2369
				}
2370

    
2371
				$fd = fopen("{$g['varetc_path']}/hostapd_{$if}.conf", "w");
2372
				fwrite($fd, "{$wpa}");
2373
				fclose($fd);
2374

    
2375
			}
2376
			break;
2377
	}
2378

    
2379
	/*
2380
	 *    all variables are set, lets start up everything
2381
	 */
2382

    
2383
	$baseif = interface_get_wireless_base($if);
2384
	preg_match("/^(.*?)([0-9]*)$/", $baseif, $baseif_split);
2385
	$wl_sysctl_prefix = 'dev.' . $baseif_split[1] . '.' . $baseif_split[2];
2386

    
2387
	/* set sysctls for the wireless interface */
2388
	if (!empty($wl_sysctl)) {
2389
		fwrite($fd_set, "# sysctls for {$baseif}\n");
2390
		foreach ($wl_sysctl as $wl_sysctl_line) {
2391
			fwrite($fd_set, "{$sysctl} {$wl_sysctl_prefix}.{$wl_sysctl_line}\n");
2392
		}
2393
	}
2394

    
2395
	/* set ack timers according to users preference (if he/she has any) */
2396
	if($distance) {
2397
		fwrite($fd_set, "# Enable ATH distance settings\n");
2398
		fwrite($fd_set, "/sbin/athctrl.sh -i {$baseif} -d {$distance}\n");
2399
	}
2400

    
2401
	if (isset($wlcfg['wpa']['enable'])) {
2402
		if ($wlcfg['mode'] == "bss") {
2403
			fwrite($fd_set, "{$wpa_supplicant} -B -i {$if} -c {$g['varetc_path']}/wpa_supplicant_{$if}.conf\n");
2404
		}
2405
		if ($wlcfg['mode'] == "hostap") {
2406
			/* add line to script to restore old mac to make hostapd happy */
2407
			if (file_exists("{$g['tmp_path']}/{$if}_oldmac")) {
2408
				$if_oldmac = file_get_contents("{$g['tmp_path']}/{$if}_oldmac");
2409
				if (is_macaddr($if_oldmac))
2410
					fwrite($fd_set, "{$ifconfig} " . escapeshellarg($if) .
2411
						" link " . escapeshellarg($if_oldmac) . "\n");
2412
			}
2413

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

    
2416
			/* add line to script to restore spoofed mac after running hostapd */
2417
			if (file_exists("{$g['tmp_path']}/{$if}_oldmac")) {
2418
				if ($wl['spoofmac'])
2419
					$if_curmac = $wl['spoofmac'];
2420
				else
2421
					$if_curmac = get_interface_mac($if);
2422
				if (is_macaddr($if_curmac))
2423
					fwrite($fd_set, "{$ifconfig} " . escapeshellarg($if) .
2424
						" link " . escapeshellarg($if_curmac) . "\n");
2425
			}
2426
		}
2427
	}
2428

    
2429
	fclose($fd_set);
2430
	conf_mount_ro();
2431

    
2432
	/* Making sure regulatory settings have actually changed
2433
	 * before applying, because changing them requires bringing
2434
	 * down all wireless networks on the interface. */
2435
	exec("{$ifconfig} " . escapeshellarg($if), $output);
2436
	$ifconfig_str = implode($output);
2437
	unset($output);
2438
	$reg_changing = false;
2439

    
2440
	/* special case for the debug country code */
2441
	if ($wlcfg['regcountry'] == 'DEBUG' && !preg_match("/\sregdomain\s+DEBUG\s/si", $ifconfig_str))
2442
		$reg_changing = true;
2443
	else if ($wlcfg['regdomain'] && !preg_match("/\sregdomain\s+{$wlcfg['regdomain']}\s/si", $ifconfig_str))
2444
		$reg_changing = true;
2445
	else if ($wlcfg['regcountry'] && !preg_match("/\scountry\s+{$wlcfg['regcountry']}\s/si", $ifconfig_str))
2446
		$reg_changing = true;
2447
	else if ($wlcfg['reglocation'] == 'anywhere' && preg_match("/\s(indoor|outdoor)\s/si", $ifconfig_str))
2448
		$reg_changing = true;
2449
	else if ($wlcfg['reglocation'] && $wlcfg['reglocation'] != 'anywhere' && !preg_match("/\s{$wlcfg['reglocation']}\s/si", $ifconfig_str))
2450
		$reg_changing = true;
2451

    
2452
	if ($reg_changing) {
2453
		/* set regulatory domain */
2454
		if($wlcfg['regdomain'])
2455
			$wlregcmd[] = "regdomain " . escapeshellarg($wlcfg['regdomain']);
2456

    
2457
		/* set country */
2458
		if($wlcfg['regcountry'])
2459
			$wlregcmd[] = "country " . escapeshellarg($wlcfg['regcountry']);
2460

    
2461
		/* set location */
2462
		if($wlcfg['reglocation'])
2463
			$wlregcmd[] = escapeshellarg($wlcfg['reglocation']);
2464

    
2465
		$wlregcmd_args = implode(" ", $wlregcmd);
2466

    
2467
		/* build a complete list of the wireless clones for this interface */
2468
		$clone_list = array();
2469
		if (does_interface_exist(interface_get_wireless_clone($baseif)))
2470
			$clone_list[] = interface_get_wireless_clone($baseif);
2471
		if (is_array($config['wireless']['clone'])) {
2472
			foreach ($config['wireless']['clone'] as $clone) {
2473
				if ($clone['if'] == $baseif)
2474
					$clone_list[] = $clone['cloneif'];
2475
			}
2476
		}
2477

    
2478
		/* find which clones are up and bring them down */
2479
		$clones_up = array();
2480
		foreach ($clone_list as $clone_if) {
2481
			$clone_status = pfSense_get_interface_addresses($clone_if);
2482
			if ($clone_status['status'] == 'up') {
2483
				$clones_up[] = $clone_if;
2484
				mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " down");
2485
			}
2486
		}
2487

    
2488
		/* apply the regulatory settings */
2489
		mwexec("{$ifconfig} " . escapeshellarg($if) . " {$wlregcmd_args}");
2490

    
2491
		/* bring the clones back up that were previously up */
2492
		foreach ($clones_up as $clone_if) {
2493
			mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " up");
2494

    
2495
			/*
2496
			 * Rerun the setup script for the interface if it isn't this interface, the interface
2497
			 * is in infrastructure mode, and WPA is enabled.
2498
			 * This can be removed if wpa_supplicant stops dying when you bring the interface down.
2499
			 */
2500
			if ($clone_if != $if) {
2501
				$friendly_if = convert_real_interface_to_friendly_interface_name($clone_if);
2502
				if ( !empty($friendly_if)
2503
				    && $config['interfaces'][$friendly_if]['wireless']['mode'] == "bss"
2504
				    && isset($config['interfaces'][$friendly_if]['wireless']['wpa']['enable']) ) {
2505
					mwexec("/bin/sh {$g['tmp_path']}/{$clone_if}_setup.sh");
2506
				}
2507
			}
2508
		}
2509
	}
2510

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

    
2515
	/* configure wireless */
2516
	$wlcmd_args = implode(" ", $wlcmd);
2517
	mwexec("/sbin/ifconfig {$if} $wlcmd_args", false);
2518

    
2519
	
2520
	sleep(1);
2521
	/* execute hostapd and wpa_supplicant if required in shell */
2522
	mwexec("/bin/sh {$g['tmp_path']}/{$if}_setup.sh");
2523

    
2524
	return 0;
2525

    
2526
}
2527

    
2528
function kill_hostapd($interface) {
2529
	return "/bin/pkill -f \"hostapd .*{$interface}\"\n";
2530
}
2531

    
2532
function kill_wpasupplicant($interface) {
2533
	return "/bin/pkill -f \"wpa_supplicant .*{$interface}\"\n";
2534
}
2535

    
2536
function find_dhclient_process($interface) {
2537
	if ($interface)
2538
		$pid = `/bin/pgrep -axf "dhclient: {$interface}"`;
2539
	else
2540
		$pid = 0;
2541

    
2542
	return intval($pid);
2543
}
2544

    
2545
function find_dhcp6c_process($interface) {
2546
	if ($interface)
2547
		$pid = `/bin/pgrep -axf "dhcp6c" |grep  "{$interface}"`;
2548
	else
2549
		$pid = 0;
2550

    
2551
	return intval($pid);
2552
}
2553

    
2554
function interface_configure($interface = "wan", $reloadall = false, $linkupevent = false) {
2555
	global $config, $g;
2556
	global $interface_sn_arr_cache, $interface_ip_arr_cache;
2557
	global $interface_snv6_arr_cache, $interface_ipv6_arr_cache;
2558

    
2559
	$wancfg = $config['interfaces'][$interface];
2560

    
2561
	$realif = get_real_interface($interface);
2562
	$realhwif_array = get_parent_interface($interface);
2563
	// Need code to handle MLPPP if we ever use $realhwif for MLPPP handling
2564
	$realhwif = $realhwif_array[0];
2565

    
2566
			
2567
	if (!$g['booting'] && !substr($realif, 0, 4) == "ovpn") {
2568
		/* remove all IPv4 addresses */
2569
		while (mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " -alias", true) == 0);
2570
		while (mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 -alias", true) == 0);
2571

    
2572
		switch ($wancfg['ipaddr']) {
2573
			case 'pppoe':
2574
			case 'l2tp':
2575
			case 'pptp':
2576
			case 'ppp':
2577
				break;
2578
			default:
2579
				interface_bring_down($interface);
2580
				break;
2581
		}
2582
	}
2583

    
2584
	/* wireless configuration? */
2585
	if (is_array($wancfg['wireless']))
2586
		interface_wireless_configure($realif, $wancfg, $wancfg['wireless']);
2587

    
2588
	if ($wancfg['spoofmac']) {
2589
		mwexec("/sbin/ifconfig " . escapeshellarg($realhwif) .
2590
			" link " . escapeshellarg($wancfg['spoofmac']));
2591

    
2592
                /*
2593
                 * All vlans need to spoof their parent mac address, too.  see
2594
                 * ticket #1514: http://cvstrac.pfsense.com/tktview?tn=1514,33
2595
                 */
2596
                if (is_array($config['vlans']['vlan'])) {
2597
                        foreach ($config['vlans']['vlan'] as $vlan) {
2598
                                if ($vlan['if'] == $realhwif)
2599
                                        mwexec("/sbin/ifconfig " . escapeshellarg($vlan['vlanif']) .
2600
                                                " link " . escapeshellarg($wancfg['spoofmac']));
2601
                        }
2602
                }
2603
	}  else {
2604
		$mac = get_interface_mac($realhwif);
2605
		if ($mac == "ff:ff:ff:ff:ff:ff") {
2606
			/*   this is not a valid mac address.  generate a
2607
			 *   temporary mac address so the machine can get online.
2608
			 */
2609
			echo "Generating new MAC address.";
2610
			$random_mac = generate_random_mac_address();
2611
			mwexec("/sbin/ifconfig " . escapeshellarg($realhwif) .
2612
				" link " . escapeshellarg($random_mac));
2613
			$wancfg['spoofmac'] = $random_mac;
2614
			write_config();
2615
			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");
2616
		}
2617
	}
2618

    
2619
	/* media */
2620
	if ($wancfg['media'] || $wancfg['mediaopt']) {
2621
		$cmd = "/sbin/ifconfig " . escapeshellarg($realhwif);
2622
		if ($wancfg['media'])
2623
			$cmd .= " media " . escapeshellarg($wancfg['media']);
2624
		if ($wancfg['mediaopt'])
2625
			$cmd .= " mediaopt " . escapeshellarg($wancfg['mediaopt']);
2626
		mwexec($cmd);
2627
	}
2628
	if (!empty($wancfg['mtu']))
2629
		pfSense_interface_mtu($realhwif, $wancfg['mtu']);
2630

    
2631
	$options = pfSense_get_interface_addresses($realhwif);
2632
	if (is_array($options) && isset($options['caps']['polling'])) {
2633
		if (isset($config['system']['polling']))
2634
			pfSense_interface_capabilities($realif, IFCAP_POLLING);
2635
		else
2636
			pfSense_interface_capabilities($realif, -IFCAP_POLLING);
2637
	}
2638

    
2639
	/* skip vlans for checksumming and polling */
2640
        if (!stristr($realhwif, "vlan") && is_array($options)) {
2641
		$flags = 0;
2642
		if(isset($config['system']['disablechecksumoffloading'])) {
2643
			if (isset($options['encaps']['txcsum']))
2644
				$flags |= IFCAP_TXCSUM;
2645
			if (isset($options['encaps']['rxcsum']))
2646
				$flags |= IFCAP_RXCSUM;
2647
        	} else {
2648
 			if (!isset($options['caps']['txcsum']))
2649
				$flags |= IFCAP_TXCSUM;
2650
			if (!isset($options['caps']['rxcsum']))
2651
				$flags |= IFCAP_RXCSUM;
2652
        	}
2653

    
2654
        	if(isset($config['system']['disablesegmentationoffloading'])) {
2655
                	if (isset($options['encaps']['tso4']))
2656
				$flags |= IFCAP_TSO;
2657
                	if (isset($options['encaps']['tso6']))
2658
				$flags |= IFCAP_TSO;
2659
        	} else {
2660
                	if (!isset($options['caps']['tso4']))
2661
				$flags |= IFCAP_TSO;
2662
                	if (!isset($options['caps']['tso6']))
2663
				$flags |= IFCAP_TSO;
2664
        	}
2665

    
2666
        	if(isset($config['system']['disablelargereceiveoffloading'])) {
2667
                	if (isset($options['encaps']['lro']))
2668
				$flags |= IFCAP_LRO;
2669
        	} else {
2670
                	if (!isset($options['caps']['lro']))
2671
				$flags |= IFCAP_LRO;
2672
        	}
2673

    
2674
        	/* if the NIC supports polling *AND* it is enabled in the GUI */
2675
        	if (!isset($config['system']['polling']) || !isset($options['caps']['polling'])) {
2676
			$flags |= IFCAP_POLLING;
2677
		}
2678
               	pfSense_interface_capabilities($realhwif, -$flags);
2679
	}
2680

    
2681
	/* invalidate interface/ip/sn cache */
2682
	get_interface_arr(true);
2683
	unset($interface_ip_arr_cache[$realif]);
2684
	unset($interface_sn_arr_cache[$realif]);
2685
	unset($interface_ipv6_arr_cache[$realif]);
2686
	unset($interface_snv6_arr_cache[$realif]);
2687

    
2688
	switch ($wancfg['ipaddr']) {
2689
		case 'carpdev-dhcp':
2690
			interface_carpdev_dhcp_configure($interface);
2691
			break;
2692
		case 'dhcp':
2693
			interface_dhcp_configure($interface);
2694
			break;
2695
		case 'pppoe':
2696
		case 'l2tp':
2697
		case 'pptp':
2698
		case 'ppp':
2699
			interface_ppps_configure($interface);
2700
			break;
2701
		default:
2702
			if ($wancfg['ipaddr'] <> "" && $wancfg['subnet'] <> "") {
2703
				pfSense_interface_setaddress($realif, "{$wancfg['ipaddr']}/{$wancfg['subnet']}");
2704
			} else if (substr($realif, 0, 3) == "gre") {
2705
				if (is_array($config['gres']['gre'])) {
2706
					foreach ($config['gres']['gre'] as $gre)
2707
						if ($gre['greif'] == $realif)
2708
							interface_gre_configure($gre);
2709
				}
2710
			} else if (substr($realif, 0, 3) == "gif") {
2711
				 if (is_array($config['gifs']['gif'])) {
2712
					foreach ($config['gifs']['gif'] as $gif)
2713
						if($gif['gifif'] == $realif)
2714
							interface_gif_configure($gif);
2715
				}
2716
			} else if (substr($realif, 0, 4) == "ovpn") {
2717
				/* XXX: Should be done anything?! */
2718
			}
2719
			break;
2720
	}
2721

    
2722
	switch ($wancfg['ipaddrv6']) {
2723
		default:
2724
			if ($wancfg['ipaddrv6'] <> "" && $wancfg['subnetv6'] <> "") {
2725
				pfSense_interface_setaddress($realif, "{$wancfg['ipaddrv6']}/{$wancfg['subnetv6']}");
2726
				mwexec("/sbin/ifconfig {$realif} inet6 {$wancfg['ipaddrv6']} prefixlen {$wancfg['subnetv6']} ");
2727
			}
2728
			break;
2729
	}
2730

    
2731
	if(does_interface_exist($wancfg['if']))
2732
		interfaces_bring_up($wancfg['if']);
2733

    
2734
	interface_netgraph_needed($interface);
2735
 	
2736
	if (!$g['booting']) {
2737
		link_interface_to_vips($interface, "update");
2738

    
2739
		unset($gre);
2740
		$gre = link_interface_to_gre($interface);
2741
		if (!empty($gre))
2742
			array_walk($gre, 'interface_gre_configure');
2743

    
2744
		unset($gif);
2745
		$gif = link_interface_to_gif($interface);
2746
		if (!empty($gif))
2747
                       	array_walk($gif, 'interface_gif_configure');
2748

    
2749
		if ($linkupevent == false) {
2750
			unset($bridgetmp);
2751
			$bridgetmp = link_interface_to_bridge($interface);
2752
			if (!empty($bridgetmp))
2753
				interface_bridge_add_member($bridgetmp, $realif);
2754
		}
2755

    
2756
		$grouptmp = link_interface_to_group($interface);
2757
		if (!empty($grouptmp))
2758
			array_walk($grouptmp, 'interface_group_add_member');
2759

    
2760
		if ($interface == "lan")
2761
			/* make new hosts file */
2762
			system_hosts_generate();
2763

    
2764
		if ($reloadall == true) {
2765

    
2766
			/* reconfigure static routes (kernel may have deleted them) */
2767
			system_routing_configure($interface);
2768

    
2769
			/* reload ipsec tunnels */
2770
			vpn_ipsec_configure();
2771

    
2772
			/* restart dnsmasq */
2773
			services_dnsmasq_configure();
2774

    
2775
			/* update dyndns */
2776
			send_event("service reload dyndns {$interface}");
2777

    
2778
			/* reload captive portal */
2779
			captiveportal_init_rules();
2780
		}
2781
	}
2782

    
2783
	return 0;
2784
}
2785

    
2786
function interface_carpdev_dhcp_configure($interface = "wan") {
2787
	global $config, $g;
2788

    
2789
	$wancfg = $config['interfaces'][$interface];
2790
	$wanif = $wancfg['if'];
2791
	/* bring wan interface up before starting dhclient */
2792
	if($wanif)
2793
		interfaces_bring_up($wanif);
2794
	else 
2795
		log_error("Could not bring wanif up in terface_carpdev_dhcp_configure()");
2796

    
2797
	return 0;
2798
}
2799

    
2800
function interface_dhcp_configure($interface = "wan") {
2801
	global $config, $g;
2802

    
2803
	$wancfg = $config['interfaces'][$interface];
2804
	$wanif = $wancfg['if'];
2805
	if (empty($wancfg))
2806
		$wancfg = array();
2807

    
2808
	$wanif = get_real_interface($interface);
2809
	/* bring wan interface up before starting dhclient */
2810
	if($wanif)
2811
		interfaces_bring_up($wanif);
2812
	else 
2813
		log_error("Could not bring up {$wanif} interface in interface_dhcp_configure()");
2814

    
2815
	/* launch v6 before v4, dhclient can hold up the execution if no dhcp4 is available */
2816
	interface_dhcpv6_configure($interface);
2817
	interface_dhcpv4_configure($interface);
2818

    
2819
	return 0;
2820

    
2821
}
2822

    
2823
function interface_dhcpv6_configure($interface = "wan") {
2824
	global $config, $g;
2825
	$iflist = get_configured_interface_with_descr(false, true);
2826

    
2827
	$wancfg = $config['interfaces'][$interface];
2828
	$wanif = $wancfg['if'];
2829
	if (empty($wancfg))
2830
		$wancfg = array();
2831

    
2832
	$wanif = get_real_interface($interface);
2833

    
2834
	/* Add IPv6 dhclient here, only wide-dhcp6c works for now. */
2835
	$fd = fopen("{$g['varetc_path']}/dhcp6c_{$interface}.conf", "w");
2836
	if (!$fd) {
2837
		printf("Error: cannot open dhcp6c_{$interface}.conf in interfaces_wan_dhcp_configure() for writing.\n");
2838
		return 1;
2839
	}
2840

    
2841
	$dhcp6cconf = "";
2842
 	$dhcp6cconf .= "interface {$wanif} {\n";
2843
	$dhcp6cconf .= " 	send ia-na 0;	# request stateful address\n";
2844
	if(is_numeric($wancfg['dhcp6-ia-pd-len'])) {
2845
		$dhcp6cconf .= " 	send ia-pd 0;	# request prefix delegation\n";
2846
	}
2847
	$dhcp6cconf .= "request domain-name-servers;\n";
2848
	$dhcp6cconf .= "request domain-name;\n";
2849
	$dhcp6cconf .= "script \"/etc/rc.newwanipv6\";	# we'd like some nameservers please\n";
2850

    
2851
	$dhcp6cconf .= "};\n";
2852
	$dhcp6cconf .= "id-assoc na 0 { };\n";
2853
	if(is_numeric($wancfg['dhcp6-ia-pd-len'])) {
2854
		/* Setup the prefix delegation */
2855
		$dhcp6cconf .= "	id-assoc pd 0 {\n";
2856
		foreach($iflist as $friendly => $pdinterface) {
2857
			// log_error("setting up $friendly - $pdinterface - {$pdinterface['dhcp6-pd-sla-id']}");
2858
			if(is_numeric($config['interfaces'][$friendly]['dhcp6-pd-sla-id'])) {
2859
				$realif = get_real_interface($friendly);
2860
				$dhcp6cconf .= "	prefix-interface {$realif} {\n";
2861
				$dhcp6cconf .= "		sla-id {$config['interfaces'][$friendly]['dhcp6-pd-sla-id']};\n";
2862
				$dhcp6cconf .= "		sla-len {$wancfg['dhcp6-ia-pd-len']};\n";
2863
				$dhcp6cconf .= "	};\n";
2864
			}
2865
		}
2866
		$dhcp6cconf .= "};\n";
2867
	}
2868

    
2869
	fwrite($fd, $dhcp6cconf);
2870
	fclose($fd);
2871

    
2872
	/* accept router advertisements for this interface */
2873
	mwexec("/sbin/sysctl -w net.inet6.ip6.accept_rtadv=1");
2874
	/* fire up dhcp6c for IPv6 first, this backgrounds immediately */
2875
	mwexec("/usr/local/sbin/dhcp6c -d -c {$g['varetc_path']}/dhcp6c_{$interface}.conf {$wanif}");
2876

    
2877
	return 0;
2878
}
2879

    
2880
function interface_dhcpv4_configure($interface = "wan") {
2881
	global $config, $g;
2882

    
2883
	$wancfg = $config['interfaces'][$interface];
2884
	$wanif = $wancfg['if'];
2885
	if (empty($wancfg))
2886
		$wancfg = array();
2887

    
2888
	/* generate dhclient_wan.conf */
2889
	$fd = fopen("{$g['varetc_path']}/dhclient_{$interface}.conf", "w");
2890
	if (!$fd) {
2891
		printf("Error: cannot open dhclient_{$interface}.conf in interfaces_wan_dhcp_configure() for writing.\n");
2892
		return 1;
2893
	}
2894

    
2895
	if ($wancfg['dhcphostname']) {
2896
		$dhclientconf_hostname = "send dhcp-client-identifier \"{$wancfg['dhcphostname']}\";\n";
2897
		$dhclientconf_hostname .= "\tsend host-name \"{$wancfg['dhcphostname']}\";\n";
2898
	} else {
2899
		$dhclientconf_hostname = "";
2900
	}
2901

    
2902
	$wanif = get_real_interface($interface);
2903
	if (empty($wanif)) {
2904
		log_error("Invalid interface \"{$interface}\" in interface_dhcp_configure()");
2905
		return 0;
2906
	}
2907
 	$dhclientconf = "";
2908
	
2909
	$dhclientconf .= <<<EOD
2910
interface "{$wanif}" {
2911
timeout 60;
2912
retry 1;
2913
select-timeout 0;
2914
initial-interval 1;
2915
	{$dhclientconf_hostname}
2916
	script "/sbin/dhclient-script";
2917
}
2918

    
2919
EOD;
2920

    
2921
if(is_ipaddr($wancfg['alias-address'])) {
2922
	$subnetmask = gen_subnet_mask($wancfg['alias-subnet']);
2923
	$dhclientconf .= <<<EOD
2924
alias {
2925
	interface  "{$wanif}";
2926
	fixed-address {$wancfg['alias-address']};
2927
	option subnet-mask {$subnetmask};
2928
}
2929

    
2930
EOD;
2931
}
2932
	fwrite($fd, $dhclientconf);
2933
	fclose($fd);
2934

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

    
2938
	return 0;
2939
}
2940

    
2941
function interfaces_group_setup() {
2942
	global $config;
2943

    
2944
	if (!is_array($config['ifgroups']['ifgroupentry']))
2945
		return;
2946

    
2947
	foreach ($config['ifgroups']['ifgroupentry'] as $groupar)
2948
		interface_group_setup($groupar);
2949

    
2950
	return;
2951
}
2952

    
2953
function interface_group_setup(&$groupname /* The parameter is an array */) {
2954
	global $config;
2955

    
2956
	if (!is_array($groupname))
2957
		return;
2958
	$members = explode(" ", $groupname['members']);
2959
	foreach($members as $ifs) {
2960
		$realif = get_real_interface($ifs);
2961
		if ($realif)
2962
			mwexec("/sbin/ifconfig {$realif} group {$groupname['ifname']}");
2963
	}
2964

    
2965
	return;
2966
}
2967

    
2968
function interface_group_add_member($interface, $groupname) {
2969
	$interface = get_real_interface($interface);
2970
	mwexec("/sbin/ifconfig {$interface} group {$groupname}", true);
2971
}
2972
 
2973
/* COMPAT Function */
2974
function convert_friendly_interface_to_real_interface_name($interface) {
2975
	return get_real_interface($interface);
2976
}
2977

    
2978
/* COMPAT Function */
2979
function get_real_wan_interface($interface = "wan") {
2980
	return get_real_interface($interface);
2981
}
2982

    
2983
/* COMPAT Function */
2984
function get_current_wan_address($interface = "wan") {
2985
	return get_interface_ip($interface);
2986
}
2987

    
2988
/*
2989
 * convert_real_interface_to_friendly_interface_name($interface): convert fxp0 -> wan, etc.
2990
 */
2991
function convert_real_interface_to_friendly_interface_name($interface = "wan") {
2992
        global $config;
2993

    
2994
	if (stristr($interface, "vip")) {
2995
                $index = intval(substr($interface, 3));
2996
                foreach ($config['virtualip']['vip'] as $counter => $vip) {
2997
                        if ($vip['mode'] == "carpdev-dhcp" || $vip['mode'] == "carp")  {
2998
                                if ($index == $vip['vhid'])
2999
                                        return $vip['interface'];
3000
                        }
3001
                }
3002
        }
3003

    
3004
        /* XXX: For speed reasons reference directly the interface array */
3005
	$ifdescrs = &$config['interfaces'];
3006
        //$ifdescrs = get_configured_interface_list(false, true);
3007

    
3008
        foreach ($ifdescrs as $if => $ifname) {
3009
                if ($config['interfaces'][$if]['if'] == $interface)
3010
                        return $if;
3011

    
3012
                if (stristr($interface, "_wlan0") && $config['interfaces'][$if]['if'] == interface_get_wireless_base($interface))
3013
                        return $if;
3014

    
3015
		// XXX: This case doesn't work anymore (segfaults - recursion?) - should be replaced with something else or just removed.
3016
		//      Not to be replaced with get_real_interface - causes slow interface listings here because of recursion!
3017
		/*
3018
                $int = get_parent_interface($if);
3019
                if ($int[0] == $interface)
3020
                        return $ifname;
3021
		*/
3022
        }
3023
        return NULL;
3024
}
3025

    
3026
/* attempt to resolve interface to friendly descr */
3027
function convert_friendly_interface_to_friendly_descr($interface) {
3028
        global $config;
3029

    
3030
        switch ($interface) {
3031
        case "l2tp":
3032
        	$ifdesc = "L2TP";
3033
                break;
3034
	case "pptp":
3035
		$ifdesc = "PPTP";
3036
		break;
3037
	case "pppoe":
3038
		$ifdesc = "PPPoE";
3039
		break;
3040
	case "openvpn":
3041
		$ifdesc = "OpenVPN";
3042
		break;
3043
	case "enc0":
3044
	case "ipsec":
3045
		$ifdesc = "IPsec";
3046
		break;
3047
        default:
3048
                if (isset($config['interfaces'][$interface])) {
3049
                        if (empty($config['interfaces'][$interface]['descr']))
3050
                                $ifdesc = strtoupper($interface);
3051
                        else
3052
                                $ifdesc = strtoupper($config['interfaces'][$interface]['descr']);
3053
			break;
3054
		} else if (substr($interface, 0, 3) == "vip") {
3055
			if (is_array($config['virtualip']['vip'])) {
3056
				foreach ($config['virtualip']['vip'] as $counter => $vip) {
3057
					if ($vip['mode'] == "carpdev-dhcp" || $vip['mode'] == "carp")  {
3058
						if ($interface == "vip{$vip['vhid']}")
3059
							return "{$vip['subnet']} - {$vip['descr']}";
3060
					}
3061
				}
3062
                        }
3063
                } else {
3064
			/* if list */
3065
			$ifdescrs = get_configured_interface_with_descr(false, true);
3066
			foreach ($ifdescrs as $if => $ifname) {
3067
					if ($if == $interface || $ifname == $interface)
3068
						return $ifname;
3069
			}
3070
		}
3071
                break;
3072
        }
3073

    
3074
        return $ifdesc;
3075
}
3076

    
3077
function convert_real_interface_to_friendly_descr($interface) {
3078
        global $config;
3079

    
3080
        $ifdesc = convert_real_interface_to_friendly_interface_name("{$interface}");
3081

    
3082
        if ($ifdesc) {
3083
                $iflist = get_configured_interface_with_descr(false, true);
3084
                return $iflist[$ifdesc];
3085
        }
3086

    
3087
        return $interface;
3088
}
3089

    
3090
/*
3091
 *  get_parent_interface($interface):
3092
 *			--returns the (real or virtual) parent interface(s) array for a given interface friendly name (i.e. wan)
3093
 *				or virtual interface (i.e. vlan)
3094
 *				(We need array because MLPPP and bridge interfaces have more than one parent.)
3095
 *			-- returns $interface passed in if $interface parent is not found
3096
 *			-- returns empty array if an invalid interface is passed
3097
 *	(Only handles ppps and vlans now.)
3098
 */
3099
function get_parent_interface($interface) {
3100
	global $config;
3101

    
3102
	$parents = array();
3103
	//Check that we got a valid interface passed
3104
	$realif = get_real_interface($interface);
3105
	if ($realif == NULL)
3106
		return $parents;
3107

    
3108
	// If we got a real interface, find it's friendly assigned name
3109
	$interface = convert_real_interface_to_friendly_interface_name($interface);
3110
		
3111
	if (!empty($interface) && isset($config['interfaces'][$interface])) {
3112
		$ifcfg = $config['interfaces'][$interface];
3113
		switch ($ifcfg['ipaddr']) {
3114
			case "ppp":
3115
			case "pppoe":
3116
			case "pptp":
3117
			case "l2tp":
3118
				if (empty($parents))
3119
					if (is_array($config['ppps']['ppp']))
3120
						foreach ($config['ppps']['ppp'] as $pppidx => $ppp) {
3121
							if ($ppp_if == $ppp['if']) {
3122
								$ports = explode(',', $ppp['ports']);
3123
								foreach ($ports as $pid => $parent_if) 
3124
									$parents[$pid] = get_real_interface($parent_if);
3125
								break;
3126
							}
3127
						}
3128
				break;
3129
			case "dhcp":
3130
			case "static":
3131
			default:
3132
				// Handle _vlans
3133
				if (strstr($realif,"_vlan"))
3134
					if (is_array($config['vlans']['vlan'])) 
3135
						foreach ($config['vlans']['vlan'] as $vlanidx => $vlan)
3136
							if ($ifcfg['if'] == $vlan['vlanif']){
3137
								$parents[0] = $vlan['if'];
3138
								break;
3139
							}
3140
				break;
3141
		}
3142
	}
3143
	
3144
	if (empty($parents))
3145
		$parents[0] = $realif;
3146
	
3147
	return $parents;
3148
}
3149

    
3150
function interface_is_wireless_clone($wlif) {
3151
	if(!stristr($wlif, "_wlan")) {
3152
		return false;
3153
	} else {
3154
		return true;
3155
	}
3156
}
3157

    
3158
function interface_get_wireless_base($wlif) {
3159
	if(!stristr($wlif, "_wlan")) {
3160
		return $wlif;
3161
	} else {
3162
		return substr($wlif, 0, stripos($wlif, "_wlan"));
3163
	}
3164
}
3165

    
3166
function interface_get_wireless_clone($wlif) {
3167
	if(!stristr($wlif, "_wlan")) {
3168
		return $wlif . "_wlan0";
3169
	} else {
3170
		return $wlif;
3171
	}
3172
}
3173

    
3174
function get_real_interface($interface = "wan") {
3175
    global $config;
3176

    
3177
	$wanif = NULL;
3178

    
3179
	switch ($interface) {
3180
	case "l2tp":
3181
		$wanif = "l2tp";
3182
		break;
3183
	case "pptp":
3184
		$wanif = "pptp";
3185
		break;
3186
	case "pppoe":
3187
		$wanif = "pppoe";
3188
		break;
3189
	case "openvpn":
3190
		$wanif = "openvpn";
3191
		break;
3192
	case "ipsec":
3193
	case "enc0":
3194
		$wanif = "enc0";
3195
		break;
3196
	case "ppp":
3197
		$wanif = "ppp";
3198
		break;
3199
	default:
3200
		// If a real interface was alread passed simply
3201
		// pass the real interface back.  This encourages
3202
		// the usage of this function in more cases so that
3203
		// we can combine logic for more flexibility.
3204
		if(does_interface_exist($interface)) {
3205
			$wanif = $interface;
3206
			break;
3207
		}
3208
		if (empty($config['interfaces'][$interface]))
3209
			break;
3210

    
3211
		$cfg = &$config['interfaces'][$interface];
3212

    
3213
		// Wireless cloned NIC support (FreeBSD 8+)
3214
		// interface name format: $parentnic_wlanparentnic#
3215
		// example: ath0_wlan0
3216
		if (is_interface_wireless($cfg['if'])) {
3217
			$wanif = interface_get_wireless_clone($cfg['if']);
3218
			break;
3219
		}
3220
		/*
3221
		if (empty($cfg['if'])) {
3222
			$wancfg = $cfg['if'];
3223
			break;
3224
		}
3225
		*/
3226

    
3227
		switch ($cfg['ipaddr']) {
3228
			case "carpdev-dhcp":
3229
				$viparr = &$config['virtualip']['vip'];
3230
				if(is_array($viparr))
3231
				foreach ($viparr as $counter => $vip) {
3232
					if ($vip['mode'] == "carpdev-dhcp") {
3233
						if($vip['interface'] == $interface) {
3234
							$wanif = "carp{$counter}";
3235
							break;
3236
						}
3237
					}
3238
				}
3239
				break;
3240
			case "pppoe": 
3241
			case "pptp": 
3242
			case "l2tp": 
3243
			case "ppp":
3244
				$wanif = $cfg['if'];
3245
				break;
3246
			default:
3247
				$wanif = $cfg['if'];
3248
				break;
3249
		}
3250
		break;
3251
	}
3252

    
3253
    return $wanif;
3254
}
3255

    
3256
/* Guess the physical interface by providing a IP address */
3257
function guess_interface_from_ip($ipaddress) {
3258
	if(! is_ipaddr($ipaddress)) {
3259
		return false;
3260
	}
3261
	if(is_ipaddrv4($ipaddress)) {
3262
		/* create a route table we can search */
3263
		exec("netstat -rnWf inet", $output, $ret);
3264
		foreach($output as $line) {
3265
			if(preg_match("/^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\/[0-9]+[ ]+link[#]/", $line)) {
3266
				$fields = preg_split("/[ ]+/", $line);
3267
				if(ip_in_subnet($ipaddress, $fields[0])) {
3268
					return $fields[6];
3269
				}
3270
			}
3271
		}
3272
	}
3273
	/* FIXME: This works from cursory testing, regexp might need fine tuning */
3274
	if(is_ipaddrv6($ipaddress)) {
3275
		/* create a route table we can search */
3276
		exec("netstat -rnWf inet6", $output, $ret);
3277
		foreach($output as $line) {
3278
			if(preg_match("/[0-9a-f]+[:]+[0-9a-f]+[:]+[\/][0-9]+/", $line)) {
3279
				$fields = preg_split("/[ ]+/", $line);
3280
				if(ip_in_subnet($ipaddress, $fields[0])) {
3281
					return $fields[6];
3282
				}
3283
			}
3284
		}
3285
	}
3286
	$ret = exec_command("/sbin/route -n get {$ipaddress} | /usr/bin/awk '/interface/ { print \$2; };'");
3287
	if(empty($ret)) {
3288
        	return false;
3289
	}
3290
	return $ret;
3291
}
3292

    
3293
/*
3294
 * find_ip_interface($ip): return the interface where an ip is defined
3295
 */
3296
function find_ip_interface($ip)
3297
{
3298
        /* if list */
3299
        $ifdescrs = get_configured_interface_list();
3300

    
3301
        foreach ($ifdescrs as $ifdescr => $ifname) {
3302
		if ($ip == get_interface_ip($ifname)) {
3303
                	$int = get_real_interface($ifname);
3304
			return $int;
3305
		}
3306
        }
3307
        return false;
3308
}
3309

    
3310
/*
3311
 *   find_number_of_created_carp_interfaces: return the number of carp interfaces
3312
 */
3313
function find_number_of_created_carp_interfaces() {
3314
	return `/sbin/ifconfig | grep "carp:" | wc -l`;
3315
}
3316

    
3317
function get_all_carp_interfaces() {
3318
	$ints = str_replace("\n", " ", `ifconfig | grep "carp:" -B2 | grep ": flag" | cut -d: -f1`);
3319
	$ints = explode(" ", $ints);
3320
	return $ints;
3321
}
3322

    
3323
/*
3324
 * find_carp_interface($ip): return the carp interface where an ip is defined
3325
 */
3326
function find_carp_interface($ip) {
3327
	global $config;
3328
	if (is_array($config['virtualip']['vip'])) {
3329
		foreach ($config['virtualip']['vip'] as $vip) {
3330
			if ($vip['mode'] == "carp" || $vip['mode'] == "carpdev") {
3331
				if(is_ipaddrv4($ip)) {
3332
					$carp_ip = get_interface_ip($vip['interface']);
3333
				}
3334
				if(is_ipaddrv6($ip)) {
3335
					$carp_ip = get_interface_ipv6($vip['interface']);
3336
				}
3337
				exec("/sbin/ifconfig", $output, $return);
3338
				foreach($output as $line) {
3339
					$elements = preg_split("/[ ]+/i", $line);
3340
					if(strstr($elements[0], "vip"))
3341
						$curif = str_replace(":", "", $elements[0]);
3342
					if(stristr($line, $ip)) {
3343
						$if = $curif;
3344
						continue;
3345
					}
3346
				}
3347
				if ($if)
3348
					return $if;
3349
			}
3350
		}
3351
	}
3352
}
3353

    
3354
function link_carp_interface_to_parent($interface) {
3355
        global $config;
3356

    
3357
        if ($interface == "")
3358
                return;
3359

    
3360
        $carp_ip = get_interface_ip($interface);
3361
        if (!is_ipaddr($carp_ip))
3362
                return;
3363

    
3364
        /* if list */
3365
        $ifdescrs = get_configured_interface_list();
3366
        foreach ($ifdescrs as $ifdescr => $ifname) {
3367
                $interfaceip = get_interface_ip($ifname);
3368
                $subnet_bits = get_interface_subnet($ifname);
3369
                $subnet_ip = gen_subnet("{$interfaceip}", "{$subnet_bits}");
3370
                if(ip_in_subnet($carp_ip, "{$subnet_ip}/{$subnet_bits}"))
3371
                        return $ifname;
3372
        }
3373

    
3374
        return "";
3375
}
3376

    
3377
/****f* interfaces/link_ip_to_carp_interface
3378
 * NAME
3379
 *   link_ip_to_carp_interface - Find where a CARP interface links to.
3380
 * INPUTS
3381
 *   $ip
3382
 * RESULT
3383
 *   $carp_ints
3384
 ******/
3385
function link_ip_to_carp_interface($ip) {
3386
        global $config;
3387

    
3388
        if (!is_ipaddr($ip))
3389
                return;
3390

    
3391
        $carp_ints = "";
3392
        if (is_array($config['virtualip']['vip'])) {
3393
		$first = 0;
3394
		$carp_int = array();
3395
                foreach ($config['virtualip']['vip'] as $vip) {
3396
                        if ($vip['mode'] == "carp" || $vip['mode'] == "carpdev") {
3397
                                $carp_ip = $vip['subnet'];
3398
                                $carp_sn = $vip['subnet_bits'];
3399
                                $carp_nw = gen_subnet($carp_ip, $carp_sn);
3400
                                if (ip_in_subnet($ip, "{$carp_nw}/{$carp_sn}"))
3401
					$carp_int[] = "vip{$vip['vhid']}";
3402
                        }
3403
                }
3404
		if (!empty($carp_int))
3405
			$carp_ints = implode(" ", array_unique($carp_int));
3406
        }
3407

    
3408
        return $carp_ints;
3409
}
3410

    
3411
function link_interface_to_vlans($int, $action = "") {
3412
	global $config;
3413

    
3414
	if (empty($int))
3415
		return;
3416

    
3417
	if (is_array($config['vlans']['vlan'])) {
3418
                foreach ($config['vlans']['vlan'] as $vlan) {
3419
			if ($int == $vlan['if']) {
3420
				if ($action == "update") {
3421
					interfaces_bring_up($int);
3422
				} else if ($action == "")
3423
					return $vlan;
3424
			}
3425
		}
3426
	}
3427
}
3428

    
3429
function link_interface_to_vips($int, $action = "") {
3430
        global $config;
3431

    
3432
        if (is_array($config['virtualip']['vip'])) {
3433
		foreach ($config['virtualip']['vip'] as $vip) {
3434
			if ($int == $vip['interface']) {
3435
				if ($action == "update") {
3436
					interface_vip_bring_down($vip);
3437
					interfaces_vips_configure($int);
3438
				} else
3439
					return $vip;
3440
			}
3441
		}
3442
	}
3443
}
3444

    
3445
/****f* interfaces/link_interface_to_bridge
3446
 * NAME
3447
 *   link_interface_to_bridge - Finds out a bridge group for an interface
3448
 * INPUTS
3449
 *   $ip
3450
 * RESULT
3451
 *   bridge[0-99]
3452
 ******/
3453
function link_interface_to_bridge($int) {
3454
        global $config;
3455

    
3456
        if (is_array($config['bridges']['bridged'])) {
3457
                foreach ($config['bridges']['bridged'] as $bridge) {
3458
			if (in_array($int, explode(',', $bridge['members'])))
3459
                                return "{$bridge['bridgeif']}";
3460
		}
3461
	}
3462
}
3463

    
3464
function link_interface_to_group($int) {
3465
        global $config;
3466

    
3467
	$result = array();
3468

    
3469
        if (is_array($config['ifgroups']['ifgroupentry'])) {
3470
                foreach ($config['ifgroups']['ifgroupentry'] as $group) {
3471
			if (in_array($int, explode(" ", $group['members'])))
3472
				$result[$group['ifname']] = $int;
3473
		}
3474
	}
3475

    
3476
	return $result;
3477
}
3478

    
3479
function link_interface_to_gre($interface) {
3480
        global $config;
3481

    
3482
	$result = array();
3483

    
3484
        if (is_array($config['gres']['gre'])) {
3485
                foreach ($config['gres']['gre'] as $gre)
3486
                        if($gre['if'] == $interface)
3487
				$result[] = $gre;
3488
	}
3489

    
3490
	return $result;
3491
}
3492

    
3493
function link_interface_to_gif($interface) {
3494
        global $config;
3495

    
3496
	$result = array();
3497

    
3498
        if (is_array($config['gifs']['gif'])) {
3499
                foreach ($config['gifs']['gif'] as $gif)
3500
                        if($gif['if'] == $interface)
3501
                                $result[] = $gif;
3502
	}
3503

    
3504
	return $result;
3505
}
3506

    
3507
/*
3508
 * find_interface_ip($interface): return the interface ip (first found)
3509
 */
3510
function find_interface_ip($interface, $flush = false)
3511
{
3512
	global $interface_ip_arr_cache;
3513
	global $interface_sn_arr_cache;
3514

    
3515
	$interface = str_replace("\n", "", $interface);
3516
	
3517
	if (!does_interface_exist($interface))
3518
		return;
3519

    
3520
	/* Setup IP cache */
3521
	if (!isset($interface_ip_arr_cache[$interface]) or $flush) {
3522
		$ifinfo = pfSense_get_interface_addresses($interface);
3523
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
3524
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
3525
	}
3526

    
3527
	return $interface_ip_arr_cache[$interface];
3528
}
3529

    
3530
/*
3531
 * find_interface_ipv6($interface): return the interface ip (first found)
3532
 */
3533
function find_interface_ipv6($interface, $flush = false)
3534
{
3535
	global $interface_ipv6_arr_cache;
3536
	global $interface_snv6_arr_cache;
3537
	global $config;
3538
	
3539
	$interface = str_replace("\n", "", $interface);
3540
	
3541
	if (!does_interface_exist($interface))
3542
		return;
3543

    
3544
	/* Setup IP cache */
3545
	if (!isset($interface_ipv6_arr_cache[$interface]) or $flush) {
3546
		$ifinfo = pfSense_get_interface_addresses($interface);
3547
		exec("/sbin/ifconfig {$interface} inet6", $output);
3548
		foreach($output as $line) {
3549
			if(preg_match("/inet6/", $line)) {
3550
				$parts = explode(" ", $line);
3551
				if(! preg_match("/fe80::/", $parts[1])) {
3552
					$ifinfo['ipaddrv6'] = $parts[1];
3553
					if($parts[2] == "-->") {
3554
						$parts[5] = "126";
3555
						$ifinfo['subnetbitsv6'] = $parts[5];
3556
					} else {
3557
						$ifinfo['subnetbitsv6'] = $parts[3];
3558
					}
3559
				}
3560
			}
3561
		}
3562
		$interface_ipv6_arr_cache[$interface] = $ifinfo['ipaddrv6'];
3563
		$interface_snv6_arr_cache[$interface] = $ifinfo['subnetbitsv6'];
3564
	}
3565

    
3566
	return $interface_ipv6_arr_cache[$interface];
3567
}
3568

    
3569
function find_interface_subnet($interface, $flush = false)
3570
{
3571
	global $interface_sn_arr_cache;
3572
	global $interface_ip_arr_cache;
3573

    
3574
	$interface = str_replace("\n", "", $interface);
3575
	if (does_interface_exist($interface) == false)
3576
		return;
3577

    
3578
	if (!isset($interface_sn_arr_cache[$interface]) or $flush) {
3579
		$ifinfo = pfSense_get_interface_addresses($interface);
3580
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
3581
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
3582
        }
3583

    
3584
	return $interface_sn_arr_cache[$interface];
3585
}
3586

    
3587
function find_interface_subnetv6($interface, $flush = false)
3588
{
3589
	global $interface_snv6_arr_cache;
3590
	global $interface_ipv6_arr_cache;
3591

    
3592
	$interface = str_replace("\n", "", $interface);
3593
	if (does_interface_exist($interface) == false)
3594
		return;
3595

    
3596
	if (!isset($interface_snv6_arr_cache[$interface]) or $flush) {
3597
		$ifinfo = pfSense_get_interface_addresses($interface);
3598
		exec("/sbin/ifconfig {$interface} inet6", $output);
3599
		foreach($output as $line) {
3600
			if(preg_match("/inet6/", $line)) {
3601
				$parts = explode(" ", $line);
3602
				if(! preg_match("/fe80::/", $parts[1])) {
3603
					$ifinfo['ipaddrv6'] = $parts[1];
3604
					if($parts[2] == "-->") {
3605
						$parts[5] = "126";
3606
						$ifinfo['subnetbitsv6'] = $parts[5];
3607
					} else {
3608
						$ifinfo['subnetbitsv6'] = $parts[3];
3609
					}
3610
				}
3611
			}
3612
		}
3613
		$interface_ipv6_arr_cache[$interface] = $ifinfo['ipaddrv6'];
3614
		$interface_snv6_arr_cache[$interface] = $ifinfo['subnetbitsv6'];
3615
        }
3616

    
3617
	return $interface_snv6_arr_cache[$interface];
3618
}
3619

    
3620
function ip_in_interface_alias_subnet($interface, $ipalias) {
3621
	global $config;
3622

    
3623
	if (empty($interface) || !is_ipaddr($ipalias))
3624
		return false;
3625
	if (is_array($config['virtualip']['vip'])) {
3626
                foreach ($config['virtualip']['vip'] as $vip) {
3627
                        switch ($vip['mode']) {
3628
                        case "ipalias":
3629
                                if ($vip['interface'] <> $interface)
3630
                                        break;
3631
				if (ip_in_subnet($ipalias, gen_subnet($vip['subnet'], $vip['subnet_bits']) . "/" . $vip['subnet_bits']))
3632
					return true;
3633
                                break;
3634
                        }
3635
                }
3636
	}
3637

    
3638
	return false;
3639
}
3640

    
3641
function get_interface_ip($interface = "wan")
3642
{
3643
	$realif = get_real_interface($interface);
3644
	if (!$realif) {
3645
		if (preg_match("/^carp/i", $interface))
3646
			$realif = $interface;
3647
		else if (preg_match("/^vip/i", $interface))
3648
			$realif = $interface;
3649
		else
3650
			return null;
3651
	}
3652

    
3653
	$curip = find_interface_ip($realif);
3654
	if ($curip && is_ipaddr($curip) && ($curip != "0.0.0.0"))
3655
		return $curip;
3656
	else
3657
		return null;
3658
}
3659

    
3660
function get_interface_ipv6($interface = "wan")
3661
{
3662
	$realif = get_real_interface($interface);
3663
	if (!$realif) {
3664
		if (preg_match("/^carp/i", $interface))
3665
			$realif = $interface;
3666
		else if (preg_match("/^vip/i", $interface))
3667
			$realif = $interface;
3668
		else
3669
			return null;
3670
	}
3671

    
3672
	$curip = find_interface_ipv6($realif);
3673
	if ($curip && is_ipaddrv6($curip) && ($curip != "::"))
3674
		return $curip;
3675
	else
3676
		return null;
3677
}
3678

    
3679
function get_interface_subnet($interface = "wan")
3680
{
3681
	$realif = get_real_interface($interface);
3682
	if (!$realif) {
3683
                if (preg_match("/^carp/i", $interface))
3684
                        $realif = $interface;
3685
                else if (preg_match("/^vip/i", $interface))
3686
                        $realif = $interface;
3687
                else
3688
                        return null;
3689
        }
3690

    
3691
	$cursn = find_interface_subnet($realif);
3692
	if (!empty($cursn))
3693
		return $cursn;
3694

    
3695
	return null;
3696
}
3697

    
3698
function get_interface_subnetv6($interface = "wan")
3699
{
3700
	$realif = get_real_interface($interface);
3701
	if (!$realif) {
3702
                if (preg_match("/^carp/i", $interface))
3703
                        $realif = $interface;
3704
                else if (preg_match("/^vip/i", $interface))
3705
                        $realif = $interface;
3706
                else
3707
                        return null;
3708
        }
3709

    
3710
	$cursn = find_interface_subnetv6($realif);
3711
	if (!empty($cursn))
3712
		return $cursn;
3713

    
3714
	return null;
3715
}
3716

    
3717
/* return outside interfaces with a gateway */
3718
function get_interfaces_with_gateway() {
3719
	global $config;
3720

    
3721
	$ints = array();
3722

    
3723
	/* loop interfaces, check config for outbound */
3724
	foreach($config['interfaces'] as $ifdescr => $ifname) {
3725
		switch ($ifname['ipaddr']) {
3726
			case "dhcp":
3727
			case "carpdev-dhcp":
3728
			case "ppp";
3729
			case "pppoe":
3730
			case "pptp":
3731
			case "l2tp":
3732
			case "ppp";
3733
				$ints[$ifdescr] = $ifdescr;
3734
			break;
3735
			default:
3736
				if (substr($ifname['if'], 0, 5) ==  "ovpnc" ||
3737
				    !empty($ifname['gateway']))
3738
					$ints[$ifdescr] = $ifdescr;
3739
			break;
3740
		}
3741
	}
3742
	return $ints;
3743
}
3744

    
3745
/* return true if interface has a gateway */
3746
function interface_has_gateway($friendly) {
3747
	global $config;
3748

    
3749
	if (!empty($config['interfaces'][$friendly])) {
3750
		$ifname = &$config['interfaces'][$friendly];
3751
		switch ($ifname['ipaddr']) {
3752
			case "dhcp":
3753
			case "carpdev-dhcp":
3754
			case "pppoe":
3755
			case "pptp":
3756
			case "l2tp":
3757
			case "ppp";
3758
				return true;
3759
			break;
3760
			default:
3761
				if (substr($ifname['if'], 0, 5) ==  "ovpnc")
3762
					return true;
3763
				if (!empty($ifname['gateway']))
3764
					return true;
3765
			break;
3766
		}
3767
	}
3768

    
3769
	return false;
3770
}
3771

    
3772
/****f* interfaces/is_altq_capable
3773
 * NAME
3774
 *   is_altq_capable - Test if interface is capable of using ALTQ
3775
 * INPUTS
3776
 *   $int            - string containing interface name
3777
 * RESULT
3778
 *   boolean         - true or false
3779
 ******/
3780

    
3781
function is_altq_capable($int) {
3782
        /* Per:
3783
         * http://www.freebsd.org/cgi/man.cgi?query=altq&manpath=FreeBSD+7.2-current&format=html
3784
         * Only the following drivers have ALTQ support
3785
         */
3786
	$capable = array("age", "alc", "ale", "an", "ath", "aue", "awi", "bce",
3787
			"bfe", "bge", "bridge", "cas", "dc", "de", "ed", "em", "ep", "fxp", "gem",
3788
			"hme", "igb", "ipw", "iwi", "jme", "le", "lem", "msk", "mxge", "my", "nfe",
3789
			"npe", "nve", "ral", "re", "rl", "rum", "run", "bwn", "sf", "sis", "sk",
3790
			"ste", "stge", "txp", "udav", "ural", "vge", "vr", "wi", "xl",
3791
			"ndis", "tun", "ovpns", "ovpnc", "vlan", "pppoe", "pptp", "ng",
3792
			"l2tp", "ppp");
3793

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

    
3796
        if (in_array($int_family[0], $capable))
3797
                return true;
3798
	else if (stristr($int, "vlan")) /* VLANs are name $parent_$vlan now */
3799
		return true;
3800
	else if (stristr($int, "_wlan")) /* WLANs are name $parent_$wlan now */
3801
		return true;
3802
        else
3803
                return false;
3804
}
3805

    
3806
/****f* interfaces/is_interface_wireless
3807
 * NAME
3808
 *   is_interface_wireless - Returns if an interface is wireless
3809
 * RESULT
3810
 *   $tmp       - Returns if an interface is wireless
3811
 ******/
3812
function is_interface_wireless($interface) {
3813
        global $config, $g;
3814

    
3815
        $friendly = convert_real_interface_to_friendly_interface_name($interface);
3816
        if(!isset($config['interfaces'][$friendly]['wireless'])) {
3817
                if (preg_match($g['wireless_regex'], $interface)) {
3818
                        if (isset($config['interfaces'][$friendly]))
3819
                                $config['interfaces'][$friendly]['wireless'] = array();
3820
                        return true;
3821
                }
3822
                return false;
3823
        } else
3824
                return true;
3825
}
3826

    
3827
function get_wireless_modes($interface) {
3828
	/* return wireless modes and channels */
3829
	$wireless_modes = array();
3830

    
3831
	$cloned_interface = get_real_interface($interface);
3832

    
3833
	if($cloned_interface && is_interface_wireless($cloned_interface)) {
3834
		$chan_list = "/sbin/ifconfig {$cloned_interface} list chan";
3835
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
3836
		$format_list = "/usr/bin/awk '{print \$5 \" \" \$6 \",\" \$1}'";
3837

    
3838
		$interface_channels = "";
3839
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
3840
		$interface_channel_count = count($interface_channels);
3841

    
3842
		$c = 0;
3843
		while ($c < $interface_channel_count)
3844
		{
3845
			$channel_line = explode(",", $interface_channels["$c"]);
3846
			$wireless_mode = trim($channel_line[0]);
3847
			$wireless_channel = trim($channel_line[1]);
3848
			if(trim($wireless_mode) != "") {
3849
				/* if we only have 11g also set 11b channels */
3850
				if($wireless_mode == "11g") {
3851
					if(!isset($wireless_modes["11b"]))
3852
						$wireless_modes["11b"] = array();
3853
				} else if($wireless_mode == "11g ht") {
3854
					if(!isset($wireless_modes["11b"]))
3855
						$wireless_modes["11b"] = array();
3856
					if(!isset($wireless_modes["11g"]))
3857
						$wireless_modes["11g"] = array();
3858
					$wireless_mode = "11ng";
3859
				} else if($wireless_mode == "11a ht") {
3860
					if(!isset($wireless_modes["11a"]))
3861
						$wireless_modes["11a"] = array();
3862
					$wireless_mode = "11na";
3863
				}
3864
				$wireless_modes["$wireless_mode"]["$c"] = $wireless_channel;
3865
			}
3866
			$c++;
3867
		}
3868
	}
3869
	return($wireless_modes);
3870
}
3871

    
3872
/* return channel numbers, frequency, max txpower, and max regulation txpower */
3873
function get_wireless_channel_info($interface) {
3874
	$wireless_channels = array();
3875

    
3876
	$cloned_interface = get_real_interface($interface);
3877

    
3878
	if($cloned_interface && is_interface_wireless($cloned_interface)) {
3879
		$chan_list = "/sbin/ifconfig {$cloned_interface} list txpower";
3880
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
3881
		$format_list = "/usr/bin/awk '{print \$1 \",\" \$3 \" \" \$4 \",\" \$5 \",\" \$7}'";
3882

    
3883
		$interface_channels = "";
3884
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
3885

    
3886
		foreach ($interface_channels as $channel_line) {
3887
			$channel_line = explode(",", $channel_line);
3888
			if(!isset($wireless_channels[$channel_line[0]]))
3889
				$wireless_channels[$channel_line[0]] = $channel_line;
3890
		}
3891
	}
3892
	return($wireless_channels);
3893
}
3894

    
3895
/****f* interfaces/get_interface_mtu
3896
 * NAME
3897
 *   get_interface_mtu - Return the mtu of an interface
3898
 * RESULT
3899
 *   $tmp       - Returns the mtu of an interface
3900
 ******/
3901
function get_interface_mtu($interface) {
3902
        $mtu = pfSense_get_interface_addresses($interface);
3903
        return $mtu['mtu'];
3904
}
3905

    
3906
function get_interface_mac($interface) {
3907

    
3908
	$macinfo = pfSense_get_interface_addresses($interface);
3909
	return $macinfo["macaddr"];
3910
}
3911

    
3912
/****f* pfsense-utils/generate_random_mac_address
3913
 * NAME
3914
 *   generate_random_mac - generates a random mac address
3915
 * INPUTS
3916
 *   none
3917
 * RESULT
3918
 *   $mac - a random mac address
3919
 ******/
3920
function generate_random_mac_address() {
3921
        $mac = "02";
3922
        for($x=0; $x<5; $x++)
3923
                $mac .= ":" . dechex(rand(16, 255));
3924
        return $mac;
3925
}
3926

    
3927
/****f* interfaces/is_jumbo_capable
3928
 * NAME
3929
 *   is_jumbo_capable - Test if interface is jumbo frame capable.  Useful for determining VLAN capability.
3930
 * INPUTS
3931
 *   $int             - string containing interface name
3932
 * RESULT
3933
 *   boolean          - true or false
3934
 ******/
3935
function is_jumbo_capable($int) {
3936
        global $g;
3937

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

    
3940
        if (in_array($int_family[0], $g['vlan_long_frame']))
3941
                return true;
3942
        else
3943
                return false;
3944
}
3945

    
3946
function setup_pppoe_reset_file($pppif, $iface="") {
3947
	global $g;
3948
	$cron_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
3949

    
3950
	if(!empty($iface) && !empty($pppif)){
3951
		$cron_cmd = <<<EOD
3952
#!/bin/sh
3953
/usr/local/sbin/pfSctl -c 'interface reload {$iface}'
3954
/usr/bin/logger -t pppoe{$iface} "PPPoE periodic reset executed on {$iface}"
3955

    
3956
EOD;
3957

    
3958
		file_put_contents($cron_file, $cron_cmd);
3959
		chmod($cron_file, 0700);
3960
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
3961
	} else
3962
		unlink_if_exists($cron_file);
3963
}
3964

    
3965
function get_vip_descr($ipaddress) {
3966
	global $config;
3967

    
3968
	foreach ($config['virtualip']['vip'] as $vip) {
3969
		if ($vip['subnet'] == $ipaddress) {
3970
			return ($vip['descr']);
3971
		}
3972
	}
3973
	return "";
3974
}
3975

    
3976
?>
(25-25/61)