Project

General

Profile

Download (120 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(gettext("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
/*
89
 * does_vip_exist($vip): return true or false if a vip is
90
 * configured.
91
 */
92
function does_vip_exist($vip) {
93
	global $config;
94
	
95
	if(!$vip)
96
		return false;
97

    
98

    
99
	switch ($vip['mode']) {
100
	case "carp":
101
	case "carpdev":
102
		$realif = "vip{$vip['vhid']}";
103
		if (!does_interface_exist($realif)) {
104
			return false;
105
		}
106
		break;
107
	case "ipalias":
108
		$realif = get_real_interface($vip['interface']);
109
		if (!does_interface_exist($realif)) {
110
			return false;
111
		}
112
		break;
113
	case "proxyarp":
114
		/* XXX: Implement this */
115
	default:
116
		return false;
117
	}
118

    
119
	$ifacedata = pfSense_getall_interface_addresses($realif);
120
	foreach ($ifacedata as $vipips) {
121
		if ($vipips == "{$vip['subnet']}/{$vip['subnet_bits']}")
122
			return true;
123
	}
124

    
125
	return false;
126
}
127

    
128
function interface_netgraph_needed($interface = "wan") {
129
	global $config;
130

    
131
	$found = false;
132
	if (!empty($config['pptpd']) &&
133
		$config['pptpd']['mode'] == "server")
134
		$found = true;
135
	if ($found == false && !empty($config['l2tp']) &&
136
		$config['l2tp']['mode'] == "server")
137
		$found = true;
138
	if ($found == false && is_array($config['pppoes']['pppoe'])) {
139
		foreach ($config['pppoes']['pppoe'] as $pppoe) {
140
			if ($pppoe['mode'] != "server")
141
				continue;
142
			if ($pppoe['interface'] == $interface)
143
				$found = true;
144
				break;
145
		}
146
	}
147
	if ($found == false) {
148
		if (!empty($config['interfaces'][$interface])) {
149
			switch ($config['interfaces'][$interface]['ipaddr']) {
150
			case "ppp":
151
			case "pppoe":
152
			case "l2tp":
153
			case "pptp":
154
				$found = true;
155
				break;
156
			default:
157
				$found = false;
158
				break;
159
			}
160
		}
161
	}
162
	if ($found == false) {
163
		$realif = get_real_interface($interface);
164
		if (is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) {
165
			foreach ($config['ppps']['ppp'] as $pppid => $ppp) {
166

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

    
171
				if ($realif == $ppp['if']) {
172
					$found = true;
173
					break;
174
				}
175
*/			
176
				$ports = explode(',',$ppp['ports']);
177
				foreach($ports as $pid => $port){
178
					$port = get_real_interface($port);
179
					if ($realif == $port) {
180
						$found = true;
181
						break;
182
					}
183
					/* Find the parent interfaces of the vlans in the MLPPP configs 
184
					* there should be only one element in the array here 
185
					* -- this could be better . . . */
186
					$parent_if = get_parent_interface($port);
187
					if ($realif == $parent_if[0]) {
188
						$found = true;
189
						break;
190
					}
191
				}
192
			}
193
		}
194
	}
195
	
196
	if ($found == false) {
197
		$realif = get_real_interface($interface);
198
		pfSense_ngctl_detach("{$realif}:", $realif);
199
	}
200
	/* NOTE: We make sure for this on interface_ppps_configure()
201
	 *	no need to do it here agan.
202
	 *	else
203
	 *		pfSense_ngctl_attach(".", $realif);
204
	 */
205
}
206

    
207
function interfaces_loopback_configure() {
208
	global $g;
209

    
210
	if ($g['platform'] == 'jail')
211
		return;
212
	if($g['booting'])
213
		echo gettext("Configuring loopback interface...");
214
	pfSense_interface_setaddress("lo0", "127.0.0.1");
215
	interfaces_bring_up("lo0");
216
	if($g['booting'])
217
		echo gettext("done.") . "\n";
218
	return 0;
219
}
220

    
221
function interfaces_vlan_configure() {
222
	global $config, $g;
223
	if($g['booting'])
224
		echo gettext("Configuring VLAN interfaces...");
225
	if (is_array($config['vlans']['vlan']) && count($config['vlans']['vlan'])) {
226
		foreach ($config['vlans']['vlan'] as $vlan) {
227
			if(empty($vlan['vlanif']))
228
				$vlan['vlanif'] = "{$vlan['if']}_vlan{$vlan['tag']}";
229
			/* XXX: Maybe we should report any errors?! */
230
			interface_vlan_configure($vlan);
231
		}
232
	}
233
	if($g['booting'])
234
		echo gettext("done.") . "\n";
235
}
236

    
237
function interface_vlan_configure(&$vlan) {
238
        global $config, $g;
239

    
240
	if (!is_array($vlan)) {
241
		log_error(gettext("VLAN: called with wrong options. Problems with config!"));
242
		return;
243
	}
244
	$if = $vlan['if'];
245
	$vlanif  = empty($vlan['vlanif']) ? "{$if}_vlan{$vlan['tag']}" : $vlan['vlanif'];
246
	$tag = $vlan['tag'];
247

    
248
	if (empty($if)) {
249
		log_error(gettext("interface_vlan_confgure called with if undefined."));
250
		return;
251
	}
252

    
253
	/* make sure the parent interface is up */
254
	interfaces_bring_up($if);
255
	/* Since we are going to add vlan(4) try to enable all that hardware supports. */
256
	pfSense_interface_capabilities($if, IFCAP_VLAN_HWTAGGING|IFCAP_VLAN_MTU|IFCAP_VLAN_HWFILTER);
257

    
258
	if (!empty($vlanif) && does_interface_exist($vlanif)) {
259
		interface_bring_down($vlanif, true);
260
	} else {
261
		$tmpvlanif = pfSense_interface_create("vlan");
262
		pfSense_interface_rename($tmpvlanif, $vlanif);
263
		pfSense_ngctl_name("{$tmpvlanif}:", $vlanif);
264
	}
265

    
266
	pfSense_vlan_create($vlanif, $if, $tag);
267

    
268
	interfaces_bring_up($vlanif);
269

    
270
	/* invalidate interface cache */
271
	get_interface_arr(true);
272

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

    
276
	return $vlanif;
277
}
278

    
279
function interface_qinq_configure(&$vlan, $fd = NULL) {
280
        global $config, $g;
281

    
282
        if (!is_array($vlan)) {
283
                log_error(sprintf(gettext("QinQ compat VLAN: called with wrong options. Problems with config!%s"), "\n"));
284
                return;
285
        }
286

    
287
        $qinqif = $vlan['if'];
288
        $tag = $vlan['tag'];
289
        if(empty($qinqif)) {
290
                log_error(sprintf(gettext("interface_qinq_confgure called with if undefined.%s"), "\n"));
291
                return;
292
        }
293
	$vlanif = interface_vlan_configure($vlan);
294

    
295
        if ($fd == NULL) {
296
                $exec = true;
297
                $fd = fopen("{$g['tmp_path']}/netgraphcmd", "w");
298
        } else
299
                $exec = false;
300
        /* make sure the parent is converted to ng_vlan(4) and is up */
301
        interfaces_bring_up($qinqif);
302

    
303
	pfSense_ngctl_attach(".", $qinqif);
304
        if (!empty($vlanif) && does_interface_exist($vlanif)) {
305
                fwrite($fd, "shutdown {$qinqif}qinq:\n");
306
                exec("/usr/sbin/ngctl msg {$qinqif}qinq: gettable", $result);
307
                if (empty($result)) {
308
                        fwrite($fd, "mkpeer {$qinqif}: vlan lower downstream\n");
309
                        fwrite($fd, "name {$qinqif}:lower {$vlanif}qinq\n");
310
                        fwrite($fd, "connect {$qinqif}: {$vlanif}qinq: upper nomatch\n");
311
                }
312
        } else {
313
                fwrite($fd, "mkpeer {$qinqif}: vlan lower downstream\n");
314
                fwrite($fd, "name {$qinqif}:lower {$vlanif}qinq\n");
315
                fwrite($fd, "connect {$qinqif}: {$vlanif}qinq: upper nomatch\n");
316
        }
317

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

    
321
        if (!stristr($qinqif, "vlan"))
322
                mwexec("/sbin/ifconfig {$qinqif} promisc\n");
323

    
324
        $macaddr = get_interface_mac($qinqif);
325
        if (!empty($vlan['members'])) {
326
                $members = explode(" ", $vlan['members']);
327
                foreach ($members as $qtag) {
328
                        $qinq = array();
329
                        $qinq['tag'] = $qtag;
330
                        $qinq['if'] = $vlanif;
331
                        interface_qinq2_configure($qinq, $fd, $macaddr);
332
                }
333
        }
334
        if ($exec == true) {
335
                fclose($fd);
336
                mwexec("/usr/sbin/ngctl -f {$g['tmp_path']}/netgraphcmd");
337
        }
338

    
339
        interfaces_bring_up($qinqif);
340
        if (!empty($vlan['members'])) {
341
                $members = explode(" ", $vlan['members']);
342
                foreach ($members as $qif)
343
                        interfaces_bring_up("{$vlanif}_{$qif}");
344
        }
345

    
346
        return $vlanif;
347
}
348

    
349
function interfaces_qinq_configure() {
350
	global $config, $g;
351
	if($g['booting'])
352
		echo gettext("Configuring QinQ interfaces...");
353
	if (is_array($config['qinqs']['qinqentry']) && count($config['qinqs']['qinqentry'])) {
354
		foreach ($config['qinqs']['qinqentry'] as $qinq) {
355
			/* XXX: Maybe we should report any errors?! */
356
			interface_qinq_configure($qinq);
357
		}
358
	}
359
	if($g['booting'])
360
		echo gettext( "done.") . "\n";
361
}
362

    
363
function interface_qinq2_configure(&$qinq, $fd, $macaddr) {
364
        global $config, $g;
365

    
366
        if (!is_array($qinq)) {
367
                log_error(sprintf(gettext("QinQ compat VLAN: called with wrong options. Problems with config!%s"), "\n"));
368
                return;
369
        }
370

    
371
        $if = $qinq['if'];
372
        $tag = $qinq['tag'];
373
        $vlanif = "{$if}_{$tag}";
374
        if(empty($if)) {
375
                log_error(sprintf(gettext("interface_qinq_confgure called with if undefined.%s"), "\n"));
376
                return;
377
        }
378

    
379
        fwrite($fd, "shutdown {$if}h{$tag}:\n");
380
        fwrite($fd, "mkpeer {$if}qinq: eiface {$if}{$tag} ether\n");
381
        fwrite($fd, "name {$if}qinq:{$if}{$tag} {$if}h{$tag}\n");
382
        fwrite($fd, "msg {$if}qinq: addfilter { vlan={$tag} hook=\"{$if}{$tag}\" }\n");
383
        fwrite($fd, "msg {$if}h{$tag}: setifname \"{$vlanif}\"\n");
384
        fwrite($fd, "msg {$if}h{$tag}: set {$macaddr}\n");
385

    
386
        /* invalidate interface cache */
387
        get_interface_arr(true);
388

    
389
        return $vlanif;
390
}
391

    
392
function interfaces_create_wireless_clones() {
393
	global $config;
394

    
395
	if($g['booting'])
396
		echo gettext("Creating other wireless clone interfaces...");
397
	if (is_array($config['wireless']['clone']) && count($config['wireless']['clone'])) {
398
		foreach ($config['wireless']['clone'] as $clone) {
399
			if(empty($clone['cloneif']))
400
				continue;
401
			if(does_interface_exist($clone['cloneif']))
402
				continue;
403
			/* XXX: Maybe we should report any errors?! */
404
			if(interface_wireless_clone($clone['cloneif'], $clone))
405
				if($g['booting'])
406
					echo " " . $clone['cloneif'];
407
		}
408
	}
409
	if($g['booting'])
410
		echo " " . gettext("done.") . "\n";
411
}
412

    
413
function interfaces_bridge_configure($checkmember = 0) {
414
        global $config;
415

    
416
        $i = 0;
417
        if (is_array($config['bridges']['bridged']) && count($config['bridges']['bridged'])) {
418
                foreach ($config['bridges']['bridged'] as $bridge) {
419
                        if(empty($bridge['bridgeif']))
420
                                $bridge['bridgeif'] = "bridge{$i}";
421
			if ($checkmember == 1 && (strstr($bridge['members'], "gif") || strstr($bridge['members'], "gre")))
422
				continue;
423
			if ($checkmember == 2 && !strstr($bridge['members'], "gif") && !strstr($bridge['members'], "gre"))
424
				continue;
425
                        /* XXX: Maybe we should report any errors?! */
426
                        interface_bridge_configure($bridge);
427
                        $i++;
428
                }
429
        }
430
}
431

    
432
function interface_bridge_configure(&$bridge) {
433
	global $config, $g;
434

    
435
	if (!is_array($bridge))
436
	        return -1;
437

    
438
	if (empty($bridge['members'])) {
439
		log_error(sprintf(gettext("No members found on %s"), $bridge['bridgeif']));
440
		return -1;
441
	}
442

    
443
	$members = explode(',', $bridge['members']);
444
	if (!count($members))
445
		return -1;
446

    
447
	$checklist = get_configured_interface_list();
448

    
449
	if ($g['booting'] || !empty($bridge['bridgeif'])) {
450
		pfSense_interface_destroy($bridge['bridgeif']);
451
		pfSense_interface_create($bridge['bridgeif']);
452
		$bridgeif = $bridge['bridgeif'];
453
	} else
454
		$bridgeif = pfSense_interface_create("bridge");
455

    
456
	/* Calculate smaller mtu and enforce it */
457
	$smallermtu = 0;
458
	$commonrx = true;
459
	$commontx = true;
460
	foreach ($members as $member) {
461
		$realif = get_real_interface($member);
462
		$opts = pfSense_get_interface_addresses($realif);
463
		$mtu = $opts['mtu'];
464
		if (substr($realif, 0, 3) == "gif" && $mtu <= 1500)
465
			continue;
466
		if (!isset($opts['encaps']['txcsum']))
467
			$commontx = false;
468
		if (!isset($opts['encaps']['rxcsum']))
469
			$commonrx = false;
470
		if (!isset($opts['encaps']['tso4']))
471
			$commontso4 = false;
472
		if (!isset($opts['encaps']['tso6']))
473
			$commontso6 = false;
474
		if (!isset($opts['encaps']['lro']))
475
			$commonlro = false;
476
		if ($smallermtu == 0 && !empty($mtu))
477
			$smallermtu = $mtu;
478
		else if (!empty($mtu) && $mtu < $smallermtu)
479
			$smallermtu = $mtu;
480
	}
481
	 
482
	/* Just in case anything is not working well */
483
	if ($smallermtu == 0)
484
		$smallermtu = 1500; 
485

    
486
	$flags = 0;
487
	if ($commonrx === false)
488
		$flags |= IFCAP_RXCSUM;
489
	if ($commontx === false)
490
		$flags |= IFCAP_TXCSUM;
491
	if ($commontso4 === false)
492
		$flags |= IFCAP_TSO4;
493
	if ($commontso6 === false)
494
		$flags |= IFCAP_TSO6;
495
	if ($commonlro === false)
496
		$flags |= IFCAP_LRO;
497
		
498
	/* Add interfaces to bridge */
499
	foreach ($members as $member) {
500
		if (!array_key_exists($member, $checklist))
501
			continue;
502
		$realif1 = get_real_interface($member);
503
		$realif =  escapeshellarg($realif1);
504
		if (!$realif) {
505
			log_error(gettext("realif not defined in interfaces bridge - up"));
506
			continue;
507
		}
508
		/* make sure the parent interface is up */
509
		pfSense_interface_mtu($realif1, $smallermtu);
510
		pfSense_interface_capabilities($realif1, -$flags);
511
		interfaces_bring_up($realif1);
512
		mwexec("/sbin/ifconfig {$bridgeif} addm {$realif}");	
513
	}
514

    
515
	if (isset($bridge['enablestp'])) {
516
		/* Choose spanning tree proto */
517
		mwexec("/sbin/ifconfig {$bridgeif} proto {$bridge['proto']}");	
518
		
519
		if (!empty($bridge['stp'])) {
520
			$stpifs = explode(',', $bridge['stp']);
521
			foreach ($stpifs as $stpif) {
522
				$realif = get_real_interface($stpif);
523
				mwexec("/sbin/ifconfig {$bridgeif} stp {$realif}");
524
			}
525
		}
526
		if (!empty($bridge['maxage']))
527
			mwexec("/sbin/ifconfig {$bridgeif} maxage {$bridge['maxage']}");
528
		if (!empty($brige['fwdelay']))
529
			mwexec("/sbin/ifconfig {$bridgeif} fwddelay {$bridge['fwdelay']}");
530
		if (!empty($brige['hellotime']))
531
                        mwexec("/sbin/ifconfig {$bridgeif} hellotime {$bridge['hellotime']}");
532
		if (!empty($brige['priority']))
533
                        mwexec("/sbin/ifconfig {$bridgeif} priority {$bridge['priority']}");
534
		if (!empty($brige['holdcount']))
535
                        mwexec("/sbin/ifconfig {$bridgeif} holdcnt {$bridge['holdcnt']}");
536
		if (!empty($bridge['ifpriority'])) {
537
			$pconfig = explode(",", $bridge['ifpriority']);
538
			$ifpriority = array();
539
			foreach ($pconfig as $cfg) {
540
				$embcfg = explode(":", $cfg);
541
				foreach ($embcfg as $key => $value)
542
					$ifpriority[$key] = $value;
543
			}
544
			foreach ($ifpriority as $key => $value) {
545
				$realif = get_real_interface($key);
546
				mwexec("/sbin/ifconfig ${bridgeif} ifpriority {$realif} {$value}"); 
547
			}
548
		}
549
		if (!empty($bridge['ifpathcost'])) {
550
			$pconfig = explode(",", $bridges['ifpathcost']);
551
			$ifpathcost = array();
552
			foreach ($pconfig as $cfg) {
553
				$embcfg = explode(":", $cfg);
554
				foreach ($embcfg as $key => $value)
555
					$ifpathcost[$key] = $value;
556
			}
557
			foreach ($ifpathcost as $key => $value) {
558
                        	$realif = get_real_interface($key);
559
                        	mwexec("/sbin/ifconfig ${bridgeif} ifpathcost {$realif} {$value}");
560
                	}
561
		}
562
	}
563

    
564
	if ($bridge['maxaddr'] <> "")
565
		mwexec("/sbin/ifconfig {$bridgeif} maxaddr {$bridge['maxaddr']}");
566
        if ($bridge['timeout'] <> "")
567
                mwexec("/sbin/ifconfig {$bridgeif} timeout {$bridge['timeout']}");
568
        if ($bridge['span'] <> "") {
569
		$realif = get_real_interface($bridge['span']);
570
                mwexec("/sbin/ifconfig {$bridgeif} span {$realif}");
571
	}
572
	if (!empty($bridge['edge'])) {
573
        	$edgeifs = explode(',', $bridge['edge']);
574
        	foreach ($edgeifs as $edgeif) {
575
			$realif = get_real_interface($edgeif);
576
                	mwexec("/sbin/ifconfig {$bridgeif} edge {$realif}");
577
        	}
578
	}
579
	if (!empty($bridge['autoedge'])) {
580
        	$edgeifs = explode(',', $bridge['autoedge']);
581
        	foreach ($edgeifs as $edgeif) {
582
                	$realif = get_real_interface($edgeif);
583
                	mwexec("/sbin/ifconfig {$bridgeif} -autoedge {$realif}");
584
        	}
585
	}
586
	if (!empty($bridge['ptp'])) {
587
        	$ptpifs = explode(',', $bridge['ptp']);
588
        	foreach ($ptpifs as $ptpif) {
589
                	$realif = get_real_interface($ptpif);
590
                	mwexec("/sbin/ifconfig {$bridgeif} ptp {$realif}");
591
        	}
592
	}
593
	if (!empty($bridge['autoptp'])) {
594
        	$ptpifs = explode(',', $bridge['autoptp']);
595
        	foreach ($ptpifs as $ptpif) {
596
                	$realif = get_real_interface($ptpif);
597
                	mwexec("/sbin/ifconfig {$bridgeif} -autoptp {$realif}");
598
        	}
599
	}
600
	if (!empty($bridge['static'])) {
601
        	$stickyifs = explode(',', $bridge['static']);
602
        	foreach ($stickyifs as $stickyif) {
603
                	$realif = get_real_interface($stickyif);
604
                	mwexec("/sbin/ifconfig {$bridgeif} sticky {$realif}");
605
        	}
606
	}
607
	if (!empty($bridge['private'])) {
608
        	$privateifs = explode(',', $bridge['private']);
609
        	foreach ($privateifs as $privateif) {
610
                	$realif = get_real_interface($privateif);
611
               	 	mwexec("/sbin/ifconfig {$bridgeif} private {$realif}");
612
        	}
613
	}
614

    
615
	if($bridgeif)
616
		interfaces_bring_up($bridgeif);	
617
	else 
618
		log_error(gettext("bridgeif not defined -- could not bring interface up"));
619

    
620
	return $bridgeif;
621
}
622

    
623
function interface_bridge_add_member($bridgeif, $interface) {
624

    
625
	if (!does_interface_exist($bridgeif) || !does_interface_exist($interface))
626
		return;
627

    
628
	$mtu = get_interface_mtu($brigeif);
629
	$mtum = get_interface_mtu($interface);
630
	
631
	if ($mtu != $mtum && !(substr($interface, 0, 3) == "gif" && $mtu <= 1500))
632
		pfSense_interface_mtu($interface, $mtu);
633

    
634
	$options = pfSense_get_interface_addresses($bridgeif);
635
	$flags = 0;
636
	if (!isset($options['encaps']['txcsum']))
637
		$flags |= IFCAP_TXCSUM;
638

    
639
	if (!isset($options['encaps']['rxcsum']))
640
		$flags |= IFCAP_RXCSUM;
641

    
642
	pfSense_interface_capabilities($interface, -$flags);
643

    
644
	interfaces_bring_up($interface);
645
	mwexec("/sbin/ifconfig {$bridgeif} addm {$interface}");
646
}
647

    
648
function interfaces_lagg_configure() 
649
{
650
        global $config, $g;
651
		if($g['booting']) 
652
			echo gettext("Configuring LAGG interfaces...");
653
        $i = 0;
654
		if (is_array($config['laggs']['lagg']) && count($config['laggs']['lagg'])) {
655
			foreach ($config['laggs']['lagg'] as $lagg) {
656
				if(empty($lagg['laggif']))
657
					$lagg['laggif'] = "lagg{$i}";
658
				/* XXX: Maybe we should report any errors?! */
659
				interface_lagg_configure($lagg);
660
				$i++;
661
			}
662
		}
663
		if($g['booting']) 
664
			echo gettext("done.") . "\n";
665
}
666

    
667
function interface_lagg_configure(&$lagg) {
668
        global $config, $g;
669

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

    
673
	$members = explode(',', $lagg['members']);
674
	if (!count($members))
675
		return -1;
676
	
677
	$checklist = get_interface_list();
678

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

    
686
	/* Calculate smaller mtu and enforce it */
687
        $smallermtu = 0;
688
        foreach ($members as $member) {
689
		$opts = pfSense_get_interface_addresses($member);
690
                $mtu = $opts['mtu'];
691
		if (!isset($opts['encaps']['txcsum']))
692
                        $commontx = false;
693
                if (!isset($opts['encaps']['rxcsum']))
694
                        $commonrx = false;
695
		if (!isset($opts['encaps']['tso4']))
696
			$commontso4 = false;
697
		if (!isset($opts['encaps']['tso6']))
698
			$commontso6 = false;
699
		if (!isset($opts['encaps']['lro']))
700
			$commonlro = false;
701
		if ($smallermtu == 0 && !empty($mtu))
702
			$smallermtu = $mtu;
703
                else if (!empty($mtu) && $mtu < $smallermtu)
704
                        $smallermtu = $mtu;
705
        }
706

    
707
	/* Just in case anything is not working well */
708
        if ($smallermtu == 0)
709
                $smallermtu = 1500;
710

    
711
	$flags = 0;
712
        if ($commonrx === false)
713
                $flags |= IFCAP_RXCSUM;
714
        if ($commontx === false)
715
                $flags |= IFCAP_TXCSUM;
716
	if ($commontso4 === false)
717
                $flags |= IFCAP_TSO4;
718
        if ($commontso6 === false)
719
                $flags |= IFCAP_TSO6;
720
        if ($commonlro === false)
721
                $flags |= IFCAP_LRO;
722

    
723
	foreach ($members as $member) {
724
		if (!array_key_exists($member, $checklist))
725
			continue;
726
		/* make sure the parent interface is up */
727
		pfSense_interface_mtu($member, $smallermtu);
728
		pfSense_interface_capabilities($member, -$flags);
729
		interfaces_bring_up($member);
730
		mwexec("/sbin/ifconfig {$laggif} laggport {$member}");
731
	}
732
	
733
	mwexec("/sbin/ifconfig {$laggif} laggproto {$lagg['proto']}");
734

    
735
	interfaces_bring_up($laggif);
736

    
737
	return $laggif;
738
}
739

    
740
function interfaces_gre_configure($checkparent = 0) {
741
        global $config;
742

    
743
        if (is_array($config['gres']['gre']) && count($config['gres']['gre'])) {
744
                foreach ($config['gres']['gre'] as $i => $gre) {
745
                        if(empty($gre['greif']))
746
                                $gre['greif'] = "gre{$i}";
747
			if ($checkparent == 1 && strstr($gre['if'], "vip"))
748
				continue;
749
			if ($checkparent == 2 && !strstr($gre['if'], "vip"))
750
				continue;
751
                        /* XXX: Maybe we should report any errors?! */
752
                        interface_gre_configure($gre);
753
                }
754
        }
755
}
756

    
757
/* NOTE: $grekey is not used but useful for passing this function to array_walk. */
758
function interface_gre_configure(&$gre, $grekey = "") {
759
        global $config, $g;
760

    
761
	if (!is_array($gre))
762
		return -1;
763

    
764
	$realif = get_real_interface($gre['if']);
765
	$realifip = get_interface_ip($gre['if']);
766

    
767
	/* make sure the parent interface is up */
768
	interfaces_bring_up($realif);
769

    
770
	if ($g['booting'] || !(empty($gre['greif']))) {
771
		pfSense_interface_destroy($gre['greif']);
772
		pfSense_interface_create($gre['greif']);
773
		$greif = $gre['greif'];
774
	} else
775
		$greif = pfSense_interface_create("gre");
776

    
777
	/* Do not change the order here for more see gre(4) NOTES section. */
778
	mwexec("/sbin/ifconfig {$greif} tunnel {$realifip} {$gre['remote-addr']}");
779
	mwexec("/sbin/ifconfig {$greif} {$gre['tunnel-local-addr']} {$gre['tunnel-remote-addr']} netmask " . gen_subnet_mask($gre['tunnel-remote-net']));
780
	if (isset($gre['link0']) && $gre['link0'])
781
		pfSense_interface_flags($greif, IFF_LINK0);
782
	if (isset($gre['link1']) && $gre['link1'])
783
		pfSense_interface_flags($greif, IFF_LINK1);
784
	if (isset($gre['link2']) && $gre['link2'])
785
		pfSense_interface_flags($greif, IFF_LINK2);
786

    
787
	if($greif)
788
		interfaces_bring_up($greif);
789
	else 
790
		log_error(gettext("Could not bring greif up -- variable not defined."));
791

    
792
	if (isset($gre['link1']) && $gre['link1'])
793
		mwexec("/sbin/route add {$gre['tunnel-remote-addr']}/{$gre['tunnel-remote-net']} {$gre['tunnel-local-addr']}");
794
	if(is_ipaddrv4($gre['tunnel-remote-addr']))
795
		file_put_contents("{$g['tmp_path']}/{$greif}_router", $gre['tunnel-remote-addr']);
796
	if(is_ipaddrv6($gre['tunnel-remote-addr']))
797
		file_put_contents("{$g['tmp_path']}/{$greif}_routerv6", $gre['tunnel-remote-addr']);
798

    
799
	return $greif;
800
}
801

    
802
function interfaces_gif_configure($checkparent = 0) {
803
	global $config;
804

    
805
	if (is_array($config['gifs']['gif']) && count($config['gifs']['gif'])) {
806
		foreach ($config['gifs']['gif'] as $i => $gif) {
807
			if(empty($gif['gifif']))
808
				$gre['gifif'] = "gif{$i}";
809
			if ($checkparent == 1 && strstr($gif['if'], "vip"))
810
				continue;
811
			if ($checkparent == 2 && !strstr($gif['if'], "vip"))
812
				continue;
813
			/* XXX: Maybe we should report any errors?! */
814
			interface_gif_configure($gif);
815
		}
816
	}
817
}
818

    
819
/* NOTE: $gifkey is not used but useful for passing this function to array_walk. */
820
function interface_gif_configure(&$gif, $gifkey = "") {
821
	global $config, $g;
822

    
823
	if (!is_array($gif))
824
		return -1;
825

    
826
	$realif = get_real_interface($gif['if']);
827
	$realifip = get_interface_ip($gif['if']);
828

    
829
	/* make sure the parent interface is up */
830
	if($realif)
831
		interfaces_bring_up($realif);
832
	else 
833
		log_error(gettext("could not bring realif up -- variable not defined -- interface_gif_configure()"));
834

    
835
	if ($g['booting'] || !(empty($gif['gifif']))) {
836
		pfSense_interface_destroy($gif['gifif']);
837
		pfSense_interface_create($gif['gifif']);
838
		$gifif = $gif['gifif'];
839
	} else
840
		$gifif = pfSense_interface_create("gif");
841

    
842
	/* Do not change the order here for more see gif(4) NOTES section. */
843
	mwexec("/sbin/ifconfig {$gifif} tunnel {$realifip} {$gif['remote-addr']}");
844
	if((is_ipaddrv6($gif['tunnel-local-addr'])) || (is_ipaddrv6($gif['tunnel-remote-addr']))) {
845
		mwexec("/sbin/ifconfig {$gifif} inet6 {$gif['tunnel-local-addr']} {$gif['tunnel-remote-addr']} prefixlen {$gif['tunnel-remote-net']} ");
846
	} else {
847
		mwexec("/sbin/ifconfig {$gifif} {$gif['tunnel-local-addr']} {$gif['tunnel-remote-addr']} netmask " . gen_subnet_mask($gif['tunnel-remote-net']));
848
	}
849
	if (isset($gif['link0']) && $gif['link0'])
850
		pfSense_interface_flags($gifif, IFF_LINK0);
851
	if (isset($gif['link1']) && $gif['link1'])
852
		pfSense_interface_flags($gifif, IFF_LINK1);
853
	if($gifif)
854
		interfaces_bring_up($gifif);
855
	else
856
		log_error(gettext("could not bring gifif up -- variable not defined"));
857

    
858
	$iflist = get_configured_interface_list();
859
	foreach($iflist as $ifname) {
860
		if($config['interfaces'][$ifname]['if'] == $gifif) {
861
			if(get_interface_gateway($ifname)) {
862
				system_routing_configure($ifname);
863
				break;
864
			}
865
			if(get_interface_gateway_v6($ifname)) {
866
				system_routing_configure($ifname);
867
				break;
868
			}
869
		}
870
	}
871

    
872
	if(is_ipaddrv4($gif['tunnel-remote-addr']))
873
		file_put_contents("{$g['tmp_path']}/{$gifif}_router", $gif['tunnel-remote-addr']);
874
	if(is_ipaddrv6($gif['tunnel-remote-addr']))
875
		file_put_contents("{$g['tmp_path']}/{$gifif}_routerv6", $gif['tunnel-remote-addr']);
876

    
877
	return $gifif;
878
}
879

    
880
function interfaces_configure() {
881
	global $config, $g;
882

    
883
	if ($g['platform'] == 'jail')
884
		return;
885

    
886
	/* Set up our loopback interface */
887
	interfaces_loopback_configure();
888

    
889
	/* set up LAGG virtual interfaces */
890
	interfaces_lagg_configure();
891

    
892
	/* set up VLAN virtual interfaces */
893
	interfaces_vlan_configure();
894

    
895
	interfaces_qinq_configure();
896

    
897
	$iflist = get_configured_interface_with_descr();
898
	$delayed_list = array();
899
	$bridge_list = array();
900
	
901
	/* This is needed to speedup interfaces on bootup. */
902
	$reload = false;
903
	if ($g['booting'])
904
		$reload = true;
905

    
906
	foreach($iflist as $if => $ifname) {
907
		$realif = $config['interfaces'][$if]['if'];
908
		if (strstr($realif, "bridge")) 
909
			$bridge_list[$if] = $ifname;
910
		else if (strstr($realif, "gre"))
911
			$delayed_list[$if] = $ifname;
912
		else if (strstr($realif, "gif"))
913
			$delayed_list[$if] = $ifname;
914
		else if (strstr($realif, "ovpn")) {
915
			//echo "Delaying OpenVPN interface configuration...done.\n";
916
			continue;
917
		} else {
918
			if ($g['booting'])
919
				printf(gettext("Configuring %s interface..."), $ifname);
920
			if($g['debug'])
921
				log_error(sprintf(gettext("Configuring %s"), $ifname));
922
			interface_configure($if, $reload);
923
			if ($g['booting']) 
924
				echo gettext( "done.") . "\n";
925
		}
926
	}
927

    
928
	/* create the unconfigured wireless clones */
929
	interfaces_create_wireless_clones();
930

    
931
	/*
932
	 * NOTE: The following function parameter consists of
933
	 *	1 - Do not load gre/gif/bridge with parent/member as vip
934
	 *	2 - Do load gre/gif/bridge with parent/member as vip
935
	 */
936

    
937
	/* set up GRE virtual interfaces */
938
	interfaces_gre_configure(1);
939

    
940
	/* set up GIF virtual interfaces */
941
	interfaces_gif_configure(1);
942

    
943
	/* set up BRIDGe virtual interfaces */
944
	interfaces_bridge_configure(1);
945

    
946
	/* bring up vip interfaces */
947
	interfaces_vips_configure();
948

    
949
	/* set up GRE virtual interfaces */
950
	interfaces_gre_configure(2);
951

    
952
	/* set up GIF virtual interfaces */
953
	interfaces_gif_configure(2);
954

    
955
	foreach ($delayed_list as $if => $ifname) {
956
		if ($g['booting'])
957
			printf(gettext("Configuring %s interface..."), $ifname);
958
        	if ($g['debug'])
959
        		log_error(sprintf(gettext("Configuring %s"), $ifname));
960

    
961
		interface_configure($if, $reload);
962

    
963
		if ($g['booting'])
964
			echo gettext("done.") . "\n";
965
	}
966

    
967
	/* set up BRIDGe virtual interfaces */
968
	interfaces_bridge_configure(2);
969

    
970
	foreach ($bridge_list as $if => $ifname) {
971
		if ($g['booting'])
972
			printf(gettext("Configuring %s interface..."), $ifname);
973
		if($g['debug'])
974
			log_error(sprintf(gettext("Configuring %s"), $ifname));
975

    
976
		interface_configure($if, $reload);
977

    
978
		if ($g['booting'])
979
			echo gettext("done.") . "\n";
980
	}
981

    
982
	/* configure interface groups */
983
	interfaces_group_setup();
984

    
985
	if (!$g['booting']) {
986
		/* reconfigure static routes (kernel may have deleted them) */
987
		system_routing_configure();
988

    
989
		/* reload IPsec tunnels */
990
		vpn_ipsec_configure();
991

    
992
		/* reload dhcpd (interface enabled/disabled status may have changed) */
993
		services_dhcpd_configure();
994

    
995
		/* restart dnsmasq */
996
		services_dnsmasq_configure();
997

    
998
		/* reload captive portal */
999
		captiveportal_init_rules();
1000
	}
1001

    
1002
	return 0;
1003
}
1004

    
1005
function interface_reconfigure($interface = "wan", $reloadall = false) {
1006
	interface_bring_down($interface);
1007
	interface_configure($interface, $reloadall);
1008
}
1009

    
1010
function interface_vip_bring_down($vip) {
1011
	global $g;
1012

    
1013
	switch ($vip['mode']) {
1014
	case "proxyarp":
1015
		$vipif = get_real_interface($vip['interface']);
1016
		if (file_exists("{$g['varrun_path']}/choparp_{$vipif}.pid"))
1017
			killbypid("{$g['varrun_path']}/choparp_{$vipif}.pid");
1018
		break;
1019
	case "ipalias":
1020
		$vipif = get_real_interface($vip['interface']);
1021
		if(does_interface_exist($vipif))
1022
			pfSense_interface_deladdress($vipif, $vip['subnet']);
1023
		break;
1024
	case "carp":
1025
		$vipif = "vip" . $vip['vhid'];
1026
		if(does_interface_exist($vipif)) 
1027
			pfSense_interface_destroy($vipif);
1028
		break;
1029
	case "carpdev-dhcp":
1030
		$vipif = "vip" . $vip['vhid'];
1031
		if(does_interface_exist($vipif)) 
1032
			pfSense_interface_destroy($vipif);
1033
		break;
1034
	}
1035
}
1036

    
1037
function interface_bring_down($interface = "wan", $destroy = false) {
1038
	global $config, $g;
1039

    
1040
	if (!isset($config['interfaces'][$interface]))
1041
		return; 
1042

    
1043
	log_error("Calling interface down for interface {$interface}, destroy is {$destroy}");
1044

    
1045
	$ifcfg = $config['interfaces'][$interface];
1046

    
1047
	$realif = get_real_interface($interface);
1048

    
1049
	switch ($ifcfg['ipaddr']) {
1050
	case "ppp":
1051
	case "pppoe":
1052
	case "pptp":
1053
	case "l2tp":
1054
		if (is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) {
1055
			foreach ($config['ppps']['ppp'] as $pppid => $ppp) {
1056
				if ($realif == $ppp['if']) {
1057
					if (isset($ppp['ondemand']) && !$destroy){
1058
						send_event("interface reconfigure {$interface}");
1059
						break;
1060
					}
1061
					if (file_exists("{$g['varrun_path']}/{$ppp['type']}_{$interface}.pid")) {
1062
						killbypid("{$g['varrun_path']}/{$ppp['type']}_{$interface}.pid");
1063
						sleep(2);
1064
					}
1065
					unlink_if_exists("{$g['varetc_path']}/mpd_{$interface}.conf");
1066
					break;
1067
				}
1068
			}
1069
		}
1070
		break;
1071
	case "carpdev-dhcp":
1072
		/* 
1073
		 * NB: When carpdev gets enabled it would be better to be handled as all
1074
		 *	   other interfaces! 
1075
		 */
1076
	case "dhcp":
1077
		$pid = find_dhclient_process($realif);
1078
		if($pid)
1079
			mwexec("/bin/kill {$pid}");
1080
		sleep(1);
1081
		unlink_if_exists("{$g['varetc_path']}/dhclient_{$interface}.conf");
1082
		if(does_interface_exist("$realif")) {
1083
			mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete", true);
1084
			if ($destroy == true)
1085
				pfSense_interface_flags($realif, -IFF_UP);
1086
			mwexec("/usr/sbin/arp -d -i {$realif} -a");
1087
		}
1088
		break;
1089
	default:
1090
		if(does_interface_exist("$realif")) {
1091
			mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete", true);
1092
			if ($destroy == true)
1093
				pfSense_interface_flags($realif, -IFF_UP);
1094
			mwexec("/usr/sbin/arp -d -i {$realif} -a");
1095
		}
1096
		break;
1097
	}
1098

    
1099
	switch ($ifcfg['ipaddrv6']) {
1100
	case "dhcp6":
1101
		$pidv6 = find_dhcp6c_process($realif);
1102
		if($pidv6)
1103
			mwexec("/bin/kill {$pidv6}");
1104
		sleep(1);
1105
		unlink_if_exists("{$g['varetc_path']}/dhcp6c_{$interface}.conf");
1106
		if(does_interface_exist("$realif")) {
1107
			mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete", true);
1108
			if ($destroy == true)
1109
				pfSense_interface_flags($realif, -IFF_UP);
1110
			mwexec("/usr/sbin/arp -d -i {$realif} -a");
1111
		}
1112
		break;
1113
	default:
1114
		if(does_interface_exist("$realif")) {
1115
			mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete", true);
1116
			if ($destroy == true)
1117
				pfSense_interface_flags($realif, -IFF_UP);
1118
			mwexec("/usr/sbin/arp -d -i {$realif} -a");
1119
		}
1120
		break;
1121
	}
1122

    
1123

    
1124
	/* remove interface up file if it exists */
1125
	unlink_if_exists("{$g['tmp_path']}/{$realif}up");
1126
	unlink_if_exists("{$g['vardb_path']}/{$interface}ip");
1127
	unlink_if_exists("{$g['vardb_path']}/{$interface}ipv6");
1128
	unlink_if_exists("{$g['tmp_path']}/{$realif}_router");
1129
	unlink_if_exists("{$g['tmp_path']}/{$realif}_routerv6");
1130
	unlink_if_exists("{$g['varetc_path']}/nameserver_{$realif}");
1131
	unlink_if_exists("{$g['varetc_path']}/searchdomain_{$realif}");
1132
	
1133
	/* hostapd and wpa_supplicant do not need to be running when the interface is down.
1134
	 * They will also use 100% CPU if running after the wireless clone gets deleted. */
1135
	if (is_array($ifcfg['wireless'])) {
1136
		mwexec(kill_hostapd($realif));
1137
		mwexec(kill_wpasupplicant($realif));
1138
	}
1139

    
1140
	if ($destroy == true) {
1141
		if (preg_match("/^vip|^tun|^ovpn|^gif|^gre|^lagg|^bridge|vlan/i", $realif))
1142
			pfSense_interface_destroy($realif);
1143
	}	
1144

    
1145
	return;
1146
}
1147

    
1148
function interfaces_ptpid_used($ptpid) {
1149
	global $config;
1150

    
1151
	if (is_array($config['ppps']['ppp']))
1152
		foreach ($config['ppps']['ppp'] as & $settings)
1153
			if ($ptpid == $settings['ptpid'])
1154
				return true;
1155

    
1156
	return false;
1157
}
1158

    
1159
function interfaces_ptpid_next() {
1160

    
1161
	$ptpid = 0;
1162
	while(interfaces_ptpid_used($ptpid))
1163
		$ptpid++;
1164

    
1165
	return $ptpid;
1166
}
1167

    
1168
function getMPDCRONSettings($pppif_) {
1169
	global $config;
1170
	$cron_cmd_file = "{$g['varetc_path']}/pppoe_restart_";
1171
	if (is_array($config['cron']['item'])) {
1172
		for ($i = 0; $i < count($config['cron']['item']); $i++) {
1173
			$item = $config['cron']['item'][$i];
1174
			if (strpos($item['command'], $cron_cmd_file.$pppif_) !== false) {
1175
				return array("ID" => $i, "ITEM" => $item);
1176
			}
1177
		}
1178
	}
1179
	return NULL;
1180
}
1181

    
1182
function handle_pppoe_reset($post_array) {
1183
	global $config, $g;
1184

    
1185
	$cron_cmd_file = "{$g['varetc_path']}/pppoe_restart_";
1186

    
1187
	$pppif = $post_array['type'].$post_array['ptpid'];
1188
	if (!is_array($config['cron']['item'])) 
1189
		$config['cron']['item'] = array(); 
1190
	$itemhash = getMPDCRONSettings($pppif);
1191
	$item = $itemhash['ITEM'];
1192
	
1193
	// reset cron items if necessary and return
1194
	if (empty($post_array['pppoe-reset-type'])) {
1195
		if (isset($item))
1196
			unset($config['cron']['item'][$itemhash['ID']]);
1197
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
1198
		return;
1199
	}
1200

    
1201
	if (empty($item)) 
1202
		$item = array();
1203
	if (isset($post_array['pppoe-reset-type']) && $post_array['pppoe-reset-type'] == "custom") {
1204
		$item['minute'] = $post_array['pppoe_resetminute'];
1205
		$item['hour'] = $post_array['pppoe_resethour'];
1206
		if (isset($post_array['pppoe_resetdate']) && $post_array['pppoe_resetdate'] <> "") {
1207
			$date = explode("/", $post_array['pppoe_resetdate']);
1208
			$item['mday'] = $date[1];
1209
			$item['month'] = $date[0];
1210
		} else {
1211
			$item['mday'] = "*";
1212
			$item['month'] = "*";
1213
		}
1214
		$item['wday'] = "*";
1215
		$item['who'] = "root";
1216
		$item['command'] = $cron_cmd_file.$pppif;
1217
	} else if (isset($post_array['pppoe-reset-type']) && $post_array['pppoe-reset-type'] == "preset") {
1218
		switch ($post_array['pppoe_pr_preset_val']) {
1219
			case "monthly":
1220
				$item['minute'] = "0";
1221
				$item['hour'] = "0";
1222
				$item['mday'] = "1";
1223
				$item['month'] = "*";
1224
				$item['wday'] = "*";
1225
				$item['who'] = "root";
1226
				$item['command'] = $cron_cmd_file.$pppif;
1227
				break;
1228
	        case "weekly":
1229
				$item['minute'] = "0";
1230
				$item['hour'] = "0";
1231
				$item['mday'] = "*";
1232
				$item['month'] = "*";
1233
				$item['wday'] = "0";
1234
				$item['who'] = "root";
1235
				$item['command'] = $cron_cmd_file.$pppif;
1236
				break;
1237
			case "daily":
1238
				$item['minute'] = "0";
1239
				$item['hour'] = "0";
1240
				$item['mday'] = "*";
1241
				$item['month'] = "*";
1242
				$item['wday'] = "*";
1243
				$item['who'] = "root";
1244
				$item['command'] = $cron_cmd_file.$pppif;
1245
				break;
1246
			case "hourly":
1247
				$item['minute'] = "0";
1248
				$item['hour'] = "*";
1249
				$item['mday'] = "*";
1250
				$item['month'] = "*";
1251
				$item['wday'] = "*";
1252
				$item['who'] = "root";
1253
				$item['command'] = $cron_cmd_file.$pppif;
1254
				break;
1255
		} // end switch
1256
	} else {
1257
		/* test whether a cron item exists and unset() it if necessary */
1258
		$itemhash = getMPDCRONSettings($pppif);
1259
		$item = $itemhash['ITEM'];
1260
		if (isset($item))
1261
			unset($config['cron']['item'][$itemhash['ID']]); 
1262
	}// end if
1263
	if (isset($itemhash['ID'])) 
1264
		$config['cron']['item'][$itemhash['ID']] = $item;
1265
	else 
1266
		$config['cron']['item'][] = $item;
1267
}
1268

    
1269
/*	This function can configure PPPoE, MLPPP (PPPoE), PPTP.
1270
*	It writes the mpd config file to /var/etc every time the link is opened.
1271
*/
1272

    
1273
function interface_ppps_configure($interface) {
1274
	global $config, $g;
1275

    
1276
	/* Return for unassigned interfaces. This is a minimum requirement. */
1277
	if (empty($config['interfaces'][$interface]))
1278
		return 0;
1279
	$ifcfg = $config['interfaces'][$interface];
1280
	if (!isset($ifcfg['enable']))
1281
		return 0;
1282

    
1283
	// mpd5 requires a /var/spool/lock directory for PPP modem links.
1284
	if(!is_dir("/var/spool/lock")) {
1285
		exec("/bin/mkdir -p /var/spool/lock");
1286
		exec("/bin/chmod a+rw /var/spool/lock/.");
1287
	}
1288
	// mpd5 modem chat script expected in the same directory as the mpd_xxx.conf files	
1289
	if (!file_exists("{$g['varetc_path']}/mpd.script"))
1290
		mwexec("/bin/ln -s /usr/local/sbin/mpd.script {$g['varetc_path']}/.");
1291

    
1292
	if (is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) {
1293
		foreach ($config['ppps']['ppp'] as $pppid => $ppp) {
1294
			if ($ifcfg['if'] == $ppp['if'])
1295
				break;
1296
		}
1297
	}
1298
	if (!$ppp || $ifcfg['if'] != $ppp['if']){
1299
		log_error(sprintf(gettext("Can't find PPP config for %s in interface_ppps_configure()."), $ifcfg['if']));
1300
		return 0;
1301
	}
1302
	$pppif = $ifcfg['if'];
1303
	if ($ppp['type'] == "ppp")
1304
		$type = "modem";
1305
	else
1306
		$type = $ppp['type'];
1307
	$upper_type = strtoupper($ppp['type']);	
1308

    
1309
	if($g['booting']) {
1310
		$descr = isset($ifcfg['descr']) ? $ifcfg['descr'] : strtoupper($interface);
1311
		echo "starting {$pppif} link...";
1312
		// Do not re-configure the interface if we are booting and it's already been started
1313
		if(file_exists("{$g['varrun_path']}/{$ppp['type']}_{$interface}.pid"))
1314
			return 0;
1315
	}
1316

    
1317
	$ports = explode(',',$ppp['ports']);
1318
	if ($type != "modem") {
1319
		foreach ($ports as $pid => $port)
1320
			$ports[$pid] = get_real_interface($port);
1321
	}
1322
	$localips = explode(',',$ppp['localip']);
1323
	$gateways = explode(',',$ppp['gateway']);
1324
	$subnets = explode(',',$ppp['subnet']);
1325

    
1326
	/* We bring up the parent interface first because if DHCP is configured on the parent we need
1327
	 * to obtain an address first so we can write it in the mpd .conf file for PPTP and L2TP configs
1328
	 */
1329
	foreach($ports as $pid => $port){
1330
		switch ($ppp['type']) {
1331
			case "pppoe": 
1332
				/* Bring the parent interface up */
1333
				interfaces_bring_up($port);
1334
				pfSense_ngctl_attach(".", $port);
1335
				break;
1336
			case "pptp":
1337
			case "l2tp":
1338
				/* configure interface */
1339
				if(is_ipaddr($localips[$pid])){
1340
					// Manually configure interface IP/subnet
1341
					pfSense_interface_setaddress($port, "{$localips[$pid]}/{$subnets[$pid]}");
1342
					interfaces_bring_up($port);
1343
				} else if (empty($localips[$pid]))
1344
					$localips[$pid] = get_interface_ip($port); // try to get the interface IP from the port
1345
				
1346
				if(!is_ipaddr($localips[$pid])){
1347
					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!");
1348
					$localips[$pid] = "0.0.0.0";
1349
				}
1350
				/* XXX: This needs to go away soon! [It's commented out!] */
1351
				/* Configure the gateway (remote IP ) */
1352
				if (!$g['booting'] && !is_ipaddr($gateways[$pid]) && is_hostname($gateways[$pid])) {
1353
					/* XXX: Fix later 
1354
					$gateways[$pid] = gethostbyname($gateways[$pid]);
1355
					if(!is_ipaddr($gateways[$pid])) {
1356
						log_error("Could not get a valid Gateway IP from {$port} via DNS in interfaces_ppps_configure.");
1357
						return 0;
1358
					}
1359
					*/
1360
				}
1361
				if(!is_ipaddr($gateways[$pid])){
1362
					log_error(sprintf(gettext('Could not get a PPTP/L2TP Remote IP address from %1$s for %2$s in interfaces_ppps_configure.'), $dhcp_gateway, $gway));
1363
					return 0;
1364
				}
1365
				pfSense_ngctl_attach(".", $port);
1366
				break;
1367
			case "ppp":
1368
				if (!file_exists("{$port}")) {
1369
					log_error(sprintf(gettext("Device %s does not exist. PPP link cannot start without the modem device."), $port));
1370
					return 0;
1371
				}
1372
				break;
1373
			default:
1374
				log_error(sprintf(gettext("Unkown %s configured as ppp interface."), $type));
1375
				break;
1376
		}
1377
	}
1378
	
1379
	if (is_array($ports) && count($ports) > 1)
1380
		$multilink = "enable";
1381
	else
1382
		$multilink = "disable";
1383
	
1384
	if ($type == "modem"){
1385
		if (is_ipaddr($ppp['localip']))
1386
			$localip = $ppp['localip'];
1387
		else
1388
			$localip = '0.0.0.0';
1389

    
1390
		if (is_ipaddr($ppp['gateway']))
1391
			$gateway = $ppp['gateway'];
1392
		else
1393
			$gateway = "10.64.64.{$pppid}";
1394
		$ranges = "{$localip}/0 {$gateway}/0";
1395
		
1396
		if (empty($ppp['apnum']))	
1397
			$ppp['apnum'] = 1;
1398
	} else
1399
		$ranges = "0.0.0.0/0 0.0.0.0/0";
1400

    
1401
	if (isset($ppp['ondemand'])) 
1402
		$ondemand = "enable";
1403
	else
1404
		$ondemand = "disable";
1405
	if (!isset($ppp['idletimeout']))
1406
		$ppp['idletimeout'] = 0;
1407

    
1408
	if (empty($ppp['username']) && $type == "modem"){
1409
		$ppp['username'] = "user";
1410
		$ppp['password'] = "none";
1411
	}
1412
	if (empty($ppp['password']) && $type == "modem")
1413
		$passwd = "none";
1414
	else
1415
		$passwd = base64_decode($ppp['password']);
1416

    
1417
	$bandwidths = explode(',',$ppp['bandwidth']);
1418
	$mtus = explode(',',$ppp['mtu']);
1419
	$mrus = explode(',',$ppp['mru']);
1420

    
1421
	if (isset($ppp['mrru']))
1422
		$mrrus = explode(',',$ppp['mrru']);
1423

    
1424
	// Construct the mpd.conf file
1425
	$mpdconf = <<<EOD
1426
startup:
1427
	# configure the console
1428
	set console close
1429
	# configure the web server
1430
	set web close
1431

    
1432
default:
1433
{$ppp['type']}client:
1434
	create bundle static {$interface}
1435
	set bundle enable ipv6cp
1436
	set iface name {$pppif}
1437

    
1438
EOD;
1439
	$setdefaultgw = false;
1440
	$founddefaultgw = false;
1441
	if (is_array($config['gateways']['gateway_item'])) {
1442
		foreach($config['gateways']['gateway_item'] as $gateway) {
1443
			if($interface == $gateway['interface'] && isset($gateway['defaultgw'])) {
1444
				$setdefaultgw = true;
1445
				break;
1446
			} else if (isset($gateway['defaultgw']) && !empty($gateway['interface'])) {
1447
				$founddefaultgw = true;
1448
				break;
1449
			}
1450
		}
1451
	}
1452
	
1453
	if (($interface == "wan" && $founddefaultgw == false) || $setdefaultgw == true){
1454
		$setdefaultgw = true;
1455
		$mpdconf .= <<<EOD
1456
	set iface route default
1457

    
1458
EOD;
1459
	}
1460
	$mpdconf .= <<<EOD
1461
	set iface {$ondemand} on-demand
1462
	set iface idle {$ppp['idletimeout']}
1463

    
1464
EOD;
1465

    
1466
	if (isset($ppp['ondemand']))
1467
		$mpdconf .= <<<EOD
1468
	set iface addrs 10.10.1.1 10.10.1.2
1469

    
1470
EOD;
1471
	
1472
	if (isset($ppp['tcpmssfix']))
1473
		$tcpmss = "disable";
1474
	else
1475
		$tcpmss = "enable";
1476
		$mpdconf .= <<<EOD
1477
	set iface {$tcpmss} tcpmssfix
1478

    
1479
EOD;
1480

    
1481
	$mpdconf .= <<<EOD
1482
	set iface up-script /usr/local/sbin/ppp-linkup
1483
	set iface down-script /usr/local/sbin/ppp-linkdown
1484
	set ipcp ranges {$ranges}
1485

    
1486
EOD;
1487
	if (isset($ppp['vjcomp']))
1488
		$mpdconf .= <<<EOD
1489
	set ipcp no vjcomp
1490

    
1491
EOD;
1492

    
1493
	if (isset($config['system']['dnsallowoverride']))
1494
		$mpdconf .= <<<EOD
1495
	set ipcp enable req-pri-dns
1496
	set ipcp enable req-sec-dns
1497

    
1498
EOD;
1499
	if (!isset($ppp['verbose_log']))
1500
		$mpdconf .= <<<EOD
1501
	#log -bund -ccp -chat -iface -ipcp -lcp -link
1502

    
1503
EOD;
1504
	foreach($ports as $pid => $port){
1505
		$port = get_real_interface($port);
1506
		$mpdconf .= <<<EOD
1507

    
1508
	create link static {$interface}_link{$pid} {$type}
1509
	set link action bundle {$interface}
1510
	set link {$multilink} multilink
1511
	set link keep-alive 10 60
1512
	set link max-redial 0
1513

    
1514
EOD;
1515
		if (isset($ppp['shortseq']))
1516
			$mpdconf .= <<<EOD
1517
	set link no shortseq
1518

    
1519
EOD;
1520

    
1521
		if (isset($ppp['acfcomp']))
1522
			$mpdconf .= <<<EOD
1523
	set link no acfcomp
1524

    
1525
EOD;
1526

    
1527
		if (isset($ppp['protocomp']))
1528
			$mpdconf .= <<<EOD
1529
	set link no protocomp
1530

    
1531
EOD;
1532

    
1533
		$mpdconf .= <<<EOD
1534
	set link disable chap pap
1535
	set link accept chap pap eap
1536
	set link disable incoming
1537

    
1538
EOD;
1539

    
1540

    
1541
		if (!empty($bandwidths[$pid]))
1542
			$mpdconf .= <<<EOD
1543
	set link bandwidth {$bandwidths[$pid]}
1544

    
1545
EOD;
1546

    
1547
		if (empty($mtus[$pid]))
1548
			$mtus[$pid] = "1492";
1549
			$mpdconf .= <<<EOD
1550
	set link mtu {$mtus[$pid]}
1551

    
1552
EOD;
1553

    
1554
		if (!empty($mrus[$pid]))
1555
			$mpdconf .= <<<EOD
1556
	set link mru {$mrus[$pid]}
1557

    
1558
EOD;
1559

    
1560
		if (!empty($mrrus[$pid]))
1561
			$mpdconf .= <<<EOD
1562
	set link mrru {$mrrus[$pid]}
1563

    
1564
EOD;
1565

    
1566
		$mpdconf .= <<<EOD
1567
	set auth authname "{$ppp['username']}"
1568
	set auth password {$passwd}
1569

    
1570
EOD;
1571
		if ($type == "modem") {
1572
			$mpdconf .= <<<EOD
1573
	set modem device {$ppp['ports']}
1574
	set modem script DialPeer
1575
	set modem idle-script Ringback
1576
	set modem watch -cd
1577
	set modem var \$DialPrefix "DT"
1578
	set modem var \$Telephone "{$ppp['phone']}"
1579

    
1580
EOD;
1581
		}
1582
		if (isset($ppp['connect-timeout']) && $type == "modem") {
1583
			$mpdconf .= <<<EOD
1584
	set modem var \$ConnectTimeout "{$ppp['connect-timeout']}"
1585

    
1586
EOD;
1587
		}
1588
		if (isset($ppp['initstr']) && $type == "modem") {
1589
			$initstr = base64_decode($ppp['initstr']);
1590
			$mpdconf .= <<<EOD
1591
	set modem var \$InitString "{$initstr}"
1592

    
1593
EOD;
1594
		}
1595
		if (isset($ppp['simpin']) && $type == "modem") {
1596
			$mpdconf .= <<<EOD
1597
	set modem var \$SimPin "{$ppp['simpin']}"
1598
	set modem var \$PinWait "{$ppp['pin-wait']}"
1599

    
1600
EOD;
1601
		}
1602
		if (isset($ppp['apn']) && $type == "modem") {
1603
			$mpdconf .= <<<EOD
1604
	set modem var \$APN "{$ppp['apn']}"
1605
	set modem var \$APNum "{$ppp['apnum']}"
1606

    
1607
EOD;
1608
		}
1609
		if ($type == "pppoe") {
1610
			// Send a null service name if none is set.
1611
			$provider = isset($ppp['provider']) ? $ppp['provider'] : "";
1612
			$mpdconf .= <<<EOD
1613
	set pppoe service "{$provider}"
1614

    
1615
EOD;
1616
		}
1617
		if ($type == "pppoe")
1618
			$mpdconf .= <<<EOD
1619
	set pppoe iface {$port}
1620

    
1621
EOD;
1622

    
1623
		if ($type == "pptp" || $type == "l2tp") {
1624
			$mpdconf .= <<<EOD
1625
	set {$type} self {$localips[$pid]}
1626
	set {$type} peer {$gateways[$pid]}
1627

    
1628
EOD;
1629
		}
1630
		
1631
		$mpdconf .= "\topen\r\n";
1632
	} //end foreach($port)
1633

    
1634

    
1635
	/* Generate mpd.conf. If mpd_[interface].conf exists in the conf path, then link to it instead of generating a fresh conf file. */
1636
	if (file_exists("{$g['conf_path']}/mpd_{$interface}.conf"))
1637
		mwexec("/bin/ln -s {$g['conf_path']}/mpd_{$interface}.conf {$g['varetc_path']}/.");
1638
	else {
1639
		$fd = fopen("{$g['varetc_path']}/mpd_{$interface}.conf", "w");
1640
		if (!$fd) {
1641
			log_error(sprintf(gettext("Error: cannot open mpd_%s.conf in interface_ppps_configure().%s"), $interface, "\n"));
1642
			return 0;
1643
		}
1644
		// Write out mpd_ppp.conf
1645
		fwrite($fd, $mpdconf);
1646
		fclose($fd);
1647
	}
1648

    
1649
	// Create the uptime log if requested and if it doesn't exist already, or delete it if it is no longer requested.
1650
	if (isset($ppp['uptime'])) {
1651
		if (!file_exists("/conf/{$pppif}.log")) {
1652
			conf_mount_rw();
1653
			mwexec("echo /dev/null > /conf/{$pppif}.log");
1654
			conf_mount_ro();
1655
		}
1656
	} else {
1657
		if (file_exists("/conf/{$pppif}.log")) {
1658
			conf_mount_rw();
1659
			mwexec("rm -f /conf/{$pppif}.log");
1660
			conf_mount_ro();
1661
		}
1662
	}
1663

    
1664
	/* fire up mpd */
1665
	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");
1666

    
1667
	// Check for PPPoE periodic reset request 
1668
	if ($type == "pppoe") {
1669
		if (isset($ppp['pppoe-reset-type']))
1670
			setup_pppoe_reset_file($ppp['if'], $interface);
1671
		else
1672
			setup_pppoe_reset_file($ppp['if']);
1673
	}
1674
	/* wait for upto 10 seconds for the interface to appear (ppp(oe)) */
1675
	$i = 0;
1676
	while($i < 10) {
1677
		exec("/sbin/ifconfig {$ppp['if']} 2>&1", $out, $ret);
1678
		if($ret == 0)
1679
			break;
1680
		sleep(1);
1681
		$i++;
1682
	}
1683

    
1684
	return 1;
1685
}
1686

    
1687
function interfaces_carp_setup() {
1688
	global $g, $config;
1689

    
1690
	$balanacing = "";
1691
	$pfsyncinterface = "";
1692
	$pfsyncenabled = "";
1693
	if(isset($config['system']['developerspew'])) {
1694
		$mt = microtime();
1695
		echo "interfaces_carp_setup() being called $mt\n";
1696
	}
1697

    
1698
	// Prepare CmdCHAIN that will be used to execute commands.
1699
	$cmdchain = new CmdCHAIN();	
1700

    
1701
	if ($g['booting']) {
1702
		echo gettext("Configuring CARP settings...");
1703
		mute_kernel_msgs();
1704
	}
1705

    
1706
	/* suck in configuration items */
1707
	if($config['installedpackages']['carpsettings']) {
1708
		if($config['installedpackages']['carpsettings']['config']) {
1709
			foreach($config['installedpackages']['carpsettings']['config'] as $carp) {
1710
				$pfsyncenabled = $carp['pfsyncenabled'];
1711
				$balanacing = $carp['balancing'];
1712
				$pfsyncinterface = $carp['pfsyncinterface'];
1713
				$pfsyncpeerip = $carp['pfsyncpeerip'];
1714
			}
1715
		}
1716
	} else {
1717
		unset($pfsyncinterface);
1718
		unset($balanacing);
1719
		unset($pfsyncenabled);
1720
	}
1721

    
1722
	if($balanacing) {
1723
		$cmdchain->add(gettext("Enable CARP ARP-balancing"), "/sbin/sysctl net.inet.carp.arpbalance=1", true);
1724
		$cmdchain->add(gettext("Disallow CARP preemption"), "/sbin/sysctl net.inet.carp.preempt=0", true);
1725
	} else
1726
		$cmdchain->add(gettext("Enable CARP preemption"), "/sbin/sysctl net.inet.carp.preempt=1", true);		
1727

    
1728
	$cmdchain->add(gettext("Enable CARP logging"), "/sbin/sysctl net.inet.carp.log=1", true);
1729
	if (!empty($pfsyncinterface))
1730
		$carp_sync_int = get_real_interface($pfsyncinterface);
1731

    
1732
	if($g['booting']) {
1733
		/*    install rules to alllow pfsync to sync up during boot
1734
		 *    carp interfaces will remain down until the bootup sequence finishes
1735
		 */
1736
		$fd = fopen("{$g['tmp_path']}/rules.boot", "w");
1737
		if ($fd) {
1738
			fwrite($fd, "block quick proto carp \n");
1739
			fwrite($fd, "block quick proto pfsync \n");
1740
			fwrite($fd, "pass out quick from any to any keep state\n");
1741
			fclose($fd);
1742
			mwexec("/sbin/pfctl -f {$g['tmp_path']}/rules.boot");
1743
		} else
1744
			log_error(gettext("Could not create rules.boot file!"));
1745
	}
1746

    
1747
	/* setup pfsync interface */
1748
	if($carp_sync_int and $pfsyncenabled) {
1749
		if (is_ipaddr($pfsyncpeerip))
1750
			$cmdchain->add(gettext("Bring up pfsync0 syncpeer"), "/sbin/ifconfig pfsync0 syncdev {$carp_sync_int} syncpeer {$pfsyncpeerip} up", false);						
1751
		else
1752
			$cmdchain->add(gettext("Bring up pfsync0 syncdev"), "/sbin/ifconfig pfsync0 syncdev {$carp_sync_int} up", false);			
1753
	} else
1754
		$cmdchain->add(gettext("Bring up pfsync0"), "/sbin/ifconfig pfsync0 syncdev lo0 up", false);						
1755

    
1756
	sleep(1);
1757

    
1758
	/* XXX: Handle an issue with pfsync(4) and carp(4). In a cluster carp will come up before pfsync(4) has updated and so will cause issuese
1759
	 * for exiting sessions.
1760
	 */
1761
	$i = 0;
1762
	while (intval(trim(`/sbin/ifconfig pfsync0 | /usr/bin/grep 'syncok: 0' | /usr/bin/grep -v grep | /usr/bin/wc -l`)) == 0 && $i < 30) {
1763
		$i++;
1764
		sleep(1);
1765
	}
1766

    
1767
	if($config['virtualip']['vip'])
1768
		$cmdchain->add(gettext("Allow CARP."), "/sbin/sysctl net.inet.carp.allow=1", true);				
1769
	else
1770
		$cmdchain->add(gettext("Disallow CARP."), "/sbin/sysctl net.inet.carp.allow=0", true);		
1771
	
1772
	if($g['debug'])
1773
		$cmdchain->setdebug(); // optional for verbose logging
1774

    
1775
	$cmdchain->execute();
1776
	$cmdchain->clear();
1777

    
1778
	if ($g['booting']) {
1779
		unmute_kernel_msgs();
1780
		echo gettext("done.") . "\n";
1781
	}
1782
}
1783

    
1784
function interface_proxyarp_configure($interface = "") {
1785
	global $config, $g;
1786
	if(isset($config['system']['developerspew'])) {
1787
		$mt = microtime();
1788
		echo "interface_proxyarp_configure() being called $mt\n";
1789
	}
1790

    
1791
	/* kill any running choparp */
1792
	if (empty($interface))
1793
		killbyname("choparp");
1794
	else {
1795
		$vipif = get_real_interface($interface);
1796
		if (file_exists("{$g['varrun_path']}/choparp_{$vipif}.pid"))
1797
			killbypid("{$g['varrun_path']}/choparp_{$vipif}.pid");
1798
	}
1799

    
1800
	$paa = array();
1801
	if (!empty($config['virtualip']) && is_array($config['virtualip']['vip'])) {
1802

    
1803
		/* group by interface */
1804
		foreach ($config['virtualip']['vip'] as $vipent) {
1805
			if ($vipent['mode'] === "proxyarp") {
1806
				if ($vipent['interface'])
1807
					$proxyif = $vipent['interface'];
1808
				else
1809
					$proxyif = "wan";
1810
				
1811
				if (!empty($interface) && $interface != $proxyif)
1812
					continue;
1813

    
1814
				if (!is_array($paa[$proxyif]))
1815
					$paa[$proxyif] = array();
1816

    
1817
				$paa[$proxyif][] = $vipent;
1818
			}
1819
		}
1820
	}
1821

    
1822
	if (!empty($interface)) {
1823
		if (is_array($paa[$interface])) {
1824
			$paaifip = get_interface_ip($interface);
1825
                        if (!is_ipaddr($paaifip))
1826
                                return;
1827
                        $args = get_real_interface($interface) . " auto";
1828
                        foreach ($paa[$interface] as $paent) {
1829
                                if (isset($paent['subnet']))
1830
                                        $args .= " " . escapeshellarg("{$paent['subnet']}/{$paent['subnet_bits']}");
1831
                                else if (isset($paent['range']))
1832
                                        $args .= " " . escapeshellarg($paent['range']['from'] . "-" . $paent['range']['to']);
1833
                        }
1834
                        mwexec_bg("/usr/local/sbin/choparp " . $args);	
1835
		}
1836
	} else if (count($paa) > 0) {
1837
		foreach ($paa as $paif => $paents)  {
1838
			$paaifip = get_interface_ip($paif);
1839
			if (!is_ipaddr($paaifip))
1840
				continue;
1841
			$args = get_real_interface($paif) . " auto";
1842
			foreach ($paents as $paent) {
1843
				if (isset($paent['subnet']))
1844
					$args .= " " . escapeshellarg("{$paent['subnet']}/{$paent['subnet_bits']}");
1845
				else if (isset($paent['range']))
1846
					$args .= " " . escapeshellarg($paent['range']['from'] . "-" . $paent['range']['to']);
1847
			}
1848
			mwexec_bg("/usr/local/sbin/choparp " . $args);
1849
		}
1850
	}
1851
}
1852

    
1853
function interfaces_vips_configure($interface = "") {
1854
	global $g, $config;
1855
	if(isset($config['system']['developerspew'])) {
1856
		$mt = microtime();
1857
		echo "interfaces_vips_configure() being called $mt\n";
1858
	}
1859
	$paa = array();
1860
	if(is_array($config['virtualip']['vip'])) {
1861
		$carp_setuped = false;
1862
		$anyproxyarp = false;
1863
		foreach ($config['virtualip']['vip'] as $vip) {
1864
			switch ($vip['mode']) {
1865
			case "proxyarp":
1866
				/* nothing it is handled on interface_proxyarp_configure() */
1867
				if ($interface <> "" && $vip['interface'] <> $interface)
1868
					continue;
1869
				$anyproxyarp = true;
1870
				break;
1871
			case "ipalias":
1872
				if ($interface <> "" && $vip['interface'] <> $interface)
1873
					continue;
1874
				interface_ipalias_configure(&$vip);
1875
				break;
1876
			case "carp":
1877
				if ($interface <> "" && $vip['interface'] <> $interface)
1878
					continue;
1879
				if ($carp_setuped == false)
1880
					$carp_setuped = true;
1881
				interface_carp_configure($vip);
1882
				break;
1883
			case "carpdev-dhcp":
1884
				if ($interface <> "" && $vip['interface'] <> $interface)
1885
					continue;
1886
				interface_carpdev_configure($vip);
1887
				break;
1888
			}
1889
		}
1890
		if ($carp_setuped == true)
1891
			interfaces_carp_setup();
1892
		if ($anyproxyarp == true)
1893
			interface_proxyarp_configure();
1894
	}
1895
}
1896

    
1897
function interface_ipalias_configure(&$vip) {
1898

    
1899
	if ($vip['mode'] == "ipalias") {
1900
		$if = get_real_interface($vip['interface']);
1901
		mwexec("/sbin/ifconfig " . escapeshellarg($if) . " " . $vip['subnet'] . "/" . escapeshellarg($vip['subnet_bits']) . " alias");
1902
	}
1903
}
1904

    
1905
function interface_reload_carps($cif) {
1906
	global $config;
1907

    
1908
	$carpifs = link_ip_to_carp_interface(find_interface_ip($cif));
1909
	if (empty($carpifs))
1910
		return;
1911

    
1912
	$carps = explode(" ", $carpifs);
1913
	if(is_array($config['virtualip']['vip'])) {
1914
		$viparr = &$config['virtualip']['vip'];
1915
		foreach ($viparr as $vip) {
1916
			if (in_array($vip['carpif'], $carps)) {
1917
				switch ($vip['mode']) {
1918
				case "carp":
1919
					interface_vip_bring_down($vip);
1920
					sleep(1);
1921
					interface_carp_configure($vip);
1922
					break;
1923
				case "carpdev-dhcp":
1924
					interface_vip_bring_down($vip);
1925
					sleep(1);
1926
					interface_carpdev_configure($vip);
1927
					break;
1928
				case "ipalias":
1929
					interface_vip_bring_down($vip);
1930
					sleep(1);
1931
					interface_ipalias_configure($vip);
1932
					break;
1933
				}
1934
			}
1935
		}
1936
	}
1937
}
1938

    
1939
function interface_carp_configure(&$vip) {
1940
	global $config, $g;
1941
	if(isset($config['system']['developerspew'])) {
1942
		$mt = microtime();
1943
		echo "interface_carp_configure() being called $mt\n";
1944
	}
1945

    
1946
	if ($vip['mode'] != "carp")
1947
		return;
1948

    
1949
	$vip_password = $vip['password'];
1950
	$vip_password = escapeshellarg(addslashes(str_replace(" ", "", $vip_password)));
1951
	if ($vip['password'] != "")
1952
		$password = " pass {$vip_password}";
1953

    
1954
	// set the vip interface to the vhid
1955
	$vipif = "vip{$vip['vhid']}";
1956

    
1957
	/*
1958
	 * ensure the interface containing the VIP really exists
1959
 	 * prevents a panic if the interface is missing or invalid
1960
	 */
1961
	$realif = get_real_interface($vip['interface']);
1962
	if (!does_interface_exist($realif)) {
1963
		file_notice("CARP", sprintf(gettext("Interface specified for the virtual IP address %s does not exist. Skipping this VIP."), $vip['subnet']), "Firewall: Virtual IP", "");
1964
		return;
1965
	}
1966

    
1967
	if(is_ipaddrv4($vip['subnet'])) {
1968
		/* Ensure CARP IP really exists prior to loading up. */
1969
		$ww_subnet_ip = find_interface_ip($realif);
1970
		$ww_subnet_bits = find_interface_subnet($realif);
1971
		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'])) {
1972
			file_notice("CARP", sprintf(gettext("Sorry but we could not find a matching real interface subnet for the virtual IP address %s."), $vip['subnet']), "Firewall: Virtual IP", "");
1973
			return;
1974
		}
1975
	}
1976
	if(is_ipaddrv6($vip['subnet'])) {
1977
		/* Ensure CARP IP really exists prior to loading up. */
1978
		$ww_subnet_ip = find_interface_ipv6($realif);
1979
		$ww_subnet_bits = find_interface_subnetv6($realif);
1980
		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'])) {
1981
			file_notice("CARP", sprintf(gettext("Sorry but we could not find a matching real interface subnet for the virtual IPv6 address %s."), $vip['subnet']), "Firewall: Virtual IP", "");
1982
			return;
1983
		}
1984
	}
1985

    
1986
	/* create the carp interface and setup */
1987
	if (does_interface_exist($vipif)) {
1988
		pfSense_interface_flags($vipif, -IFF_UP);
1989
	} else {
1990
		$carpif = pfSense_interface_create("carp");
1991
		pfSense_interface_rename($carpif, $vipif);
1992
		pfSense_ngctl_name("{$carpif}:", $vipif);
1993
	}
1994

    
1995
	/* invalidate interface cache */
1996
	get_interface_arr(true);
1997

    
1998
	$advbase = "";
1999
	if (!empty($vip['advbase']))
2000
		$advbase = "advbase {$vip['advbase']}";
2001

    
2002
	if(is_ipaddrv4($vip['subnet'])) {
2003
		$broadcast_address = gen_subnet_max($vip['subnet'], $vip['subnet_bits']);
2004
		mwexec("/sbin/ifconfig {$vipif} {$vip['subnet']}/{$vip['subnet_bits']} vhid {$vip['vhid']} advskew {$vip['advskew']} {$advbase} {$password}");
2005
	}
2006
	if(is_ipaddrv6($vip['subnet'])) {
2007
		$broadcast_address = gen_subnet_max($vip['subnet'], $vip['subnet_bits']);
2008
		mwexec("/sbin/ifconfig {$vipif} inet6 {$vip['subnet']} prefixlen {$vip['subnet_bits']} vhid {$vip['vhid']} advskew {$vip['advskew']} {$advbase} {$password}");
2009
	}
2010

    
2011
	interfaces_bring_up($vipif);
2012
	
2013
	return $vipif;
2014
}
2015

    
2016
function interface_carpdev_configure(&$vip) {
2017
	global $g;
2018

    
2019
	if ($vip['mode'] != "carpdev-dhcp")
2020
		return;
2021

    
2022
	$vip_password = $vip['password'];
2023
	$vip_password = str_replace(" ", "", $vip_password);
2024
	if($vip['password'] != "")
2025
		$password = " pass \"" . $vip_password . "\"";
2026

    
2027
	if (empty($vip['interface']))
2028
		return;
2029

    
2030
	$vipif = "vip" . $vip['vhid'];
2031
	$realif = get_real_interface($vip['interface']);
2032
	interfaces_bring_up($realif);
2033
	/*
2034
	 * ensure the interface containing the VIP really exists
2035
	 * prevents a panic if the interface is missing or invalid
2036
	 */
2037
	if (!does_interface_exist($realif)) {
2038
		file_notice("CARP", sprintf(gettext("Interface specified for the virtual IP address %s does not exist. Skipping this VIP."), $vip['subnet']), "Firewall: Virtual IP", "");
2039
		return;
2040
	}
2041

    
2042
	if (does_interface_exist($vipif)) {
2043
		interface_bring_down($vipif);
2044
	} else {
2045
		$carpdevif = exec("/sbin/ifconfig carp create");
2046
		mwexec("/sbin/ifconfig {$carpdevif} name {$vipif}");
2047
		pfSense_ngctl_name("{$carpdevif}:", $vipif);
2048
	}
2049

    
2050
	mwexec("/sbin/ifconfig {$vipif} carpdev {$realif} vhid {$vip['vhid']} advskew {$vip['advskew']} advbase {$vip['advbase']} {$password}");
2051
	interfaces_bring_up($vipif);
2052

    
2053
	/*
2054
	 * XXX: BIG HACK but carpdev needs ip services active
2055
	 *      before even starting something as dhclient.
2056
	 *      I do not know if this is a feature or a bug
2057
	 *      but better than track it make it work ;) .
2058
	 */
2059
	//$fakeiptouse = "10.254.254." . ($carp_instances_counter+1);
2060
	//$cmdchain->add("CarpDEV hack", "/sbin/ifconfig {$carpint} inet {$fakeiptouse}", false);
2061

    
2062
	/* generate dhclient_wan.conf */
2063
	$fd = fopen("{$g['varetc_path']}/dhclient_{$vipif}.conf", "w");
2064
	if ($fd) {
2065
		$dhclientconf = "";
2066

    
2067
		$dhclientconf .= <<<EOD
2068
interface "{$vipif}" {
2069
timeout 60;
2070
retry 1;
2071
select-timeout 0;
2072
initial-interval 1;
2073
script "/sbin/dhclient-script";
2074
}
2075

    
2076
EOD;
2077

    
2078
		fwrite($fd, $dhclientconf);
2079
		fclose($fd);
2080

    
2081
		/* fire up dhclient */
2082
		mwexec("/sbin/dhclient -c {$g['varetc_path']}/dhclient_{$vipif}.conf {$vipif} >{$g['tmp_path']}/{$vipif}_output 2>{$g['tmp_path']}/{$vipif}_error_output", false);
2083
	} else {
2084
		log_error(sprintf(gettext("Error: cannot open dhclient_%s.conf in interfaces_carpdev_configure() for writing.%s"), $vipif, "\n"));
2085
		mwexec("/sbin/dhclient -b {$vipif}");
2086
	}
2087

    
2088
	return $vipif;
2089
}
2090

    
2091
function interface_wireless_clone($realif, $wlcfg) {
2092
	global $config, $g;
2093
	/*   Check to see if interface has been cloned as of yet.  
2094
	 *   If it has not been cloned then go ahead and clone it.
2095
	 */
2096
	$needs_clone = false;
2097
	if(is_array($wlcfg['wireless']))
2098
		$wlcfg_mode = $wlcfg['wireless']['mode'];
2099
	else
2100
		$wlcfg_mode = $wlcfg['mode'];
2101
	switch($wlcfg_mode) {
2102
		 case "hostap":
2103
			$mode = "wlanmode hostap";
2104
			break;
2105
		 case "adhoc":
2106
			$mode = "wlanmode adhoc";
2107
			break;
2108
		 default:
2109
			$mode = "";
2110
			break;
2111
	}
2112
	$baseif = interface_get_wireless_base($wlcfg['if']);
2113
	if(does_interface_exist($realif)) {
2114
		exec("/sbin/ifconfig {$realif}", $output, $ret);
2115
		$ifconfig_str = implode($output);
2116
		if(($wlcfg_mode == "hostap") && (! preg_match("/hostap/si", $ifconfig_str))) {
2117
			log_error(sprintf(gettext("Interface %s changed to hostap mode"), $realif));
2118
			$needs_clone = true;
2119
		}
2120
		if(($wlcfg_mode == "adhoc") && (! preg_match("/adhoc/si", $ifconfig_str))) {
2121
			log_error(sprintf(gettext("Interface %s changed to adhoc mode"), $realif));
2122
			$needs_clone = true;
2123
		}
2124
		if(($wlcfg_mode == "bss") && (preg_match("/hostap|adhoc/si", $ifconfig_str))) {
2125
			log_error(sprintf(gettext("Interface %s changed to infrastructure mode"), $realif));
2126
			$needs_clone = true;
2127
		}
2128
	} else {
2129
		$needs_clone = true;
2130
	}
2131

    
2132
	if($needs_clone == true) {
2133
		/* remove previous instance if it exists */
2134
		if(does_interface_exist($realif))
2135
			pfSense_interface_destroy($realif);
2136

    
2137
		log_error(sprintf(gettext("Cloning new wireless interface %s"), $realif));
2138
		// Create the new wlan interface. FreeBSD returns the new interface name.
2139
		// example:  wlan2
2140
		exec("/sbin/ifconfig wlan create wlandev {$baseif} {$mode} bssid 2>&1", $out, $ret);
2141
		if($ret <> 0) {
2142
			log_error(sprintf(gettext('Failed to clone interface %1$s with error code %2$s, output %3$s'), $baseif, $ret, $out[0]));
2143
			return false;
2144
		}
2145
		$newif = trim($out[0]);
2146
		// Rename the interface to {$parentnic}_wlan{$number}#: EX: ath0_wlan0
2147
		pfSense_interface_rename($newif, $realif);
2148
		// FIXME: not sure what ngctl is for. Doesn't work.
2149
		// mwexec("/usr/sbin/ngctl name {$newif}: {$realif}", false);
2150
		file_put_contents("{$g['tmp_path']}/{$realif}_oldmac", get_interface_mac($realif));
2151
	}
2152
	return true;
2153
}
2154

    
2155
function interface_sync_wireless_clones(&$ifcfg, $sync_changes = false) {
2156
	global $config, $g;
2157

    
2158
	$shared_settings = array('standard', 'turbo', 'protmode', 'txpower', 'channel',
2159
	                         'diversity', 'txantenna', 'rxantenna', 'distance',
2160
	                         'regdomain', 'regcountry', 'reglocation');
2161

    
2162
	if(!is_interface_wireless($ifcfg['if']))
2163
		return;
2164

    
2165
	$baseif = interface_get_wireless_base($ifcfg['if']);
2166

    
2167
	// Sync shared settings for assigned clones
2168
	$iflist = get_configured_interface_list(false, true);
2169
	foreach ($iflist as $if) {
2170
		if ($baseif == interface_get_wireless_base($config['interfaces'][$if]['if']) && $ifcfg['if'] != $config['interfaces'][$if]['if']) {
2171
			if (isset($config['interfaces'][$if]['wireless']['standard']) || $sync_changes) {
2172
				foreach ($shared_settings as $setting) {
2173
					if ($sync_changes) {
2174
						if (isset($ifcfg['wireless'][$setting]))
2175
							$config['interfaces'][$if]['wireless'][$setting] = $ifcfg['wireless'][$setting];
2176
						else if (isset($config['interfaces'][$if]['wireless'][$setting]))
2177
							unset($config['interfaces'][$if]['wireless'][$setting]);
2178
					} else {
2179
						if (isset($config['interfaces'][$if]['wireless'][$setting]))
2180
							$ifcfg['wireless'][$setting] = $config['interfaces'][$if]['wireless'][$setting];
2181
						else if (isset($ifcfg['wireless'][$setting]))
2182
							unset($ifcfg['wireless'][$setting]);
2183
					}
2184
				}
2185
				if (!$sync_changes)
2186
					break;
2187
			}
2188
		}
2189
	}
2190

    
2191
	// Read or write settings at shared area
2192
	if (isset($config['wireless']['interfaces'][$baseif])) {
2193
		foreach ($shared_settings as $setting) {
2194
			if ($sync_changes) {
2195
				if (isset($ifcfg['wireless'][$setting]))
2196
					$config['wireless']['interfaces'][$baseif][$setting] = $ifcfg['wireless'][$setting];
2197
				else if (isset($config['wireless']['interfaces'][$baseif][$setting]))
2198
					unset($config['wireless']['interfaces'][$baseif][$setting]);
2199
			} else if (isset($config['wireless']['interfaces'][$baseif][$setting])) {
2200
				if (isset($config['wireless']['interfaces'][$baseif][$setting]))
2201
					$ifcfg['wireless'][$setting] = $config['wireless']['interfaces'][$baseif][$setting];
2202
				else if (isset($ifcfg['wireless'][$setting]))
2203
					unset($ifcfg['wireless'][$setting]);
2204
			}
2205
		}
2206
	}
2207

    
2208
	// Sync the mode on the clone creation page with the configured mode on the interface
2209
	if (interface_is_wireless_clone($ifcfg['if'])) {
2210
		foreach ($config['wireless']['clone'] as &$clone) {
2211
			if ($clone['cloneif'] == $ifcfg['if']) {
2212
				if ($sync_changes) {
2213
					$clone['mode'] = $ifcfg['wireless']['mode'];
2214
				} else {
2215
					$ifcfg['wireless']['mode'] = $clone['mode'];
2216
				}
2217
				break;
2218
			}
2219
		}
2220
		unset($clone);
2221
	}
2222
}
2223

    
2224
function interface_wireless_configure($if, &$wl, &$wlcfg) {
2225
	global $config, $g;
2226

    
2227
	/*    open up a shell script that will be used to output the commands.
2228
	 *    since wireless is changing a lot, these series of commands are fragile
2229
     *    and will sometimes need to be verified by a operator by executing the command
2230
     *    and returning the output of the command to the developers for inspection.  please
2231
     *    do not change this routine from a shell script to individul exec commands.  -sullrich
2232
	 */
2233

    
2234
	// Remove script file
2235
	unlink_if_exists("{$g['tmp_path']}/{$if}_setup.sh");
2236

    
2237
	// Clone wireless nic if needed.
2238
	interface_wireless_clone($if, $wl);
2239

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

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

    
2247
	/* set values for /path/program */
2248
	$hostapd = "/usr/sbin/hostapd";
2249
	$wpa_supplicant = "/usr/sbin/wpa_supplicant";
2250
	$ifconfig = "/sbin/ifconfig";
2251
	$sysctl = "/sbin/sysctl";
2252
	$killall = "/usr/bin/killall";
2253

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

    
2256
	$wlcmd = array();
2257
	$wl_sysctl = array();
2258
	/* Make sure it's up */
2259
	$wlcmd[] = "up";
2260
	/* Set a/b/g standard */
2261
	$standard = str_replace(" Turbo", "", $wlcfg['standard']);
2262
	$wlcmd[] = "mode " . escapeshellarg($standard);
2263

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

    
2269
	/* Set ssid */
2270
	if($wlcfg['ssid'])
2271
		$wlcmd[] = "ssid " .escapeshellarg($wlcfg['ssid']);
2272

    
2273
	/* Set 802.11g protection mode */
2274
	$wlcmd[] = "protmode " . escapeshellarg($wlcfg['protmode']);
2275

    
2276
	/* set wireless channel value */
2277
	if(isset($wlcfg['channel'])) {
2278
		if($wlcfg['channel'] == "0") {
2279
			$wlcmd[] = "channel any";
2280
		} else {
2281
			$wlcmd[] = "channel " . escapeshellarg($wlcfg['channel']);
2282
		}
2283
	}
2284

    
2285
	/* Set antenna diversity value */
2286
	if(isset($wlcfg['diversity']))
2287
		$wl_sysctl[] = "diversity=" . escapeshellarg($wlcfg['diversity']);
2288

    
2289
	/* Set txantenna value */
2290
	if(isset($wlcfg['txantenna']))
2291
		$wl_sysctl[] = "txantenna=" . escapeshellarg($wlcfg['txantenna']);
2292

    
2293
	/* Set rxantenna value */
2294
	if(isset($wlcfg['rxantenna']))
2295
		$wl_sysctl[] = "rxantenna=" . escapeshellarg($wlcfg['rxantenna']);
2296

    
2297
	/* set Distance value */
2298
	if($wlcfg['distance'])
2299
		$distance = escapeshellarg($wlcfg['distance']);
2300

    
2301
	/* Set wireless hostap mode */
2302
	if ($wlcfg['mode'] == "hostap") {
2303
		$wlcmd[] = "mediaopt hostap";
2304
	} else {
2305
		$wlcmd[] = "-mediaopt hostap";
2306
	}
2307

    
2308
	/* Set wireless adhoc mode */
2309
	if ($wlcfg['mode'] == "adhoc") {
2310
		$wlcmd[] = "mediaopt adhoc";
2311
	} else {
2312
		$wlcmd[] = "-mediaopt adhoc";
2313
	}
2314

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

    
2317
	/* handle hide ssid option */
2318
	if(isset($wlcfg['hidessid']['enable'])) {
2319
		$wlcmd[] = "hidessid";
2320
	} else {
2321
		$wlcmd[] = "-hidessid";
2322
	}
2323

    
2324
	/* handle pureg (802.11g) only option */
2325
	if(isset($wlcfg['pureg']['enable'])) {
2326
		$wlcmd[] = "mode 11g pureg";
2327
	} else {
2328
		$wlcmd[] = "-pureg";
2329
	}
2330

    
2331
	/* handle puren (802.11n) only option */
2332
	if(isset($wlcfg['puren']['enable'])) {
2333
		$wlcmd[] = "puren";
2334
	} else {
2335
		$wlcmd[] = "-puren";
2336
	}
2337

    
2338
	/* enable apbridge option */
2339
	if(isset($wlcfg['apbridge']['enable'])) {
2340
		$wlcmd[] = "apbridge";
2341
	} else {
2342
		$wlcmd[] = "-apbridge";
2343
	}
2344

    
2345
	/* handle turbo option */
2346
	if(isset($wlcfg['turbo']['enable'])) {
2347
		$wlcmd[] = "mediaopt turbo";
2348
	} else {
2349
		$wlcmd[] = "-mediaopt turbo";
2350
	}
2351

    
2352
	/* handle txpower setting */
2353
	/* if($wlcfg['txpower'] <> "")
2354
		$wlcmd[] = "txpower " . escapeshellarg($wlcfg['txpower']);
2355
	*/
2356
	/* handle wme option */
2357
	if(isset($wlcfg['wme']['enable'])) {
2358
		$wlcmd[] = "wme";
2359
	} else {
2360
		$wlcmd[] = "-wme";
2361
	}
2362

    
2363
	/* set up wep if enabled */
2364
	$wepset = "";
2365
	if (isset($wlcfg['wep']['enable']) && is_array($wlcfg['wep']['key'])) {
2366
		switch($wlcfg['wpa']['auth_algs']) {
2367
			case "1":
2368
				$wepset .= "authmode open wepmode on ";
2369
				break;
2370
			case "2":
2371
				$wepset .= "authmode shared wepmode on ";
2372
				break;
2373
			case "3":
2374
				$wepset .= "authmode mixed wepmode on ";
2375
		}
2376
		$i = 1;
2377
		foreach ($wlcfg['wep']['key'] as $wepkey) {
2378
			$wepset .= "wepkey " . escapeshellarg("{$i}:{$wepkey['value']}") . " ";
2379
			if (isset($wepkey['txkey'])) {
2380
				$wlcmd[] = "weptxkey {$i} ";
2381
			}
2382
			$i++;
2383
		}
2384
		$wlcmd[] = $wepset;
2385
	} else {
2386
		$wlcmd[] = "authmode open wepmode off ";
2387
	}
2388

    
2389
	mwexec(kill_hostapd("{$if}"));
2390
	mwexec(kill_wpasupplicant("{$if}"));
2391

    
2392
	/* generate wpa_supplicant/hostap config if wpa is enabled */
2393
	conf_mount_rw();
2394

    
2395
	switch ($wlcfg['mode']) {
2396
		case 'bss':
2397
			if (isset($wlcfg['wpa']['enable'])) {
2398
				$wpa .= <<<EOD
2399
ctrl_interface={$g['varrun_path']}/wpa_supplicant
2400
ctrl_interface_group=0
2401
ap_scan=1
2402
#fast_reauth=1
2403
network={
2404
ssid="{$wlcfg['ssid']}"
2405
scan_ssid=1
2406
priority=5
2407
key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
2408
psk="{$wlcfg['wpa']['passphrase']}"
2409
pairwise={$wlcfg['wpa']['wpa_pairwise']}
2410
group={$wlcfg['wpa']['wpa_pairwise']}
2411
}
2412
EOD;
2413

    
2414
				$fd = fopen("{$g['varetc_path']}/wpa_supplicant_{$if}.conf", "w");
2415
				fwrite($fd, "{$wpa}");
2416
				fclose($fd);
2417
			}
2418
			break;
2419
		case 'hostap':
2420
			if($wlcfg['wpa']['passphrase']) 
2421
				$wpa_passphrase = "wpa_passphrase={$wlcfg['wpa']['passphrase']}\n";
2422
			else 
2423
				$wpa_passphrase = "";
2424
			if (isset($wlcfg['wpa']['enable'])) {
2425
				$wpa .= <<<EOD
2426
interface={$if}
2427
driver=bsd
2428
logger_syslog=-1
2429
logger_syslog_level=0
2430
logger_stdout=-1
2431
logger_stdout_level=0
2432
dump_file={$g['tmp_path']}/hostapd_{$if}.dump
2433
ctrl_interface={$g['varrun_path']}/hostapd
2434
ctrl_interface_group=wheel
2435
#accept_mac_file={$g['tmp_path']}/hostapd_{$if}.accept
2436
#deny_mac_file={$g['tmp_path']}/hostapd_{$if}.deny
2437
#macaddr_acl={$wlcfg['wpa']['macaddr_acl']}
2438
ssid={$wlcfg['ssid']}
2439
debug={$wlcfg['wpa']['debug_mode']}
2440
auth_algs={$wlcfg['wpa']['auth_algs']}
2441
wpa={$wlcfg['wpa']['wpa_mode']}
2442
wpa_key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
2443
wpa_pairwise={$wlcfg['wpa']['wpa_pairwise']}
2444
wpa_group_rekey={$wlcfg['wpa']['wpa_group_rekey']}
2445
wpa_gmk_rekey={$wlcfg['wpa']['wpa_gmk_rekey']}
2446
wpa_strict_rekey={$wlcfg['wpa']['wpa_strict_rekey']}
2447
{$wpa_passphrase}
2448

    
2449
EOD;
2450

    
2451
if (isset($wlcfg['wpa']['rsn_preauth'])) {
2452
	$wpa .= <<<EOD
2453
# Enable the next lines for preauth when roaming. Interface = wired or wireless interface talking to the AP you want to roam from/to
2454
rsn_preauth=1
2455
rsn_preauth_interfaces={$if}
2456

    
2457
EOD;
2458

    
2459
}
2460
				if($wlcfg['auth_server_addr'] && $wlcfg['auth_server_shared_secret']) {
2461
					$auth_server_port = "1812";
2462
					if($wlcfg['auth_server_port']) 
2463
						$auth_server_port = $wlcfg['auth_server_port'];
2464
					$wpa .= <<<EOD
2465

    
2466
ieee8021x=1
2467
auth_server_addr={$wlcfg['auth_server_addr']}
2468
auth_server_port={$auth_server_port}
2469
auth_server_shared_secret={$wlcfg['auth_server_shared_secret']}
2470

    
2471
EOD;
2472
				} else {
2473
					$wpa .= "ieee8021x={$wlcfg['wpa']['ieee8021x']}\n";
2474
				}
2475

    
2476
				$fd = fopen("{$g['varetc_path']}/hostapd_{$if}.conf", "w");
2477
				fwrite($fd, "{$wpa}");
2478
				fclose($fd);
2479

    
2480
			}
2481
			break;
2482
	}
2483

    
2484
	/*
2485
	 *    all variables are set, lets start up everything
2486
	 */
2487

    
2488
	$baseif = interface_get_wireless_base($if);
2489
	preg_match("/^(.*?)([0-9]*)$/", $baseif, $baseif_split);
2490
	$wl_sysctl_prefix = 'dev.' . $baseif_split[1] . '.' . $baseif_split[2];
2491

    
2492
	/* set sysctls for the wireless interface */
2493
	if (!empty($wl_sysctl)) {
2494
		fwrite($fd_set, "# sysctls for {$baseif}\n");
2495
		foreach ($wl_sysctl as $wl_sysctl_line) {
2496
			fwrite($fd_set, "{$sysctl} {$wl_sysctl_prefix}.{$wl_sysctl_line}\n");
2497
		}
2498
	}
2499

    
2500
	/* set ack timers according to users preference (if he/she has any) */
2501
	if($distance) {
2502
		fwrite($fd_set, "# Enable ATH distance settings\n");
2503
		fwrite($fd_set, "/sbin/athctrl.sh -i {$baseif} -d {$distance}\n");
2504
	}
2505

    
2506
	if (isset($wlcfg['wpa']['enable'])) {
2507
		if ($wlcfg['mode'] == "bss") {
2508
			fwrite($fd_set, "{$wpa_supplicant} -B -i {$if} -c {$g['varetc_path']}/wpa_supplicant_{$if}.conf\n");
2509
		}
2510
		if ($wlcfg['mode'] == "hostap") {
2511
			/* add line to script to restore old mac to make hostapd happy */
2512
			if (file_exists("{$g['tmp_path']}/{$if}_oldmac")) {
2513
				$if_oldmac = file_get_contents("{$g['tmp_path']}/{$if}_oldmac");
2514
				if (is_macaddr($if_oldmac))
2515
					fwrite($fd_set, "{$ifconfig} " . escapeshellarg($if) .
2516
						" link " . escapeshellarg($if_oldmac) . "\n");
2517
			}
2518

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

    
2521
			/* add line to script to restore spoofed mac after running hostapd */
2522
			if (file_exists("{$g['tmp_path']}/{$if}_oldmac")) {
2523
				if ($wl['spoofmac'])
2524
					$if_curmac = $wl['spoofmac'];
2525
				else
2526
					$if_curmac = get_interface_mac($if);
2527
				if (is_macaddr($if_curmac))
2528
					fwrite($fd_set, "{$ifconfig} " . escapeshellarg($if) .
2529
						" link " . escapeshellarg($if_curmac) . "\n");
2530
			}
2531
		}
2532
	}
2533

    
2534
	fclose($fd_set);
2535
	conf_mount_ro();
2536

    
2537
	/* Making sure regulatory settings have actually changed
2538
	 * before applying, because changing them requires bringing
2539
	 * down all wireless networks on the interface. */
2540
	exec("{$ifconfig} " . escapeshellarg($if), $output);
2541
	$ifconfig_str = implode($output);
2542
	unset($output);
2543
	$reg_changing = false;
2544

    
2545
	/* special case for the debug country code */
2546
	if ($wlcfg['regcountry'] == 'DEBUG' && !preg_match("/\sregdomain\s+DEBUG\s/si", $ifconfig_str))
2547
		$reg_changing = true;
2548
	else if ($wlcfg['regdomain'] && !preg_match("/\sregdomain\s+{$wlcfg['regdomain']}\s/si", $ifconfig_str))
2549
		$reg_changing = true;
2550
	else if ($wlcfg['regcountry'] && !preg_match("/\scountry\s+{$wlcfg['regcountry']}\s/si", $ifconfig_str))
2551
		$reg_changing = true;
2552
	else if ($wlcfg['reglocation'] == 'anywhere' && preg_match("/\s(indoor|outdoor)\s/si", $ifconfig_str))
2553
		$reg_changing = true;
2554
	else if ($wlcfg['reglocation'] && $wlcfg['reglocation'] != 'anywhere' && !preg_match("/\s{$wlcfg['reglocation']}\s/si", $ifconfig_str))
2555
		$reg_changing = true;
2556

    
2557
	if ($reg_changing) {
2558
		/* set regulatory domain */
2559
		if($wlcfg['regdomain'])
2560
			$wlregcmd[] = "regdomain " . escapeshellarg($wlcfg['regdomain']);
2561

    
2562
		/* set country */
2563
		if($wlcfg['regcountry'])
2564
			$wlregcmd[] = "country " . escapeshellarg($wlcfg['regcountry']);
2565

    
2566
		/* set location */
2567
		if($wlcfg['reglocation'])
2568
			$wlregcmd[] = escapeshellarg($wlcfg['reglocation']);
2569

    
2570
		$wlregcmd_args = implode(" ", $wlregcmd);
2571

    
2572
		/* build a complete list of the wireless clones for this interface */
2573
		$clone_list = array();
2574
		if (does_interface_exist(interface_get_wireless_clone($baseif)))
2575
			$clone_list[] = interface_get_wireless_clone($baseif);
2576
		if (is_array($config['wireless']['clone'])) {
2577
			foreach ($config['wireless']['clone'] as $clone) {
2578
				if ($clone['if'] == $baseif)
2579
					$clone_list[] = $clone['cloneif'];
2580
			}
2581
		}
2582

    
2583
		/* find which clones are up and bring them down */
2584
		$clones_up = array();
2585
		foreach ($clone_list as $clone_if) {
2586
			$clone_status = pfSense_get_interface_addresses($clone_if);
2587
			if ($clone_status['status'] == 'up') {
2588
				$clones_up[] = $clone_if;
2589
				mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " down");
2590
			}
2591
		}
2592

    
2593
		/* apply the regulatory settings */
2594
		mwexec("{$ifconfig} " . escapeshellarg($if) . " {$wlregcmd_args}");
2595

    
2596
		/* bring the clones back up that were previously up */
2597
		foreach ($clones_up as $clone_if) {
2598
			mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " up");
2599

    
2600
			/*
2601
			 * Rerun the setup script for the interface if it isn't this interface, the interface
2602
			 * is in infrastructure mode, and WPA is enabled.
2603
			 * This can be removed if wpa_supplicant stops dying when you bring the interface down.
2604
			 */
2605
			if ($clone_if != $if) {
2606
				$friendly_if = convert_real_interface_to_friendly_interface_name($clone_if);
2607
				if ( !empty($friendly_if)
2608
				    && $config['interfaces'][$friendly_if]['wireless']['mode'] == "bss"
2609
				    && isset($config['interfaces'][$friendly_if]['wireless']['wpa']['enable']) ) {
2610
					mwexec("/bin/sh {$g['tmp_path']}/{$clone_if}_setup.sh");
2611
				}
2612
			}
2613
		}
2614
	}
2615

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

    
2620
	/* configure wireless */
2621
	$wlcmd_args = implode(" ", $wlcmd);
2622
	mwexec("/sbin/ifconfig {$if} $wlcmd_args", false);
2623

    
2624
	
2625
	sleep(1);
2626
	/* execute hostapd and wpa_supplicant if required in shell */
2627
	mwexec("/bin/sh {$g['tmp_path']}/{$if}_setup.sh");
2628

    
2629
	return 0;
2630

    
2631
}
2632

    
2633
function kill_hostapd($interface) {
2634
	return "/bin/pkill -f \"hostapd .*{$interface}\"\n";
2635
}
2636

    
2637
function kill_wpasupplicant($interface) {
2638
	return "/bin/pkill -f \"wpa_supplicant .*{$interface}\"\n";
2639
}
2640

    
2641
function find_dhclient_process($interface) {
2642
	if ($interface)
2643
		$pid = `/bin/pgrep -axf "dhclient: {$interface}"`;
2644
	else
2645
		$pid = 0;
2646

    
2647
	return intval($pid);
2648
}
2649

    
2650
function find_dhcp6c_process($interface) {
2651
	if ($interface)
2652
		$pid = `/bin/ps auxw|grep "dhcp6c" |grep "{$interface}"|awk '{print $2}'`;
2653
	else
2654
		$pid = 0;
2655

    
2656
	return intval($pid);
2657
}
2658

    
2659
function interface_configure($interface = "wan", $reloadall = false, $linkupevent = false) {
2660
	global $config, $g;
2661
	global $interface_sn_arr_cache, $interface_ip_arr_cache;
2662
	global $interface_snv6_arr_cache, $interface_ipv6_arr_cache;
2663

    
2664
	$wancfg = $config['interfaces'][$interface];
2665

    
2666
	$realif = get_real_interface($interface);
2667
	$realhwif_array = get_parent_interface($interface);
2668
	// Need code to handle MLPPP if we ever use $realhwif for MLPPP handling
2669
	$realhwif = $realhwif_array[0];
2670

    
2671
	/* Disable Accepting router advertisements unless specifically requested */
2672
	log_error("Deny router advertisements for interface {$interface}");
2673
	mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 -accept_rtadv");
2674
			
2675
	if (!$g['booting'] && !substr($realif, 0, 4) == "ovpn") {
2676
		/* remove all IPv4 and IPv6 addresses */
2677
		while (mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " -alias", true) == 0);
2678
		while (mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 -alias", true) == 0);
2679

    
2680
		/* only bring down the interface when both v4 and v6 are set to NONE */
2681
		if(($wancfg['ipaddr'] <> "none") && ($wancfg['ipaddrv6'] <> "none")) {
2682
			interface_bring_down($interface);
2683
		}
2684
	}
2685

    
2686
	/* wireless configuration? */
2687
	if (is_array($wancfg['wireless']))
2688
		interface_wireless_configure($realif, $wancfg, $wancfg['wireless']);
2689

    
2690
	if ($wancfg['spoofmac']) {
2691
		mwexec("/sbin/ifconfig " . escapeshellarg($realhwif) .
2692
			" link " . escapeshellarg($wancfg['spoofmac']));
2693

    
2694
                /*
2695
                 * All vlans need to spoof their parent mac address, too.  see
2696
                 * ticket #1514: http://cvstrac.pfsense.com/tktview?tn=1514,33
2697
                 */
2698
                if (is_array($config['vlans']['vlan'])) {
2699
                        foreach ($config['vlans']['vlan'] as $vlan) {
2700
                                if ($vlan['if'] == $realhwif)
2701
                                        mwexec("/sbin/ifconfig " . escapeshellarg($vlan['vlanif']) .
2702
                                                " link " . escapeshellarg($wancfg['spoofmac']));
2703
                        }
2704
                }
2705
	}  else {
2706
		$mac = get_interface_mac($realhwif);
2707
		if ($mac == "ff:ff:ff:ff:ff:ff") {
2708
			/*   this is not a valid mac address.  generate a
2709
			 *   temporary mac address so the machine can get online.
2710
			 */
2711
			echo gettext("Generating new MAC address.");
2712
			$random_mac = generate_random_mac_address();
2713
			mwexec("/sbin/ifconfig " . escapeshellarg($realhwif) .
2714
				" link " . escapeshellarg($random_mac));
2715
			$wancfg['spoofmac'] = $random_mac;
2716
			write_config();
2717
			file_notice("MAC Address altered", sprintf(gettext('The INVALID MAC address (ff:ff:ff:ff:ff:ff) on interface %1$s has been automatically replaced with %2$s'), $realif, $random_mac), "Interfaces");
2718
		}
2719
	}
2720

    
2721
	/* media */
2722
	if ($wancfg['media'] || $wancfg['mediaopt']) {
2723
		$cmd = "/sbin/ifconfig " . escapeshellarg($realhwif);
2724
		if ($wancfg['media'])
2725
			$cmd .= " media " . escapeshellarg($wancfg['media']);
2726
		if ($wancfg['mediaopt'])
2727
			$cmd .= " mediaopt " . escapeshellarg($wancfg['mediaopt']);
2728
		mwexec($cmd);
2729
	}
2730
	if (!empty($wancfg['mtu']))
2731
		pfSense_interface_mtu($realhwif, $wancfg['mtu']);
2732
	else {
2733
		$mtu = get_interface_default_mtu(remove_numbers($realhwif));
2734
		if ($mtu != get_interface_mtu($realhwif))
2735
			pfSense_interface_mtu($realhwif, $mtu);
2736
	}
2737

    
2738
	$options = pfSense_get_interface_addresses($realhwif);
2739
	if (is_array($options) && isset($options['caps']['polling'])) {
2740
		if (isset($config['system']['polling']))
2741
			pfSense_interface_capabilities($realif, IFCAP_POLLING);
2742
		else
2743
			pfSense_interface_capabilities($realif, -IFCAP_POLLING);
2744
	}
2745

    
2746
	/* skip vlans for checksumming and polling */
2747
        if (!stristr($realhwif, "vlan") && is_array($options)) {
2748
		$flags = 0;
2749
		if(isset($config['system']['disablechecksumoffloading'])) {
2750
			if (isset($options['encaps']['txcsum']))
2751
				$flags |= IFCAP_TXCSUM;
2752
			if (isset($options['encaps']['rxcsum']))
2753
				$flags |= IFCAP_RXCSUM;
2754
        	} else {
2755
 			if (!isset($options['caps']['txcsum']))
2756
				$flags |= IFCAP_TXCSUM;
2757
			if (!isset($options['caps']['rxcsum']))
2758
				$flags |= IFCAP_RXCSUM;
2759
        	}
2760

    
2761
        	if(isset($config['system']['disablesegmentationoffloading'])) {
2762
                	if (isset($options['encaps']['tso4']))
2763
				$flags |= IFCAP_TSO;
2764
                	if (isset($options['encaps']['tso6']))
2765
				$flags |= IFCAP_TSO;
2766
        	} else {
2767
                	if (!isset($options['caps']['tso4']))
2768
				$flags |= IFCAP_TSO;
2769
                	if (!isset($options['caps']['tso6']))
2770
				$flags |= IFCAP_TSO;
2771
        	}
2772

    
2773
        	if(isset($config['system']['disablelargereceiveoffloading'])) {
2774
                	if (isset($options['encaps']['lro']))
2775
				$flags |= IFCAP_LRO;
2776
        	} else {
2777
                	if (!isset($options['caps']['lro']))
2778
				$flags |= IFCAP_LRO;
2779
        	}
2780

    
2781
        	/* if the NIC supports polling *AND* it is enabled in the GUI */
2782
        	if (!isset($config['system']['polling']) || !isset($options['caps']['polling'])) {
2783
			$flags |= IFCAP_POLLING;
2784
		}
2785
               	pfSense_interface_capabilities($realhwif, -$flags);
2786
	}
2787

    
2788
	/* invalidate interface/ip/sn cache */
2789
	get_interface_arr(true);
2790
	unset($interface_ip_arr_cache[$realif]);
2791
	unset($interface_sn_arr_cache[$realif]);
2792
	unset($interface_ipv6_arr_cache[$realif]);
2793
	unset($interface_snv6_arr_cache[$realif]);
2794

    
2795
	switch ($wancfg['ipaddr']) {
2796
		case 'carpdev-dhcp':
2797
			interface_carpdev_dhcp_configure($interface);
2798
			break;
2799
		case 'dhcp':
2800
			interface_dhcp_configure($interface);
2801
			break;
2802
		case 'pppoe':
2803
		case 'l2tp':
2804
		case 'pptp':
2805
		case 'ppp':
2806
			interface_ppps_configure($interface);
2807
			break;
2808
		default:
2809
			if (is_ipaddr($wancfg['ipaddr']) && $wancfg['subnet'] <> "") {
2810
				pfSense_interface_setaddress($realif, "{$wancfg['ipaddr']}/{$wancfg['subnet']}");
2811
			} else if (substr($realif, 0, 3) == "gre") {
2812
				if (is_array($config['gres']['gre'])) {
2813
					foreach ($config['gres']['gre'] as $gre)
2814
						if ($gre['greif'] == $realif)
2815
							interface_gre_configure($gre);
2816
				}
2817
			} else if (substr($realif, 0, 3) == "gif") {
2818
				 if (is_array($config['gifs']['gif'])) {
2819
					foreach ($config['gifs']['gif'] as $gif)
2820
						if($gif['gifif'] == $realif)
2821
							interface_gif_configure($gif);
2822
				}
2823
			} else if (substr($realif, 0, 4) == "ovpn") {
2824
				/* XXX: Should be done anything?! */
2825
			}
2826
			break;
2827
	}
2828

    
2829
	switch ($wancfg['ipaddrv6']) {
2830
		case 'dhcp6':
2831
			interface_dhcpv6_configure($interface);
2832
			break;
2833
		default:
2834
			if (is_ipaddr($wancfg['ipaddrv6']) && $wancfg['subnetv6'] <> "") {
2835
				pfSense_interface_setaddress($realif, "{$wancfg['ipaddrv6']}/{$wancfg['subnetv6']}");
2836
				// FIXME: Add IPv6 Support to the pfSense module
2837
				mwexec("/sbin/ifconfig {$realif} inet6 {$wancfg['ipaddrv6']} prefixlen {$wancfg['subnetv6']} ");
2838
			}
2839
			break;
2840
	}
2841

    
2842
	if(does_interface_exist($wancfg['if']))
2843
		interfaces_bring_up($wancfg['if']);
2844

    
2845
	interface_netgraph_needed($interface);
2846
 	
2847
	if (!$g['booting']) {
2848
		link_interface_to_vips($interface, "update");
2849

    
2850
		unset($gre);
2851
		$gre = link_interface_to_gre($interface);
2852
		if (!empty($gre))
2853
			array_walk($gre, 'interface_gre_configure');
2854

    
2855
		unset($gif);
2856
		$gif = link_interface_to_gif($interface);
2857
		if (!empty($gif))
2858
			array_walk($gif, 'interface_gif_configure');
2859

    
2860
		if ($linkupevent == false || substr($realif, 0, 4) == "ovpn") {
2861
			unset($bridgetmp);
2862
			$bridgetmp = link_interface_to_bridge($interface);
2863
			if (!empty($bridgetmp))
2864
				interface_bridge_add_member($bridgetmp, $realif);
2865
		}
2866

    
2867
		$grouptmp = link_interface_to_group($interface);
2868
		if (!empty($grouptmp))
2869
			array_walk($grouptmp, 'interface_group_add_member');
2870

    
2871
		if ($interface == "lan")
2872
			/* make new hosts file */
2873
			system_hosts_generate();
2874

    
2875
		if ($reloadall == true) {
2876

    
2877
			/* reconfigure static routes (kernel may have deleted them) */
2878
			system_routing_configure($interface);
2879

    
2880
			/* reload ipsec tunnels */
2881
			vpn_ipsec_configure();
2882

    
2883
			/* restart dnsmasq */
2884
			services_dnsmasq_configure();
2885

    
2886
			/* update dyndns */
2887
			send_event("service reload dyndns {$interface}");
2888

    
2889
			/* reload captive portal */
2890
			captiveportal_init_rules();
2891
		}
2892
	}
2893

    
2894
	return 0;
2895
}
2896

    
2897
function interface_carpdev_dhcp_configure($interface = "wan") {
2898
	global $config, $g;
2899

    
2900
	$wancfg = $config['interfaces'][$interface];
2901
	$wanif = $wancfg['if'];
2902
	/* bring wan interface up before starting dhclient */
2903
	if($wanif)
2904
		interfaces_bring_up($wanif);
2905
	else 
2906
		log_error(gettext("Could not bring wanif up in terface_carpdev_dhcp_configure()"));
2907

    
2908
	return 0;
2909
}
2910

    
2911
function interface_dhcpv6_configure($interface = "wan") {
2912
	global $config, $g;
2913
	$iflist = get_configured_interface_with_descr(false, true);
2914

    
2915
	$wancfg = $config['interfaces'][$interface];
2916
	$wanif = $wancfg['if'];
2917
	if (empty($wancfg))
2918
		$wancfg = array();
2919

    
2920
	$wanif = get_real_interface($interface);
2921

    
2922
	/* Add ISC IPv6 dhclient here, only wide-dhcp6c works for now. */
2923
	$fd = fopen("{$g['varetc_path']}/dhcp6c_{$interface}.conf", "w");
2924
	if (!$fd) {
2925
		printf("Error: cannot open dhcp6c_{$interface}.conf in interfaces_wan_dhcpv6_configure() for writing.\n");
2926
		return 1;
2927
	}
2928

    
2929
	$dhcp6cconf = "";
2930
 	$dhcp6cconf .= "interface {$wanif} {\n";
2931
	$dhcp6cconf .= " 	send ia-na 0;	# request stateful address\n";
2932
	if(is_numeric($wancfg['dhcp6-ia-pd-len'])) {
2933
		$dhcp6cconf .= " 	send ia-pd 0;	# request prefix delegation\n";
2934
	}
2935
	$dhcp6cconf .= "request domain-name-servers;\n";
2936
	$dhcp6cconf .= "request domain-name;\n";
2937
	$dhcp6cconf .= "script \"/etc/rc.newwanipv6\";	# we'd like some nameservers please\n";
2938

    
2939
	$dhcp6cconf .= "};\n";
2940
	$dhcp6cconf .= "id-assoc na 0 { };\n";
2941
	if(is_numeric($wancfg['dhcp6-ia-pd-len'])) {
2942
		/* Setup the prefix delegation */
2943
		$dhcp6cconf .= "	id-assoc pd 0 {\n";
2944
		foreach($iflist as $friendly => $pdinterface) {
2945
			// log_error("setting up $friendly - $pdinterface - {$pdinterface['dhcp6-pd-sla-id']}");
2946
			if(is_numeric($config['interfaces'][$friendly]['dhcp6-pd-sla-id'])) {
2947
				$realif = get_real_interface($friendly);
2948
				$dhcp6cconf .= "	prefix-interface {$realif} {\n";
2949
				$dhcp6cconf .= "		sla-id {$config['interfaces'][$friendly]['dhcp6-pd-sla-id']};\n";
2950
				$dhcp6cconf .= "		sla-len {$wancfg['dhcp6-ia-pd-len']};\n";
2951
				$dhcp6cconf .= "	};\n";
2952
			}
2953
		}
2954
		$dhcp6cconf .= "};\n";
2955
	}
2956

    
2957
	fwrite($fd, $dhcp6cconf);
2958
	fclose($fd);
2959

    
2960
	/* accept router advertisements for this interface */
2961
	mwexec("/sbin/sysctl -w net.inet6.ip6.accept_rtadv=1");
2962
	log_error("Accept router advertisements on interface {$wanif} ");
2963
	mwexec("/sbin/ifconfig {$wanif} inet6 accept_rtadv");
2964
	mwexec("/sbin/ifconfig {$wanif} inet6 defroute_rtadv");
2965
	sleep(1);
2966
	/* fire up dhcp6c for IPv6 first, this backgrounds immediately */
2967
	sleep(1);
2968
	mwexec("/usr/local/sbin/dhcp6c -d -c {$g['varetc_path']}/dhcp6c_{$interface}.conf {$wanif}");
2969
	// sleep(1);
2970
	// mwexec("/sbin/rtsol -d -O /etc/rc.newwanipv6 {$wanif}");
2971

    
2972
	return 0;
2973
}
2974

    
2975
function interface_dhcp_configure($interface = "wan") {
2976
	global $config, $g;
2977

    
2978
	$wancfg = $config['interfaces'][$interface];
2979
	$wanif = $wancfg['if'];
2980
	if (empty($wancfg))
2981
		$wancfg = array();
2982

    
2983
	/* generate dhclient_wan.conf */
2984
	$fd = fopen("{$g['varetc_path']}/dhclient_{$interface}.conf", "w");
2985
	if (!$fd) {
2986
		printf(printf(gettext("Error: cannot open dhclient_%s.conf in interfaces_wan_dhcp_configure() for writing.%s"), $interface, "\n"));
2987
		return 1;
2988
	}
2989

    
2990
	if ($wancfg['dhcphostname']) {
2991
		$dhclientconf_hostname = "send dhcp-client-identifier \"{$wancfg['dhcphostname']}\";\n";
2992
		$dhclientconf_hostname .= "\tsend host-name \"{$wancfg['dhcphostname']}\";\n";
2993
	} else {
2994
		$dhclientconf_hostname = "";
2995
	}
2996

    
2997
	$wanif = get_real_interface($interface);
2998
	if (empty($wanif)) {
2999
		log_error(sprintf(gettext("Invalid interface \"%s\" in interface_dhcp_configure()"), $interface));
3000
		return 0;
3001
	}
3002
 	$dhclientconf = "";
3003
	
3004
	$dhclientconf .= <<<EOD
3005
interface "{$wanif}" {
3006
timeout 60;
3007
retry 1;
3008
select-timeout 0;
3009
initial-interval 1;
3010
	{$dhclientconf_hostname}
3011
	script "/sbin/dhclient-script";
3012
}
3013

    
3014
EOD;
3015

    
3016
if(is_ipaddr($wancfg['alias-address'])) {
3017
	$subnetmask = gen_subnet_mask($wancfg['alias-subnet']);
3018
	$dhclientconf .= <<<EOD
3019
alias {
3020
	interface  "{$wanif}";
3021
	fixed-address {$wancfg['alias-address']};
3022
	option subnet-mask {$subnetmask};
3023
}
3024

    
3025
EOD;
3026
}
3027
	fwrite($fd, $dhclientconf);
3028
	fclose($fd);
3029

    
3030
	/* bring wan interface up before starting dhclient */
3031
	if($wanif)
3032
		interfaces_bring_up($wanif);
3033
	else 
3034
		log_error(printf(gettext("Could not bring up %s interface in interface_dhcp_configure()"), $wanif));
3035

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

    
3039
	return 0;
3040
}
3041

    
3042
function interfaces_group_setup() {
3043
	global $config;
3044

    
3045
	if (!is_array($config['ifgroups']['ifgroupentry']))
3046
		return;
3047

    
3048
	foreach ($config['ifgroups']['ifgroupentry'] as $groupar)
3049
		interface_group_setup($groupar);
3050

    
3051
	return;
3052
}
3053

    
3054
function interface_group_setup(&$groupname /* The parameter is an array */) {
3055
	global $config;
3056

    
3057
	if (!is_array($groupname))
3058
		return;
3059
	$members = explode(" ", $groupname['members']);
3060
	foreach($members as $ifs) {
3061
		$realif = get_real_interface($ifs);
3062
		if ($realif)
3063
			mwexec("/sbin/ifconfig {$realif} group {$groupname['ifname']}");
3064
	}
3065

    
3066
	return;
3067
}
3068

    
3069
function interface_group_add_member($interface, $groupname) {
3070
	$interface = get_real_interface($interface);
3071
	mwexec("/sbin/ifconfig {$interface} group {$groupname}", true);
3072
}
3073
 
3074
/* COMPAT Function */
3075
function convert_friendly_interface_to_real_interface_name($interface) {
3076
	return get_real_interface($interface);
3077
}
3078

    
3079
/* COMPAT Function */
3080
function get_real_wan_interface($interface = "wan") {
3081
	return get_real_interface($interface);
3082
}
3083

    
3084
/* COMPAT Function */
3085
function get_current_wan_address($interface = "wan") {
3086
	return get_interface_ip($interface);
3087
}
3088

    
3089
/*
3090
 * convert_real_interface_to_friendly_interface_name($interface): convert fxp0 -> wan, etc.
3091
 */
3092
function convert_real_interface_to_friendly_interface_name($interface = "wan") {
3093
        global $config;
3094

    
3095
	if (stristr($interface, "vip")) {
3096
                $index = intval(substr($interface, 3));
3097
                foreach ($config['virtualip']['vip'] as $counter => $vip) {
3098
                        if ($vip['mode'] == "carpdev-dhcp" || $vip['mode'] == "carp")  {
3099
                                if ($index == $vip['vhid'])
3100
                                        return $vip['interface'];
3101
                        }
3102
                }
3103
        }
3104

    
3105
        /* XXX: For speed reasons reference directly the interface array */
3106
	$ifdescrs = &$config['interfaces'];
3107
        //$ifdescrs = get_configured_interface_list(false, true);
3108

    
3109
        foreach ($ifdescrs as $if => $ifname) {
3110
                if ($config['interfaces'][$if]['if'] == $interface)
3111
                        return $if;
3112

    
3113
                if (stristr($interface, "_wlan0") && $config['interfaces'][$if]['if'] == interface_get_wireless_base($interface))
3114
                        return $if;
3115

    
3116
		// XXX: This case doesn't work anymore (segfaults - recursion?) - should be replaced with something else or just removed.
3117
		//      Not to be replaced with get_real_interface - causes slow interface listings here because of recursion!
3118
		/*
3119
                $int = get_parent_interface($if);
3120
                if ($int[0] == $interface)
3121
                        return $ifname;
3122
		*/
3123
        }
3124
        return NULL;
3125
}
3126

    
3127
/* attempt to resolve interface to friendly descr */
3128
function convert_friendly_interface_to_friendly_descr($interface) {
3129
        global $config;
3130

    
3131
        switch ($interface) {
3132
        case "l2tp":
3133
        	$ifdesc = "L2TP";
3134
                break;
3135
	case "pptp":
3136
		$ifdesc = "PPTP";
3137
		break;
3138
	case "pppoe":
3139
		$ifdesc = "PPPoE";
3140
		break;
3141
	case "openvpn":
3142
		$ifdesc = "OpenVPN";
3143
		break;
3144
	case "enc0":
3145
	case "ipsec":
3146
		$ifdesc = "IPsec";
3147
		break;
3148
        default:
3149
                if (isset($config['interfaces'][$interface])) {
3150
                        if (empty($config['interfaces'][$interface]['descr']))
3151
                                $ifdesc = strtoupper($interface);
3152
                        else
3153
                                $ifdesc = strtoupper($config['interfaces'][$interface]['descr']);
3154
			break;
3155
		} else if (substr($interface, 0, 3) == "vip") {
3156
			if (is_array($config['virtualip']['vip'])) {
3157
				foreach ($config['virtualip']['vip'] as $counter => $vip) {
3158
					if ($vip['mode'] == "carpdev-dhcp" || $vip['mode'] == "carp")  {
3159
						if ($interface == "vip{$vip['vhid']}")
3160
							return "{$vip['subnet']} - {$vip['descr']}";
3161
					}
3162
				}
3163
                        }
3164
                } else {
3165
			/* if list */
3166
			$ifdescrs = get_configured_interface_with_descr(false, true);
3167
			foreach ($ifdescrs as $if => $ifname) {
3168
					if ($if == $interface || $ifname == $interface)
3169
						return $ifname;
3170
			}
3171
		}
3172
                break;
3173
        }
3174

    
3175
        return $ifdesc;
3176
}
3177

    
3178
function convert_real_interface_to_friendly_descr($interface) {
3179
        global $config;
3180

    
3181
        $ifdesc = convert_real_interface_to_friendly_interface_name("{$interface}");
3182

    
3183
        if ($ifdesc) {
3184
                $iflist = get_configured_interface_with_descr(false, true);
3185
                return $iflist[$ifdesc];
3186
        }
3187

    
3188
        return $interface;
3189
}
3190

    
3191
/*
3192
 *  get_parent_interface($interface):
3193
 *			--returns the (real or virtual) parent interface(s) array for a given interface friendly name (i.e. wan)
3194
 *				or virtual interface (i.e. vlan)
3195
 *				(We need array because MLPPP and bridge interfaces have more than one parent.)
3196
 *			-- returns $interface passed in if $interface parent is not found
3197
 *			-- returns empty array if an invalid interface is passed
3198
 *	(Only handles ppps and vlans now.)
3199
 */
3200
function get_parent_interface($interface) {
3201
	global $config;
3202

    
3203
	$parents = array();
3204
	//Check that we got a valid interface passed
3205
	$realif = get_real_interface($interface);
3206
	if ($realif == NULL)
3207
		return $parents;
3208

    
3209
	// If we got a real interface, find it's friendly assigned name
3210
	$interface = convert_real_interface_to_friendly_interface_name($interface);
3211
		
3212
	if (!empty($interface) && isset($config['interfaces'][$interface])) {
3213
		$ifcfg = $config['interfaces'][$interface];
3214
		switch ($ifcfg['ipaddr']) {
3215
			case "ppp":
3216
			case "pppoe":
3217
			case "pptp":
3218
			case "l2tp":
3219
				if (empty($parents))
3220
					if (is_array($config['ppps']['ppp']))
3221
						foreach ($config['ppps']['ppp'] as $pppidx => $ppp) {
3222
							if ($ppp_if == $ppp['if']) {
3223
								$ports = explode(',', $ppp['ports']);
3224
								foreach ($ports as $pid => $parent_if) 
3225
									$parents[$pid] = get_real_interface($parent_if);
3226
								break;
3227
							}
3228
						}
3229
				break;
3230
			case "dhcp":
3231
			case "static":
3232
			default:
3233
				// Handle _vlans
3234
				if (strstr($realif,"_vlan"))
3235
					if (is_array($config['vlans']['vlan'])) 
3236
						foreach ($config['vlans']['vlan'] as $vlanidx => $vlan)
3237
							if ($ifcfg['if'] == $vlan['vlanif']){
3238
								$parents[0] = $vlan['if'];
3239
								break;
3240
							}
3241
				break;
3242
		}
3243
	}
3244
	
3245
	if (empty($parents))
3246
		$parents[0] = $realif;
3247
	
3248
	return $parents;
3249
}
3250

    
3251
function interface_is_wireless_clone($wlif) {
3252
	if(!stristr($wlif, "_wlan")) {
3253
		return false;
3254
	} else {
3255
		return true;
3256
	}
3257
}
3258

    
3259
function interface_get_wireless_base($wlif) {
3260
	if(!stristr($wlif, "_wlan")) {
3261
		return $wlif;
3262
	} else {
3263
		return substr($wlif, 0, stripos($wlif, "_wlan"));
3264
	}
3265
}
3266

    
3267
function interface_get_wireless_clone($wlif) {
3268
	if(!stristr($wlif, "_wlan")) {
3269
		return $wlif . "_wlan0";
3270
	} else {
3271
		return $wlif;
3272
	}
3273
}
3274

    
3275
function get_real_interface($interface = "wan") {
3276
    global $config;
3277

    
3278
	$wanif = NULL;
3279

    
3280
	switch ($interface) {
3281
	case "l2tp":
3282
		$wanif = "l2tp";
3283
		break;
3284
	case "pptp":
3285
		$wanif = "pptp";
3286
		break;
3287
	case "pppoe":
3288
		$wanif = "pppoe";
3289
		break;
3290
	case "openvpn":
3291
		$wanif = "openvpn";
3292
		break;
3293
	case "ipsec":
3294
	case "enc0":
3295
		$wanif = "enc0";
3296
		break;
3297
	case "ppp":
3298
		$wanif = "ppp";
3299
		break;
3300
	default:
3301
		// If a real interface was alread passed simply
3302
		// pass the real interface back.  This encourages
3303
		// the usage of this function in more cases so that
3304
		// we can combine logic for more flexibility.
3305
		if(does_interface_exist($interface)) {
3306
			$wanif = $interface;
3307
			break;
3308
		}
3309
		if (empty($config['interfaces'][$interface]))
3310
			break;
3311

    
3312
		$cfg = &$config['interfaces'][$interface];
3313

    
3314
		// Wireless cloned NIC support (FreeBSD 8+)
3315
		// interface name format: $parentnic_wlanparentnic#
3316
		// example: ath0_wlan0
3317
		if (is_interface_wireless($cfg['if'])) {
3318
			$wanif = interface_get_wireless_clone($cfg['if']);
3319
			break;
3320
		}
3321
		/*
3322
		if (empty($cfg['if'])) {
3323
			$wancfg = $cfg['if'];
3324
			break;
3325
		}
3326
		*/
3327

    
3328
		switch ($cfg['ipaddr']) {
3329
			case "carpdev-dhcp":
3330
				$viparr = &$config['virtualip']['vip'];
3331
				if(is_array($viparr))
3332
				foreach ($viparr as $counter => $vip) {
3333
					if ($vip['mode'] == "carpdev-dhcp") {
3334
						if($vip['interface'] == $interface) {
3335
							$wanif = "carp{$counter}";
3336
							break;
3337
						}
3338
					}
3339
				}
3340
				break;
3341
			case "pppoe": 
3342
			case "pptp": 
3343
			case "l2tp": 
3344
			case "ppp":
3345
				$wanif = $cfg['if'];
3346
				break;
3347
			default:
3348
				$wanif = $cfg['if'];
3349
				break;
3350
		}
3351
		break;
3352
	}
3353

    
3354
    return $wanif;
3355
}
3356

    
3357
/* Guess the physical interface by providing a IP address */
3358
function guess_interface_from_ip($ipaddress) {
3359
	if(! is_ipaddr($ipaddress)) {
3360
		return false;
3361
	}
3362
	if(is_ipaddrv4($ipaddress)) {
3363
		/* create a route table we can search */
3364
		exec("netstat -rnWf inet", $output, $ret);
3365
		foreach($output as $line) {
3366
			if(preg_match("/^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\/[0-9]+[ ]+link[#]/", $line)) {
3367
				$fields = preg_split("/[ ]+/", $line);
3368
				if(ip_in_subnet($ipaddress, $fields[0])) {
3369
					return $fields[6];
3370
				}
3371
			}
3372
		}
3373
	}
3374
	/* FIXME: This works from cursory testing, regexp might need fine tuning */
3375
	if(is_ipaddrv6($ipaddress)) {
3376
		/* create a route table we can search */
3377
		exec("netstat -rnWf inet6", $output, $ret);
3378
		foreach($output as $line) {
3379
			if(preg_match("/[0-9a-f]+[:]+[0-9a-f]+[:]+[\/][0-9]+/", $line)) {
3380
				$fields = preg_split("/[ ]+/", $line);
3381
				if(ip_in_subnet($ipaddress, $fields[0])) {
3382
					return $fields[6];
3383
				}
3384
			}
3385
		}
3386
	}
3387
	$ret = exec_command("/sbin/route -n get {$ipaddress} | /usr/bin/awk '/interface/ { print \$2; };'");
3388
	if(empty($ret)) {
3389
        	return false;
3390
	}
3391
	return $ret;
3392
}
3393

    
3394
/*
3395
 * find_ip_interface($ip): return the interface where an ip is defined
3396
 */
3397
function find_ip_interface($ip)
3398
{
3399
        /* if list */
3400
        $ifdescrs = get_configured_interface_list();
3401

    
3402
        foreach ($ifdescrs as $ifdescr => $ifname) {
3403
		if ($ip == get_interface_ip($ifname)) {
3404
                	$int = get_real_interface($ifname);
3405
			return $int;
3406
		}
3407
        }
3408
        return false;
3409
}
3410

    
3411
/*
3412
 *   find_number_of_created_carp_interfaces: return the number of carp interfaces
3413
 */
3414
function find_number_of_created_carp_interfaces() {
3415
	return `/sbin/ifconfig | grep "carp:" | wc -l`;
3416
}
3417

    
3418
function get_all_carp_interfaces() {
3419
	$ints = str_replace("\n", " ", `ifconfig | grep "carp:" -B2 | grep ": flag" | cut -d: -f1`);
3420
	$ints = explode(" ", $ints);
3421
	return $ints;
3422
}
3423

    
3424
/*
3425
 * find_carp_interface($ip): return the carp interface where an ip is defined
3426
 */
3427
function find_carp_interface($ip) {
3428
	global $config;
3429
	if (is_array($config['virtualip']['vip'])) {
3430
		foreach ($config['virtualip']['vip'] as $vip) {
3431
			if ($vip['mode'] == "carp" || $vip['mode'] == "carpdev") {
3432
				if(is_ipaddrv4($ip)) {
3433
					$carp_ip = get_interface_ip($vip['interface']);
3434
				}
3435
				if(is_ipaddrv6($ip)) {
3436
					$carp_ip = get_interface_ipv6($vip['interface']);
3437
				}
3438
				exec("/sbin/ifconfig", $output, $return);
3439
				foreach($output as $line) {
3440
					$elements = preg_split("/[ ]+/i", $line);
3441
					if(strstr($elements[0], "vip"))
3442
						$curif = str_replace(":", "", $elements[0]);
3443
					if(stristr($line, $ip)) {
3444
						$if = $curif;
3445
						continue;
3446
					}
3447
				}
3448
				if ($if)
3449
					return $if;
3450
			}
3451
		}
3452
	}
3453
}
3454

    
3455
function link_carp_interface_to_parent($interface) {
3456
        global $config;
3457

    
3458
        if ($interface == "")
3459
                return;
3460

    
3461
        $carp_ip = get_interface_ip($interface);
3462
        if (!is_ipaddr($carp_ip))
3463
                return;
3464

    
3465
        /* if list */
3466
        $ifdescrs = get_configured_interface_list();
3467
        foreach ($ifdescrs as $ifdescr => $ifname) {
3468
                $interfaceip = get_interface_ip($ifname);
3469
                $subnet_bits = get_interface_subnet($ifname);
3470
                $subnet_ip = gen_subnet("{$interfaceip}", "{$subnet_bits}");
3471
                if(ip_in_subnet($carp_ip, "{$subnet_ip}/{$subnet_bits}"))
3472
                        return $ifname;
3473
        }
3474

    
3475
        return "";
3476
}
3477

    
3478
/****f* interfaces/link_ip_to_carp_interface
3479
 * NAME
3480
 *   link_ip_to_carp_interface - Find where a CARP interface links to.
3481
 * INPUTS
3482
 *   $ip
3483
 * RESULT
3484
 *   $carp_ints
3485
 ******/
3486
function link_ip_to_carp_interface($ip) {
3487
        global $config;
3488

    
3489
        if (!is_ipaddr($ip))
3490
                return;
3491

    
3492
        $carp_ints = "";
3493
        if (is_array($config['virtualip']['vip'])) {
3494
		$first = 0;
3495
		$carp_int = array();
3496
                foreach ($config['virtualip']['vip'] as $vip) {
3497
                        if ($vip['mode'] == "carp" || $vip['mode'] == "carpdev") {
3498
                                $carp_ip = $vip['subnet'];
3499
                                $carp_sn = $vip['subnet_bits'];
3500
                                $carp_nw = gen_subnet($carp_ip, $carp_sn);
3501
                                if (ip_in_subnet($ip, "{$carp_nw}/{$carp_sn}"))
3502
					$carp_int[] = "vip{$vip['vhid']}";
3503
                        }
3504
                }
3505
		if (!empty($carp_int))
3506
			$carp_ints = implode(" ", array_unique($carp_int));
3507
        }
3508

    
3509
        return $carp_ints;
3510
}
3511

    
3512
function link_interface_to_vlans($int, $action = "") {
3513
	global $config;
3514

    
3515
	if (empty($int))
3516
		return;
3517

    
3518
	if (is_array($config['vlans']['vlan'])) {
3519
                foreach ($config['vlans']['vlan'] as $vlan) {
3520
			if ($int == $vlan['if']) {
3521
				if ($action == "update") {
3522
					interfaces_bring_up($int);
3523
				} else if ($action == "")
3524
					return $vlan;
3525
			}
3526
		}
3527
	}
3528
}
3529

    
3530
function link_interface_to_vips($int, $action = "") {
3531
        global $config;
3532

    
3533
        if (is_array($config['virtualip']['vip'])) {
3534
		foreach ($config['virtualip']['vip'] as $vip) {
3535
			if ($int == $vip['interface']) {
3536
				if ($action == "update") {
3537
					if ($vip['mode'] == "carp" && !does_interface_exist("vip{$vip['vhid']}"))
3538
						interfaces_vips_configure($int);
3539
					else {
3540
						interface_vip_bring_down($vip);
3541
						interfaces_vips_configure($int);
3542
					}
3543
				} else
3544
					return $vip;
3545
			}
3546
		}
3547
	}
3548
}
3549

    
3550
/****f* interfaces/link_interface_to_bridge
3551
 * NAME
3552
 *   link_interface_to_bridge - Finds out a bridge group for an interface
3553
 * INPUTS
3554
 *   $ip
3555
 * RESULT
3556
 *   bridge[0-99]
3557
 ******/
3558
function link_interface_to_bridge($int) {
3559
        global $config;
3560

    
3561
        if (is_array($config['bridges']['bridged'])) {
3562
                foreach ($config['bridges']['bridged'] as $bridge) {
3563
			if (in_array($int, explode(',', $bridge['members'])))
3564
                                return "{$bridge['bridgeif']}";
3565
		}
3566
	}
3567
}
3568

    
3569
function link_interface_to_group($int) {
3570
        global $config;
3571

    
3572
	$result = array();
3573

    
3574
        if (is_array($config['ifgroups']['ifgroupentry'])) {
3575
                foreach ($config['ifgroups']['ifgroupentry'] as $group) {
3576
			if (in_array($int, explode(" ", $group['members'])))
3577
				$result[$group['ifname']] = $int;
3578
		}
3579
	}
3580

    
3581
	return $result;
3582
}
3583

    
3584
function link_interface_to_gre($interface) {
3585
        global $config;
3586

    
3587
	$result = array();
3588

    
3589
        if (is_array($config['gres']['gre'])) {
3590
                foreach ($config['gres']['gre'] as $gre)
3591
                        if($gre['if'] == $interface)
3592
				$result[] = $gre;
3593
	}
3594

    
3595
	return $result;
3596
}
3597

    
3598
function link_interface_to_gif($interface) {
3599
        global $config;
3600

    
3601
	$result = array();
3602

    
3603
        if (is_array($config['gifs']['gif'])) {
3604
                foreach ($config['gifs']['gif'] as $gif)
3605
                        if($gif['if'] == $interface)
3606
                                $result[] = $gif;
3607
	}
3608

    
3609
	return $result;
3610
}
3611

    
3612
/*
3613
 * find_interface_ip($interface): return the interface ip (first found)
3614
 */
3615
function find_interface_ip($interface, $flush = false)
3616
{
3617
	global $interface_ip_arr_cache;
3618
	global $interface_sn_arr_cache;
3619

    
3620
	$interface = str_replace("\n", "", $interface);
3621
	
3622
	if (!does_interface_exist($interface))
3623
		return;
3624

    
3625
	/* Setup IP cache */
3626
	if (!isset($interface_ip_arr_cache[$interface]) or $flush) {
3627
		$ifinfo = pfSense_get_interface_addresses($interface);
3628
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
3629
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
3630
	}
3631

    
3632
	return $interface_ip_arr_cache[$interface];
3633
}
3634

    
3635
/*
3636
 * find_interface_ipv6($interface): return the interface ip (first found)
3637
 */
3638
function find_interface_ipv6($interface, $flush = false)
3639
{
3640
	global $interface_ipv6_arr_cache;
3641
	global $interface_snv6_arr_cache;
3642
	global $config;
3643
	
3644
	$interface = str_replace("\n", "", $interface);
3645
	
3646
	if (!does_interface_exist($interface))
3647
		return;
3648

    
3649
	/* Setup IP cache */
3650
	if (!isset($interface_ipv6_arr_cache[$interface]) or $flush) {
3651
		$ifinfo = pfSense_get_interface_addresses($interface);
3652
		// FIXME: Add IPv6 support to the pfSense module
3653
		exec("/sbin/ifconfig {$interface} inet6", $output);
3654
		foreach($output as $line) {
3655
			if(preg_match("/inet6/", $line)) {
3656
				$parts = explode(" ", $line);
3657
				if(! preg_match("/fe80::/", $parts[1])) {
3658
					$ifinfo['ipaddrv6'] = $parts[1];
3659
					if($parts[2] == "-->") {
3660
						$parts[5] = "126";
3661
						$ifinfo['subnetbitsv6'] = $parts[5];
3662
					} else {
3663
						$ifinfo['subnetbitsv6'] = $parts[3];
3664
					}
3665
				}
3666
			}
3667
		}
3668
		$interface_ipv6_arr_cache[$interface] = $ifinfo['ipaddrv6'];
3669
		$interface_snv6_arr_cache[$interface] = $ifinfo['subnetbitsv6'];
3670
	}
3671

    
3672
	return $interface_ipv6_arr_cache[$interface];
3673
}
3674

    
3675
function find_interface_subnet($interface, $flush = false)
3676
{
3677
	global $interface_sn_arr_cache;
3678
	global $interface_ip_arr_cache;
3679

    
3680
	$interface = str_replace("\n", "", $interface);
3681
	if (does_interface_exist($interface) == false)
3682
		return;
3683

    
3684
	if (!isset($interface_sn_arr_cache[$interface]) or $flush) {
3685
		$ifinfo = pfSense_get_interface_addresses($interface);
3686
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
3687
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
3688
        }
3689

    
3690
	return $interface_sn_arr_cache[$interface];
3691
}
3692

    
3693
function find_interface_subnetv6($interface, $flush = false)
3694
{
3695
	global $interface_snv6_arr_cache;
3696
	global $interface_ipv6_arr_cache;
3697

    
3698
	$interface = str_replace("\n", "", $interface);
3699
	if (does_interface_exist($interface) == false)
3700
		return;
3701

    
3702
	if (!isset($interface_snv6_arr_cache[$interface]) or $flush) {
3703
		$ifinfo = pfSense_get_interface_addresses($interface);
3704
		// FIXME: Add IPv6 support to the pfSense module
3705
		exec("/sbin/ifconfig {$interface} inet6", $output);
3706
		foreach($output as $line) {
3707
			if(preg_match("/inet6/", $line)) {
3708
				$parts = explode(" ", $line);
3709
				if(! preg_match("/fe80::/", $parts[1])) {
3710
					$ifinfo['ipaddrv6'] = $parts[1];
3711
					if($parts[2] == "-->") {
3712
						$parts[5] = "126";
3713
						$ifinfo['subnetbitsv6'] = $parts[5];
3714
					} else {
3715
						$ifinfo['subnetbitsv6'] = $parts[3];
3716
					}
3717
				}
3718
			}
3719
		}
3720
		$interface_ipv6_arr_cache[$interface] = $ifinfo['ipaddrv6'];
3721
		$interface_snv6_arr_cache[$interface] = $ifinfo['subnetbitsv6'];
3722
        }
3723

    
3724
	return $interface_snv6_arr_cache[$interface];
3725
}
3726

    
3727
function ip_in_interface_alias_subnet($interface, $ipalias) {
3728
	global $config;
3729

    
3730
	if (empty($interface) || !is_ipaddr($ipalias))
3731
		return false;
3732
	if (is_array($config['virtualip']['vip'])) {
3733
                foreach ($config['virtualip']['vip'] as $vip) {
3734
                        switch ($vip['mode']) {
3735
                        case "ipalias":
3736
                                if ($vip['interface'] <> $interface)
3737
                                        break;
3738
				if (ip_in_subnet($ipalias, gen_subnet($vip['subnet'], $vip['subnet_bits']) . "/" . $vip['subnet_bits']))
3739
					return true;
3740
                                break;
3741
                        }
3742
                }
3743
	}
3744

    
3745
	return false;
3746
}
3747

    
3748
function get_interface_ip($interface = "wan")
3749
{
3750
	$realif = get_real_interface($interface);
3751
	if (!$realif) {
3752
		if (preg_match("/^carp/i", $interface))
3753
			$realif = $interface;
3754
		else if (preg_match("/^vip/i", $interface))
3755
			$realif = $interface;
3756
		else
3757
			return null;
3758
	}
3759

    
3760
	$curip = find_interface_ip($realif);
3761
	if ($curip && is_ipaddr($curip) && ($curip != "0.0.0.0"))
3762
		return $curip;
3763
	else
3764
		return null;
3765
}
3766

    
3767
function get_interface_ipv6($interface = "wan")
3768
{
3769
	$realif = get_real_interface($interface);
3770
	if (!$realif) {
3771
		if (preg_match("/^carp/i", $interface))
3772
			$realif = $interface;
3773
		else if (preg_match("/^vip/i", $interface))
3774
			$realif = $interface;
3775
		else
3776
			return null;
3777
	}
3778

    
3779
	$curip = find_interface_ipv6($realif);
3780
	if ($curip && is_ipaddrv6($curip) && ($curip != "::"))
3781
		return $curip;
3782
	else
3783
		return null;
3784
}
3785

    
3786
function get_interface_subnet($interface = "wan")
3787
{
3788
	$realif = get_real_interface($interface);
3789
	if (!$realif) {
3790
                if (preg_match("/^carp/i", $interface))
3791
                        $realif = $interface;
3792
                else if (preg_match("/^vip/i", $interface))
3793
                        $realif = $interface;
3794
                else
3795
                        return null;
3796
        }
3797

    
3798
	$cursn = find_interface_subnet($realif);
3799
	if (!empty($cursn))
3800
		return $cursn;
3801

    
3802
	return null;
3803
}
3804

    
3805
function get_interface_subnetv6($interface = "wan")
3806
{
3807
	$realif = get_real_interface($interface);
3808
	if (!$realif) {
3809
                if (preg_match("/^carp/i", $interface))
3810
                        $realif = $interface;
3811
                else if (preg_match("/^vip/i", $interface))
3812
                        $realif = $interface;
3813
                else
3814
                        return null;
3815
        }
3816

    
3817
	$cursn = find_interface_subnetv6($realif);
3818
	if (!empty($cursn))
3819
		return $cursn;
3820

    
3821
	return null;
3822
}
3823

    
3824
/* return outside interfaces with a gateway */
3825
function get_interfaces_with_gateway() {
3826
	global $config;
3827

    
3828
	$ints = array();
3829

    
3830
	/* loop interfaces, check config for outbound */
3831
	foreach($config['interfaces'] as $ifdescr => $ifname) {
3832
		switch ($ifname['ipaddr']) {
3833
			case "dhcp":
3834
			case "carpdev-dhcp":
3835
			case "ppp";
3836
			case "pppoe":
3837
			case "pptp":
3838
			case "l2tp":
3839
			case "ppp";
3840
				$ints[$ifdescr] = $ifdescr;
3841
			break;
3842
			default:
3843
				if (substr($ifname['if'], 0, 5) ==  "ovpnc" ||
3844
				    !empty($ifname['gateway']))
3845
					$ints[$ifdescr] = $ifdescr;
3846
			break;
3847
		}
3848
	}
3849
	return $ints;
3850
}
3851

    
3852
/* return true if interface has a gateway */
3853
function interface_has_gateway($friendly) {
3854
	global $config;
3855

    
3856
	if (!empty($config['interfaces'][$friendly])) {
3857
		$ifname = &$config['interfaces'][$friendly];
3858
		switch ($ifname['ipaddr']) {
3859
			case "dhcp":
3860
			case "carpdev-dhcp":
3861
			case "pppoe":
3862
			case "pptp":
3863
			case "l2tp":
3864
			case "ppp";
3865
				return true;
3866
			break;
3867
			default:
3868
				if (substr($ifname['if'], 0, 5) ==  "ovpnc")
3869
					return true;
3870
				if (!empty($ifname['gateway']))
3871
					return true;
3872
			break;
3873
		}
3874
	}
3875

    
3876
	return false;
3877
}
3878

    
3879
/* return true if interface has a gateway */
3880
function interface_has_gatewayv6($friendly) {
3881
	global $config;
3882

    
3883
	if (!empty($config['interfaces'][$friendly])) {
3884
		$ifname = &$config['interfaces'][$friendly];
3885
		switch ($ifname['ipaddrv6']) {
3886
			case "dhcp6":
3887
				return true;
3888
			break;
3889
			default:
3890
				if (substr($ifname['if'], 0, 5) ==  "ovpnc")
3891
					return true;
3892
				if (!empty($ifname['gatewayv6']))
3893
					return true;
3894
			break;
3895
		}
3896
	}
3897

    
3898
	return false;
3899
}
3900

    
3901
/****f* interfaces/is_altq_capable
3902
 * NAME
3903
 *   is_altq_capable - Test if interface is capable of using ALTQ
3904
 * INPUTS
3905
 *   $int            - string containing interface name
3906
 * RESULT
3907
 *   boolean         - true or false
3908
 ******/
3909

    
3910
function is_altq_capable($int) {
3911
        /* Per:
3912
         * http://www.freebsd.org/cgi/man.cgi?query=altq&manpath=FreeBSD+7.2-current&format=html
3913
         * Only the following drivers have ALTQ support
3914
         */
3915
	$capable = array("age", "alc", "ale", "an", "ath", "aue", "awi", "bce",
3916
			"bfe", "bge", "bridge", "cas", "dc", "de", "ed", "em", "ep", "fxp", "gem",
3917
			"hme", "igb", "ipw", "iwi", "jme", "le", "lem", "msk", "mxge", "my", "nfe",
3918
			"npe", "nve", "ral", "re", "rl", "rum", "run", "bwn", "sf", "sis", "sk",
3919
			"ste", "stge", "txp", "udav", "ural", "vge", "vr", "wi", "xl",
3920
			"ndis", "tun", "ovpns", "ovpnc", "vlan", "pppoe", "pptp", "ng",
3921
			"l2tp", "ppp");
3922

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

    
3925
        if (in_array($int_family[0], $capable))
3926
                return true;
3927
	else if (stristr($int, "vlan")) /* VLANs are name $parent_$vlan now */
3928
		return true;
3929
	else if (stristr($int, "_wlan")) /* WLANs are name $parent_$wlan now */
3930
		return true;
3931
        else
3932
                return false;
3933
}
3934

    
3935
/****f* interfaces/is_interface_wireless
3936
 * NAME
3937
 *   is_interface_wireless - Returns if an interface is wireless
3938
 * RESULT
3939
 *   $tmp       - Returns if an interface is wireless
3940
 ******/
3941
function is_interface_wireless($interface) {
3942
        global $config, $g;
3943

    
3944
        $friendly = convert_real_interface_to_friendly_interface_name($interface);
3945
        if(!isset($config['interfaces'][$friendly]['wireless'])) {
3946
                if (preg_match($g['wireless_regex'], $interface)) {
3947
                        if (isset($config['interfaces'][$friendly]))
3948
                                $config['interfaces'][$friendly]['wireless'] = array();
3949
                        return true;
3950
                }
3951
                return false;
3952
        } else
3953
                return true;
3954
}
3955

    
3956
function get_wireless_modes($interface) {
3957
	/* return wireless modes and channels */
3958
	$wireless_modes = array();
3959

    
3960
	$cloned_interface = get_real_interface($interface);
3961

    
3962
	if($cloned_interface && is_interface_wireless($cloned_interface)) {
3963
		$chan_list = "/sbin/ifconfig {$cloned_interface} list chan";
3964
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
3965
		$format_list = "/usr/bin/awk '{print \$5 \" \" \$6 \",\" \$1}'";
3966

    
3967
		$interface_channels = "";
3968
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
3969
		$interface_channel_count = count($interface_channels);
3970

    
3971
		$c = 0;
3972
		while ($c < $interface_channel_count)
3973
		{
3974
			$channel_line = explode(",", $interface_channels["$c"]);
3975
			$wireless_mode = trim($channel_line[0]);
3976
			$wireless_channel = trim($channel_line[1]);
3977
			if(trim($wireless_mode) != "") {
3978
				/* if we only have 11g also set 11b channels */
3979
				if($wireless_mode == "11g") {
3980
					if(!isset($wireless_modes["11b"]))
3981
						$wireless_modes["11b"] = array();
3982
				} else if($wireless_mode == "11g ht") {
3983
					if(!isset($wireless_modes["11b"]))
3984
						$wireless_modes["11b"] = array();
3985
					if(!isset($wireless_modes["11g"]))
3986
						$wireless_modes["11g"] = array();
3987
					$wireless_mode = "11ng";
3988
				} else if($wireless_mode == "11a ht") {
3989
					if(!isset($wireless_modes["11a"]))
3990
						$wireless_modes["11a"] = array();
3991
					$wireless_mode = "11na";
3992
				}
3993
				$wireless_modes["$wireless_mode"]["$c"] = $wireless_channel;
3994
			}
3995
			$c++;
3996
		}
3997
	}
3998
	return($wireless_modes);
3999
}
4000

    
4001
/* return channel numbers, frequency, max txpower, and max regulation txpower */
4002
function get_wireless_channel_info($interface) {
4003
	$wireless_channels = array();
4004

    
4005
	$cloned_interface = get_real_interface($interface);
4006

    
4007
	if($cloned_interface && is_interface_wireless($cloned_interface)) {
4008
		$chan_list = "/sbin/ifconfig {$cloned_interface} list txpower";
4009
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
4010
		$format_list = "/usr/bin/awk '{print \$1 \",\" \$3 \" \" \$4 \",\" \$5 \",\" \$7}'";
4011

    
4012
		$interface_channels = "";
4013
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
4014

    
4015
		foreach ($interface_channels as $channel_line) {
4016
			$channel_line = explode(",", $channel_line);
4017
			if(!isset($wireless_channels[$channel_line[0]]))
4018
				$wireless_channels[$channel_line[0]] = $channel_line;
4019
		}
4020
	}
4021
	return($wireless_channels);
4022
}
4023

    
4024
/****f* interfaces/get_interface_mtu
4025
 * NAME
4026
 *   get_interface_mtu - Return the mtu of an interface
4027
 * RESULT
4028
 *   $tmp       - Returns the mtu of an interface
4029
 ******/
4030
function get_interface_mtu($interface) {
4031
        $mtu = pfSense_get_interface_addresses($interface);
4032
        return $mtu['mtu'];
4033
}
4034

    
4035
function get_interface_mac($interface) {
4036

    
4037
	$macinfo = pfSense_get_interface_addresses($interface);
4038
	return $macinfo["macaddr"];
4039
}
4040

    
4041
/****f* pfsense-utils/generate_random_mac_address
4042
 * NAME
4043
 *   generate_random_mac - generates a random mac address
4044
 * INPUTS
4045
 *   none
4046
 * RESULT
4047
 *   $mac - a random mac address
4048
 ******/
4049
function generate_random_mac_address() {
4050
        $mac = "02";
4051
        for($x=0; $x<5; $x++)
4052
                $mac .= ":" . dechex(rand(16, 255));
4053
        return $mac;
4054
}
4055

    
4056
/****f* interfaces/is_jumbo_capable
4057
 * NAME
4058
 *   is_jumbo_capable - Test if interface is jumbo frame capable.  Useful for determining VLAN capability.
4059
 * INPUTS
4060
 *   $int             - string containing interface name
4061
 * RESULT
4062
 *   boolean          - true or false
4063
 ******/
4064
function is_jumbo_capable($int) {
4065
        global $g;
4066

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

    
4069
        if (in_array($int_family[0], $g['vlan_long_frame']))
4070
                return true;
4071
        else
4072
                return false;
4073
}
4074

    
4075
function setup_pppoe_reset_file($pppif, $iface="") {
4076
	global $g;
4077
	$cron_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
4078

    
4079
	if(!empty($iface) && !empty($pppif)){
4080
		$cron_cmd = <<<EOD
4081
#!/bin/sh
4082
/usr/local/sbin/pfSctl -c 'interface reload {$iface}'
4083
/usr/bin/logger -t pppoe{$iface} "PPPoE periodic reset executed on {$iface}"
4084

    
4085
EOD;
4086

    
4087
		file_put_contents($cron_file, $cron_cmd);
4088
		chmod($cron_file, 0700);
4089
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
4090
	} else
4091
		unlink_if_exists($cron_file);
4092
}
4093

    
4094
function get_interface_default_mtu($type = "ethernet") {
4095
	switch ($type) {
4096
	case "gre":
4097
		return 1476;
4098
		break;
4099
	case "gif":
4100
		return 1280;
4101
		break;
4102
	case "tun":
4103
	case "vlan":
4104
	case "tap":
4105
	case "ethernet":
4106
	default:
4107
		return 1500;
4108
		break;
4109
	}
4110

    
4111
	/* Never reached */
4112
	return 1500;
4113
}
4114

    
4115
function get_vip_descr($ipaddress) {
4116
	global $config;
4117

    
4118
	foreach ($config['virtualip']['vip'] as $vip) {
4119
		if ($vip['subnet'] == $ipaddress) {
4120
			return ($vip['descr']);
4121
		}
4122
	}
4123
	return "";
4124
}
4125

    
4126
function interfaces_staticarp_configure($if) {
4127
	global $config, $g;
4128
	if(isset($config['system']['developerspew'])) {
4129
		$mt = microtime();
4130
		echo "interfaces_staticarp_configure($if) being called $mt\n";
4131
	}
4132

    
4133
	$ifcfg = $config['interfaces'][$if];
4134

    
4135
	if (empty($if) || empty($ifcfg['if']))
4136
		return 0;
4137

    
4138
	/* Enable staticarp, if enabled */
4139
	if(isset($config['dhcpd'][$if]['staticarp'])) {
4140
		mwexec("/sbin/ifconfig " . escapeshellarg($ifcfg['if']) . " staticarp " );
4141
		mwexec("/usr/sbin/arp -d -i " . escapeshellarg($ifcfg['if']) . " -a > /dev/null 2>&1 ");
4142
		if (is_array($config['dhcpd'][$if]['staticmap'])) {
4143

    
4144
			foreach ($config['dhcpd'][$if]['staticmap'] as $arpent) {
4145
				mwexec("/usr/sbin/arp -s " . escapeshellarg($arpent['ipaddr']) . " " . escapeshellarg($arpent['mac']));
4146

    
4147
			}
4148

    
4149
		}
4150
	} else {
4151
		mwexec("/sbin/ifconfig " . escapeshellarg($ifcfg['if']) . " -staticarp " );
4152
		mwexec("/usr/sbin/arp -d -i " . escapeshellarg($ifcfg['if']) . " -a > /dev/null 2>&1 ");
4153
	}
4154

    
4155
	return 0;
4156
}
4157

    
4158
?>
(25-25/61)