Project

General

Profile

Download (116 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 (substr($realif, 0, 3) == "gif" && $mtu < 1500)
421
			continue;
422
		if (!isset($opts['encaps']['txcsum']))
423
			$commontx = false;
424
		if (!isset($opts['encaps']['rxcsum']))
425
			$commonrx = false;
426
		if (!isset($opts['encaps']['tso4']))
427
			$commontso4 = false;
428
		if (!isset($opts['encaps']['tso6']))
429
			$commontso6 = false;
430
		if (!isset($opts['encaps']['lro']))
431
			$commonlro = false;
432
		if ($smallermtu == 0 && !empty($mtu))
433
			$smallermtu = $mtu;
434
		else if (!empty($mtu) && $mtu < $smallermtu)
435
			$smallermtu = $mtu;
436
	}
437
	 
438
	/* Just in case anything is not working well */
439
	if ($smallermtu == 0)
440
		$smallermtu = 1500; 
441

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

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

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

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

    
576
	return $bridgeif;
577
}
578

    
579
function interface_bridge_add_member($bridgeif, $interface) {
580

    
581
	if (!does_interface_exist($bridgeif) || !does_interface_exist($interface))
582
		return;
583

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

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

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

    
598
	pfSense_interface_capabilities($interface, -$flags);
599

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

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

    
623
function interface_lagg_configure(&$lagg) {
624
        global $config, $g;
625

    
626
        if (!is_array($lagg))
627
		return -1;
628

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

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

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

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

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

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

    
691
	interfaces_bring_up($laggif);
692

    
693
	return $laggif;
694
}
695

    
696
function interfaces_gre_configure($checkparent = 0) {
697
        global $config;
698

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

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

    
717
	if (!is_array($gre))
718
		return -1;
719

    
720
	$realif = get_real_interface($gre['if']);
721
	$realifip = get_interface_ip($gre['if']);
722

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

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

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

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

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

    
755
	return $greif;
756
}
757

    
758
function interfaces_gif_configure($checkparent = 0) {
759
	global $config;
760

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

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

    
779
	if (!is_array($gif))
780
		return -1;
781

    
782
	$realif = get_real_interface($gif['if']);
783
	$realifip = get_interface_ip($gif['if']);
784

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

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

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

    
814
	$iflist = get_configured_interface_list();
815
	foreach($iflist as $ifname) {
816
		if($config['interfaces'][$ifname]['if'] == $gifif) {
817
			if(get_interface_gateway($ifname)) {
818
				system_routing_configure($ifname);
819
				break;
820
			}
821
			if(get_interface_gateway_v6($ifname)) {
822
				system_routing_configure($ifname);
823
				break;
824
			}
825
		}
826
	}
827

    
828
	if(is_ipaddrv4($gif['tunnel-remote-addr']))
829
		file_put_contents("{$g['tmp_path']}/{$gifif}_router", $gif['tunnel-remote-addr']);
830
	if(is_ipaddrv6($gif['tunnel-remote-addr']))
831
		file_put_contents("{$g['tmp_path']}/{$gifif}_routerv6", $gif['tunnel-remote-addr']);
832

    
833
	return $gifif;
834
}
835

    
836
function interfaces_configure() {
837
	global $config, $g;
838

    
839
	/* Set up our loopback interface */
840
	interfaces_loopback_configure();
841

    
842
	/* set up LAGG virtual interfaces */
843
	interfaces_lagg_configure();
844

    
845
	/* set up VLAN virtual interfaces */
846
	interfaces_vlan_configure();
847

    
848
	interfaces_qinq_configure();
849

    
850
	$iflist = get_configured_interface_with_descr();
851
	$delayed_list = array();
852
	$bridge_list = array();
853
	
854
	/* This is needed to speedup interfaces on bootup. */
855
	$reload = false;
856
	if ($g['booting'])
857
		$reload = true;
858

    
859
	foreach($iflist as $if => $ifname) {
860
		$realif = $config['interfaces'][$if]['if'];
861
		if (strstr($realif, "bridge")) 
862
			$bridge_list[$if] = $ifname;
863
		else if (strstr($realif, "gre"))
864
			$delayed_list[$if] = $ifname;
865
		else if (strstr($realif, "gif"))
866
			$delayed_list[$if] = $ifname;
867
		else if (strstr($realif, "ovpn")) {
868
			//echo "Delaying OpenVPN interface configuration...done.\n";
869
			continue;
870
		} else {
871
			if ($g['booting'])
872
				echo "Configuring {$ifname} interface...";
873
			if($g['debug'])
874
				log_error("Configuring {$ifname}");
875
			interface_configure($if, $reload);
876
			if ($g['booting']) 
877
				echo "done.\n";
878
		}
879
	}
880

    
881
	/* create the unconfigured wireless clones */
882
	interfaces_create_wireless_clones();
883

    
884
	/*
885
	 * NOTE: The following function parameter consists of
886
	 *	1 - Do not load gre/gif/bridge with parent/member as vip
887
	 *	2 - Do load gre/gif/bridge with parent/member as vip
888
	 */
889

    
890
	/* set up GRE virtual interfaces */
891
	interfaces_gre_configure(1);
892

    
893
	/* set up GIF virtual interfaces */
894
	interfaces_gif_configure(1);
895

    
896
	/* set up BRIDGe virtual interfaces */
897
	interfaces_bridge_configure(1);
898

    
899
	/* bring up vip interfaces */
900
	interfaces_vips_configure();
901

    
902
	/* set up GRE virtual interfaces */
903
	interfaces_gre_configure(2);
904

    
905
	/* set up GIF virtual interfaces */
906
	interfaces_gif_configure(2);
907

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

    
914
		interface_configure($if, $reload);
915

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

    
920
	/* set up BRIDGe virtual interfaces */
921
	interfaces_bridge_configure(2);
922

    
923
	foreach ($bridge_list as $if => $ifname) {
924
		if ($g['booting'])
925
			echo "Configuring {$ifname} interface...";
926
		if($g['debug'])
927
			log_error("Configuring {$ifname}");
928

    
929
		interface_configure($if, $reload);
930

    
931
		if ($g['booting'])
932
			echo "done.\n";
933
	}
934

    
935
	/* configure interface groups */
936
	interfaces_group_setup();
937

    
938
	if (!$g['booting']) {
939
		/* reconfigure static routes (kernel may have deleted them) */
940
		system_routing_configure();
941

    
942
		/* reload IPsec tunnels */
943
		vpn_ipsec_configure();
944

    
945
		/* reload dhcpd (interface enabled/disabled status may have changed) */
946
		services_dhcpd_configure();
947

    
948
		/* restart dnsmasq */
949
		services_dnsmasq_configure();
950

    
951
		/* reload captive portal */
952
		captiveportal_init_rules();
953
	}
954

    
955
	return 0;
956
}
957

    
958
function interface_reconfigure($interface = "wan") {
959
	interface_bring_down($interface);
960
	interface_configure($interface, true);
961
}
962

    
963
function interface_vip_bring_down($vip) {
964
	global $g;
965

    
966
	switch ($vip['mode']) {
967
	case "proxyarp":
968
		$vipif = get_real_interface($vip['interface']);
969
		if (file_exists("{$g['varrun_path']}/choparp_{$vipif}.pid"))
970
			killbypid("{$g['varrun_path']}/choparp_{$vipif}.pid");
971
		break;
972
	case "ipalias":
973
		$vipif = get_real_interface($vip['interface']);
974
		if(does_interface_exist($vipif))
975
			pfSense_interface_deladdress($vipif, $vip['subnet']);
976
		break;
977
	case "carp":
978
		$vipif = "vip" . $vip['vhid'];
979
		if(does_interface_exist($vipif)) 
980
			pfSense_interface_destroy($vipif);
981
		break;
982
	case "carpdev-dhcp":
983
		$vipif = "vip" . $vip['vhid'];
984
		if(does_interface_exist($vipif)) 
985
			pfSense_interface_destroy($vipif);
986
		break;
987
	}
988
}
989

    
990
function interface_bring_down($interface = "wan", $destroy = false) {
991
	global $config, $g;
992

    
993
	if (!isset($config['interfaces'][$interface]))
994
		return; 
995

    
996
	$ifcfg = $config['interfaces'][$interface];
997

    
998
	$realif = get_real_interface($interface);
999

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

    
1054
	/* remove interface up file if it exists */
1055
	unlink_if_exists("{$g['tmp_path']}/{$realif}up");
1056
	unlink_if_exists("{$g['vardb_path']}/{$interface}ip");
1057
	unlink_if_exists("{$g['vardb_path']}/{$interface}ipv6");
1058
	unlink_if_exists("{$g['tmp_path']}/{$realif}_router");
1059
	unlink_if_exists("{$g['tmp_path']}/{$realif}_routerv6");
1060
	unlink_if_exists("{$g['varetc_path']}/nameserver_{$realif}");
1061
	unlink_if_exists("{$g['varetc_path']}/searchdomain_{$realif}");
1062
	
1063
	/* hostapd and wpa_supplicant do not need to be running when the interface is down.
1064
	 * They will also use 100% CPU if running after the wireless clone gets deleted. */
1065
	if (is_array($ifcfg['wireless'])) {
1066
		mwexec(kill_hostapd($realif));
1067
		mwexec(kill_wpasupplicant($realif));
1068
	}
1069

    
1070
	if ($destroy == true) {
1071
		if (preg_match("/^vip|^tun|^ovpn|^gif|^gre|^lagg|^bridge|vlan/i", $realif))
1072
			pfSense_interface_destroy($realif);
1073
	}	
1074

    
1075
	return;
1076
}
1077

    
1078
function interfaces_ptpid_used($ptpid) {
1079
	global $config;
1080

    
1081
	if (is_array($config['ppps']['ppp']))
1082
		foreach ($config['ppps']['ppp'] as & $settings)
1083
			if ($ptpid == $settings['ptpid'])
1084
				return true;
1085

    
1086
	return false;
1087
}
1088

    
1089
function interfaces_ptpid_next() {
1090

    
1091
	$ptpid = 0;
1092
	while(interfaces_ptpid_used($ptpid))
1093
		$ptpid++;
1094

    
1095
	return $ptpid;
1096
}
1097

    
1098
function getMPDCRONSettings($pppif_) {
1099
	global $config;
1100
	$cron_cmd_file = "{$g['varetc_path']}/pppoe_restart_";
1101
	if (is_array($config['cron']['item'])) {
1102
		for ($i = 0; $i < count($config['cron']['item']); $i++) {
1103
			$item = $config['cron']['item'][$i];
1104
			if (strpos($item['command'], $cron_cmd_file.$pppif_) !== false) {
1105
				return array("ID" => $i, "ITEM" => $item);
1106
			}
1107
		}
1108
	}
1109
	return NULL;
1110
}
1111

    
1112
function handle_pppoe_reset($post_array) {
1113
	global $config, $g;
1114

    
1115
	$cron_cmd_file = "{$g['varetc_path']}/pppoe_restart_";
1116

    
1117
	$pppif = $post_array['type'].$post_array['ptpid'];
1118
	if (!is_array($config['cron']['item'])) 
1119
		$config['cron']['item'] = array(); 
1120
	$itemhash = getMPDCRONSettings($pppif);
1121
	$item = $itemhash['ITEM'];
1122
	
1123
	// reset cron items if necessary and return
1124
	if (empty($post_array['pppoe-reset-type'])) {
1125
		if (isset($item))
1126
			unset($config['cron']['item'][$itemhash['ID']]);
1127
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
1128
		return;
1129
	}
1130

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

    
1199
/*	This function can configure PPPoE, MLPPP (PPPoE), PPTP.
1200
*	It writes the mpd config file to /var/etc every time the link is opened.
1201
*/
1202

    
1203
function interface_ppps_configure($interface) {
1204
	global $config, $g;
1205

    
1206
	/* Return for unassigned interfaces. This is a minimum requirement. */
1207
	if (empty($config['interfaces'][$interface]))
1208
		return 0;
1209
	$ifcfg = $config['interfaces'][$interface];
1210
	if (!isset($ifcfg['enable']))
1211
		return 0;
1212

    
1213
	// mpd5 requires a /var/spool/lock directory for PPP modem links.
1214
	if(!is_dir("/var/spool/lock")) {
1215
		exec("/bin/mkdir -p /var/spool/lock");
1216
		exec("/bin/chmod a+rw /var/spool/lock/.");
1217
	}
1218
	// mpd5 modem chat script expected in the same directory as the mpd_xxx.conf files	
1219
	if (!file_exists("{$g['varetc_path']}/mpd.script"))
1220
		mwexec("/bin/ln -s /usr/local/sbin/mpd.script {$g['varetc_path']}/.");
1221

    
1222
	if (is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) {
1223
		foreach ($config['ppps']['ppp'] as $pppid => $ppp) {
1224
			if ($ifcfg['if'] == $ppp['if'])
1225
				break;
1226
		}
1227
	}
1228
	if (!$ppp || $ifcfg['if'] != $ppp['if']){
1229
		log_error("Can't find PPP config for {$ifcfg['if']} in interface_ppps_configure().");
1230
		return 0;
1231
	}
1232
	$pppif = $ifcfg['if'];
1233
	if ($ppp['type'] == "ppp")
1234
		$type = "modem";
1235
	else
1236
		$type = $ppp['type'];
1237
	$upper_type = strtoupper($ppp['type']);	
1238

    
1239
	if($g['booting']) {
1240
		$descr = isset($ifcfg['descr']) ? $ifcfg['descr'] : strtoupper($interface);
1241
		echo "starting {$pppif} link...";
1242
		// Do not re-configure the interface if we are booting and it's already been started
1243
		if(file_exists("{$g['varrun_path']}/{$ppp['type']}_{$interface}.pid"))
1244
			return 0;
1245
	}
1246

    
1247
	$ports = explode(',',$ppp['ports']);
1248
	if ($type != "modem") {
1249
		foreach ($ports as $pid => $port)
1250
			$ports[$pid] = get_real_interface($port);
1251
	}
1252
	$localips = explode(',',$ppp['localip']);
1253
	$gateways = explode(',',$ppp['gateway']);
1254
	$subnets = explode(',',$ppp['subnet']);
1255

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

    
1320
		if (is_ipaddr($ppp['gateway']))
1321
			$gateway = $ppp['gateway'];
1322
		else
1323
			$gateway = "10.64.64.{$pppid}";
1324
		$ranges = "{$localip}/0 {$gateway}/0";
1325
		
1326
		if (empty($ppp['apnum']))	
1327
			$ppp['apnum'] = 1;
1328
	} else
1329
		$ranges = "0.0.0.0/0 0.0.0.0/0";
1330

    
1331
	if (isset($ppp['ondemand'])) 
1332
		$ondemand = "enable";
1333
	else
1334
		$ondemand = "disable";
1335
	if (!isset($ppp['idletimeout']))
1336
		$ppp['idletimeout'] = 0;
1337

    
1338
	if (empty($ppp['username']) && $type == "modem"){
1339
		$ppp['username'] = "user";
1340
		$ppp['password'] = "none";
1341
	}
1342
	if (empty($ppp['password']) && $type == "modem")
1343
		$passwd = "none";
1344
	else
1345
		$passwd = base64_decode($ppp['password']);
1346

    
1347
	$bandwidths = explode(',',$ppp['bandwidth']);
1348
	$mtus = explode(',',$ppp['mtu']);
1349
	$mrus = explode(',',$ppp['mru']);
1350

    
1351
	if (isset($ppp['mrru']))
1352
		$mrrus = explode(',',$ppp['mrru']);
1353

    
1354
	// Construct the mpd.conf file
1355
	$mpdconf = <<<EOD
1356
startup:
1357
	# configure the console
1358
	set console close
1359
	# configure the web server
1360
	set web close
1361

    
1362
default:
1363
{$ppp['type']}client:
1364
	create bundle static {$interface}
1365
	set bundle enable ipv6cp
1366
	set iface name {$pppif}
1367

    
1368
EOD;
1369
	$setdefaultgw = false;
1370
	$founddefaultgw = false;
1371
	if (is_array($config['gateways']['gateway_item'])) {
1372
		foreach($config['gateways']['gateway_item'] as $gateway) {
1373
			if($interface == $gateway['interface'] && isset($gateway['defaultgw'])) {
1374
				$setdefaultgw = true;
1375
				break;
1376
			} else if (isset($gateway['defaultgw']) && !empty($gateway['interface'])) {
1377
				$founddefaultgw = true;
1378
				break;
1379
			}
1380
		}
1381
	}
1382
	
1383
	if (($interface == "wan" && $founddefaultgw == false) || $setdefaultgw == true){
1384
		$setdefaultgw = true;
1385
		$mpdconf .= <<<EOD
1386
	set iface route default
1387

    
1388
EOD;
1389
	}
1390
	$mpdconf .= <<<EOD
1391
	set iface {$ondemand} on-demand
1392
	set iface idle {$ppp['idletimeout']}
1393

    
1394
EOD;
1395

    
1396
	if (isset($ppp['ondemand']))
1397
		$mpdconf .= <<<EOD
1398
	set iface addrs 10.10.1.1 10.10.1.2
1399

    
1400
EOD;
1401
	
1402
	if (isset($ppp['tcpmssfix']))
1403
		$tcpmss = "disable";
1404
	else
1405
		$tcpmss = "enable";
1406
		$mpdconf .= <<<EOD
1407
	set iface {$tcpmss} tcpmssfix
1408

    
1409
EOD;
1410

    
1411
	$mpdconf .= <<<EOD
1412
	set iface up-script /usr/local/sbin/ppp-linkup
1413
	set iface down-script /usr/local/sbin/ppp-linkdown
1414
	set ipcp ranges {$ranges}
1415

    
1416
EOD;
1417
	if (isset($ppp['vjcomp']))
1418
		$mpdconf .= <<<EOD
1419
	set ipcp no vjcomp
1420

    
1421
EOD;
1422

    
1423
	if (isset($config['system']['dnsallowoverride']))
1424
		$mpdconf .= <<<EOD
1425
	set ipcp enable req-pri-dns
1426
	set ipcp enable req-sec-dns
1427

    
1428
EOD;
1429
	if (!isset($ppp['verbose_log']))
1430
		$mpdconf .= <<<EOD
1431
	#log -bund -ccp -chat -iface -ipcp -lcp -link
1432

    
1433
EOD;
1434
	foreach($ports as $pid => $port){
1435
		$port = get_real_interface($port);
1436
		$mpdconf .= <<<EOD
1437

    
1438
	create link static {$interface}_link{$pid} {$type}
1439
	set link action bundle {$interface}
1440
	set link {$multilink} multilink
1441
	set link keep-alive 10 60
1442
	set link max-redial 0
1443

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

    
1449
EOD;
1450

    
1451
		if (isset($ppp['acfcomp']))
1452
			$mpdconf .= <<<EOD
1453
	set link no acfcomp
1454

    
1455
EOD;
1456

    
1457
		if (isset($ppp['protocomp']))
1458
			$mpdconf .= <<<EOD
1459
	set link no protocomp
1460

    
1461
EOD;
1462

    
1463
		$mpdconf .= <<<EOD
1464
	set link disable chap pap
1465
	set link accept chap pap eap
1466
	set link disable incoming
1467

    
1468
EOD;
1469

    
1470

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

    
1475
EOD;
1476

    
1477
		if (empty($mtus[$pid]))
1478
			$mtus[$pid] = "1492";
1479
			$mpdconf .= <<<EOD
1480
	set link mtu {$mtus[$pid]}
1481

    
1482
EOD;
1483

    
1484
		if (!empty($mrus[$pid]))
1485
			$mpdconf .= <<<EOD
1486
	set link mru {$mrus[$pid]}
1487

    
1488
EOD;
1489

    
1490
		if (!empty($mrrus[$pid]))
1491
			$mpdconf .= <<<EOD
1492
	set link mrru {$mrrus[$pid]}
1493

    
1494
EOD;
1495

    
1496
		$mpdconf .= <<<EOD
1497
	set auth authname "{$ppp['username']}"
1498
	set auth password {$passwd}
1499

    
1500
EOD;
1501
		if ($type == "modem") {
1502
			$mpdconf .= <<<EOD
1503
	set modem device {$ppp['ports']}
1504
	set modem script DialPeer
1505
	set modem idle-script Ringback
1506
	set modem watch -cd
1507
	set modem var \$DialPrefix "DT"
1508
	set modem var \$Telephone "{$ppp['phone']}"
1509

    
1510
EOD;
1511
		}
1512
		if (isset($ppp['connect-timeout']) && $type == "modem") {
1513
			$mpdconf .= <<<EOD
1514
	set modem var \$ConnectTimeout "{$ppp['connect-timeout']}"
1515

    
1516
EOD;
1517
		}
1518
		if (isset($ppp['initstr']) && $type == "modem") {
1519
			$initstr = base64_decode($ppp['initstr']);
1520
			$mpdconf .= <<<EOD
1521
	set modem var \$InitString "{$initstr}"
1522

    
1523
EOD;
1524
		}
1525
		if (isset($ppp['simpin']) && $type == "modem") {
1526
			$mpdconf .= <<<EOD
1527
	set modem var \$SimPin "{$ppp['simpin']}"
1528
	set modem var \$PinWait "{$ppp['pin-wait']}"
1529

    
1530
EOD;
1531
		}
1532
		if (isset($ppp['apn']) && $type == "modem") {
1533
			$mpdconf .= <<<EOD
1534
	set modem var \$APN "{$ppp['apn']}"
1535
	set modem var \$APNum "{$ppp['apnum']}"
1536

    
1537
EOD;
1538
		}
1539
		if (isset($ppp['provider']) && $type == "pppoe") {
1540
			$mpdconf .= <<<EOD
1541
	set pppoe service "{$ppp['provider']}"
1542

    
1543
EOD;
1544
		}
1545
		if ($type == "pppoe")
1546
			$mpdconf .= <<<EOD
1547
	set pppoe iface {$port}
1548

    
1549
EOD;
1550

    
1551
		if ($type == "pptp" || $type == "l2tp") {
1552
			$mpdconf .= <<<EOD
1553
	set {$type} self {$localips[$pid]}
1554
	set {$type} peer {$gateways[$pid]}
1555

    
1556
EOD;
1557
		}
1558
		
1559
		$mpdconf .= "\topen\r\n";
1560
	} //end foreach($port)
1561

    
1562

    
1563
	/* Generate mpd.conf. If mpd_[interface].conf exists in the conf path, then link to it instead of generating a fresh conf file. */
1564
	if (file_exists("{$g['conf_path']}/mpd_{$interface}.conf"))
1565
		mwexec("/bin/ln -s {$g['conf_path']}/mpd_{$interface}.conf {$g['varetc_path']}/.");
1566
	else {
1567
		$fd = fopen("{$g['varetc_path']}/mpd_{$interface}.conf", "w");
1568
		if (!$fd) {
1569
			log_error("Error: cannot open mpd_{$interface}.conf in interface_ppps_configure().\n");
1570
			return 0;
1571
		}
1572
		// Write out mpd_ppp.conf
1573
		fwrite($fd, $mpdconf);
1574
		fclose($fd);
1575
	}
1576

    
1577
	// Create the uptime log if requested and if it doesn't exist already, or delete it if it is no longer requested.
1578
	if (isset($ppp['uptime'])) {
1579
		if (!file_exists("/conf/{$pppif}.log")) {
1580
			conf_mount_rw();
1581
			mwexec("echo /dev/null > /conf/{$pppif}.log");
1582
			conf_mount_ro();
1583
		}
1584
	} else {
1585
		if (file_exists("/conf/{$pppif}.log")) {
1586
			conf_mount_rw();
1587
			mwexec("rm -f /conf/{$pppif}.log");
1588
			conf_mount_ro();
1589
		}
1590
	}
1591

    
1592
	/* fire up mpd */
1593
	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");
1594

    
1595
	// Check for PPPoE periodic reset request 
1596
	if ($type == "pppoe") {
1597
		if (isset($ppp['pppoe-reset-type']))
1598
			setup_pppoe_reset_file($ppp['if'], $interface);
1599
		else
1600
			setup_pppoe_reset_file($ppp['if']);
1601
	}
1602

    
1603
	return 1;
1604
}
1605

    
1606
function interfaces_carp_setup() {
1607
	global $g, $config;
1608

    
1609
	$balanacing = "";
1610
	$pfsyncinterface = "";
1611
	$pfsyncenabled = "";
1612
	if(isset($config['system']['developerspew'])) {
1613
		$mt = microtime();
1614
		echo "interfaces_carp_setup() being called $mt\n";
1615
	}
1616

    
1617
	// Prepare CmdCHAIN that will be used to execute commands.
1618
	$cmdchain = new CmdCHAIN();	
1619

    
1620
	if ($g['booting']) {
1621
		echo "Configuring CARP settings...";
1622
		mute_kernel_msgs();
1623
	}
1624

    
1625
	/* suck in configuration items */
1626
	if($config['installedpackages']['carpsettings']) {
1627
		if($config['installedpackages']['carpsettings']['config']) {
1628
			foreach($config['installedpackages']['carpsettings']['config'] as $carp) {
1629
				$pfsyncenabled = $carp['pfsyncenabled'];
1630
				$balanacing = $carp['balancing'];
1631
				$pfsyncinterface = $carp['pfsyncinterface'];
1632
				$pfsyncpeerip = $carp['pfsyncpeerip'];
1633
			}
1634
		}
1635
	} else {
1636
		unset($pfsyncinterface);
1637
		unset($balanacing);
1638
		unset($pfsyncenabled);
1639
	}
1640

    
1641
	if($balanacing) {
1642
		$cmdchain->add("Enable CARP ARP-balancing", "/sbin/sysctl net.inet.carp.arpbalance=1", true);
1643
		$cmdchain->add("Disallow CARP preemption", "/sbin/sysctl net.inet.carp.preempt=0", true);
1644
	} else
1645
		$cmdchain->add("Enable CARP preemption", "/sbin/sysctl net.inet.carp.preempt=1", true);		
1646

    
1647
	$cmdchain->add("Enable CARP logging", "/sbin/sysctl net.inet.carp.log=1", true);
1648
	if (!empty($pfsyncinterface))
1649
		$carp_sync_int = get_real_interface($pfsyncinterface);
1650

    
1651
	if($g['booting']) {
1652
		/*    install rules to alllow pfsync to sync up during boot
1653
		 *    carp interfaces will remain down until the bootup sequence finishes
1654
		 */
1655
		$fd = fopen("{$g['tmp_path']}/rules.boot", "w");
1656
		if ($fd) {
1657
			fwrite($fd, "block quick proto carp \n");
1658
			fwrite($fd, "block quick proto pfsync \n");
1659
			fwrite($fd, "pass out quick from any to any keep state\n");
1660
			fclose($fd);
1661
			mwexec("/sbin/pfctl -f {$g['tmp_path']}/rules.boot");
1662
		} else
1663
			log_error("Could not create rules.boot file!");
1664
	}
1665

    
1666
	/* setup pfsync interface */
1667
	if($carp_sync_int and $pfsyncenabled) {
1668
		if (is_ipaddr($pfsyncpeerip))
1669
			$cmdchain->add("Bring up pfsync0 syncpeer", "/sbin/ifconfig pfsync0 syncdev {$carp_sync_int} syncpeer {$pfsyncpeerip} up", false);						
1670
		else
1671
			$cmdchain->add("Bring up pfsync0 syncdev", "/sbin/ifconfig pfsync0 syncdev {$carp_sync_int} up", false);			
1672
	} else
1673
		$cmdchain->add("Bring up pfsync0", "/sbin/ifconfig pfsync0 syncdev lo0 up", false);						
1674

    
1675
	if($config['virtualip']['vip'])
1676
		$cmdchain->add("Allow CARP.", "/sbin/sysctl net.inet.carp.allow=1", true);				
1677
	else
1678
		$cmdchain->add("Disallow CARP.", "/sbin/sysctl net.inet.carp.allow=0", true);		
1679
	
1680
	if($g['debug'])
1681
		$cmdchain->setdebug(); // optional for verbose logging
1682

    
1683
	$cmdchain->execute();
1684
	$cmdchain->clear();
1685

    
1686
	if ($g['booting']) {
1687
		unmute_kernel_msgs();
1688
		echo "done.\n";
1689
	}
1690
}
1691

    
1692
function interface_proxyarp_configure($interface = "") {
1693
	global $config, $g;
1694
	if(isset($config['system']['developerspew'])) {
1695
		$mt = microtime();
1696
		echo "interface_proxyarp_configure() being called $mt\n";
1697
	}
1698

    
1699
	/* kill any running choparp */
1700
	if (empty($interface))
1701
		killbyname("choparp");
1702
	else {
1703
		$vipif = get_real_interface($interface);
1704
		if (file_exists("{$g['varrun_path']}/choparp_{$vipif}.pid"))
1705
			killbypid("{$g['varrun_path']}/choparp_{$vipif}.pid");
1706
	}
1707

    
1708
	$paa = array();
1709
	if (!empty($config['virtualip']) && is_array($config['virtualip']['vip'])) {
1710

    
1711
		/* group by interface */
1712
		foreach ($config['virtualip']['vip'] as $vipent) {
1713
			if ($vipent['mode'] === "proxyarp") {
1714
				if ($vipent['interface'])
1715
					$proxyif = $vipent['interface'];
1716
				else
1717
					$proxyif = "wan";
1718
				
1719
				if (!empty($interface) && $interface != $proxyif)
1720
					continue;
1721

    
1722
				if (!is_array($paa[$proxyif]))
1723
					$paa[$proxyif] = array();
1724

    
1725
				$paa[$proxyif][] = $vipent;
1726
			}
1727
		}
1728
	}
1729

    
1730
	if (!empty($interface)) {
1731
		if (is_array($paa[$interface])) {
1732
			$paaifip = get_interface_ip($interface);
1733
                        if (!is_ipaddr($paaifip))
1734
                                return;
1735
                        $args = get_real_interface($interface) . " auto";
1736
                        foreach ($paa[$interface] as $paent) {
1737
                                if (isset($paent['subnet']))
1738
                                        $args .= " " . escapeshellarg("{$paent['subnet']}/{$paent['subnet_bits']}");
1739
                                else if (isset($paent['range']))
1740
                                        $args .= " " . escapeshellarg($paent['range']['from'] . "-" . $paent['range']['to']);
1741
                        }
1742
                        mwexec_bg("/usr/local/sbin/choparp " . $args);	
1743
		}
1744
	} else if (count($paa) > 0) {
1745
		foreach ($paa as $paif => $paents)  {
1746
			$paaifip = get_interface_ip($paif);
1747
			if (!is_ipaddr($paaifip))
1748
				continue;
1749
			$args = get_real_interface($paif) . " auto";
1750
			foreach ($paents as $paent) {
1751
				if (isset($paent['subnet']))
1752
					$args .= " " . escapeshellarg("{$paent['subnet']}/{$paent['subnet_bits']}");
1753
				else if (isset($paent['range']))
1754
					$args .= " " . escapeshellarg($paent['range']['from'] . "-" . $paent['range']['to']);
1755
			}
1756
			mwexec_bg("/usr/local/sbin/choparp " . $args);
1757
		}
1758
	}
1759
}
1760

    
1761
function interfaces_vips_configure($interface = "") {
1762
	global $g, $config;
1763
	if(isset($config['system']['developerspew'])) {
1764
		$mt = microtime();
1765
		echo "interfaces_vips_configure() being called $mt\n";
1766
	}
1767
	$paa = array();
1768
	if(is_array($config['virtualip']['vip'])) {
1769
		$carp_setuped = false;
1770
		$anyproxyarp = false;
1771
		foreach ($config['virtualip']['vip'] as $vip) {
1772
			switch ($vip['mode']) {
1773
			case "proxyarp":
1774
				/* nothing it is handled on interface_proxyarp_configure() */
1775
				if ($interface <> "" && $vip['interface'] <> $interface)
1776
					continue;
1777
				$anyproxyarp = true;
1778
				break;
1779
			case "ipalias":
1780
				if ($interface <> "" && $vip['interface'] <> $interface)
1781
					continue;
1782
				interface_ipalias_configure(&$vip);
1783
				break;
1784
			case "carp":
1785
				if ($interface <> "" && $vip['interface'] <> $interface)
1786
					continue;
1787
				if ($carp_setuped == false)
1788
					$carp_setuped = true;
1789
				interface_carp_configure($vip);
1790
				break;
1791
			case "carpdev-dhcp":
1792
				if ($interface <> "" && $vip['interface'] <> $interface)
1793
					continue;
1794
				interface_carpdev_configure($vip);
1795
				break;
1796
			}
1797
		}
1798
		if ($carp_setuped == true)
1799
			interfaces_carp_setup();
1800
		if ($anyproxyarp == true)
1801
			interface_proxyarp_configure();
1802
	}
1803
}
1804

    
1805
function interface_ipalias_configure(&$vip) {
1806

    
1807
	if ($vip['mode'] == "ipalias") {
1808
		$if = get_real_interface($vip['interface']);
1809
		mwexec("/sbin/ifconfig " . escapeshellarg($if) . " " . $vip['subnet'] . "/" . escapeshellarg($vip['subnet_bits']) . " alias");
1810
	}
1811
}
1812

    
1813
function interface_reload_carps($cif) {
1814
	global $config;
1815

    
1816
	$carpifs = link_ip_to_carp_interface(find_interface_ip($cif));
1817
	if (empty($carpifs))
1818
		return;
1819

    
1820
	$carps = explode(" ", $carpifs);
1821
	if(is_array($config['virtualip']['vip'])) {
1822
		$viparr = &$config['virtualip']['vip'];
1823
		foreach ($viparr as $vip) {
1824
			if (in_array($vip['carpif'], $carps)) {
1825
				switch ($vip['mode']) {
1826
				case "carp":
1827
					interface_vip_bring_down($vip);
1828
					sleep(1);
1829
					interface_carp_configure($vip);
1830
					break;
1831
				case "carpdev-dhcp":
1832
					interface_vip_bring_down($vip);
1833
					sleep(1);
1834
					interface_carpdev_configure($vip);
1835
					break;
1836
				case "ipalias":
1837
					interface_vip_bring_down($vip);
1838
					sleep(1);
1839
					interface_ipalias_configure($vip);
1840
					break;
1841
				}
1842
			}
1843
		}
1844
	}
1845
}
1846

    
1847
function interface_carp_configure(&$vip) {
1848
	global $config, $g;
1849
	if(isset($config['system']['developerspew'])) {
1850
		$mt = microtime();
1851
		echo "interface_carp_configure() being called $mt\n";
1852
	}
1853

    
1854
	if ($vip['mode'] != "carp")
1855
		return;
1856

    
1857
	$vip_password = $vip['password'];
1858
	$vip_password = escapeshellarg(addslashes(str_replace(" ", "", $vip_password)));
1859
	if ($vip['password'] != "")
1860
		$password = " pass {$vip_password}";
1861

    
1862
	// set the vip interface to the vhid
1863
	$vipif = "vip{$vip['vhid']}";
1864

    
1865
	/*
1866
	 * ensure the interface containing the VIP really exists
1867
 	 * prevents a panic if the interface is missing or invalid
1868
	 */
1869
	$realif = get_real_interface($vip['interface']);
1870
	if (!does_interface_exist($realif)) {
1871
		file_notice("CARP", "Interface specified for the virtual IP address {$vip['subnet']} does not exist. Skipping this VIP.", "Firewall: Virtual IP", "");
1872
		return;
1873
	}
1874

    
1875
	if(is_ipaddrv4($vip['subnet'])) {
1876
		/* Ensure CARP IP really exists prior to loading up. */
1877
		$ww_subnet_ip = find_interface_ip($realif);
1878
		$ww_subnet_bits = find_interface_subnet($realif);
1879
		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'])) {
1880
			file_notice("CARP", "Sorry but we could not find a matching real interface subnet for the virtual IP address {$vip['subnet']}.", "Firewall: Virtual IP", "");
1881
			return;
1882
		}
1883
	}
1884
	if(is_ipaddrv6($vip['subnet'])) {
1885
		/* Ensure CARP IP really exists prior to loading up. */
1886
		$ww_subnet_ip = find_interface_ipv6($realif);
1887
		$ww_subnet_bits = find_interface_subnetv6($realif);
1888
		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'])) {
1889
			file_notice("CARP", "Sorry but we could not find a matching real interface subnet for the virtual IPv6 address {$vip['subnet']}.", "Firewall: Virtual IP", "");
1890
			return;
1891
		}
1892
	}
1893

    
1894
	/* create the carp interface and setup */
1895
	if (does_interface_exist($vipif)) {
1896
		pfSense_interface_flags($vipif, -IFF_UP);
1897
	} else {
1898
		$carpif = pfSense_interface_create("carp");
1899
		pfSense_interface_rename($carpif, $vipif);
1900
		pfSense_ngctl_name("{$carpif}:", $vipif);
1901
	}
1902

    
1903
	/* invalidate interface cache */
1904
	get_interface_arr(true);
1905

    
1906
	$advbase = "";
1907
	if (!empty($vip['advbase']))
1908
		$advbase = "advbase {$vip['advbase']}";
1909

    
1910
	if(is_ipaddrv4($vip['subnet'])) {
1911
		$broadcast_address = gen_subnet_max($vip['subnet'], $vip['subnet_bits']);
1912
		mwexec("/sbin/ifconfig {$vipif} {$vip['subnet']}/{$vip['subnet_bits']} vhid {$vip['vhid']} advskew {$vip['advskew']} {$advbase} {$password}");
1913
	}
1914
	if(is_ipaddrv6($vip['subnet'])) {
1915
		$broadcast_address = gen_subnet_max($vip['subnet'], $vip['subnet_bits']);
1916
		mwexec("/sbin/ifconfig {$vipif} inet6 {$vip['subnet']} prefixlen {$vip['subnet_bits']} vhid {$vip['vhid']} advskew {$vip['advskew']} {$advbase} {$password}");
1917
	}
1918

    
1919
	interfaces_bring_up($vipif);
1920
	
1921
	return $vipif;
1922
}
1923

    
1924
function interface_carpdev_configure(&$vip) {
1925
	global $g;
1926

    
1927
	if ($vip['mode'] != "carpdev-dhcp")
1928
		return;
1929

    
1930
	$vip_password = $vip['password'];
1931
	$vip_password = str_replace(" ", "", $vip_password);
1932
	if($vip['password'] != "")
1933
		$password = " pass \"" . $vip_password . "\"";
1934

    
1935
	if (empty($vip['interface']))
1936
		return;
1937

    
1938
	$vipif = "vip" . $vip['vhid'];
1939
	$realif = get_real_interface($vip['interface']);
1940
	interfaces_bring_up($realif);
1941
	/*
1942
	 * ensure the interface containing the VIP really exists
1943
	 * prevents a panic if the interface is missing or invalid
1944
	 */
1945
	if (!does_interface_exist($realif)) {
1946
		file_notice("CARP", "Interface specified for the virtual IP address {$vip['subnet']} does not exist. Skipping this VIP.", "Firewall: Virtual IP", "");
1947
		return;
1948
	}
1949

    
1950
	if (does_interface_exist($vipif)) {
1951
		interface_bring_down($vipif);
1952
	} else {
1953
		$carpdevif = exec("/sbin/ifconfig carp create");
1954
		mwexec("/sbin/ifconfig {$carpdevif} name {$vipif}");
1955
		pfSense_ngctl_name("{$carpdevif}:", $vipif);
1956
	}
1957

    
1958
	mwexec("/sbin/ifconfig {$vipif} carpdev {$realif} vhid {$vip['vhid']} advskew {$vip['advskew']} advbase {$vip['advbase']} {$password}");
1959
	interfaces_bring_up($vipif);
1960

    
1961
	/*
1962
	 * XXX: BIG HACK but carpdev needs ip services active
1963
	 *      before even starting something as dhclient.
1964
	 *      I do not know if this is a feature or a bug
1965
	 *      but better than track it make it work ;) .
1966
	 */
1967
	//$fakeiptouse = "10.254.254." . ($carp_instances_counter+1);
1968
	//$cmdchain->add("CarpDEV hack", "/sbin/ifconfig {$carpint} inet {$fakeiptouse}", false);
1969

    
1970
	/* generate dhclient_wan.conf */
1971
	$fd = fopen("{$g['varetc_path']}/dhclient_{$vipif}.conf", "w");
1972
	if ($fd) {
1973
		$dhclientconf = "";
1974

    
1975
		$dhclientconf .= <<<EOD
1976
interface "{$vipif}" {
1977
timeout 60;
1978
retry 1;
1979
select-timeout 0;
1980
initial-interval 1;
1981
script "/sbin/dhclient-script";
1982
}
1983

    
1984
EOD;
1985

    
1986
		fwrite($fd, $dhclientconf);
1987
		fclose($fd);
1988

    
1989
		/* fire up dhclient */
1990
		mwexec("/sbin/dhclient -c {$g['varetc_path']}/dhclient_{$vipif}.conf {$vipif} >{$g['tmp_path']}/{$vipif}_output 2>{$g['tmp_path']}/{$vipif}_error_output", false);
1991
	} else {
1992
		log_error("Error: cannot open dhclient_{$vipif}.conf in interfaces_carpdev_configure() for writing.\n");
1993
		mwexec("/sbin/dhclient -b {$vipif}");
1994
	}
1995

    
1996
	return $vipif;
1997
}
1998

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

    
2040
	if($needs_clone == true) {
2041
		/* remove previous instance if it exists */
2042
		if(does_interface_exist($realif))
2043
			pfSense_interface_destroy($realif);
2044

    
2045
		log_error("Cloning new wireless interface {$realif}");
2046
		// Create the new wlan interface. FreeBSD returns the new interface name.
2047
		// example:  wlan2
2048
		exec("/sbin/ifconfig wlan create wlandev {$baseif} {$mode} bssid 2>&1", $out, $ret);
2049
		if($ret <> 0) {
2050
			log_error("Failed to clone interface {$baseif} with error code {$ret}, output {$out[0]}");
2051
			return false;
2052
		}
2053
		$newif = trim($out[0]);
2054
		// Rename the interface to {$parentnic}_wlan{$number}#: EX: ath0_wlan0
2055
		pfSense_interface_rename($newif, $realif);
2056
		// FIXME: not sure what ngctl is for. Doesn't work.
2057
		// mwexec("/usr/sbin/ngctl name {$newif}: {$realif}", false);
2058
		file_put_contents("{$g['tmp_path']}/{$realif}_oldmac", get_interface_mac($realif));
2059
	}
2060
	return true;
2061
}
2062

    
2063
function interface_sync_wireless_clones(&$ifcfg, $sync_changes = false) {
2064
	global $config, $g;
2065

    
2066
	$shared_settings = array('standard', 'turbo', 'protmode', 'txpower', 'channel',
2067
	                         'diversity', 'txantenna', 'rxantenna', 'distance',
2068
	                         'regdomain', 'regcountry', 'reglocation');
2069

    
2070
	if(!is_interface_wireless($ifcfg['if']))
2071
		return;
2072

    
2073
	$baseif = interface_get_wireless_base($ifcfg['if']);
2074

    
2075
	// Sync shared settings for assigned clones
2076
	$iflist = get_configured_interface_list(false, true);
2077
	foreach ($iflist as $if) {
2078
		if ($baseif == interface_get_wireless_base($config['interfaces'][$if]['if']) && $ifcfg['if'] != $config['interfaces'][$if]['if']) {
2079
			if (isset($config['interfaces'][$if]['wireless']['standard']) || $sync_changes) {
2080
				foreach ($shared_settings as $setting) {
2081
					if ($sync_changes) {
2082
						if (isset($ifcfg['wireless'][$setting]))
2083
							$config['interfaces'][$if]['wireless'][$setting] = $ifcfg['wireless'][$setting];
2084
						else if (isset($config['interfaces'][$if]['wireless'][$setting]))
2085
							unset($config['interfaces'][$if]['wireless'][$setting]);
2086
					} else {
2087
						if (isset($config['interfaces'][$if]['wireless'][$setting]))
2088
							$ifcfg['wireless'][$setting] = $config['interfaces'][$if]['wireless'][$setting];
2089
						else if (isset($ifcfg['wireless'][$setting]))
2090
							unset($ifcfg['wireless'][$setting]);
2091
					}
2092
				}
2093
				if (!$sync_changes)
2094
					break;
2095
			}
2096
		}
2097
	}
2098

    
2099
	// Read or write settings at shared area
2100
	if (isset($config['wireless']['interfaces'][$baseif])) {
2101
		foreach ($shared_settings as $setting) {
2102
			if ($sync_changes) {
2103
				if (isset($ifcfg['wireless'][$setting]))
2104
					$config['wireless']['interfaces'][$baseif][$setting] = $ifcfg['wireless'][$setting];
2105
				else if (isset($config['wireless']['interfaces'][$baseif][$setting]))
2106
					unset($config['wireless']['interfaces'][$baseif][$setting]);
2107
			} else if (isset($config['wireless']['interfaces'][$baseif][$setting])) {
2108
				if (isset($config['wireless']['interfaces'][$baseif][$setting]))
2109
					$ifcfg['wireless'][$setting] = $config['wireless']['interfaces'][$baseif][$setting];
2110
				else if (isset($ifcfg['wireless'][$setting]))
2111
					unset($ifcfg['wireless'][$setting]);
2112
			}
2113
		}
2114
	}
2115

    
2116
	// Sync the mode on the clone creation page with the configured mode on the interface
2117
	if (interface_is_wireless_clone($ifcfg['if'])) {
2118
		foreach ($config['wireless']['clone'] as &$clone) {
2119
			if ($clone['cloneif'] == $ifcfg['if']) {
2120
				if ($sync_changes) {
2121
					$clone['mode'] = $ifcfg['wireless']['mode'];
2122
				} else {
2123
					$ifcfg['wireless']['mode'] = $clone['mode'];
2124
				}
2125
				break;
2126
			}
2127
		}
2128
		unset($clone);
2129
	}
2130
}
2131

    
2132
function interface_wireless_configure($if, &$wl, &$wlcfg) {
2133
	global $config, $g;
2134

    
2135
	/*    open up a shell script that will be used to output the commands.
2136
	 *    since wireless is changing a lot, these series of commands are fragile
2137
     *    and will sometimes need to be verified by a operator by executing the command
2138
     *    and returning the output of the command to the developers for inspection.  please
2139
     *    do not change this routine from a shell script to individul exec commands.  -sullrich
2140
	 */
2141

    
2142
	// Remove script file
2143
	unlink_if_exists("{$g['tmp_path']}/{$if}_setup.sh");
2144

    
2145
	// Clone wireless nic if needed.
2146
	interface_wireless_clone($if, $wl);
2147

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

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

    
2155
	/* set values for /path/program */
2156
	$hostapd = "/usr/sbin/hostapd";
2157
	$wpa_supplicant = "/usr/sbin/wpa_supplicant";
2158
	$ifconfig = "/sbin/ifconfig";
2159
	$sysctl = "/sbin/sysctl";
2160
	$killall = "/usr/bin/killall";
2161

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

    
2164
	$wlcmd = array();
2165
	$wl_sysctl = array();
2166
	/* Make sure it's up */
2167
	$wlcmd[] = "up";
2168
	/* Set a/b/g standard */
2169
	$standard = str_replace(" Turbo", "", $wlcfg['standard']);
2170
	$wlcmd[] = "mode " . escapeshellarg($standard);
2171

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

    
2177
	/* Set ssid */
2178
	if($wlcfg['ssid'])
2179
		$wlcmd[] = "ssid " .escapeshellarg($wlcfg['ssid']);
2180

    
2181
	/* Set 802.11g protection mode */
2182
	$wlcmd[] = "protmode " . escapeshellarg($wlcfg['protmode']);
2183

    
2184
	/* set wireless channel value */
2185
	if(isset($wlcfg['channel'])) {
2186
		if($wlcfg['channel'] == "0") {
2187
			$wlcmd[] = "channel any";
2188
		} else {
2189
			$wlcmd[] = "channel " . escapeshellarg($wlcfg['channel']);
2190
		}
2191
	}
2192

    
2193
	/* Set antenna diversity value */
2194
	if(isset($wlcfg['diversity']))
2195
		$wl_sysctl[] = "diversity=" . escapeshellarg($wlcfg['diversity']);
2196

    
2197
	/* Set txantenna value */
2198
	if(isset($wlcfg['txantenna']))
2199
		$wl_sysctl[] = "txantenna=" . escapeshellarg($wlcfg['txantenna']);
2200

    
2201
	/* Set rxantenna value */
2202
	if(isset($wlcfg['rxantenna']))
2203
		$wl_sysctl[] = "rxantenna=" . escapeshellarg($wlcfg['rxantenna']);
2204

    
2205
	/* set Distance value */
2206
	if($wlcfg['distance'])
2207
		$distance = escapeshellarg($wlcfg['distance']);
2208

    
2209
	/* Set wireless hostap mode */
2210
	if ($wlcfg['mode'] == "hostap") {
2211
		$wlcmd[] = "mediaopt hostap";
2212
	} else {
2213
		$wlcmd[] = "-mediaopt hostap";
2214
	}
2215

    
2216
	/* Set wireless adhoc mode */
2217
	if ($wlcfg['mode'] == "adhoc") {
2218
		$wlcmd[] = "mediaopt adhoc";
2219
	} else {
2220
		$wlcmd[] = "-mediaopt adhoc";
2221
	}
2222

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

    
2225
	/* handle hide ssid option */
2226
	if(isset($wlcfg['hidessid']['enable'])) {
2227
		$wlcmd[] = "hidessid";
2228
	} else {
2229
		$wlcmd[] = "-hidessid";
2230
	}
2231

    
2232
	/* handle pureg (802.11g) only option */
2233
	if(isset($wlcfg['pureg']['enable'])) {
2234
		$wlcmd[] = "mode 11g pureg";
2235
	} else {
2236
		$wlcmd[] = "-pureg";
2237
	}
2238

    
2239
	/* handle puren (802.11n) only option */
2240
	if(isset($wlcfg['puren']['enable'])) {
2241
		$wlcmd[] = "puren";
2242
	} else {
2243
		$wlcmd[] = "-puren";
2244
	}
2245

    
2246
	/* enable apbridge option */
2247
	if(isset($wlcfg['apbridge']['enable'])) {
2248
		$wlcmd[] = "apbridge";
2249
	} else {
2250
		$wlcmd[] = "-apbridge";
2251
	}
2252

    
2253
	/* handle turbo option */
2254
	if(isset($wlcfg['turbo']['enable'])) {
2255
		$wlcmd[] = "mediaopt turbo";
2256
	} else {
2257
		$wlcmd[] = "-mediaopt turbo";
2258
	}
2259

    
2260
	/* handle txpower setting */
2261
	/* if($wlcfg['txpower'] <> "")
2262
		$wlcmd[] = "txpower " . escapeshellarg($wlcfg['txpower']);
2263
	*/
2264
	/* handle wme option */
2265
	if(isset($wlcfg['wme']['enable'])) {
2266
		$wlcmd[] = "wme";
2267
	} else {
2268
		$wlcmd[] = "-wme";
2269
	}
2270

    
2271
	/* set up wep if enabled */
2272
	$wepset = "";
2273
	if (isset($wlcfg['wep']['enable']) && is_array($wlcfg['wep']['key'])) {
2274
		switch($wlcfg['wpa']['auth_algs']) {
2275
			case "1":
2276
				$wepset .= "authmode open wepmode on ";
2277
				break;
2278
			case "2":
2279
				$wepset .= "authmode shared wepmode on ";
2280
				break;
2281
			case "3":
2282
				$wepset .= "authmode mixed wepmode on ";
2283
		}
2284
		$i = 1;
2285
		foreach ($wlcfg['wep']['key'] as $wepkey) {
2286
			$wepset .= "wepkey " . escapeshellarg("{$i}:{$wepkey['value']}") . " ";
2287
			if (isset($wepkey['txkey'])) {
2288
				$wlcmd[] = "weptxkey {$i} ";
2289
			}
2290
			$i++;
2291
		}
2292
		$wlcmd[] = $wepset;
2293
	} else {
2294
		$wlcmd[] = "authmode open wepmode off ";
2295
	}
2296

    
2297
	mwexec(kill_hostapd("{$if}"));
2298
	mwexec(kill_wpasupplicant("{$if}"));
2299

    
2300
	/* generate wpa_supplicant/hostap config if wpa is enabled */
2301
	conf_mount_rw();
2302

    
2303
	switch ($wlcfg['mode']) {
2304
		case 'bss':
2305
			if (isset($wlcfg['wpa']['enable'])) {
2306
				$wpa .= <<<EOD
2307
ctrl_interface={$g['varrun_path']}/wpa_supplicant
2308
ctrl_interface_group=0
2309
ap_scan=1
2310
#fast_reauth=1
2311
network={
2312
ssid="{$wlcfg['ssid']}"
2313
scan_ssid=1
2314
priority=5
2315
key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
2316
psk="{$wlcfg['wpa']['passphrase']}"
2317
pairwise={$wlcfg['wpa']['wpa_pairwise']}
2318
group={$wlcfg['wpa']['wpa_pairwise']}
2319
}
2320
EOD;
2321

    
2322
				$fd = fopen("{$g['varetc_path']}/wpa_supplicant_{$if}.conf", "w");
2323
				fwrite($fd, "{$wpa}");
2324
				fclose($fd);
2325
			}
2326
			break;
2327
		case 'hostap':
2328
			if($wlcfg['wpa']['passphrase']) 
2329
				$wpa_passphrase = "wpa_passphrase={$wlcfg['wpa']['passphrase']}\n";
2330
			else 
2331
				$wpa_passphrase = "";
2332
			if (isset($wlcfg['wpa']['enable'])) {
2333
				$wpa .= <<<EOD
2334
interface={$if}
2335
driver=bsd
2336
logger_syslog=-1
2337
logger_syslog_level=0
2338
logger_stdout=-1
2339
logger_stdout_level=0
2340
dump_file={$g['tmp_path']}/hostapd_{$if}.dump
2341
ctrl_interface={$g['varrun_path']}/hostapd
2342
ctrl_interface_group=wheel
2343
#accept_mac_file={$g['tmp_path']}/hostapd_{$if}.accept
2344
#deny_mac_file={$g['tmp_path']}/hostapd_{$if}.deny
2345
#macaddr_acl={$wlcfg['wpa']['macaddr_acl']}
2346
ssid={$wlcfg['ssid']}
2347
debug={$wlcfg['wpa']['debug_mode']}
2348
auth_algs={$wlcfg['wpa']['auth_algs']}
2349
wpa={$wlcfg['wpa']['wpa_mode']}
2350
wpa_key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
2351
wpa_pairwise={$wlcfg['wpa']['wpa_pairwise']}
2352
wpa_group_rekey={$wlcfg['wpa']['wpa_group_rekey']}
2353
wpa_gmk_rekey={$wlcfg['wpa']['wpa_gmk_rekey']}
2354
wpa_strict_rekey={$wlcfg['wpa']['wpa_strict_rekey']}
2355
{$wpa_passphrase}
2356

    
2357
EOD;
2358

    
2359
if (isset($wlcfg['wpa']['rsn_preauth'])) {
2360
	$wpa .= <<<EOD
2361
# Enable the next lines for preauth when roaming. Interface = wired or wireless interface talking to the AP you want to roam from/to
2362
rsn_preauth=1
2363
rsn_preauth_interfaces={$if}
2364

    
2365
EOD;
2366

    
2367
}
2368
				if($wlcfg['auth_server_addr'] && $wlcfg['auth_server_shared_secret']) {
2369
					$auth_server_port = "1812";
2370
					if($wlcfg['auth_server_port']) 
2371
						$auth_server_port = $wlcfg['auth_server_port'];
2372
					$wpa .= <<<EOD
2373

    
2374
ieee8021x=1
2375
auth_server_addr={$wlcfg['auth_server_addr']}
2376
auth_server_port={$auth_server_port}
2377
auth_server_shared_secret={$wlcfg['auth_server_shared_secret']}
2378

    
2379
EOD;
2380
				} else {
2381
					$wpa .= "ieee8021x={$wlcfg['wpa']['ieee8021x']}\n";
2382
				}
2383

    
2384
				$fd = fopen("{$g['varetc_path']}/hostapd_{$if}.conf", "w");
2385
				fwrite($fd, "{$wpa}");
2386
				fclose($fd);
2387

    
2388
			}
2389
			break;
2390
	}
2391

    
2392
	/*
2393
	 *    all variables are set, lets start up everything
2394
	 */
2395

    
2396
	$baseif = interface_get_wireless_base($if);
2397
	preg_match("/^(.*?)([0-9]*)$/", $baseif, $baseif_split);
2398
	$wl_sysctl_prefix = 'dev.' . $baseif_split[1] . '.' . $baseif_split[2];
2399

    
2400
	/* set sysctls for the wireless interface */
2401
	if (!empty($wl_sysctl)) {
2402
		fwrite($fd_set, "# sysctls for {$baseif}\n");
2403
		foreach ($wl_sysctl as $wl_sysctl_line) {
2404
			fwrite($fd_set, "{$sysctl} {$wl_sysctl_prefix}.{$wl_sysctl_line}\n");
2405
		}
2406
	}
2407

    
2408
	/* set ack timers according to users preference (if he/she has any) */
2409
	if($distance) {
2410
		fwrite($fd_set, "# Enable ATH distance settings\n");
2411
		fwrite($fd_set, "/sbin/athctrl.sh -i {$baseif} -d {$distance}\n");
2412
	}
2413

    
2414
	if (isset($wlcfg['wpa']['enable'])) {
2415
		if ($wlcfg['mode'] == "bss") {
2416
			fwrite($fd_set, "{$wpa_supplicant} -B -i {$if} -c {$g['varetc_path']}/wpa_supplicant_{$if}.conf\n");
2417
		}
2418
		if ($wlcfg['mode'] == "hostap") {
2419
			/* add line to script to restore old mac to make hostapd happy */
2420
			if (file_exists("{$g['tmp_path']}/{$if}_oldmac")) {
2421
				$if_oldmac = file_get_contents("{$g['tmp_path']}/{$if}_oldmac");
2422
				if (is_macaddr($if_oldmac))
2423
					fwrite($fd_set, "{$ifconfig} " . escapeshellarg($if) .
2424
						" link " . escapeshellarg($if_oldmac) . "\n");
2425
			}
2426

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

    
2429
			/* add line to script to restore spoofed mac after running hostapd */
2430
			if (file_exists("{$g['tmp_path']}/{$if}_oldmac")) {
2431
				if ($wl['spoofmac'])
2432
					$if_curmac = $wl['spoofmac'];
2433
				else
2434
					$if_curmac = get_interface_mac($if);
2435
				if (is_macaddr($if_curmac))
2436
					fwrite($fd_set, "{$ifconfig} " . escapeshellarg($if) .
2437
						" link " . escapeshellarg($if_curmac) . "\n");
2438
			}
2439
		}
2440
	}
2441

    
2442
	fclose($fd_set);
2443
	conf_mount_ro();
2444

    
2445
	/* Making sure regulatory settings have actually changed
2446
	 * before applying, because changing them requires bringing
2447
	 * down all wireless networks on the interface. */
2448
	exec("{$ifconfig} " . escapeshellarg($if), $output);
2449
	$ifconfig_str = implode($output);
2450
	unset($output);
2451
	$reg_changing = false;
2452

    
2453
	/* special case for the debug country code */
2454
	if ($wlcfg['regcountry'] == 'DEBUG' && !preg_match("/\sregdomain\s+DEBUG\s/si", $ifconfig_str))
2455
		$reg_changing = true;
2456
	else if ($wlcfg['regdomain'] && !preg_match("/\sregdomain\s+{$wlcfg['regdomain']}\s/si", $ifconfig_str))
2457
		$reg_changing = true;
2458
	else if ($wlcfg['regcountry'] && !preg_match("/\scountry\s+{$wlcfg['regcountry']}\s/si", $ifconfig_str))
2459
		$reg_changing = true;
2460
	else if ($wlcfg['reglocation'] == 'anywhere' && preg_match("/\s(indoor|outdoor)\s/si", $ifconfig_str))
2461
		$reg_changing = true;
2462
	else if ($wlcfg['reglocation'] && $wlcfg['reglocation'] != 'anywhere' && !preg_match("/\s{$wlcfg['reglocation']}\s/si", $ifconfig_str))
2463
		$reg_changing = true;
2464

    
2465
	if ($reg_changing) {
2466
		/* set regulatory domain */
2467
		if($wlcfg['regdomain'])
2468
			$wlregcmd[] = "regdomain " . escapeshellarg($wlcfg['regdomain']);
2469

    
2470
		/* set country */
2471
		if($wlcfg['regcountry'])
2472
			$wlregcmd[] = "country " . escapeshellarg($wlcfg['regcountry']);
2473

    
2474
		/* set location */
2475
		if($wlcfg['reglocation'])
2476
			$wlregcmd[] = escapeshellarg($wlcfg['reglocation']);
2477

    
2478
		$wlregcmd_args = implode(" ", $wlregcmd);
2479

    
2480
		/* build a complete list of the wireless clones for this interface */
2481
		$clone_list = array();
2482
		if (does_interface_exist(interface_get_wireless_clone($baseif)))
2483
			$clone_list[] = interface_get_wireless_clone($baseif);
2484
		if (is_array($config['wireless']['clone'])) {
2485
			foreach ($config['wireless']['clone'] as $clone) {
2486
				if ($clone['if'] == $baseif)
2487
					$clone_list[] = $clone['cloneif'];
2488
			}
2489
		}
2490

    
2491
		/* find which clones are up and bring them down */
2492
		$clones_up = array();
2493
		foreach ($clone_list as $clone_if) {
2494
			$clone_status = pfSense_get_interface_addresses($clone_if);
2495
			if ($clone_status['status'] == 'up') {
2496
				$clones_up[] = $clone_if;
2497
				mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " down");
2498
			}
2499
		}
2500

    
2501
		/* apply the regulatory settings */
2502
		mwexec("{$ifconfig} " . escapeshellarg($if) . " {$wlregcmd_args}");
2503

    
2504
		/* bring the clones back up that were previously up */
2505
		foreach ($clones_up as $clone_if) {
2506
			mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " up");
2507

    
2508
			/*
2509
			 * Rerun the setup script for the interface if it isn't this interface, the interface
2510
			 * is in infrastructure mode, and WPA is enabled.
2511
			 * This can be removed if wpa_supplicant stops dying when you bring the interface down.
2512
			 */
2513
			if ($clone_if != $if) {
2514
				$friendly_if = convert_real_interface_to_friendly_interface_name($clone_if);
2515
				if ( !empty($friendly_if)
2516
				    && $config['interfaces'][$friendly_if]['wireless']['mode'] == "bss"
2517
				    && isset($config['interfaces'][$friendly_if]['wireless']['wpa']['enable']) ) {
2518
					mwexec("/bin/sh {$g['tmp_path']}/{$clone_if}_setup.sh");
2519
				}
2520
			}
2521
		}
2522
	}
2523

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

    
2528
	/* configure wireless */
2529
	$wlcmd_args = implode(" ", $wlcmd);
2530
	mwexec("/sbin/ifconfig {$if} $wlcmd_args", false);
2531

    
2532
	
2533
	sleep(1);
2534
	/* execute hostapd and wpa_supplicant if required in shell */
2535
	mwexec("/bin/sh {$g['tmp_path']}/{$if}_setup.sh");
2536

    
2537
	return 0;
2538

    
2539
}
2540

    
2541
function kill_hostapd($interface) {
2542
	return "/bin/pkill -f \"hostapd .*{$interface}\"\n";
2543
}
2544

    
2545
function kill_wpasupplicant($interface) {
2546
	return "/bin/pkill -f \"wpa_supplicant .*{$interface}\"\n";
2547
}
2548

    
2549
function find_dhclient_process($interface) {
2550
	if ($interface)
2551
		$pid = `/bin/pgrep -axf "dhclient: {$interface}"`;
2552
	else
2553
		$pid = 0;
2554

    
2555
	return intval($pid);
2556
}
2557

    
2558
function find_dhcp6c_process($interface) {
2559
	if ($interface)
2560
		$pid = `/bin/ps auxw|grep "dhcp6c" |grep "{$interface}"|awk '{print $2}'`;
2561
	else
2562
		$pid = 0;
2563

    
2564
	return intval($pid);
2565
}
2566

    
2567
function interface_configure($interface = "wan", $reloadall = false, $linkupevent = false) {
2568
	global $config, $g;
2569
	global $interface_sn_arr_cache, $interface_ip_arr_cache;
2570
	global $interface_snv6_arr_cache, $interface_ipv6_arr_cache;
2571

    
2572
	$wancfg = $config['interfaces'][$interface];
2573

    
2574
	$realif = get_real_interface($interface);
2575
	$realhwif_array = get_parent_interface($interface);
2576
	// Need code to handle MLPPP if we ever use $realhwif for MLPPP handling
2577
	$realhwif = $realhwif_array[0];
2578

    
2579
			
2580
	if (!$g['booting'] && !substr($realif, 0, 4) == "ovpn") {
2581
		/* remove all IPv4 and IPv6 addresses */
2582
		while (mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " -alias", true) == 0);
2583
		while (mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 -alias", true) == 0);
2584
		/* Disable Accepting router advertisements unless specifically requested */
2585
		while (mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 -accept_rtadv") == 0);
2586

    
2587
		switch ($wancfg['ipaddr']) {
2588
			case 'pppoe':
2589
			case 'l2tp':
2590
			case 'pptp':
2591
			case 'ppp':
2592
				break;
2593
			default:
2594
				interface_bring_down($interface);
2595
				break;
2596
		}
2597
	}
2598

    
2599
	/* wireless configuration? */
2600
	if (is_array($wancfg['wireless']))
2601
		interface_wireless_configure($realif, $wancfg, $wancfg['wireless']);
2602

    
2603
	if ($wancfg['spoofmac']) {
2604
		mwexec("/sbin/ifconfig " . escapeshellarg($realhwif) .
2605
			" link " . escapeshellarg($wancfg['spoofmac']));
2606

    
2607
                /*
2608
                 * All vlans need to spoof their parent mac address, too.  see
2609
                 * ticket #1514: http://cvstrac.pfsense.com/tktview?tn=1514,33
2610
                 */
2611
                if (is_array($config['vlans']['vlan'])) {
2612
                        foreach ($config['vlans']['vlan'] as $vlan) {
2613
                                if ($vlan['if'] == $realhwif)
2614
                                        mwexec("/sbin/ifconfig " . escapeshellarg($vlan['vlanif']) .
2615
                                                " link " . escapeshellarg($wancfg['spoofmac']));
2616
                        }
2617
                }
2618
	}  else {
2619
		$mac = get_interface_mac($realhwif);
2620
		if ($mac == "ff:ff:ff:ff:ff:ff") {
2621
			/*   this is not a valid mac address.  generate a
2622
			 *   temporary mac address so the machine can get online.
2623
			 */
2624
			echo "Generating new MAC address.";
2625
			$random_mac = generate_random_mac_address();
2626
			mwexec("/sbin/ifconfig " . escapeshellarg($realhwif) .
2627
				" link " . escapeshellarg($random_mac));
2628
			$wancfg['spoofmac'] = $random_mac;
2629
			write_config();
2630
			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");
2631
		}
2632
	}
2633

    
2634
	/* media */
2635
	if ($wancfg['media'] || $wancfg['mediaopt']) {
2636
		$cmd = "/sbin/ifconfig " . escapeshellarg($realhwif);
2637
		if ($wancfg['media'])
2638
			$cmd .= " media " . escapeshellarg($wancfg['media']);
2639
		if ($wancfg['mediaopt'])
2640
			$cmd .= " mediaopt " . escapeshellarg($wancfg['mediaopt']);
2641
		mwexec($cmd);
2642
	}
2643
	if (!empty($wancfg['mtu']))
2644
		pfSense_interface_mtu($realhwif, $wancfg['mtu']);
2645
	else {
2646
		$mtu = get_interface_default_mtu(remove_numbers($realhwif));
2647
		if ($mtu != get_interface_mtu($realhwif))
2648
			pfSense_interface_mtu($realhwif, $mtu);
2649
	}
2650

    
2651
	$options = pfSense_get_interface_addresses($realhwif);
2652
	if (is_array($options) && isset($options['caps']['polling'])) {
2653
		if (isset($config['system']['polling']))
2654
			pfSense_interface_capabilities($realif, IFCAP_POLLING);
2655
		else
2656
			pfSense_interface_capabilities($realif, -IFCAP_POLLING);
2657
	}
2658

    
2659
	/* skip vlans for checksumming and polling */
2660
        if (!stristr($realhwif, "vlan") && is_array($options)) {
2661
		$flags = 0;
2662
		if(isset($config['system']['disablechecksumoffloading'])) {
2663
			if (isset($options['encaps']['txcsum']))
2664
				$flags |= IFCAP_TXCSUM;
2665
			if (isset($options['encaps']['rxcsum']))
2666
				$flags |= IFCAP_RXCSUM;
2667
        	} else {
2668
 			if (!isset($options['caps']['txcsum']))
2669
				$flags |= IFCAP_TXCSUM;
2670
			if (!isset($options['caps']['rxcsum']))
2671
				$flags |= IFCAP_RXCSUM;
2672
        	}
2673

    
2674
        	if(isset($config['system']['disablesegmentationoffloading'])) {
2675
                	if (isset($options['encaps']['tso4']))
2676
				$flags |= IFCAP_TSO;
2677
                	if (isset($options['encaps']['tso6']))
2678
				$flags |= IFCAP_TSO;
2679
        	} else {
2680
                	if (!isset($options['caps']['tso4']))
2681
				$flags |= IFCAP_TSO;
2682
                	if (!isset($options['caps']['tso6']))
2683
				$flags |= IFCAP_TSO;
2684
        	}
2685

    
2686
        	if(isset($config['system']['disablelargereceiveoffloading'])) {
2687
                	if (isset($options['encaps']['lro']))
2688
				$flags |= IFCAP_LRO;
2689
        	} else {
2690
                	if (!isset($options['caps']['lro']))
2691
				$flags |= IFCAP_LRO;
2692
        	}
2693

    
2694
        	/* if the NIC supports polling *AND* it is enabled in the GUI */
2695
        	if (!isset($config['system']['polling']) || !isset($options['caps']['polling'])) {
2696
			$flags |= IFCAP_POLLING;
2697
		}
2698
               	pfSense_interface_capabilities($realhwif, -$flags);
2699
	}
2700

    
2701
	/* invalidate interface/ip/sn cache */
2702
	get_interface_arr(true);
2703
	unset($interface_ip_arr_cache[$realif]);
2704
	unset($interface_sn_arr_cache[$realif]);
2705
	unset($interface_ipv6_arr_cache[$realif]);
2706
	unset($interface_snv6_arr_cache[$realif]);
2707

    
2708
	switch ($wancfg['ipaddr']) {
2709
		case 'carpdev-dhcp':
2710
			interface_carpdev_dhcp_configure($interface);
2711
			break;
2712
		case 'dhcp':
2713
			interface_dhcp_configure($interface);
2714
			break;
2715
		case 'pppoe':
2716
		case 'l2tp':
2717
		case 'pptp':
2718
		case 'ppp':
2719
			interface_ppps_configure($interface);
2720
			break;
2721
		default:
2722
			if ($wancfg['ipaddr'] <> "" && $wancfg['subnet'] <> "") {
2723
				pfSense_interface_setaddress($realif, "{$wancfg['ipaddr']}/{$wancfg['subnet']}");
2724
			} else if (substr($realif, 0, 3) == "gre") {
2725
				if (is_array($config['gres']['gre'])) {
2726
					foreach ($config['gres']['gre'] as $gre)
2727
						if ($gre['greif'] == $realif)
2728
							interface_gre_configure($gre);
2729
				}
2730
			} else if (substr($realif, 0, 3) == "gif") {
2731
				 if (is_array($config['gifs']['gif'])) {
2732
					foreach ($config['gifs']['gif'] as $gif)
2733
						if($gif['gifif'] == $realif)
2734
							interface_gif_configure($gif);
2735
				}
2736
			} else if (substr($realif, 0, 4) == "ovpn") {
2737
				/* XXX: Should be done anything?! */
2738
			}
2739
			break;
2740
	}
2741

    
2742
	switch ($wancfg['ipaddrv6']) {
2743
		default:
2744
			if ($wancfg['ipaddrv6'] <> "" && $wancfg['subnetv6'] <> "") {
2745
				pfSense_interface_setaddress($realif, "{$wancfg['ipaddrv6']}/{$wancfg['subnetv6']}");
2746
				// FIXME: Add IPv6 Support to the pfSense module
2747
				mwexec("/sbin/ifconfig {$realif} inet6 {$wancfg['ipaddrv6']} prefixlen {$wancfg['subnetv6']} ");
2748
			}
2749
			break;
2750
	}
2751

    
2752
	if(does_interface_exist($wancfg['if']))
2753
		interfaces_bring_up($wancfg['if']);
2754

    
2755
	interface_netgraph_needed($interface);
2756
 	
2757
	if (!$g['booting']) {
2758
		link_interface_to_vips($interface, "update");
2759

    
2760
		unset($gre);
2761
		$gre = link_interface_to_gre($interface);
2762
		if (!empty($gre))
2763
			array_walk($gre, 'interface_gre_configure');
2764

    
2765
		unset($gif);
2766
		$gif = link_interface_to_gif($interface);
2767
		if (!empty($gif))
2768
                       	array_walk($gif, 'interface_gif_configure');
2769

    
2770
		if ($linkupevent == false) {
2771
			unset($bridgetmp);
2772
			$bridgetmp = link_interface_to_bridge($interface);
2773
			if (!empty($bridgetmp))
2774
				interface_bridge_add_member($bridgetmp, $realif);
2775
		}
2776

    
2777
		$grouptmp = link_interface_to_group($interface);
2778
		if (!empty($grouptmp))
2779
			array_walk($grouptmp, 'interface_group_add_member');
2780

    
2781
		if ($interface == "lan")
2782
			/* make new hosts file */
2783
			system_hosts_generate();
2784

    
2785
		if ($reloadall == true) {
2786

    
2787
			/* reconfigure static routes (kernel may have deleted them) */
2788
			system_routing_configure($interface);
2789

    
2790
			/* reload ipsec tunnels */
2791
			vpn_ipsec_configure();
2792

    
2793
			/* restart dnsmasq */
2794
			services_dnsmasq_configure();
2795

    
2796
			/* update dyndns */
2797
			send_event("service reload dyndns {$interface}");
2798

    
2799
			/* reload captive portal */
2800
			captiveportal_init_rules();
2801
		}
2802
	}
2803

    
2804
	return 0;
2805
}
2806

    
2807
function interface_carpdev_dhcp_configure($interface = "wan") {
2808
	global $config, $g;
2809

    
2810
	$wancfg = $config['interfaces'][$interface];
2811
	$wanif = $wancfg['if'];
2812
	/* bring wan interface up before starting dhclient */
2813
	if($wanif)
2814
		interfaces_bring_up($wanif);
2815
	else 
2816
		log_error("Could not bring wanif up in terface_carpdev_dhcp_configure()");
2817

    
2818
	return 0;
2819
}
2820

    
2821
function interface_dhcp_configure($interface = "wan") {
2822
	global $config, $g;
2823

    
2824
	$wancfg = $config['interfaces'][$interface];
2825
	$wanif = $wancfg['if'];
2826
	if (empty($wancfg))
2827
		$wancfg = array();
2828

    
2829
	$wanif = get_real_interface($interface);
2830
	/* bring wan interface up before starting dhclient */
2831
	if($wanif)
2832
		interfaces_bring_up($wanif);
2833
	else 
2834
		log_error("Could not bring up {$wanif} interface in interface_dhcp_configure()");
2835

    
2836
	/* launch v6 before v4, dhclient can hold up the execution if no dhcp4 is available */
2837
	interface_dhcpv6_configure($interface);
2838
	interface_dhcpv4_configure($interface);
2839

    
2840
	return 0;
2841

    
2842
}
2843

    
2844
function interface_dhcpv6_configure($interface = "wan") {
2845
	global $config, $g;
2846
	$iflist = get_configured_interface_with_descr(false, true);
2847

    
2848
	$wancfg = $config['interfaces'][$interface];
2849
	$wanif = $wancfg['if'];
2850
	if (empty($wancfg))
2851
		$wancfg = array();
2852

    
2853
	$wanif = get_real_interface($interface);
2854

    
2855
	/* Add IPv6 dhclient here, only wide-dhcp6c works for now. */
2856
	$fd = fopen("{$g['varetc_path']}/dhcp6c_{$interface}.conf", "w");
2857
	if (!$fd) {
2858
		printf("Error: cannot open dhcp6c_{$interface}.conf in interfaces_wan_dhcp_configure() for writing.\n");
2859
		return 1;
2860
	}
2861

    
2862
	$dhcp6cconf = "";
2863
 	$dhcp6cconf .= "interface {$wanif} {\n";
2864
	$dhcp6cconf .= " 	send ia-na 0;	# request stateful address\n";
2865
	if(is_numeric($wancfg['dhcp6-ia-pd-len'])) {
2866
		$dhcp6cconf .= " 	send ia-pd 0;	# request prefix delegation\n";
2867
	}
2868
	$dhcp6cconf .= "request domain-name-servers;\n";
2869
	$dhcp6cconf .= "request domain-name;\n";
2870
	$dhcp6cconf .= "script \"/etc/rc.newwanipv6\";	# we'd like some nameservers please\n";
2871

    
2872
	$dhcp6cconf .= "};\n";
2873
	$dhcp6cconf .= "id-assoc na 0 { };\n";
2874
	if(is_numeric($wancfg['dhcp6-ia-pd-len'])) {
2875
		/* Setup the prefix delegation */
2876
		$dhcp6cconf .= "	id-assoc pd 0 {\n";
2877
		foreach($iflist as $friendly => $pdinterface) {
2878
			// log_error("setting up $friendly - $pdinterface - {$pdinterface['dhcp6-pd-sla-id']}");
2879
			if(is_numeric($config['interfaces'][$friendly]['dhcp6-pd-sla-id'])) {
2880
				$realif = get_real_interface($friendly);
2881
				$dhcp6cconf .= "	prefix-interface {$realif} {\n";
2882
				$dhcp6cconf .= "		sla-id {$config['interfaces'][$friendly]['dhcp6-pd-sla-id']};\n";
2883
				$dhcp6cconf .= "		sla-len {$wancfg['dhcp6-ia-pd-len']};\n";
2884
				$dhcp6cconf .= "	};\n";
2885
			}
2886
		}
2887
		$dhcp6cconf .= "};\n";
2888
	}
2889

    
2890
	fwrite($fd, $dhcp6cconf);
2891
	fclose($fd);
2892

    
2893
	/* accept router advertisements for this interface */
2894
	// mwexec("/sbin/sysctl -w net.inet6.ip6.accept_rtadv=1");
2895
	mwexec("/sbin/ifconfig {$wanif} inet6 accept_rtadv");
2896
	/* fire up dhcp6c for IPv6 first, this backgrounds immediately */
2897
	mwexec("/usr/local/sbin/dhcp6c -d -c {$g['varetc_path']}/dhcp6c_{$interface}.conf {$wanif}");
2898

    
2899
	return 0;
2900
}
2901

    
2902
function interface_dhcpv4_configure($interface = "wan") {
2903
	global $config, $g;
2904

    
2905
	$wancfg = $config['interfaces'][$interface];
2906
	$wanif = $wancfg['if'];
2907
	if (empty($wancfg))
2908
		$wancfg = array();
2909

    
2910
	/* generate dhclient_wan.conf */
2911
	$fd = fopen("{$g['varetc_path']}/dhclient_{$interface}.conf", "w");
2912
	if (!$fd) {
2913
		printf("Error: cannot open dhclient_{$interface}.conf in interfaces_wan_dhcp_configure() for writing.\n");
2914
		return 1;
2915
	}
2916

    
2917
	if ($wancfg['dhcphostname']) {
2918
		$dhclientconf_hostname = "send dhcp-client-identifier \"{$wancfg['dhcphostname']}\";\n";
2919
		$dhclientconf_hostname .= "\tsend host-name \"{$wancfg['dhcphostname']}\";\n";
2920
	} else {
2921
		$dhclientconf_hostname = "";
2922
	}
2923

    
2924
	$wanif = get_real_interface($interface);
2925
	if (empty($wanif)) {
2926
		log_error("Invalid interface \"{$interface}\" in interface_dhcp_configure()");
2927
		return 0;
2928
	}
2929
 	$dhclientconf = "";
2930
	
2931
	$dhclientconf .= <<<EOD
2932
interface "{$wanif}" {
2933
timeout 60;
2934
retry 1;
2935
select-timeout 0;
2936
initial-interval 1;
2937
	{$dhclientconf_hostname}
2938
	script "/sbin/dhclient-script";
2939
}
2940

    
2941
EOD;
2942

    
2943
if(is_ipaddr($wancfg['alias-address'])) {
2944
	$subnetmask = gen_subnet_mask($wancfg['alias-subnet']);
2945
	$dhclientconf .= <<<EOD
2946
alias {
2947
	interface  "{$wanif}";
2948
	fixed-address {$wancfg['alias-address']};
2949
	option subnet-mask {$subnetmask};
2950
}
2951

    
2952
EOD;
2953
}
2954
	fwrite($fd, $dhclientconf);
2955
	fclose($fd);
2956

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

    
2960
	return 0;
2961
}
2962

    
2963
function interfaces_group_setup() {
2964
	global $config;
2965

    
2966
	if (!is_array($config['ifgroups']['ifgroupentry']))
2967
		return;
2968

    
2969
	foreach ($config['ifgroups']['ifgroupentry'] as $groupar)
2970
		interface_group_setup($groupar);
2971

    
2972
	return;
2973
}
2974

    
2975
function interface_group_setup(&$groupname /* The parameter is an array */) {
2976
	global $config;
2977

    
2978
	if (!is_array($groupname))
2979
		return;
2980
	$members = explode(" ", $groupname['members']);
2981
	foreach($members as $ifs) {
2982
		$realif = get_real_interface($ifs);
2983
		if ($realif)
2984
			mwexec("/sbin/ifconfig {$realif} group {$groupname['ifname']}");
2985
	}
2986

    
2987
	return;
2988
}
2989

    
2990
function interface_group_add_member($interface, $groupname) {
2991
	$interface = get_real_interface($interface);
2992
	mwexec("/sbin/ifconfig {$interface} group {$groupname}", true);
2993
}
2994
 
2995
/* COMPAT Function */
2996
function convert_friendly_interface_to_real_interface_name($interface) {
2997
	return get_real_interface($interface);
2998
}
2999

    
3000
/* COMPAT Function */
3001
function get_real_wan_interface($interface = "wan") {
3002
	return get_real_interface($interface);
3003
}
3004

    
3005
/* COMPAT Function */
3006
function get_current_wan_address($interface = "wan") {
3007
	return get_interface_ip($interface);
3008
}
3009

    
3010
/*
3011
 * convert_real_interface_to_friendly_interface_name($interface): convert fxp0 -> wan, etc.
3012
 */
3013
function convert_real_interface_to_friendly_interface_name($interface = "wan") {
3014
        global $config;
3015

    
3016
	if (stristr($interface, "vip")) {
3017
                $index = intval(substr($interface, 3));
3018
                foreach ($config['virtualip']['vip'] as $counter => $vip) {
3019
                        if ($vip['mode'] == "carpdev-dhcp" || $vip['mode'] == "carp")  {
3020
                                if ($index == $vip['vhid'])
3021
                                        return $vip['interface'];
3022
                        }
3023
                }
3024
        }
3025

    
3026
        /* XXX: For speed reasons reference directly the interface array */
3027
	$ifdescrs = &$config['interfaces'];
3028
        //$ifdescrs = get_configured_interface_list(false, true);
3029

    
3030
        foreach ($ifdescrs as $if => $ifname) {
3031
                if ($config['interfaces'][$if]['if'] == $interface)
3032
                        return $if;
3033

    
3034
                if (stristr($interface, "_wlan0") && $config['interfaces'][$if]['if'] == interface_get_wireless_base($interface))
3035
                        return $if;
3036

    
3037
		// XXX: This case doesn't work anymore (segfaults - recursion?) - should be replaced with something else or just removed.
3038
		//      Not to be replaced with get_real_interface - causes slow interface listings here because of recursion!
3039
		/*
3040
                $int = get_parent_interface($if);
3041
                if ($int[0] == $interface)
3042
                        return $ifname;
3043
		*/
3044
        }
3045
        return NULL;
3046
}
3047

    
3048
/* attempt to resolve interface to friendly descr */
3049
function convert_friendly_interface_to_friendly_descr($interface) {
3050
        global $config;
3051

    
3052
        switch ($interface) {
3053
        case "l2tp":
3054
        	$ifdesc = "L2TP";
3055
                break;
3056
	case "pptp":
3057
		$ifdesc = "PPTP";
3058
		break;
3059
	case "pppoe":
3060
		$ifdesc = "PPPoE";
3061
		break;
3062
	case "openvpn":
3063
		$ifdesc = "OpenVPN";
3064
		break;
3065
	case "enc0":
3066
	case "ipsec":
3067
		$ifdesc = "IPsec";
3068
		break;
3069
        default:
3070
                if (isset($config['interfaces'][$interface])) {
3071
                        if (empty($config['interfaces'][$interface]['descr']))
3072
                                $ifdesc = strtoupper($interface);
3073
                        else
3074
                                $ifdesc = strtoupper($config['interfaces'][$interface]['descr']);
3075
			break;
3076
		} else if (substr($interface, 0, 3) == "vip") {
3077
			if (is_array($config['virtualip']['vip'])) {
3078
				foreach ($config['virtualip']['vip'] as $counter => $vip) {
3079
					if ($vip['mode'] == "carpdev-dhcp" || $vip['mode'] == "carp")  {
3080
						if ($interface == "vip{$vip['vhid']}")
3081
							return "{$vip['subnet']} - {$vip['descr']}";
3082
					}
3083
				}
3084
                        }
3085
                } else {
3086
			/* if list */
3087
			$ifdescrs = get_configured_interface_with_descr(false, true);
3088
			foreach ($ifdescrs as $if => $ifname) {
3089
					if ($if == $interface || $ifname == $interface)
3090
						return $ifname;
3091
			}
3092
		}
3093
                break;
3094
        }
3095

    
3096
        return $ifdesc;
3097
}
3098

    
3099
function convert_real_interface_to_friendly_descr($interface) {
3100
        global $config;
3101

    
3102
        $ifdesc = convert_real_interface_to_friendly_interface_name("{$interface}");
3103

    
3104
        if ($ifdesc) {
3105
                $iflist = get_configured_interface_with_descr(false, true);
3106
                return $iflist[$ifdesc];
3107
        }
3108

    
3109
        return $interface;
3110
}
3111

    
3112
/*
3113
 *  get_parent_interface($interface):
3114
 *			--returns the (real or virtual) parent interface(s) array for a given interface friendly name (i.e. wan)
3115
 *				or virtual interface (i.e. vlan)
3116
 *				(We need array because MLPPP and bridge interfaces have more than one parent.)
3117
 *			-- returns $interface passed in if $interface parent is not found
3118
 *			-- returns empty array if an invalid interface is passed
3119
 *	(Only handles ppps and vlans now.)
3120
 */
3121
function get_parent_interface($interface) {
3122
	global $config;
3123

    
3124
	$parents = array();
3125
	//Check that we got a valid interface passed
3126
	$realif = get_real_interface($interface);
3127
	if ($realif == NULL)
3128
		return $parents;
3129

    
3130
	// If we got a real interface, find it's friendly assigned name
3131
	$interface = convert_real_interface_to_friendly_interface_name($interface);
3132
		
3133
	if (!empty($interface) && isset($config['interfaces'][$interface])) {
3134
		$ifcfg = $config['interfaces'][$interface];
3135
		switch ($ifcfg['ipaddr']) {
3136
			case "ppp":
3137
			case "pppoe":
3138
			case "pptp":
3139
			case "l2tp":
3140
				if (empty($parents))
3141
					if (is_array($config['ppps']['ppp']))
3142
						foreach ($config['ppps']['ppp'] as $pppidx => $ppp) {
3143
							if ($ppp_if == $ppp['if']) {
3144
								$ports = explode(',', $ppp['ports']);
3145
								foreach ($ports as $pid => $parent_if) 
3146
									$parents[$pid] = get_real_interface($parent_if);
3147
								break;
3148
							}
3149
						}
3150
				break;
3151
			case "dhcp":
3152
			case "static":
3153
			default:
3154
				// Handle _vlans
3155
				if (strstr($realif,"_vlan"))
3156
					if (is_array($config['vlans']['vlan'])) 
3157
						foreach ($config['vlans']['vlan'] as $vlanidx => $vlan)
3158
							if ($ifcfg['if'] == $vlan['vlanif']){
3159
								$parents[0] = $vlan['if'];
3160
								break;
3161
							}
3162
				break;
3163
		}
3164
	}
3165
	
3166
	if (empty($parents))
3167
		$parents[0] = $realif;
3168
	
3169
	return $parents;
3170
}
3171

    
3172
function interface_is_wireless_clone($wlif) {
3173
	if(!stristr($wlif, "_wlan")) {
3174
		return false;
3175
	} else {
3176
		return true;
3177
	}
3178
}
3179

    
3180
function interface_get_wireless_base($wlif) {
3181
	if(!stristr($wlif, "_wlan")) {
3182
		return $wlif;
3183
	} else {
3184
		return substr($wlif, 0, stripos($wlif, "_wlan"));
3185
	}
3186
}
3187

    
3188
function interface_get_wireless_clone($wlif) {
3189
	if(!stristr($wlif, "_wlan")) {
3190
		return $wlif . "_wlan0";
3191
	} else {
3192
		return $wlif;
3193
	}
3194
}
3195

    
3196
function get_real_interface($interface = "wan") {
3197
    global $config;
3198

    
3199
	$wanif = NULL;
3200

    
3201
	switch ($interface) {
3202
	case "l2tp":
3203
		$wanif = "l2tp";
3204
		break;
3205
	case "pptp":
3206
		$wanif = "pptp";
3207
		break;
3208
	case "pppoe":
3209
		$wanif = "pppoe";
3210
		break;
3211
	case "openvpn":
3212
		$wanif = "openvpn";
3213
		break;
3214
	case "ipsec":
3215
	case "enc0":
3216
		$wanif = "enc0";
3217
		break;
3218
	case "ppp":
3219
		$wanif = "ppp";
3220
		break;
3221
	default:
3222
		// If a real interface was alread passed simply
3223
		// pass the real interface back.  This encourages
3224
		// the usage of this function in more cases so that
3225
		// we can combine logic for more flexibility.
3226
		if(does_interface_exist($interface)) {
3227
			$wanif = $interface;
3228
			break;
3229
		}
3230
		if (empty($config['interfaces'][$interface]))
3231
			break;
3232

    
3233
		$cfg = &$config['interfaces'][$interface];
3234

    
3235
		// Wireless cloned NIC support (FreeBSD 8+)
3236
		// interface name format: $parentnic_wlanparentnic#
3237
		// example: ath0_wlan0
3238
		if (is_interface_wireless($cfg['if'])) {
3239
			$wanif = interface_get_wireless_clone($cfg['if']);
3240
			break;
3241
		}
3242
		/*
3243
		if (empty($cfg['if'])) {
3244
			$wancfg = $cfg['if'];
3245
			break;
3246
		}
3247
		*/
3248

    
3249
		switch ($cfg['ipaddr']) {
3250
			case "carpdev-dhcp":
3251
				$viparr = &$config['virtualip']['vip'];
3252
				if(is_array($viparr))
3253
				foreach ($viparr as $counter => $vip) {
3254
					if ($vip['mode'] == "carpdev-dhcp") {
3255
						if($vip['interface'] == $interface) {
3256
							$wanif = "carp{$counter}";
3257
							break;
3258
						}
3259
					}
3260
				}
3261
				break;
3262
			case "pppoe": 
3263
			case "pptp": 
3264
			case "l2tp": 
3265
			case "ppp":
3266
				$wanif = $cfg['if'];
3267
				break;
3268
			default:
3269
				$wanif = $cfg['if'];
3270
				break;
3271
		}
3272
		break;
3273
	}
3274

    
3275
    return $wanif;
3276
}
3277

    
3278
/* Guess the physical interface by providing a IP address */
3279
function guess_interface_from_ip($ipaddress) {
3280
	if(! is_ipaddr($ipaddress)) {
3281
		return false;
3282
	}
3283
	if(is_ipaddrv4($ipaddress)) {
3284
		/* create a route table we can search */
3285
		exec("netstat -rnWf inet", $output, $ret);
3286
		foreach($output as $line) {
3287
			if(preg_match("/^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\/[0-9]+[ ]+link[#]/", $line)) {
3288
				$fields = preg_split("/[ ]+/", $line);
3289
				if(ip_in_subnet($ipaddress, $fields[0])) {
3290
					return $fields[6];
3291
				}
3292
			}
3293
		}
3294
	}
3295
	/* FIXME: This works from cursory testing, regexp might need fine tuning */
3296
	if(is_ipaddrv6($ipaddress)) {
3297
		/* create a route table we can search */
3298
		exec("netstat -rnWf inet6", $output, $ret);
3299
		foreach($output as $line) {
3300
			if(preg_match("/[0-9a-f]+[:]+[0-9a-f]+[:]+[\/][0-9]+/", $line)) {
3301
				$fields = preg_split("/[ ]+/", $line);
3302
				if(ip_in_subnet($ipaddress, $fields[0])) {
3303
					return $fields[6];
3304
				}
3305
			}
3306
		}
3307
	}
3308
	$ret = exec_command("/sbin/route -n get {$ipaddress} | /usr/bin/awk '/interface/ { print \$2; };'");
3309
	if(empty($ret)) {
3310
        	return false;
3311
	}
3312
	return $ret;
3313
}
3314

    
3315
/*
3316
 * find_ip_interface($ip): return the interface where an ip is defined
3317
 */
3318
function find_ip_interface($ip)
3319
{
3320
        /* if list */
3321
        $ifdescrs = get_configured_interface_list();
3322

    
3323
        foreach ($ifdescrs as $ifdescr => $ifname) {
3324
		if ($ip == get_interface_ip($ifname)) {
3325
                	$int = get_real_interface($ifname);
3326
			return $int;
3327
		}
3328
        }
3329
        return false;
3330
}
3331

    
3332
/*
3333
 *   find_number_of_created_carp_interfaces: return the number of carp interfaces
3334
 */
3335
function find_number_of_created_carp_interfaces() {
3336
	return `/sbin/ifconfig | grep "carp:" | wc -l`;
3337
}
3338

    
3339
function get_all_carp_interfaces() {
3340
	$ints = str_replace("\n", " ", `ifconfig | grep "carp:" -B2 | grep ": flag" | cut -d: -f1`);
3341
	$ints = explode(" ", $ints);
3342
	return $ints;
3343
}
3344

    
3345
/*
3346
 * find_carp_interface($ip): return the carp interface where an ip is defined
3347
 */
3348
function find_carp_interface($ip) {
3349
	global $config;
3350
	if (is_array($config['virtualip']['vip'])) {
3351
		foreach ($config['virtualip']['vip'] as $vip) {
3352
			if ($vip['mode'] == "carp" || $vip['mode'] == "carpdev") {
3353
				if(is_ipaddrv4($ip)) {
3354
					$carp_ip = get_interface_ip($vip['interface']);
3355
				}
3356
				if(is_ipaddrv6($ip)) {
3357
					$carp_ip = get_interface_ipv6($vip['interface']);
3358
				}
3359
				exec("/sbin/ifconfig", $output, $return);
3360
				foreach($output as $line) {
3361
					$elements = preg_split("/[ ]+/i", $line);
3362
					if(strstr($elements[0], "vip"))
3363
						$curif = str_replace(":", "", $elements[0]);
3364
					if(stristr($line, $ip)) {
3365
						$if = $curif;
3366
						continue;
3367
					}
3368
				}
3369
				if ($if)
3370
					return $if;
3371
			}
3372
		}
3373
	}
3374
}
3375

    
3376
function link_carp_interface_to_parent($interface) {
3377
        global $config;
3378

    
3379
        if ($interface == "")
3380
                return;
3381

    
3382
        $carp_ip = get_interface_ip($interface);
3383
        if (!is_ipaddr($carp_ip))
3384
                return;
3385

    
3386
        /* if list */
3387
        $ifdescrs = get_configured_interface_list();
3388
        foreach ($ifdescrs as $ifdescr => $ifname) {
3389
                $interfaceip = get_interface_ip($ifname);
3390
                $subnet_bits = get_interface_subnet($ifname);
3391
                $subnet_ip = gen_subnet("{$interfaceip}", "{$subnet_bits}");
3392
                if(ip_in_subnet($carp_ip, "{$subnet_ip}/{$subnet_bits}"))
3393
                        return $ifname;
3394
        }
3395

    
3396
        return "";
3397
}
3398

    
3399
/****f* interfaces/link_ip_to_carp_interface
3400
 * NAME
3401
 *   link_ip_to_carp_interface - Find where a CARP interface links to.
3402
 * INPUTS
3403
 *   $ip
3404
 * RESULT
3405
 *   $carp_ints
3406
 ******/
3407
function link_ip_to_carp_interface($ip) {
3408
        global $config;
3409

    
3410
        if (!is_ipaddr($ip))
3411
                return;
3412

    
3413
        $carp_ints = "";
3414
        if (is_array($config['virtualip']['vip'])) {
3415
		$first = 0;
3416
		$carp_int = array();
3417
                foreach ($config['virtualip']['vip'] as $vip) {
3418
                        if ($vip['mode'] == "carp" || $vip['mode'] == "carpdev") {
3419
                                $carp_ip = $vip['subnet'];
3420
                                $carp_sn = $vip['subnet_bits'];
3421
                                $carp_nw = gen_subnet($carp_ip, $carp_sn);
3422
                                if (ip_in_subnet($ip, "{$carp_nw}/{$carp_sn}"))
3423
					$carp_int[] = "vip{$vip['vhid']}";
3424
                        }
3425
                }
3426
		if (!empty($carp_int))
3427
			$carp_ints = implode(" ", array_unique($carp_int));
3428
        }
3429

    
3430
        return $carp_ints;
3431
}
3432

    
3433
function link_interface_to_vlans($int, $action = "") {
3434
	global $config;
3435

    
3436
	if (empty($int))
3437
		return;
3438

    
3439
	if (is_array($config['vlans']['vlan'])) {
3440
                foreach ($config['vlans']['vlan'] as $vlan) {
3441
			if ($int == $vlan['if']) {
3442
				if ($action == "update") {
3443
					interfaces_bring_up($int);
3444
				} else if ($action == "")
3445
					return $vlan;
3446
			}
3447
		}
3448
	}
3449
}
3450

    
3451
function link_interface_to_vips($int, $action = "") {
3452
        global $config;
3453

    
3454
        if (is_array($config['virtualip']['vip'])) {
3455
		foreach ($config['virtualip']['vip'] as $vip) {
3456
			if ($int == $vip['interface']) {
3457
				if ($action == "update") {
3458
					interface_vip_bring_down($vip);
3459
					interfaces_vips_configure($int);
3460
				} else
3461
					return $vip;
3462
			}
3463
		}
3464
	}
3465
}
3466

    
3467
/****f* interfaces/link_interface_to_bridge
3468
 * NAME
3469
 *   link_interface_to_bridge - Finds out a bridge group for an interface
3470
 * INPUTS
3471
 *   $ip
3472
 * RESULT
3473
 *   bridge[0-99]
3474
 ******/
3475
function link_interface_to_bridge($int) {
3476
        global $config;
3477

    
3478
        if (is_array($config['bridges']['bridged'])) {
3479
                foreach ($config['bridges']['bridged'] as $bridge) {
3480
			if (in_array($int, explode(',', $bridge['members'])))
3481
                                return "{$bridge['bridgeif']}";
3482
		}
3483
	}
3484
}
3485

    
3486
function link_interface_to_group($int) {
3487
        global $config;
3488

    
3489
	$result = array();
3490

    
3491
        if (is_array($config['ifgroups']['ifgroupentry'])) {
3492
                foreach ($config['ifgroups']['ifgroupentry'] as $group) {
3493
			if (in_array($int, explode(" ", $group['members'])))
3494
				$result[$group['ifname']] = $int;
3495
		}
3496
	}
3497

    
3498
	return $result;
3499
}
3500

    
3501
function link_interface_to_gre($interface) {
3502
        global $config;
3503

    
3504
	$result = array();
3505

    
3506
        if (is_array($config['gres']['gre'])) {
3507
                foreach ($config['gres']['gre'] as $gre)
3508
                        if($gre['if'] == $interface)
3509
				$result[] = $gre;
3510
	}
3511

    
3512
	return $result;
3513
}
3514

    
3515
function link_interface_to_gif($interface) {
3516
        global $config;
3517

    
3518
	$result = array();
3519

    
3520
        if (is_array($config['gifs']['gif'])) {
3521
                foreach ($config['gifs']['gif'] as $gif)
3522
                        if($gif['if'] == $interface)
3523
                                $result[] = $gif;
3524
	}
3525

    
3526
	return $result;
3527
}
3528

    
3529
/*
3530
 * find_interface_ip($interface): return the interface ip (first found)
3531
 */
3532
function find_interface_ip($interface, $flush = false)
3533
{
3534
	global $interface_ip_arr_cache;
3535
	global $interface_sn_arr_cache;
3536

    
3537
	$interface = str_replace("\n", "", $interface);
3538
	
3539
	if (!does_interface_exist($interface))
3540
		return;
3541

    
3542
	/* Setup IP cache */
3543
	if (!isset($interface_ip_arr_cache[$interface]) or $flush) {
3544
		$ifinfo = pfSense_get_interface_addresses($interface);
3545
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
3546
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
3547
	}
3548

    
3549
	return $interface_ip_arr_cache[$interface];
3550
}
3551

    
3552
/*
3553
 * find_interface_ipv6($interface): return the interface ip (first found)
3554
 */
3555
function find_interface_ipv6($interface, $flush = false)
3556
{
3557
	global $interface_ipv6_arr_cache;
3558
	global $interface_snv6_arr_cache;
3559
	global $config;
3560
	
3561
	$interface = str_replace("\n", "", $interface);
3562
	
3563
	if (!does_interface_exist($interface))
3564
		return;
3565

    
3566
	/* Setup IP cache */
3567
	if (!isset($interface_ipv6_arr_cache[$interface]) or $flush) {
3568
		$ifinfo = pfSense_get_interface_addresses($interface);
3569
		// FIXME: Add IPv6 support to the pfSense module
3570
		exec("/sbin/ifconfig {$interface} inet6", $output);
3571
		foreach($output as $line) {
3572
			if(preg_match("/inet6/", $line)) {
3573
				$parts = explode(" ", $line);
3574
				if(! preg_match("/fe80::/", $parts[1])) {
3575
					$ifinfo['ipaddrv6'] = $parts[1];
3576
					if($parts[2] == "-->") {
3577
						$parts[5] = "126";
3578
						$ifinfo['subnetbitsv6'] = $parts[5];
3579
					} else {
3580
						$ifinfo['subnetbitsv6'] = $parts[3];
3581
					}
3582
				}
3583
			}
3584
		}
3585
		$interface_ipv6_arr_cache[$interface] = $ifinfo['ipaddrv6'];
3586
		$interface_snv6_arr_cache[$interface] = $ifinfo['subnetbitsv6'];
3587
	}
3588

    
3589
	return $interface_ipv6_arr_cache[$interface];
3590
}
3591

    
3592
function find_interface_subnet($interface, $flush = false)
3593
{
3594
	global $interface_sn_arr_cache;
3595
	global $interface_ip_arr_cache;
3596

    
3597
	$interface = str_replace("\n", "", $interface);
3598
	if (does_interface_exist($interface) == false)
3599
		return;
3600

    
3601
	if (!isset($interface_sn_arr_cache[$interface]) or $flush) {
3602
		$ifinfo = pfSense_get_interface_addresses($interface);
3603
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
3604
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
3605
        }
3606

    
3607
	return $interface_sn_arr_cache[$interface];
3608
}
3609

    
3610
function find_interface_subnetv6($interface, $flush = false)
3611
{
3612
	global $interface_snv6_arr_cache;
3613
	global $interface_ipv6_arr_cache;
3614

    
3615
	$interface = str_replace("\n", "", $interface);
3616
	if (does_interface_exist($interface) == false)
3617
		return;
3618

    
3619
	if (!isset($interface_snv6_arr_cache[$interface]) or $flush) {
3620
		$ifinfo = pfSense_get_interface_addresses($interface);
3621
		// FIXME: Add IPv6 support to the pfSense module
3622
		exec("/sbin/ifconfig {$interface} inet6", $output);
3623
		foreach($output as $line) {
3624
			if(preg_match("/inet6/", $line)) {
3625
				$parts = explode(" ", $line);
3626
				if(! preg_match("/fe80::/", $parts[1])) {
3627
					$ifinfo['ipaddrv6'] = $parts[1];
3628
					if($parts[2] == "-->") {
3629
						$parts[5] = "126";
3630
						$ifinfo['subnetbitsv6'] = $parts[5];
3631
					} else {
3632
						$ifinfo['subnetbitsv6'] = $parts[3];
3633
					}
3634
				}
3635
			}
3636
		}
3637
		$interface_ipv6_arr_cache[$interface] = $ifinfo['ipaddrv6'];
3638
		$interface_snv6_arr_cache[$interface] = $ifinfo['subnetbitsv6'];
3639
        }
3640

    
3641
	return $interface_snv6_arr_cache[$interface];
3642
}
3643

    
3644
function ip_in_interface_alias_subnet($interface, $ipalias) {
3645
	global $config;
3646

    
3647
	if (empty($interface) || !is_ipaddr($ipalias))
3648
		return false;
3649
	if (is_array($config['virtualip']['vip'])) {
3650
                foreach ($config['virtualip']['vip'] as $vip) {
3651
                        switch ($vip['mode']) {
3652
                        case "ipalias":
3653
                                if ($vip['interface'] <> $interface)
3654
                                        break;
3655
				if (ip_in_subnet($ipalias, gen_subnet($vip['subnet'], $vip['subnet_bits']) . "/" . $vip['subnet_bits']))
3656
					return true;
3657
                                break;
3658
                        }
3659
                }
3660
	}
3661

    
3662
	return false;
3663
}
3664

    
3665
function get_interface_ip($interface = "wan")
3666
{
3667
	$realif = get_real_interface($interface);
3668
	if (!$realif) {
3669
		if (preg_match("/^carp/i", $interface))
3670
			$realif = $interface;
3671
		else if (preg_match("/^vip/i", $interface))
3672
			$realif = $interface;
3673
		else
3674
			return null;
3675
	}
3676

    
3677
	$curip = find_interface_ip($realif);
3678
	if ($curip && is_ipaddr($curip) && ($curip != "0.0.0.0"))
3679
		return $curip;
3680
	else
3681
		return null;
3682
}
3683

    
3684
function get_interface_ipv6($interface = "wan")
3685
{
3686
	$realif = get_real_interface($interface);
3687
	if (!$realif) {
3688
		if (preg_match("/^carp/i", $interface))
3689
			$realif = $interface;
3690
		else if (preg_match("/^vip/i", $interface))
3691
			$realif = $interface;
3692
		else
3693
			return null;
3694
	}
3695

    
3696
	$curip = find_interface_ipv6($realif);
3697
	if ($curip && is_ipaddrv6($curip) && ($curip != "::"))
3698
		return $curip;
3699
	else
3700
		return null;
3701
}
3702

    
3703
function get_interface_subnet($interface = "wan")
3704
{
3705
	$realif = get_real_interface($interface);
3706
	if (!$realif) {
3707
                if (preg_match("/^carp/i", $interface))
3708
                        $realif = $interface;
3709
                else if (preg_match("/^vip/i", $interface))
3710
                        $realif = $interface;
3711
                else
3712
                        return null;
3713
        }
3714

    
3715
	$cursn = find_interface_subnet($realif);
3716
	if (!empty($cursn))
3717
		return $cursn;
3718

    
3719
	return null;
3720
}
3721

    
3722
function get_interface_subnetv6($interface = "wan")
3723
{
3724
	$realif = get_real_interface($interface);
3725
	if (!$realif) {
3726
                if (preg_match("/^carp/i", $interface))
3727
                        $realif = $interface;
3728
                else if (preg_match("/^vip/i", $interface))
3729
                        $realif = $interface;
3730
                else
3731
                        return null;
3732
        }
3733

    
3734
	$cursn = find_interface_subnetv6($realif);
3735
	if (!empty($cursn))
3736
		return $cursn;
3737

    
3738
	return null;
3739
}
3740

    
3741
/* return outside interfaces with a gateway */
3742
function get_interfaces_with_gateway() {
3743
	global $config;
3744

    
3745
	$ints = array();
3746

    
3747
	/* loop interfaces, check config for outbound */
3748
	foreach($config['interfaces'] as $ifdescr => $ifname) {
3749
		switch ($ifname['ipaddr']) {
3750
			case "dhcp":
3751
			case "carpdev-dhcp":
3752
			case "ppp";
3753
			case "pppoe":
3754
			case "pptp":
3755
			case "l2tp":
3756
			case "ppp";
3757
				$ints[$ifdescr] = $ifdescr;
3758
			break;
3759
			default:
3760
				if (substr($ifname['if'], 0, 5) ==  "ovpnc" ||
3761
				    !empty($ifname['gateway']))
3762
					$ints[$ifdescr] = $ifdescr;
3763
			break;
3764
		}
3765
	}
3766
	return $ints;
3767
}
3768

    
3769
/* return true if interface has a gateway */
3770
function interface_has_gateway($friendly) {
3771
	global $config;
3772

    
3773
	if (!empty($config['interfaces'][$friendly])) {
3774
		$ifname = &$config['interfaces'][$friendly];
3775
		switch ($ifname['ipaddr']) {
3776
			case "dhcp":
3777
			case "carpdev-dhcp":
3778
			case "pppoe":
3779
			case "pptp":
3780
			case "l2tp":
3781
			case "ppp";
3782
				return true;
3783
			break;
3784
			default:
3785
				if (substr($ifname['if'], 0, 5) ==  "ovpnc")
3786
					return true;
3787
				if (!empty($ifname['gateway']))
3788
					return true;
3789
			break;
3790
		}
3791
	}
3792

    
3793
	return false;
3794
}
3795

    
3796
/****f* interfaces/is_altq_capable
3797
 * NAME
3798
 *   is_altq_capable - Test if interface is capable of using ALTQ
3799
 * INPUTS
3800
 *   $int            - string containing interface name
3801
 * RESULT
3802
 *   boolean         - true or false
3803
 ******/
3804

    
3805
function is_altq_capable($int) {
3806
        /* Per:
3807
         * http://www.freebsd.org/cgi/man.cgi?query=altq&manpath=FreeBSD+7.2-current&format=html
3808
         * Only the following drivers have ALTQ support
3809
         */
3810
	$capable = array("age", "alc", "ale", "an", "ath", "aue", "awi", "bce",
3811
			"bfe", "bge", "bridge", "cas", "dc", "de", "ed", "em", "ep", "fxp", "gem",
3812
			"hme", "igb", "ipw", "iwi", "jme", "le", "lem", "msk", "mxge", "my", "nfe",
3813
			"npe", "nve", "ral", "re", "rl", "rum", "run", "bwn", "sf", "sis", "sk",
3814
			"ste", "stge", "txp", "udav", "ural", "vge", "vr", "wi", "xl",
3815
			"ndis", "tun", "ovpns", "ovpnc", "vlan", "pppoe", "pptp", "ng",
3816
			"l2tp", "ppp");
3817

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

    
3820
        if (in_array($int_family[0], $capable))
3821
                return true;
3822
	else if (stristr($int, "vlan")) /* VLANs are name $parent_$vlan now */
3823
		return true;
3824
	else if (stristr($int, "_wlan")) /* WLANs are name $parent_$wlan now */
3825
		return true;
3826
        else
3827
                return false;
3828
}
3829

    
3830
/****f* interfaces/is_interface_wireless
3831
 * NAME
3832
 *   is_interface_wireless - Returns if an interface is wireless
3833
 * RESULT
3834
 *   $tmp       - Returns if an interface is wireless
3835
 ******/
3836
function is_interface_wireless($interface) {
3837
        global $config, $g;
3838

    
3839
        $friendly = convert_real_interface_to_friendly_interface_name($interface);
3840
        if(!isset($config['interfaces'][$friendly]['wireless'])) {
3841
                if (preg_match($g['wireless_regex'], $interface)) {
3842
                        if (isset($config['interfaces'][$friendly]))
3843
                                $config['interfaces'][$friendly]['wireless'] = array();
3844
                        return true;
3845
                }
3846
                return false;
3847
        } else
3848
                return true;
3849
}
3850

    
3851
function get_wireless_modes($interface) {
3852
	/* return wireless modes and channels */
3853
	$wireless_modes = array();
3854

    
3855
	$cloned_interface = get_real_interface($interface);
3856

    
3857
	if($cloned_interface && is_interface_wireless($cloned_interface)) {
3858
		$chan_list = "/sbin/ifconfig {$cloned_interface} list chan";
3859
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
3860
		$format_list = "/usr/bin/awk '{print \$5 \" \" \$6 \",\" \$1}'";
3861

    
3862
		$interface_channels = "";
3863
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
3864
		$interface_channel_count = count($interface_channels);
3865

    
3866
		$c = 0;
3867
		while ($c < $interface_channel_count)
3868
		{
3869
			$channel_line = explode(",", $interface_channels["$c"]);
3870
			$wireless_mode = trim($channel_line[0]);
3871
			$wireless_channel = trim($channel_line[1]);
3872
			if(trim($wireless_mode) != "") {
3873
				/* if we only have 11g also set 11b channels */
3874
				if($wireless_mode == "11g") {
3875
					if(!isset($wireless_modes["11b"]))
3876
						$wireless_modes["11b"] = array();
3877
				} else if($wireless_mode == "11g ht") {
3878
					if(!isset($wireless_modes["11b"]))
3879
						$wireless_modes["11b"] = array();
3880
					if(!isset($wireless_modes["11g"]))
3881
						$wireless_modes["11g"] = array();
3882
					$wireless_mode = "11ng";
3883
				} else if($wireless_mode == "11a ht") {
3884
					if(!isset($wireless_modes["11a"]))
3885
						$wireless_modes["11a"] = array();
3886
					$wireless_mode = "11na";
3887
				}
3888
				$wireless_modes["$wireless_mode"]["$c"] = $wireless_channel;
3889
			}
3890
			$c++;
3891
		}
3892
	}
3893
	return($wireless_modes);
3894
}
3895

    
3896
/* return channel numbers, frequency, max txpower, and max regulation txpower */
3897
function get_wireless_channel_info($interface) {
3898
	$wireless_channels = array();
3899

    
3900
	$cloned_interface = get_real_interface($interface);
3901

    
3902
	if($cloned_interface && is_interface_wireless($cloned_interface)) {
3903
		$chan_list = "/sbin/ifconfig {$cloned_interface} list txpower";
3904
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
3905
		$format_list = "/usr/bin/awk '{print \$1 \",\" \$3 \" \" \$4 \",\" \$5 \",\" \$7}'";
3906

    
3907
		$interface_channels = "";
3908
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
3909

    
3910
		foreach ($interface_channels as $channel_line) {
3911
			$channel_line = explode(",", $channel_line);
3912
			if(!isset($wireless_channels[$channel_line[0]]))
3913
				$wireless_channels[$channel_line[0]] = $channel_line;
3914
		}
3915
	}
3916
	return($wireless_channels);
3917
}
3918

    
3919
/****f* interfaces/get_interface_mtu
3920
 * NAME
3921
 *   get_interface_mtu - Return the mtu of an interface
3922
 * RESULT
3923
 *   $tmp       - Returns the mtu of an interface
3924
 ******/
3925
function get_interface_mtu($interface) {
3926
        $mtu = pfSense_get_interface_addresses($interface);
3927
        return $mtu['mtu'];
3928
}
3929

    
3930
function get_interface_mac($interface) {
3931

    
3932
	$macinfo = pfSense_get_interface_addresses($interface);
3933
	return $macinfo["macaddr"];
3934
}
3935

    
3936
/****f* pfsense-utils/generate_random_mac_address
3937
 * NAME
3938
 *   generate_random_mac - generates a random mac address
3939
 * INPUTS
3940
 *   none
3941
 * RESULT
3942
 *   $mac - a random mac address
3943
 ******/
3944
function generate_random_mac_address() {
3945
        $mac = "02";
3946
        for($x=0; $x<5; $x++)
3947
                $mac .= ":" . dechex(rand(16, 255));
3948
        return $mac;
3949
}
3950

    
3951
/****f* interfaces/is_jumbo_capable
3952
 * NAME
3953
 *   is_jumbo_capable - Test if interface is jumbo frame capable.  Useful for determining VLAN capability.
3954
 * INPUTS
3955
 *   $int             - string containing interface name
3956
 * RESULT
3957
 *   boolean          - true or false
3958
 ******/
3959
function is_jumbo_capable($int) {
3960
        global $g;
3961

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

    
3964
        if (in_array($int_family[0], $g['vlan_long_frame']))
3965
                return true;
3966
        else
3967
                return false;
3968
}
3969

    
3970
function setup_pppoe_reset_file($pppif, $iface="") {
3971
	global $g;
3972
	$cron_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
3973

    
3974
	if(!empty($iface) && !empty($pppif)){
3975
		$cron_cmd = <<<EOD
3976
#!/bin/sh
3977
/usr/local/sbin/pfSctl -c 'interface reload {$iface}'
3978
/usr/bin/logger -t pppoe{$iface} "PPPoE periodic reset executed on {$iface}"
3979

    
3980
EOD;
3981

    
3982
		file_put_contents($cron_file, $cron_cmd);
3983
		chmod($cron_file, 0700);
3984
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
3985
	} else
3986
		unlink_if_exists($cron_file);
3987
}
3988

    
3989
function get_interface_default_mtu($type = "ethernet") {
3990
	switch ($type) {
3991
	case "gre":
3992
		return 1476;
3993
		break;
3994
	case "gif":
3995
		return 1280;
3996
		break;
3997
	case "tun":
3998
	case "vlan":
3999
	case "tap":
4000
	case "ethernet":
4001
	default:
4002
		return 1500;
4003
		break;
4004
	}
4005

    
4006
	/* Never reached */
4007
	return 1500;
4008
}
4009

    
4010
function get_vip_descr($ipaddress) {
4011
	global $config;
4012

    
4013
	foreach ($config['virtualip']['vip'] as $vip) {
4014
		if ($vip['subnet'] == $ipaddress) {
4015
			return ($vip['descr']);
4016
		}
4017
	}
4018
	return "";
4019
}
4020

    
4021
?>
(25-25/61)