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
	/* fire up dhcp6c for IPv6 first, this backgrounds immediately */
2965
	mwexec("/usr/local/sbin/dhcp6c -d -c {$g['varetc_path']}/dhcp6c_{$interface}.conf {$wanif}");
2966

    
2967
	return 0;
2968
}
2969

    
2970
function interface_dhcp_configure($interface = "wan") {
2971
	global $config, $g;
2972

    
2973
	$wancfg = $config['interfaces'][$interface];
2974
	$wanif = $wancfg['if'];
2975
	if (empty($wancfg))
2976
		$wancfg = array();
2977

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

    
2985
	if ($wancfg['dhcphostname']) {
2986
		$dhclientconf_hostname = "send dhcp-client-identifier \"{$wancfg['dhcphostname']}\";\n";
2987
		$dhclientconf_hostname .= "\tsend host-name \"{$wancfg['dhcphostname']}\";\n";
2988
	} else {
2989
		$dhclientconf_hostname = "";
2990
	}
2991

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

    
3009
EOD;
3010

    
3011
if(is_ipaddr($wancfg['alias-address'])) {
3012
	$subnetmask = gen_subnet_mask($wancfg['alias-subnet']);
3013
	$dhclientconf .= <<<EOD
3014
alias {
3015
	interface  "{$wanif}";
3016
	fixed-address {$wancfg['alias-address']};
3017
	option subnet-mask {$subnetmask};
3018
}
3019

    
3020
EOD;
3021
}
3022
	fwrite($fd, $dhclientconf);
3023
	fclose($fd);
3024

    
3025
	/* bring wan interface up before starting dhclient */
3026
	if($wanif)
3027
		interfaces_bring_up($wanif);
3028
	else 
3029
		log_error(printf(gettext("Could not bring up %s interface in interface_dhcp_configure()"), $wanif));
3030

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

    
3034
	return 0;
3035
}
3036

    
3037
function interfaces_group_setup() {
3038
	global $config;
3039

    
3040
	if (!is_array($config['ifgroups']['ifgroupentry']))
3041
		return;
3042

    
3043
	foreach ($config['ifgroups']['ifgroupentry'] as $groupar)
3044
		interface_group_setup($groupar);
3045

    
3046
	return;
3047
}
3048

    
3049
function interface_group_setup(&$groupname /* The parameter is an array */) {
3050
	global $config;
3051

    
3052
	if (!is_array($groupname))
3053
		return;
3054
	$members = explode(" ", $groupname['members']);
3055
	foreach($members as $ifs) {
3056
		$realif = get_real_interface($ifs);
3057
		if ($realif)
3058
			mwexec("/sbin/ifconfig {$realif} group {$groupname['ifname']}");
3059
	}
3060

    
3061
	return;
3062
}
3063

    
3064
function interface_group_add_member($interface, $groupname) {
3065
	$interface = get_real_interface($interface);
3066
	mwexec("/sbin/ifconfig {$interface} group {$groupname}", true);
3067
}
3068
 
3069
/* COMPAT Function */
3070
function convert_friendly_interface_to_real_interface_name($interface) {
3071
	return get_real_interface($interface);
3072
}
3073

    
3074
/* COMPAT Function */
3075
function get_real_wan_interface($interface = "wan") {
3076
	return get_real_interface($interface);
3077
}
3078

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

    
3084
/*
3085
 * convert_real_interface_to_friendly_interface_name($interface): convert fxp0 -> wan, etc.
3086
 */
3087
function convert_real_interface_to_friendly_interface_name($interface = "wan") {
3088
        global $config;
3089

    
3090
	if (stristr($interface, "vip")) {
3091
                $index = intval(substr($interface, 3));
3092
                foreach ($config['virtualip']['vip'] as $counter => $vip) {
3093
                        if ($vip['mode'] == "carpdev-dhcp" || $vip['mode'] == "carp")  {
3094
                                if ($index == $vip['vhid'])
3095
                                        return $vip['interface'];
3096
                        }
3097
                }
3098
        }
3099

    
3100
        /* XXX: For speed reasons reference directly the interface array */
3101
	$ifdescrs = &$config['interfaces'];
3102
        //$ifdescrs = get_configured_interface_list(false, true);
3103

    
3104
        foreach ($ifdescrs as $if => $ifname) {
3105
                if ($config['interfaces'][$if]['if'] == $interface)
3106
                        return $if;
3107

    
3108
                if (stristr($interface, "_wlan0") && $config['interfaces'][$if]['if'] == interface_get_wireless_base($interface))
3109
                        return $if;
3110

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

    
3122
/* attempt to resolve interface to friendly descr */
3123
function convert_friendly_interface_to_friendly_descr($interface) {
3124
        global $config;
3125

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

    
3170
        return $ifdesc;
3171
}
3172

    
3173
function convert_real_interface_to_friendly_descr($interface) {
3174
        global $config;
3175

    
3176
        $ifdesc = convert_real_interface_to_friendly_interface_name("{$interface}");
3177

    
3178
        if ($ifdesc) {
3179
                $iflist = get_configured_interface_with_descr(false, true);
3180
                return $iflist[$ifdesc];
3181
        }
3182

    
3183
        return $interface;
3184
}
3185

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

    
3198
	$parents = array();
3199
	//Check that we got a valid interface passed
3200
	$realif = get_real_interface($interface);
3201
	if ($realif == NULL)
3202
		return $parents;
3203

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

    
3246
function interface_is_wireless_clone($wlif) {
3247
	if(!stristr($wlif, "_wlan")) {
3248
		return false;
3249
	} else {
3250
		return true;
3251
	}
3252
}
3253

    
3254
function interface_get_wireless_base($wlif) {
3255
	if(!stristr($wlif, "_wlan")) {
3256
		return $wlif;
3257
	} else {
3258
		return substr($wlif, 0, stripos($wlif, "_wlan"));
3259
	}
3260
}
3261

    
3262
function interface_get_wireless_clone($wlif) {
3263
	if(!stristr($wlif, "_wlan")) {
3264
		return $wlif . "_wlan0";
3265
	} else {
3266
		return $wlif;
3267
	}
3268
}
3269

    
3270
function get_real_interface($interface = "wan") {
3271
    global $config;
3272

    
3273
	$wanif = NULL;
3274

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

    
3307
		$cfg = &$config['interfaces'][$interface];
3308

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

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

    
3349
    return $wanif;
3350
}
3351

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

    
3389
/*
3390
 * find_ip_interface($ip): return the interface where an ip is defined
3391
 */
3392
function find_ip_interface($ip)
3393
{
3394
        /* if list */
3395
        $ifdescrs = get_configured_interface_list();
3396

    
3397
        foreach ($ifdescrs as $ifdescr => $ifname) {
3398
		if ($ip == get_interface_ip($ifname)) {
3399
                	$int = get_real_interface($ifname);
3400
			return $int;
3401
		}
3402
        }
3403
        return false;
3404
}
3405

    
3406
/*
3407
 *   find_number_of_created_carp_interfaces: return the number of carp interfaces
3408
 */
3409
function find_number_of_created_carp_interfaces() {
3410
	return `/sbin/ifconfig | grep "carp:" | wc -l`;
3411
}
3412

    
3413
function get_all_carp_interfaces() {
3414
	$ints = str_replace("\n", " ", `ifconfig | grep "carp:" -B2 | grep ": flag" | cut -d: -f1`);
3415
	$ints = explode(" ", $ints);
3416
	return $ints;
3417
}
3418

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

    
3450
function link_carp_interface_to_parent($interface) {
3451
        global $config;
3452

    
3453
        if ($interface == "")
3454
                return;
3455

    
3456
        $carp_ip = get_interface_ip($interface);
3457
        if (!is_ipaddr($carp_ip))
3458
                return;
3459

    
3460
        /* if list */
3461
        $ifdescrs = get_configured_interface_list();
3462
        foreach ($ifdescrs as $ifdescr => $ifname) {
3463
                $interfaceip = get_interface_ip($ifname);
3464
                $subnet_bits = get_interface_subnet($ifname);
3465
                $subnet_ip = gen_subnet("{$interfaceip}", "{$subnet_bits}");
3466
                if(ip_in_subnet($carp_ip, "{$subnet_ip}/{$subnet_bits}"))
3467
                        return $ifname;
3468
        }
3469

    
3470
        return "";
3471
}
3472

    
3473
/****f* interfaces/link_ip_to_carp_interface
3474
 * NAME
3475
 *   link_ip_to_carp_interface - Find where a CARP interface links to.
3476
 * INPUTS
3477
 *   $ip
3478
 * RESULT
3479
 *   $carp_ints
3480
 ******/
3481
function link_ip_to_carp_interface($ip) {
3482
        global $config;
3483

    
3484
        if (!is_ipaddr($ip))
3485
                return;
3486

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

    
3504
        return $carp_ints;
3505
}
3506

    
3507
function link_interface_to_vlans($int, $action = "") {
3508
	global $config;
3509

    
3510
	if (empty($int))
3511
		return;
3512

    
3513
	if (is_array($config['vlans']['vlan'])) {
3514
                foreach ($config['vlans']['vlan'] as $vlan) {
3515
			if ($int == $vlan['if']) {
3516
				if ($action == "update") {
3517
					interfaces_bring_up($int);
3518
				} else if ($action == "")
3519
					return $vlan;
3520
			}
3521
		}
3522
	}
3523
}
3524

    
3525
function link_interface_to_vips($int, $action = "") {
3526
        global $config;
3527

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

    
3545
/****f* interfaces/link_interface_to_bridge
3546
 * NAME
3547
 *   link_interface_to_bridge - Finds out a bridge group for an interface
3548
 * INPUTS
3549
 *   $ip
3550
 * RESULT
3551
 *   bridge[0-99]
3552
 ******/
3553
function link_interface_to_bridge($int) {
3554
        global $config;
3555

    
3556
        if (is_array($config['bridges']['bridged'])) {
3557
                foreach ($config['bridges']['bridged'] as $bridge) {
3558
			if (in_array($int, explode(',', $bridge['members'])))
3559
                                return "{$bridge['bridgeif']}";
3560
		}
3561
	}
3562
}
3563

    
3564
function link_interface_to_group($int) {
3565
        global $config;
3566

    
3567
	$result = array();
3568

    
3569
        if (is_array($config['ifgroups']['ifgroupentry'])) {
3570
                foreach ($config['ifgroups']['ifgroupentry'] as $group) {
3571
			if (in_array($int, explode(" ", $group['members'])))
3572
				$result[$group['ifname']] = $int;
3573
		}
3574
	}
3575

    
3576
	return $result;
3577
}
3578

    
3579
function link_interface_to_gre($interface) {
3580
        global $config;
3581

    
3582
	$result = array();
3583

    
3584
        if (is_array($config['gres']['gre'])) {
3585
                foreach ($config['gres']['gre'] as $gre)
3586
                        if($gre['if'] == $interface)
3587
				$result[] = $gre;
3588
	}
3589

    
3590
	return $result;
3591
}
3592

    
3593
function link_interface_to_gif($interface) {
3594
        global $config;
3595

    
3596
	$result = array();
3597

    
3598
        if (is_array($config['gifs']['gif'])) {
3599
                foreach ($config['gifs']['gif'] as $gif)
3600
                        if($gif['if'] == $interface)
3601
                                $result[] = $gif;
3602
	}
3603

    
3604
	return $result;
3605
}
3606

    
3607
/*
3608
 * find_interface_ip($interface): return the interface ip (first found)
3609
 */
3610
function find_interface_ip($interface, $flush = false)
3611
{
3612
	global $interface_ip_arr_cache;
3613
	global $interface_sn_arr_cache;
3614

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

    
3620
	/* Setup IP cache */
3621
	if (!isset($interface_ip_arr_cache[$interface]) or $flush) {
3622
		$ifinfo = pfSense_get_interface_addresses($interface);
3623
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
3624
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
3625
	}
3626

    
3627
	return $interface_ip_arr_cache[$interface];
3628
}
3629

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

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

    
3667
	return $interface_ipv6_arr_cache[$interface];
3668
}
3669

    
3670
function find_interface_subnet($interface, $flush = false)
3671
{
3672
	global $interface_sn_arr_cache;
3673
	global $interface_ip_arr_cache;
3674

    
3675
	$interface = str_replace("\n", "", $interface);
3676
	if (does_interface_exist($interface) == false)
3677
		return;
3678

    
3679
	if (!isset($interface_sn_arr_cache[$interface]) or $flush) {
3680
		$ifinfo = pfSense_get_interface_addresses($interface);
3681
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
3682
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
3683
        }
3684

    
3685
	return $interface_sn_arr_cache[$interface];
3686
}
3687

    
3688
function find_interface_subnetv6($interface, $flush = false)
3689
{
3690
	global $interface_snv6_arr_cache;
3691
	global $interface_ipv6_arr_cache;
3692

    
3693
	$interface = str_replace("\n", "", $interface);
3694
	if (does_interface_exist($interface) == false)
3695
		return;
3696

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

    
3719
	return $interface_snv6_arr_cache[$interface];
3720
}
3721

    
3722
function ip_in_interface_alias_subnet($interface, $ipalias) {
3723
	global $config;
3724

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

    
3740
	return false;
3741
}
3742

    
3743
function get_interface_ip($interface = "wan")
3744
{
3745
	$realif = get_real_interface($interface);
3746
	if (!$realif) {
3747
		if (preg_match("/^carp/i", $interface))
3748
			$realif = $interface;
3749
		else if (preg_match("/^vip/i", $interface))
3750
			$realif = $interface;
3751
		else
3752
			return null;
3753
	}
3754

    
3755
	$curip = find_interface_ip($realif);
3756
	if ($curip && is_ipaddr($curip) && ($curip != "0.0.0.0"))
3757
		return $curip;
3758
	else
3759
		return null;
3760
}
3761

    
3762
function get_interface_ipv6($interface = "wan")
3763
{
3764
	$realif = get_real_interface($interface);
3765
	if (!$realif) {
3766
		if (preg_match("/^carp/i", $interface))
3767
			$realif = $interface;
3768
		else if (preg_match("/^vip/i", $interface))
3769
			$realif = $interface;
3770
		else
3771
			return null;
3772
	}
3773

    
3774
	$curip = find_interface_ipv6($realif);
3775
	if ($curip && is_ipaddrv6($curip) && ($curip != "::"))
3776
		return $curip;
3777
	else
3778
		return null;
3779
}
3780

    
3781
function get_interface_subnet($interface = "wan")
3782
{
3783
	$realif = get_real_interface($interface);
3784
	if (!$realif) {
3785
                if (preg_match("/^carp/i", $interface))
3786
                        $realif = $interface;
3787
                else if (preg_match("/^vip/i", $interface))
3788
                        $realif = $interface;
3789
                else
3790
                        return null;
3791
        }
3792

    
3793
	$cursn = find_interface_subnet($realif);
3794
	if (!empty($cursn))
3795
		return $cursn;
3796

    
3797
	return null;
3798
}
3799

    
3800
function get_interface_subnetv6($interface = "wan")
3801
{
3802
	$realif = get_real_interface($interface);
3803
	if (!$realif) {
3804
                if (preg_match("/^carp/i", $interface))
3805
                        $realif = $interface;
3806
                else if (preg_match("/^vip/i", $interface))
3807
                        $realif = $interface;
3808
                else
3809
                        return null;
3810
        }
3811

    
3812
	$cursn = find_interface_subnetv6($realif);
3813
	if (!empty($cursn))
3814
		return $cursn;
3815

    
3816
	return null;
3817
}
3818

    
3819
/* return outside interfaces with a gateway */
3820
function get_interfaces_with_gateway() {
3821
	global $config;
3822

    
3823
	$ints = array();
3824

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

    
3847
/* return true if interface has a gateway */
3848
function interface_has_gateway($friendly) {
3849
	global $config;
3850

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

    
3871
	return false;
3872
}
3873

    
3874
/* return true if interface has a gateway */
3875
function interface_has_gatewayv6($friendly) {
3876
	global $config;
3877

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

    
3893
	return false;
3894
}
3895

    
3896
/****f* interfaces/is_altq_capable
3897
 * NAME
3898
 *   is_altq_capable - Test if interface is capable of using ALTQ
3899
 * INPUTS
3900
 *   $int            - string containing interface name
3901
 * RESULT
3902
 *   boolean         - true or false
3903
 ******/
3904

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

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

    
3920
        if (in_array($int_family[0], $capable))
3921
                return true;
3922
	else if (stristr($int, "vlan")) /* VLANs are name $parent_$vlan now */
3923
		return true;
3924
	else if (stristr($int, "_wlan")) /* WLANs are name $parent_$wlan now */
3925
		return true;
3926
        else
3927
                return false;
3928
}
3929

    
3930
/****f* interfaces/is_interface_wireless
3931
 * NAME
3932
 *   is_interface_wireless - Returns if an interface is wireless
3933
 * RESULT
3934
 *   $tmp       - Returns if an interface is wireless
3935
 ******/
3936
function is_interface_wireless($interface) {
3937
        global $config, $g;
3938

    
3939
        $friendly = convert_real_interface_to_friendly_interface_name($interface);
3940
        if(!isset($config['interfaces'][$friendly]['wireless'])) {
3941
                if (preg_match($g['wireless_regex'], $interface)) {
3942
                        if (isset($config['interfaces'][$friendly]))
3943
                                $config['interfaces'][$friendly]['wireless'] = array();
3944
                        return true;
3945
                }
3946
                return false;
3947
        } else
3948
                return true;
3949
}
3950

    
3951
function get_wireless_modes($interface) {
3952
	/* return wireless modes and channels */
3953
	$wireless_modes = array();
3954

    
3955
	$cloned_interface = get_real_interface($interface);
3956

    
3957
	if($cloned_interface && is_interface_wireless($cloned_interface)) {
3958
		$chan_list = "/sbin/ifconfig {$cloned_interface} list chan";
3959
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
3960
		$format_list = "/usr/bin/awk '{print \$5 \" \" \$6 \",\" \$1}'";
3961

    
3962
		$interface_channels = "";
3963
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
3964
		$interface_channel_count = count($interface_channels);
3965

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

    
3996
/* return channel numbers, frequency, max txpower, and max regulation txpower */
3997
function get_wireless_channel_info($interface) {
3998
	$wireless_channels = array();
3999

    
4000
	$cloned_interface = get_real_interface($interface);
4001

    
4002
	if($cloned_interface && is_interface_wireless($cloned_interface)) {
4003
		$chan_list = "/sbin/ifconfig {$cloned_interface} list txpower";
4004
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
4005
		$format_list = "/usr/bin/awk '{print \$1 \",\" \$3 \" \" \$4 \",\" \$5 \",\" \$7}'";
4006

    
4007
		$interface_channels = "";
4008
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
4009

    
4010
		foreach ($interface_channels as $channel_line) {
4011
			$channel_line = explode(",", $channel_line);
4012
			if(!isset($wireless_channels[$channel_line[0]]))
4013
				$wireless_channels[$channel_line[0]] = $channel_line;
4014
		}
4015
	}
4016
	return($wireless_channels);
4017
}
4018

    
4019
/****f* interfaces/get_interface_mtu
4020
 * NAME
4021
 *   get_interface_mtu - Return the mtu of an interface
4022
 * RESULT
4023
 *   $tmp       - Returns the mtu of an interface
4024
 ******/
4025
function get_interface_mtu($interface) {
4026
        $mtu = pfSense_get_interface_addresses($interface);
4027
        return $mtu['mtu'];
4028
}
4029

    
4030
function get_interface_mac($interface) {
4031

    
4032
	$macinfo = pfSense_get_interface_addresses($interface);
4033
	return $macinfo["macaddr"];
4034
}
4035

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

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

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

    
4064
        if (in_array($int_family[0], $g['vlan_long_frame']))
4065
                return true;
4066
        else
4067
                return false;
4068
}
4069

    
4070
function setup_pppoe_reset_file($pppif, $iface="") {
4071
	global $g;
4072
	$cron_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
4073

    
4074
	if(!empty($iface) && !empty($pppif)){
4075
		$cron_cmd = <<<EOD
4076
#!/bin/sh
4077
/usr/local/sbin/pfSctl -c 'interface reload {$iface}'
4078
/usr/bin/logger -t pppoe{$iface} "PPPoE periodic reset executed on {$iface}"
4079

    
4080
EOD;
4081

    
4082
		file_put_contents($cron_file, $cron_cmd);
4083
		chmod($cron_file, 0700);
4084
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
4085
	} else
4086
		unlink_if_exists($cron_file);
4087
}
4088

    
4089
function get_interface_default_mtu($type = "ethernet") {
4090
	switch ($type) {
4091
	case "gre":
4092
		return 1476;
4093
		break;
4094
	case "gif":
4095
		return 1280;
4096
		break;
4097
	case "tun":
4098
	case "vlan":
4099
	case "tap":
4100
	case "ethernet":
4101
	default:
4102
		return 1500;
4103
		break;
4104
	}
4105

    
4106
	/* Never reached */
4107
	return 1500;
4108
}
4109

    
4110
function get_vip_descr($ipaddress) {
4111
	global $config;
4112

    
4113
	foreach ($config['virtualip']['vip'] as $vip) {
4114
		if ($vip['subnet'] == $ipaddress) {
4115
			return ($vip['descr']);
4116
		}
4117
	}
4118
	return "";
4119
}
4120

    
4121
function interfaces_staticarp_configure($if) {
4122
	global $config, $g;
4123
	if(isset($config['system']['developerspew'])) {
4124
		$mt = microtime();
4125
		echo "interfaces_staticarp_configure($if) being called $mt\n";
4126
	}
4127

    
4128
	$ifcfg = $config['interfaces'][$if];
4129

    
4130
	if (empty($if) || empty($ifcfg['if']))
4131
		return 0;
4132

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

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

    
4142
			}
4143

    
4144
		}
4145
	} else {
4146
		mwexec("/sbin/ifconfig " . escapeshellarg($ifcfg['if']) . " -staticarp " );
4147
		mwexec("/usr/sbin/arp -d -i " . escapeshellarg($ifcfg['if']) . " -a > /dev/null 2>&1 ");
4148
	}
4149

    
4150
	return 0;
4151
}
4152

    
4153
?>
(25-25/61)