Project

General

Profile

Download (138 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("util.inc");
48
require_once("gwlb.inc");
49

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

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

    
65
        /* If the cache doesn't exist, build it */
66
        if (!isset($interface_arr_cache) or $flush)
67
                $interface_arr_cache = pfSense_interface_listget();
68

    
69
        return $interface_arr_cache;
70
}
71

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

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

    
89
/*
90
 * does_vip_exist($vip): return true or false if a vip is
91
 * configured.
92
 */
93
function does_vip_exist($vip) {
94
	global $config;
95
	
96
	if(!$vip)
97
		return false;
98

    
99

    
100
	switch ($vip['mode']) {
101
	case "carp":
102
		$realif = "{$vip['interface']}_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_configure 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_configure 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_qinq2_configure 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 (isset($config['wireless']['clone']) && 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

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

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

    
429
function interface_bridge_configure(&$bridge, $checkmember = 0) {
430
	global $config, $g;
431

    
432
	if (!is_array($bridge))
433
	        return -1;
434

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

    
440
	$members = explode(',', $bridge['members']);
441
	if (!count($members))
442
		return -1;
443

    
444
	/* Calculate smaller mtu and enforce it */
445
	$smallermtu = 0;
446
	$commonrx = true;
447
	$commontx = true;
448
	$foundgif = false;
449
	foreach ($members as $member) {
450
		$realif = get_real_interface($member);
451
		$opts = pfSense_get_interface_addresses($realif);
452
		$mtu = $opts['mtu'];
453
		if (substr($realif, 0, 3) == "gif") {
454
			$foundgif = true;
455
			if ($checkmember == 1)
456
				return;
457
			if ($mtu <= 1500)
458
				continue;
459
		}
460
		if (!isset($opts['encaps']['txcsum']))
461
			$commontx = false;
462
		if (!isset($opts['encaps']['rxcsum']))
463
			$commonrx = false;
464
		if (!isset($opts['encaps']['tso4']))
465
			$commontso4 = false;
466
		if (!isset($opts['encaps']['tso6']))
467
			$commontso6 = false;
468
		if (!isset($opts['encaps']['lro']))
469
			$commonlro = false;
470
		if ($smallermtu == 0 && !empty($mtu))
471
			$smallermtu = $mtu;
472
		else if (!empty($mtu) && $mtu < $smallermtu)
473
			$smallermtu = $mtu;
474
	}
475
	if ($foundgif == false && $checkmember == 2)
476
		return;
477

    
478
	/* Just in case anything is not working well */
479
	if ($smallermtu == 0)
480
		$smallermtu = 1500; 
481

    
482
	$flags = 0;
483
	if ($commonrx === false)
484
		$flags |= IFCAP_RXCSUM;
485
	if ($commontx === false)
486
		$flags |= IFCAP_TXCSUM;
487
	if ($commontso4 === false)
488
		$flags |= IFCAP_TSO4;
489
	if ($commontso6 === false)
490
		$flags |= IFCAP_TSO6;
491
	if ($commonlro === false)
492
		$flags |= IFCAP_LRO;
493

    
494
	if ($g['booting'] || !empty($bridge['bridgeif'])) {
495
		pfSense_interface_destroy($bridge['bridgeif']);
496
		pfSense_interface_create($bridge['bridgeif']);
497
		$bridgeif = $bridge['bridgeif'];
498
	} else
499
		$bridgeif = pfSense_interface_create("bridge");
500

    
501
	$checklist = get_configured_interface_list();
502

    
503
	/* Add interfaces to bridge */
504
	foreach ($members as $member) {
505
		if (!array_key_exists($member, $checklist))
506
			continue;
507
		$realif1 = get_real_interface($member);
508
		$realif =  escapeshellarg($realif1);
509
		if (!$realif) {
510
			log_error(gettext("realif not defined in interfaces bridge - up"));
511
			continue;
512
		}
513
		/* make sure the parent interface is up */
514
		pfSense_interface_mtu($realif1, $smallermtu);
515
		pfSense_interface_capabilities($realif1, -$flags);
516
		interfaces_bring_up($realif1);
517
		pfSense_bridge_add_member($bridgeif, $realif1);
518
	}
519

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

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

    
620
	if($bridgeif)
621
		interfaces_bring_up($bridgeif);	
622
	else 
623
		log_error(gettext("bridgeif not defined -- could not bring interface up"));
624

    
625
	return $bridgeif;
626
}
627

    
628
function interface_bridge_add_member($bridgeif, $interface) {
629

    
630
	if (!does_interface_exist($bridgeif) || !does_interface_exist($interface))
631
		return;
632

    
633
	$mtu = get_interface_mtu($bridgeif);
634
	$mtum = get_interface_mtu($interface);
635
	
636
	if ($mtu != $mtum && !(substr($interface, 0, 3) == "gif" && $mtu <= 1500))
637
		pfSense_interface_mtu($interface, $mtu);
638

    
639
	$options = pfSense_get_interface_addresses($bridgeif);
640
	$flags = 0;
641
	if (!isset($options['encaps']['txcsum']))
642
		$flags |= IFCAP_TXCSUM;
643

    
644
	if (!isset($options['encaps']['rxcsum']))
645
		$flags |= IFCAP_RXCSUM;
646

    
647
	pfSense_interface_capabilities($interface, -$flags);
648

    
649
	interfaces_bring_up($interface);
650
	pfSense_bridge_add_member($bridgeif, $interface);
651
}
652

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

    
672
function interface_lagg_configure(&$lagg) {
673
        global $config, $g;
674

    
675
        if (!is_array($lagg))
676
		return -1;
677

    
678
	$members = explode(',', $lagg['members']);
679
	if (!count($members))
680
		return -1;
681
	
682
	if ($g['booting'] || !(empty($lagg['laggif']))) {
683
		pfSense_interface_destroy($lagg['laggif']);
684
		pfSense_interface_create($lagg['laggif']);
685
                $laggif = $lagg['laggif'];
686
        } else
687
		$laggif = pfSense_interface_create("lagg");
688

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

    
710
	/* Just in case anything is not working well */
711
        if ($smallermtu == 0)
712
                $smallermtu = 1500;
713

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

    
726
	$checklist = get_interface_list();
727

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

    
740
	interfaces_bring_up($laggif);
741

    
742
	return $laggif;
743
}
744

    
745
function interfaces_gre_configure($checkparent = 0) {
746
        global $config;
747

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

    
762
/* NOTE: $grekey is not used but useful for passing this function to array_walk. */
763
function interface_gre_configure(&$gre, $grekey = "") {
764
        global $config, $g;
765

    
766
	if (!is_array($gre))
767
		return -1;
768

    
769
	$realif = get_real_interface($gre['if']);
770
	$realifip = get_interface_ip($gre['if']);
771

    
772
	/* make sure the parent interface is up */
773
	interfaces_bring_up($realif);
774

    
775
	if ($g['booting'] || !(empty($gre['greif']))) {
776
		pfSense_interface_destroy($gre['greif']);
777
		pfSense_interface_create($gre['greif']);
778
		$greif = $gre['greif'];
779
	} else
780
		$greif = pfSense_interface_create("gre");
781

    
782
	/* Do not change the order here for more see gre(4) NOTES section. */
783
	mwexec("/sbin/ifconfig {$greif} tunnel {$realifip} {$gre['remote-addr']}");
784
	if((is_ipaddrv6($gre['tunnel-local-addr'])) || (is_ipaddrv6($gre['tunnel-remote-addr']))) {
785
		mwexec("/sbin/ifconfig {$greif} inet6 {$gre['tunnel-local-addr']} {$gre['tunnel-remote-addr']} prefixlen /{$gre['tunnel-remote-net']} ");
786
	} else {
787
		mwexec("/sbin/ifconfig {$greif} {$gre['tunnel-local-addr']} {$gre['tunnel-remote-addr']} netmask " . gen_subnet_mask($gre['tunnel-remote-net']));
788
	}
789
	if (isset($gre['link0']) && $gre['link0'])
790
		pfSense_interface_flags($greif, IFF_LINK0);
791
	if (isset($gre['link1']) && $gre['link1'])
792
		pfSense_interface_flags($greif, IFF_LINK1);
793
	if (isset($gre['link2']) && $gre['link2'])
794
		pfSense_interface_flags($greif, IFF_LINK2);
795

    
796
	if($greif)
797
		interfaces_bring_up($greif);
798
	else 
799
		log_error(gettext("Could not bring greif up -- variable not defined."));
800

    
801
	if (isset($gre['link1']) && $gre['link1'])
802
		mwexec("/sbin/route add {$gre['tunnel-remote-addr']}/{$gre['tunnel-remote-net']} {$gre['tunnel-local-addr']}");
803
	if(is_ipaddrv4($gre['tunnel-remote-addr']))
804
		file_put_contents("{$g['tmp_path']}/{$greif}_router", $gre['tunnel-remote-addr']);
805
	if(is_ipaddrv6($gre['tunnel-remote-addr']))
806
		file_put_contents("{$g['tmp_path']}/{$greif}_routerv6", $gre['tunnel-remote-addr']);
807

    
808
	return $greif;
809
}
810

    
811
function interfaces_gif_configure($checkparent = 0) {
812
	global $config;
813

    
814
	if (is_array($config['gifs']['gif']) && count($config['gifs']['gif'])) {
815
		foreach ($config['gifs']['gif'] as $i => $gif) {
816
			if(empty($gif['gifif']))
817
				$gre['gifif'] = "gif{$i}";
818
			if ($checkparent == 1 && strstr($gif['if'], "_vip"))
819
				continue;
820
			if ($checkparent == 2 && !strstr($gif['if'], "_vip"))
821
				continue;
822
			/* XXX: Maybe we should report any errors?! */
823
			interface_gif_configure($gif);
824
		}
825
	}
826
}
827

    
828
/* NOTE: $gifkey is not used but useful for passing this function to array_walk. */
829
function interface_gif_configure(&$gif, $gifkey = "") {
830
	global $config, $g;
831

    
832
	if (!is_array($gif))
833
		return -1;
834

    
835
	$realif = get_real_interface($gif['if']);
836
	$ipaddr = $gif['ipaddr'];
837

    
838
	if (is_ipaddrv4($gif['remote-addr'])) {
839
		if (is_ipaddrv4($ipaddr))
840
			$realifip = $ipaddr;
841
		else
842
			$realifip = get_interface_ip($gif['if']);
843
		$realifgw = get_interface_gateway($gif['if']);
844
	} else if (is_ipaddrv6($gif['remote-addr'])) {
845
		if (is_ipaddrv6($ipaddr))
846
			$realifip = $ipaddr;
847
		else
848
			$realifip = get_interface_ipv6($gif['if']);
849
		$realifgw = get_interface_gatewayv6($gif['if']);
850
	}
851
	/* make sure the parent interface is up */
852
	if($realif)
853
		interfaces_bring_up($realif);
854
	else 
855
		log_error(gettext("could not bring realif up -- variable not defined -- interface_gif_configure()"));
856

    
857
	if ($g['booting'] || !(empty($gif['gifif']))) {
858
		pfSense_interface_destroy($gif['gifif']);
859
		pfSense_interface_create($gif['gifif']);
860
		$gifif = $gif['gifif'];
861
	} else
862
		$gifif = pfSense_interface_create("gif");
863

    
864
	/* Do not change the order here for more see gif(4) NOTES section. */
865
	mwexec("/sbin/ifconfig {$gifif} tunnel {$realifip} {$gif['remote-addr']}");
866
	if((is_ipaddrv6($gif['tunnel-local-addr'])) || (is_ipaddrv6($gif['tunnel-remote-addr']))) {
867
		mwexec("/sbin/ifconfig {$gifif} inet6 {$gif['tunnel-local-addr']} {$gif['tunnel-remote-addr']} prefixlen /{$gif['tunnel-remote-net']} ");
868
	} else {
869
		mwexec("/sbin/ifconfig {$gifif} {$gif['tunnel-local-addr']} {$gif['tunnel-remote-addr']} netmask " . gen_subnet_mask($gif['tunnel-remote-net']));
870
	}
871
	if (isset($gif['link0']) && $gif['link0'])
872
		pfSense_interface_flags($gifif, IFF_LINK0);
873
	if (isset($gif['link1']) && $gif['link1'])
874
		pfSense_interface_flags($gifif, IFF_LINK1);
875
	if($gifif)
876
		interfaces_bring_up($gifif);
877
	else
878
		log_error(gettext("could not bring gifif up -- variable not defined"));
879

    
880
	$iflist = get_configured_interface_list();
881
	foreach($iflist as $ifname) {
882
		if($config['interfaces'][$ifname]['if'] == $gifif) {
883
			if(get_interface_gateway($ifname)) {
884
				system_routing_configure($ifname);
885
				break;
886
			}
887
			if(get_interface_gateway_v6($ifname)) {
888
				system_routing_configure($ifname);
889
				break;
890
			}
891
		}
892
	}
893

    
894

    
895
	if(is_ipaddrv4($gif['tunnel-remote-addr']))
896
		file_put_contents("{$g['tmp_path']}/{$gifif}_router", $gif['tunnel-remote-addr']);
897
	if(is_ipaddrv6($gif['tunnel-remote-addr']))
898
		file_put_contents("{$g['tmp_path']}/{$gifif}_routerv6", $gif['tunnel-remote-addr']);
899

    
900
        if (is_ipaddrv4($realifgw)) {
901
                mwexec("route change -host {$gif['remote-addr']} {$realifgw}");
902
        }
903
        if (is_ipaddrv6($realifgw)) {
904
                mwexec("route change -host -inet6 {$gif['remote-addr']} {$realifgw}");
905
        }
906

    
907
	return $gifif;
908
}
909

    
910
function interfaces_configure() {
911
	global $config, $g;
912

    
913
	if ($g['platform'] == 'jail')
914
		return;
915

    
916
	/* Set up our loopback interface */
917
	interfaces_loopback_configure();
918

    
919
	/* set up LAGG virtual interfaces */
920
	interfaces_lagg_configure();
921

    
922
	/* set up VLAN virtual interfaces */
923
	interfaces_vlan_configure();
924

    
925
	interfaces_qinq_configure();
926

    
927
	$iflist = get_configured_interface_with_descr();
928
	$delayed_list = array();
929
	$bridge_list = array();
930
	
931
	/* This is needed to speedup interfaces on bootup. */
932
	$reload = false;
933
	if (!$g['booting'])
934
		$reload = true;
935

    
936
	foreach($iflist as $if => $ifname) {
937
		$realif = $config['interfaces'][$if]['if'];
938
		if (strstr($realif, "bridge")) 
939
			$bridge_list[$if] = $ifname;
940
		else if (strstr($realif, "gre"))
941
			$delayed_list[$if] = $ifname;
942
		else if (strstr($realif, "gif"))
943
			$delayed_list[$if] = $ifname;
944
		else if (strstr($realif, "ovpn")) {
945
			//echo "Delaying OpenVPN interface configuration...done.\n";
946
			continue;
947
		} else {
948
			if ($g['booting'])
949
				printf(gettext("Configuring %s interface..."), $ifname);
950

    
951
			if($g['debug'])
952
				log_error(sprintf(gettext("Configuring %s"), $ifname));
953
			interface_configure($if, $reload);
954
			if ($g['booting']) 
955
				echo gettext( "done.") . "\n";
956
		}
957
	}
958

    
959
	/* create the unconfigured wireless clones */
960
	interfaces_create_wireless_clones();
961

    
962
	/*
963
	 * NOTE: The following function parameter consists of
964
	 *	1 - Do not load gre/gif/bridge with parent/member as vip
965
	 *	2 - Do load gre/gif/bridge with parent/member as vip
966
	 */
967

    
968
	/* set up GRE virtual interfaces */
969
	interfaces_gre_configure(1);
970

    
971
	/* set up GIF virtual interfaces */
972
	interfaces_gif_configure(1);
973

    
974
	/* set up BRIDGe virtual interfaces */
975
	interfaces_bridge_configure(1);
976

    
977
	/* bring up vip interfaces */
978
	interfaces_vips_configure();
979

    
980
	/* set up GRE virtual interfaces */
981
	interfaces_gre_configure(2);
982

    
983
	/* set up GIF virtual interfaces */
984
	interfaces_gif_configure(2);
985

    
986
	foreach ($delayed_list as $if => $ifname) {
987
		if ($g['booting'])
988
			printf(gettext("Configuring %s interface..."), $ifname);
989
        	if ($g['debug'])
990
        		log_error(sprintf(gettext("Configuring %s"), $ifname));
991

    
992
		interface_configure($if, $reload);
993

    
994
		if ($g['booting'])
995
			echo gettext("done.") . "\n";
996
	}
997

    
998
	/* set up BRIDGe virtual interfaces */
999
	interfaces_bridge_configure(2);
1000

    
1001
	foreach ($bridge_list as $if => $ifname) {
1002
		if ($g['booting'])
1003
			printf(gettext("Configuring %s interface..."), $ifname);
1004
		if($g['debug'])
1005
			log_error(sprintf(gettext("Configuring %s"), $ifname));
1006

    
1007
		interface_configure($if, $reload);
1008

    
1009
		if ($g['booting'])
1010
			echo gettext("done.") . "\n";
1011
	}
1012

    
1013
	/* configure interface groups */
1014
	interfaces_group_setup();
1015

    
1016
	if (!$g['booting']) {
1017
		/* reconfigure static routes (kernel may have deleted them) */
1018
		system_routing_configure();
1019

    
1020
		/* reload IPsec tunnels */
1021
		vpn_ipsec_configure();
1022

    
1023
		/* reload dhcpd (interface enabled/disabled status may have changed) */
1024
		services_dhcpd_configure();
1025

    
1026
		/* restart dnsmasq */
1027
		services_dnsmasq_configure();
1028

    
1029
		/* reload captive portal */
1030
		if (function_exists('captiveportal_init_rules'))
1031
			captiveportal_init_rules();
1032
	}
1033

    
1034
	return 0;
1035
}
1036

    
1037
function interface_reconfigure($interface = "wan", $reloadall = false) {
1038
	interface_bring_down($interface);
1039
	interface_configure($interface, $reloadall);
1040
}
1041

    
1042
function interface_vip_bring_down($vip) {
1043
	global $g;
1044

    
1045
	switch ($vip['mode']) {
1046
	case "proxyarp":
1047
		$vipif = get_real_interface($vip['interface']);
1048
		if (file_exists("{$g['varrun_path']}/choparp_{$vipif}.pid"))
1049
			killbypid("{$g['varrun_path']}/choparp_{$vipif}.pid");
1050
		break;
1051
	case "ipalias":
1052
		$vipif = get_real_interface($vip['interface']);
1053
		if(does_interface_exist($vipif))
1054
			pfSense_interface_deladdress($vipif, $vip['subnet']);
1055
		break;
1056
	case "carp":
1057
		$vipif = "{$vip['interface']}_vip{$vip['vhid']}";
1058
		if (does_interface_exist($vipif)) 
1059
			pfSense_interface_destroy($vipif);
1060
		break;
1061
	}
1062
}
1063

    
1064
function interface_bring_down($interface = "wan", $destroy = false) {
1065
	global $config, $g;
1066

    
1067
	if (!isset($config['interfaces'][$interface]))
1068
		return; 
1069
	log_error("Calling interface down for interface {$interface}, destroy is " . (($destroy) ? 'true' : 'false'));
1070

    
1071
	$ifcfg = $config['interfaces'][$interface];
1072

    
1073
	$realif = get_real_interface($interface);
1074

    
1075
	switch ($ifcfg['ipaddr']) {
1076
	case "ppp":
1077
	case "pppoe":
1078
	case "pptp":
1079
	case "l2tp":
1080
		if (is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) {
1081
			foreach ($config['ppps']['ppp'] as $pppid => $ppp) {
1082
				if ($realif == $ppp['if']) {
1083
					if (isset($ppp['ondemand']) && !$destroy){
1084
						send_event("interface reconfigure {$interface}");
1085
						break;
1086
					}
1087
					if (file_exists("{$g['varrun_path']}/{$ppp['type']}_{$interface}.pid")) {
1088
						killbypid("{$g['varrun_path']}/{$ppp['type']}_{$interface}.pid");
1089
						sleep(2);
1090
					}
1091
					unlink_if_exists("{$g['varetc_path']}/mpd_{$interface}.conf");
1092
					break;
1093
				}
1094
			}
1095
		}
1096
		break;
1097
	case "dhcp":
1098
		$pid = find_dhclient_process($realif);
1099
		if($pid)
1100
			mwexec("/bin/kill {$pid}");
1101
		sleep(1);
1102
		unlink_if_exists("{$g['varetc_path']}/dhclient_{$interface}.conf");
1103
		if(does_interface_exist("$realif")) {
1104
			mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete", true);
1105
			if ($destroy == true)
1106
				pfSense_interface_flags($realif, -IFF_UP);
1107
			mwexec("/usr/sbin/arp -d -i {$realif} -a");
1108
		}
1109
		break;
1110
	default:
1111
		if(does_interface_exist("$realif")) {
1112
			mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete", true);
1113
			if ($destroy == true)
1114
				pfSense_interface_flags($realif, -IFF_UP);
1115
			mwexec("/usr/sbin/arp -d -i {$realif} -a");
1116
		}
1117
		break;
1118
	}
1119

    
1120
	switch ($ifcfg['ipaddrv6']) {
1121
	case "slaac":
1122
	case "dhcp6":
1123
		$pidv6 = find_dhcp6c_process($realif);
1124
		if($pidv6)
1125
			mwexec("/bin/kill {$pidv6}");
1126
		sleep(3);
1127
		unlink_if_exists("{$g['varetc_path']}/dhcp6c_{$interface}.conf");
1128
		if(does_interface_exist("$realif")) {
1129
			$ip6 = get_interface_ipv6($interface);
1130
			if (is_ipaddrv6($ip6))
1131
				mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 {$ip6} delete", true);
1132
			if ($destroy == true)
1133
				pfSense_interface_flags($realif, -IFF_UP);
1134
			mwexec("/usr/sbin/arp -d -i {$realif} -a");
1135
		}
1136
		break;
1137
	case "6rd":
1138
	case "6to4":
1139
		$realif = "stf0";
1140
		if(does_interface_exist("$realif")) {
1141
			$ip6 = get_interface_ipv6($interface);
1142
			if (is_ipaddrv6($ip6))
1143
				mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 {$ip6} delete", true);
1144
			if ($destroy == true)
1145
				pfSense_interface_flags($realif, -IFF_UP);
1146
		}		
1147
		break;
1148
	default:
1149
		if(does_interface_exist("$realif")) {
1150
			$ip6 = get_interface_ipv6($interface);
1151
			if (is_ipaddrv6($ip6))
1152
				mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 {$ip6} delete", true);
1153
			if ($destroy == true)
1154
				pfSense_interface_flags($realif, -IFF_UP);
1155
			mwexec("/usr/sbin/arp -d -i {$realif} -a");
1156
		}
1157
		break;
1158
	}
1159

    
1160
	if (file_exists("{$g['tmp_path']}/{$realif}_router"))
1161
		$old_router = trim(file_get_contents("{$g['tmp_path']}/{$realif}_router"));
1162
//	log_error("Checking for old router states: {$g['tmp_path']}/{$realif}_router = {$old_router}");
1163
	if (!empty($old_router)) {
1164
		log_error("Clearing states to old gateway {$old_router}.");
1165
		mwexec("/sbin/pfctl -b 0.0.0.0/32 -b {$old_router}/32");
1166
	}
1167

    
1168
	/* remove interface up file if it exists */
1169
	unlink_if_exists("{$g['tmp_path']}/{$realif}up");
1170
	unlink_if_exists("{$g['vardb_path']}/{$interface}ip");
1171
	unlink_if_exists("{$g['vardb_path']}/{$interface}ipv6");
1172
	unlink_if_exists("{$g['tmp_path']}/{$realif}_router");
1173
	unlink_if_exists("{$g['tmp_path']}/{$realif}_routerv6");
1174
	unlink_if_exists("{$g['varetc_path']}/nameserver_{$realif}");
1175
	unlink_if_exists("{$g['varetc_path']}/searchdomain_{$realif}");
1176
	
1177
	/* hostapd and wpa_supplicant do not need to be running when the interface is down.
1178
	 * They will also use 100% CPU if running after the wireless clone gets deleted. */
1179
	if (is_array($ifcfg['wireless'])) {
1180
		mwexec(kill_hostapd($realif));
1181
		mwexec(kill_wpasupplicant($realif));
1182
	}
1183

    
1184
	if ($destroy == true) {
1185
		if (preg_match("/^[a-z0-9]+_vip|^tun|^ovpn|^gif|^gre|^lagg|^bridge|vlan|^stf/i", $realif))
1186
			pfSense_interface_destroy($realif);
1187
	}	
1188

    
1189
	return;
1190
}
1191

    
1192
function interfaces_ptpid_used($ptpid) {
1193
	global $config;
1194

    
1195
	if (is_array($config['ppps']['ppp']))
1196
		foreach ($config['ppps']['ppp'] as & $settings)
1197
			if ($ptpid == $settings['ptpid'])
1198
				return true;
1199

    
1200
	return false;
1201
}
1202

    
1203
function interfaces_ptpid_next() {
1204

    
1205
	$ptpid = 0;
1206
	while(interfaces_ptpid_used($ptpid))
1207
		$ptpid++;
1208

    
1209
	return $ptpid;
1210
}
1211

    
1212
function getMPDCRONSettings($pppif) {
1213
	global $config;
1214

    
1215
	$cron_cmd_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
1216
	if (is_array($config['cron']['item'])) {
1217
		foreach ($config['cron']['item'] as $i => $item) {
1218
			if (stripos($item['command'], $cron_cmd_file) !== false)
1219
				return array("ID" => $i, "ITEM" => $item);
1220
		}
1221
	}
1222

    
1223
	return NULL;
1224
}
1225

    
1226
function handle_pppoe_reset($post_array) {
1227
	global $config, $g;
1228

    
1229
	$pppif = "{$post_array['type']}{$post_array['ptpid']}";
1230
	$cron_cmd_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
1231

    
1232
	if (!is_array($config['cron']['item'])) 
1233
		$config['cron']['item'] = array(); 
1234

    
1235
	$itemhash = getMPDCRONSettings($pppif);
1236
	
1237
	// reset cron items if necessary and return
1238
	if (empty($post_array['pppoe-reset-type'])) {
1239
		if (isset($itemhash))
1240
			unset($config['cron']['item'][$itemhash['ID']]);
1241
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
1242
		return;
1243
	}
1244

    
1245
	if (empty($itemhash)) 
1246
		$itemhash = array();
1247
	$item = array();
1248
	if (isset($post_array['pppoe-reset-type']) && $post_array['pppoe-reset-type'] == "custom") {
1249
		$item['minute'] = $post_array['pppoe_resetminute'];
1250
		$item['hour'] = $post_array['pppoe_resethour'];
1251
		if (isset($post_array['pppoe_resetdate']) && $post_array['pppoe_resetdate'] <> "") {
1252
			$date = explode("/", $post_array['pppoe_resetdate']);
1253
			$item['mday'] = $date[1];
1254
			$item['month'] = $date[0];
1255
		} else {
1256
			$item['mday'] = "*";
1257
			$item['month'] = "*";
1258
		}
1259
		$item['wday'] = "*";
1260
		$item['who'] = "root";
1261
		$item['command'] = $cron_cmd_file;
1262
	} else if (isset($post_array['pppoe-reset-type']) && $post_array['pppoe-reset-type'] == "preset") {
1263
		switch ($post_array['pppoe_pr_preset_val']) {
1264
		case "monthly":
1265
			$item['minute'] = "0";
1266
			$item['hour'] = "0";
1267
			$item['mday'] = "1";
1268
			$item['month'] = "*";
1269
			$item['wday'] = "*";
1270
			break;
1271
	        case "weekly":
1272
			$item['minute'] = "0";
1273
			$item['hour'] = "0";
1274
			$item['mday'] = "*";
1275
			$item['month'] = "*";
1276
			$item['wday'] = "0";
1277
			break;
1278
		case "daily":
1279
			$item['minute'] = "0";
1280
			$item['hour'] = "0";
1281
			$item['mday'] = "*";
1282
			$item['month'] = "*";
1283
			$item['wday'] = "*";
1284
			break;
1285
		case "hourly":
1286
			$item['minute'] = "0";
1287
			$item['hour'] = "*";
1288
			$item['mday'] = "*";
1289
			$item['month'] = "*";
1290
			$item['wday'] = "*";
1291
			break;
1292
		} // end switch
1293
		$item['who'] = "root";
1294
		$item['command'] = $cron_cmd_file;
1295
	}
1296
	if (empty($item))
1297
		return;
1298
	if (isset($item['ID'])) 
1299
		$config['cron']['item'][$item['ID']] = $item;
1300
	else 
1301
		$config['cron']['item'][] = $item;
1302
}
1303

    
1304
/*
1305
 * This function can configure PPPoE, MLPPP (PPPoE), PPTP.
1306
 * It writes the mpd config file to /var/etc every time the link is opened.
1307
 */
1308
function interface_ppps_configure($interface) {
1309
	global $config, $g;
1310

    
1311
	/* Return for unassigned interfaces. This is a minimum requirement. */
1312
	if (empty($config['interfaces'][$interface]))
1313
		return 0;
1314
	$ifcfg = $config['interfaces'][$interface];
1315
	if (!isset($ifcfg['enable']))
1316
		return 0;
1317

    
1318
	// mpd5 requires a /var/spool/lock directory for PPP modem links.
1319
	if(!is_dir("/var/spool/lock")) {
1320
		exec("/bin/mkdir -p /var/spool/lock");
1321
		exec("/bin/chmod a+rw /var/spool/lock/.");
1322
	}
1323
	// mpd5 modem chat script expected in the same directory as the mpd_xxx.conf files
1324
	if (!file_exists("{$g['varetc_path']}/mpd.script"))
1325
		mwexec("/bin/ln -s /usr/local/sbin/mpd.script {$g['varetc_path']}/.");
1326

    
1327
	if (is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) {
1328
		foreach ($config['ppps']['ppp'] as $pppid => $ppp) {
1329
			if ($ifcfg['if'] == $ppp['if'])
1330
				break;
1331
		}
1332
	}
1333
	if (!$ppp || $ifcfg['if'] != $ppp['if']){
1334
		log_error(sprintf(gettext("Can't find PPP config for %s in interface_ppps_configure()."), $ifcfg['if']));
1335
		return 0;
1336
	}
1337
	$pppif = $ifcfg['if'];
1338
	if ($ppp['type'] == "ppp")
1339
		$type = "modem";
1340
	else
1341
		$type = $ppp['type'];
1342
	$upper_type = strtoupper($ppp['type']);	
1343

    
1344
	if($g['booting']) {
1345
		$descr = isset($ifcfg['descr']) ? $ifcfg['descr'] : strtoupper($interface);
1346
		echo "starting {$pppif} link...";
1347
		// Do not re-configure the interface if we are booting and it's already been started
1348
		if(file_exists("{$g['varrun_path']}/{$ppp['type']}_{$interface}.pid"))
1349
			return 0;
1350
	}
1351

    
1352
	$ports = explode(',',$ppp['ports']);
1353
	if ($type != "modem") {
1354
		foreach ($ports as $pid => $port)
1355
			$ports[$pid] = get_real_interface($port);
1356
	}
1357
	$localips = explode(',',$ppp['localip']);
1358
	$gateways = explode(',',$ppp['gateway']);
1359
	$subnets = explode(',',$ppp['subnet']);
1360

    
1361
	/* We bring up the parent interface first because if DHCP is configured on the parent we need
1362
	 * to obtain an address first so we can write it in the mpd .conf file for PPTP and L2TP configs
1363
	 */
1364
	foreach($ports as $pid => $port){
1365
		switch ($ppp['type']) {
1366
			case "pppoe": 
1367
				/* Bring the parent interface up */
1368
				interfaces_bring_up($port);
1369
				pfSense_ngctl_attach(".", $port);
1370
				break;
1371
			case "pptp":
1372
			case "l2tp":
1373
				/* configure interface */
1374
				if(is_ipaddr($localips[$pid])){
1375
					// Manually configure interface IP/subnet
1376
					pfSense_interface_setaddress($port, "{$localips[$pid]}/{$subnets[$pid]}");
1377
					interfaces_bring_up($port);
1378
				} else if (empty($localips[$pid]))
1379
					$localips[$pid] = get_interface_ip($port); // try to get the interface IP from the port
1380
				
1381
				if(!is_ipaddr($localips[$pid])){
1382
					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!");
1383
					$localips[$pid] = "0.0.0.0";
1384
				}
1385
				/* XXX: This needs to go away soon! [It's commented out!] */
1386
				/* Configure the gateway (remote IP ) */
1387
				if (!$g['booting'] && !is_ipaddr($gateways[$pid]) && is_hostname($gateways[$pid])) {
1388
					/* XXX: Fix later 
1389
					$gateways[$pid] = gethostbyname($gateways[$pid]);
1390
					if(!is_ipaddr($gateways[$pid])) {
1391
						log_error("Could not get a valid Gateway IP from {$port} via DNS in interfaces_ppps_configure.");
1392
						return 0;
1393
					}
1394
					*/
1395
				}
1396
				if(!is_ipaddr($gateways[$pid])){
1397
					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));
1398
					return 0;
1399
				}
1400
				pfSense_ngctl_attach(".", $port);
1401
				break;
1402
			case "ppp":
1403
				if (!file_exists("{$port}")) {
1404
					log_error(sprintf(gettext("Device %s does not exist. PPP link cannot start without the modem device."), $port));
1405
					return 0;
1406
				}
1407
				break;
1408
			default:
1409
				log_error(sprintf(gettext("Unkown %s configured as ppp interface."), $type));
1410
				break;
1411
		}
1412
	}
1413
	
1414
	if (is_array($ports) && count($ports) > 1)
1415
		$multilink = "enable";
1416
	else
1417
		$multilink = "disable";
1418
	
1419
	if ($type == "modem"){
1420
		if (is_ipaddr($ppp['localip']))
1421
			$localip = $ppp['localip'];
1422
		else
1423
			$localip = '0.0.0.0';
1424

    
1425
		if (is_ipaddr($ppp['gateway']))
1426
			$gateway = $ppp['gateway'];
1427
		else
1428
			$gateway = "10.64.64.{$pppid}";
1429
		$ranges = "{$localip}/0 {$gateway}/0";
1430
		
1431
		if (empty($ppp['apnum']))	
1432
			$ppp['apnum'] = 1;
1433
	} else
1434
		$ranges = "0.0.0.0/0 0.0.0.0/0";
1435

    
1436
	if (isset($ppp['ondemand'])) 
1437
		$ondemand = "enable";
1438
	else
1439
		$ondemand = "disable";
1440
	if (!isset($ppp['idletimeout']))
1441
		$ppp['idletimeout'] = 0;
1442

    
1443
	if (empty($ppp['username']) && $type == "modem"){
1444
		$ppp['username'] = "user";
1445
		$ppp['password'] = "none";
1446
	}
1447
	if (empty($ppp['password']) && $type == "modem")
1448
		$passwd = "none";
1449
	else
1450
		$passwd = base64_decode($ppp['password']);
1451

    
1452
	$bandwidths = explode(',',$ppp['bandwidth']);
1453
	$defaultmtu = "1492";
1454
	if (!empty($ifcfg['mtu']))
1455
		$defaultmtu = intval($ifcfg['mtu']);
1456
	$mtus = explode(',',$ppp['mtu']);
1457
	$mrus = explode(',',$ppp['mru']);
1458

    
1459
	if (isset($ppp['mrru']))
1460
		$mrrus = explode(',',$ppp['mrru']);
1461

    
1462
	// Construct the mpd.conf file
1463
	$mpdconf = <<<EOD
1464
startup:
1465
	# configure the console
1466
	set console close
1467
	# configure the web server
1468
	set web close
1469

    
1470
default:
1471
{$ppp['type']}client:
1472
	create bundle static {$interface}
1473
	set bundle enable ipv6cp
1474
	set iface name {$pppif}
1475

    
1476
EOD;
1477
	$setdefaultgw = false;
1478
	$founddefaultgw = false;
1479
	if (is_array($config['gateways']['gateway_item'])) {
1480
		foreach($config['gateways']['gateway_item'] as $gateway) {
1481
			if($interface == $gateway['interface'] && isset($gateway['defaultgw'])) {
1482
				$setdefaultgw = true;
1483
				break;
1484
			} else if (isset($gateway['defaultgw']) && !empty($gateway['interface'])) {
1485
				$founddefaultgw = true;
1486
				break;
1487
			}
1488
		}
1489
	}
1490
	
1491
	if (($interface == "wan" && $founddefaultgw == false) || $setdefaultgw == true){
1492
		$setdefaultgw = true;
1493
		$mpdconf .= <<<EOD
1494
	set iface route default
1495

    
1496
EOD;
1497
	}
1498
	$mpdconf .= <<<EOD
1499
	set iface {$ondemand} on-demand
1500
	set iface idle {$ppp['idletimeout']}
1501

    
1502
EOD;
1503

    
1504
	if (isset($ppp['ondemand']))
1505
		$mpdconf .= <<<EOD
1506
	set iface addrs 10.10.1.1 10.10.1.2
1507

    
1508
EOD;
1509
	
1510
	if (isset($ppp['tcpmssfix']))
1511
		$tcpmss = "disable";
1512
	else
1513
		$tcpmss = "enable";
1514
		$mpdconf .= <<<EOD
1515
	set iface {$tcpmss} tcpmssfix
1516

    
1517
EOD;
1518

    
1519
	$mpdconf .= <<<EOD
1520
	set iface up-script /usr/local/sbin/ppp-linkup
1521
	set iface down-script /usr/local/sbin/ppp-linkdown
1522
	set ipcp ranges {$ranges}
1523

    
1524
EOD;
1525
	if (isset($ppp['vjcomp']))
1526
		$mpdconf .= <<<EOD
1527
	set ipcp no vjcomp
1528

    
1529
EOD;
1530

    
1531
	if (isset($config['system']['dnsallowoverride']))
1532
		$mpdconf .= <<<EOD
1533
	set ipcp enable req-pri-dns
1534
	set ipcp enable req-sec-dns
1535

    
1536
EOD;
1537
	if (!isset($ppp['verbose_log']))
1538
		$mpdconf .= <<<EOD
1539
	#log -bund -ccp -chat -iface -ipcp -lcp -link
1540

    
1541
EOD;
1542
	foreach($ports as $pid => $port){
1543
		$port = get_real_interface($port);
1544
		$mpdconf .= <<<EOD
1545

    
1546
	create link static {$interface}_link{$pid} {$type}
1547
	set link action bundle {$interface}
1548
	set link {$multilink} multilink
1549
	set link keep-alive 10 60
1550
	set link max-redial 0
1551

    
1552
EOD;
1553
		if (isset($ppp['shortseq']))
1554
			$mpdconf .= <<<EOD
1555
	set link no shortseq
1556

    
1557
EOD;
1558

    
1559
		if (isset($ppp['acfcomp']))
1560
			$mpdconf .= <<<EOD
1561
	set link no acfcomp
1562

    
1563
EOD;
1564

    
1565
		if (isset($ppp['protocomp']))
1566
			$mpdconf .= <<<EOD
1567
	set link no protocomp
1568

    
1569
EOD;
1570

    
1571
		$mpdconf .= <<<EOD
1572
	set link disable chap pap
1573
	set link accept chap pap eap
1574
	set link disable incoming
1575

    
1576
EOD;
1577

    
1578

    
1579
		if (!empty($bandwidths[$pid]))
1580
			$mpdconf .= <<<EOD
1581
	set link bandwidth {$bandwidths[$pid]}
1582

    
1583
EOD;
1584

    
1585
		if (empty($mtus[$pid]))
1586
			$mtus[$pid] = $defaultmtu;
1587
			$mpdconf .= <<<EOD
1588
	set link mtu {$mtus[$pid]}
1589

    
1590
EOD;
1591

    
1592
		if (!empty($mrus[$pid]))
1593
			$mpdconf .= <<<EOD
1594
	set link mru {$mrus[$pid]}
1595

    
1596
EOD;
1597

    
1598
		if (!empty($mrrus[$pid]))
1599
			$mpdconf .= <<<EOD
1600
	set link mrru {$mrrus[$pid]}
1601

    
1602
EOD;
1603

    
1604
		$mpdconf .= <<<EOD
1605
	set auth authname "{$ppp['username']}"
1606
	set auth password {$passwd}
1607

    
1608
EOD;
1609
		if ($type == "modem") {
1610
			$mpdconf .= <<<EOD
1611
	set modem device {$ppp['ports']}
1612
	set modem script DialPeer
1613
	set modem idle-script Ringback
1614
	set modem watch -cd
1615
	set modem var \$DialPrefix "DT"
1616
	set modem var \$Telephone "{$ppp['phone']}"
1617

    
1618
EOD;
1619
		}
1620
		if (isset($ppp['connect-timeout']) && $type == "modem") {
1621
			$mpdconf .= <<<EOD
1622
	set modem var \$ConnectTimeout "{$ppp['connect-timeout']}"
1623

    
1624
EOD;
1625
		}
1626
		if (isset($ppp['initstr']) && $type == "modem") {
1627
			$initstr = base64_decode($ppp['initstr']);
1628
			$mpdconf .= <<<EOD
1629
	set modem var \$InitString "{$initstr}"
1630

    
1631
EOD;
1632
		}
1633
		if (isset($ppp['simpin']) && $type == "modem") {
1634
			if($ppp['pin-wait'] == "")
1635
				$ppp['pin-wait'] = 0;
1636
			$mpdconf .= <<<EOD
1637
	set modem var \$SimPin "{$ppp['simpin']}"
1638
	set modem var \$PinWait "{$ppp['pin-wait']}"
1639

    
1640
EOD;
1641
		}
1642
		if (isset($ppp['apn']) && $type == "modem") {
1643
			$mpdconf .= <<<EOD
1644
	set modem var \$APN "{$ppp['apn']}"
1645
	set modem var \$APNum "{$ppp['apnum']}"
1646

    
1647
EOD;
1648
		}
1649
		if ($type == "pppoe") {
1650
			// Send a null service name if none is set.
1651
			$provider = isset($ppp['provider']) ? $ppp['provider'] : "";
1652
			$mpdconf .= <<<EOD
1653
	set pppoe service "{$provider}"
1654

    
1655
EOD;
1656
		}
1657
		if ($type == "pppoe")
1658
			$mpdconf .= <<<EOD
1659
	set pppoe iface {$port}
1660

    
1661
EOD;
1662

    
1663
		if ($type == "pptp" || $type == "l2tp") {
1664
			$mpdconf .= <<<EOD
1665
	set {$type} self {$localips[$pid]}
1666
	set {$type} peer {$gateways[$pid]}
1667

    
1668
EOD;
1669
		}
1670
		
1671
		$mpdconf .= "\topen\n";
1672
	} //end foreach($port)
1673

    
1674

    
1675
	/* Generate mpd.conf. If mpd_[interface].conf exists in the conf path, then link to it instead of generating a fresh conf file. */
1676
	if (file_exists("{$g['conf_path']}/mpd_{$interface}.conf"))
1677
		mwexec("/bin/ln -s {$g['conf_path']}/mpd_{$interface}.conf {$g['varetc_path']}/.");
1678
	else {
1679
		$fd = fopen("{$g['varetc_path']}/mpd_{$interface}.conf", "w");
1680
		if (!$fd) {
1681
			log_error(sprintf(gettext("Error: cannot open mpd_%s.conf in interface_ppps_configure().%s"), $interface, "\n"));
1682
			return 0;
1683
		}
1684
		// Write out mpd_ppp.conf
1685
		fwrite($fd, $mpdconf);
1686
		fclose($fd);
1687
		unset($mpdconf);
1688
	}
1689

    
1690
	// Create the uptime log if requested and if it doesn't exist already, or delete it if it is no longer requested.
1691
	if (isset($ppp['uptime'])) {
1692
		if (!file_exists("/conf/{$pppif}.log")) {
1693
			conf_mount_rw();
1694
			mwexec("echo /dev/null > /conf/{$pppif}.log");
1695
			conf_mount_ro();
1696
		}
1697
	} else {
1698
		if (file_exists("/conf/{$pppif}.log")) {
1699
			conf_mount_rw();
1700
			mwexec("rm -f /conf/{$pppif}.log");
1701
			conf_mount_ro();
1702
		}
1703
	}
1704

    
1705
	/* clean up old lock files */
1706
	foreach($ports as $port) {
1707
		if(file_exists("{$g['var_path']}/spool/lock/LCK..{$port}"))
1708
			unlink("{$g['var_path']}/spool/lock/LCK..{$port}");
1709
	}
1710

    
1711
	/* fire up mpd */
1712
	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");
1713

    
1714
	// Check for PPPoE periodic reset request 
1715
	if ($type == "pppoe") {
1716
		if (!empty($ppp['pppoe-reset-type']))
1717
			interface_setup_pppoe_reset_file($ppp['if'], $interface);
1718
		else
1719
			interface_setup_pppoe_reset_file($ppp['if']);
1720
	}
1721
	/* wait for upto 10 seconds for the interface to appear (ppp(oe)) */
1722
	$i = 0;
1723
	while($i < 10) {
1724
		exec("/sbin/ifconfig {$ppp['if']} 2>&1", $out, $ret);
1725
		if($ret == 0)
1726
			break;
1727
		sleep(1);
1728
		$i++;
1729
	}
1730

    
1731
	/* we only support the 3gstats.php for huawei modems for now. Will add more later. */
1732
	/* We should be able to launch the right version for each modem */
1733
	/* We can also guess the mondev from the manufacturer */
1734
	exec("usbconfig | egrep -ie '(huawei)'", $usbmodemoutput);
1735
	mwexec("/bin/ps auxww|grep \"{$interface}\" |grep \"[3]gstats\" | awk '{print $2}' |xargs kill");
1736
	foreach($ports as $port) {
1737
		if(preg_match("/huawei/i", implode("\n", $usbmodemoutput))) {
1738
			$mondev  = substr(basename($port), 0, -1);
1739
			$devlist = glob("/dev/{$mondev}?");
1740
			$mondev = basename(end($devlist));
1741
		}
1742
		if(preg_match("/zte/i", implode("\n", $usbmodemoutput))) {
1743
			$mondev  = substr(basename($port), 0, -1) . "1";
1744
		}
1745
		log_error("Starting 3gstats.php on device '{$mondev}' for interface '{$interface}'");
1746
		mwexec_bg("/usr/local/bin/3gstats.php {$mondev} {$interface}");
1747
	}
1748

    
1749
	return 1;
1750
}
1751

    
1752
function interfaces_carp_setup() {
1753
	global $g, $config;
1754

    
1755
	if (isset($config['system']['developerspew'])) {
1756
		$mt = microtime();
1757
		echo "interfaces_carp_setup() being called $mt\n";
1758
	}
1759

    
1760
	if ($g['booting']) {
1761
		echo gettext("Configuring CARP settings...");
1762
		mute_kernel_msgs();
1763
	}
1764

    
1765
	/* suck in configuration items */
1766
	if ($config['hasync']) {
1767
		$pfsyncenabled = $config['hasync']['pfsyncenabled'];
1768
		$balanacing = $config['hasync']['balancing'];
1769
		$pfsyncinterface = $config['hasync']['pfsyncinterface'];
1770
		$pfsyncpeerip = $config['hasync']['pfsyncpeerip'];
1771
	} else {
1772
		unset($pfsyncinterface);
1773
		unset($balanacing);
1774
		unset($pfsyncenabled);
1775
	}
1776

    
1777
	if ($balanacing) {
1778
		mwexec("/sbin/sysctl net.inet.carp.arpbalance=1", true);
1779
		mwexec("/sbin/sysctl net.inet.carp.preempt=0", true);
1780
	} else
1781
		mwexec("/sbin/sysctl net.inet.carp.preempt=1", true);		
1782

    
1783
	mwexec("sbin/sysctl net.inet.carp.log=1", true);
1784
	if (!empty($pfsyncinterface))
1785
		$carp_sync_int = get_real_interface($pfsyncinterface);
1786
	else
1787
		unset($carp_sync_int);
1788

    
1789
	/* setup pfsync interface */
1790
	if ($carp_sync_int and $pfsyncenabled) {
1791
		if (is_ipaddr($pfsyncpeerip))
1792
			mwexec("/sbin/ifconfig pfsync0 syncdev {$carp_sync_int} syncpeer {$pfsyncpeerip} up", false);						
1793
		else
1794
			mwexec("/sbin/ifconfig pfsync0 syncdev {$carp_sync_int} up", false);			
1795

    
1796
		sleep(1);
1797

    
1798
		/* 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 issues
1799
		 * for existing sessions.
1800
		 */
1801
		log_error("waiting for pfsync...");
1802
		$i = 0;
1803
		while (intval(trim(`/sbin/ifconfig pfsync0 | /usr/bin/grep 'syncok: 0' | /usr/bin/grep -v grep | /usr/bin/wc -l`)) == 0 && $i < 30) {
1804
			$i++;
1805
			sleep(1);
1806
		}
1807
		log_error("pfsync done in $i seconds.");
1808
		log_error("Configuring CARP settings finalize...");
1809
	}
1810

    
1811
	if($config['virtualip']['vip'])
1812
		mwexec("/sbin/sysctl net.inet.carp.allow=1", true);				
1813
	else
1814
		mwexec("/sbin/sysctl net.inet.carp.allow=0", true);		
1815
	
1816
	if ($g['booting']) {
1817
		unmute_kernel_msgs();
1818
		echo gettext("done.") . "\n";
1819
	}
1820
}
1821

    
1822
function interface_proxyarp_configure($interface = "") {
1823
	global $config, $g;
1824
	if(isset($config['system']['developerspew'])) {
1825
		$mt = microtime();
1826
		echo "interface_proxyarp_configure() being called $mt\n";
1827
	}
1828

    
1829
	/* kill any running choparp */
1830
	if (empty($interface))
1831
		killbyname("choparp");
1832
	else {
1833
		$vipif = get_real_interface($interface);
1834
		if (file_exists("{$g['varrun_path']}/choparp_{$vipif}.pid"))
1835
			killbypid("{$g['varrun_path']}/choparp_{$vipif}.pid");
1836
	}
1837

    
1838
	$paa = array();
1839
	if (!empty($config['virtualip']) && is_array($config['virtualip']['vip'])) {
1840

    
1841
		/* group by interface */
1842
		foreach ($config['virtualip']['vip'] as $vipent) {
1843
			if ($vipent['mode'] === "proxyarp") {
1844
				if ($vipent['interface'])
1845
					$proxyif = $vipent['interface'];
1846
				else
1847
					$proxyif = "wan";
1848
				
1849
				if (!empty($interface) && $interface != $proxyif)
1850
					continue;
1851

    
1852
				if (!is_array($paa[$proxyif]))
1853
					$paa[$proxyif] = array();
1854

    
1855
				$paa[$proxyif][] = $vipent;
1856
			}
1857
		}
1858
	}
1859

    
1860
	if (!empty($interface)) {
1861
		if (is_array($paa[$interface])) {
1862
			$paaifip = get_interface_ip($interface);
1863
                        if (!is_ipaddr($paaifip))
1864
                                return;
1865
                        $args = get_real_interface($interface) . " auto";
1866
                        foreach ($paa[$interface] as $paent) {
1867
                                if (isset($paent['subnet']))
1868
                                        $args .= " " . escapeshellarg("{$paent['subnet']}/{$paent['subnet_bits']}");
1869
                                else if (isset($paent['range']))
1870
                                        $args .= " " . escapeshellarg($paent['range']['from'] . "-" . $paent['range']['to']);
1871
                        }
1872
                        mwexec_bg("/usr/local/sbin/choparp " . $args);	
1873
		}
1874
	} else if (count($paa) > 0) {
1875
		foreach ($paa as $paif => $paents)  {
1876
			$paaifip = get_interface_ip($paif);
1877
			if (!is_ipaddr($paaifip))
1878
				continue;
1879
			$args = get_real_interface($paif) . " auto";
1880
			foreach ($paents as $paent) {
1881
				if (isset($paent['subnet']))
1882
					$args .= " " . escapeshellarg("{$paent['subnet']}/{$paent['subnet_bits']}");
1883
				else if (isset($paent['range']))
1884
					$args .= " " . escapeshellarg($paent['range']['from'] . "-" . $paent['range']['to']);
1885
			}
1886
			mwexec_bg("/usr/local/sbin/choparp " . $args);
1887
		}
1888
	}
1889
}
1890

    
1891
function interfaces_vips_configure($interface = "") {
1892
	global $g, $config;
1893
	if(isset($config['system']['developerspew'])) {
1894
		$mt = microtime();
1895
		echo "interfaces_vips_configure() being called $mt\n";
1896
	}
1897
	$paa = array();
1898
	if(is_array($config['virtualip']['vip'])) {
1899
		$carp_setuped = false;
1900
		$anyproxyarp = false;
1901
		foreach ($config['virtualip']['vip'] as $vip) {
1902
			switch ($vip['mode']) {
1903
			case "proxyarp":
1904
				/* nothing it is handled on interface_proxyarp_configure() */
1905
				if ($interface <> "" && $vip['interface'] <> $interface)
1906
					continue;
1907
				$anyproxyarp = true;
1908
				break;
1909
			case "ipalias":
1910
				if ($interface <> "" && $vip['interface'] <> $interface)
1911
					continue;
1912
				interface_ipalias_configure(&$vip);
1913
				break;
1914
			case "carp":
1915
				if ($interface <> "" && $vip['interface'] <> $interface)
1916
					continue;
1917
				if ($carp_setuped == false)
1918
					$carp_setuped = true;
1919
				interface_carp_configure($vip);
1920
				break;
1921
			}
1922
		}
1923
		if ($carp_setuped == true)
1924
			interfaces_carp_setup();
1925
		if ($anyproxyarp == true)
1926
			interface_proxyarp_configure();
1927
	}
1928
}
1929

    
1930
function interface_ipalias_configure(&$vip) {
1931
	if ($vip['mode'] == "ipalias") {
1932
		$if = get_real_interface($vip['interface']);
1933
		$af = "inet";
1934
		if(is_ipaddrv6($vip['subnet']))
1935
			$af = "inet6";
1936
		mwexec("/sbin/ifconfig " . escapeshellarg($if) ." {$af} ". escapeshellarg($vip['subnet']) ."/" . escapeshellarg($vip['subnet_bits']) . " alias");
1937
	}
1938
}
1939

    
1940
function interface_reload_carps($cif) {
1941
	global $config;
1942

    
1943
	$carpifs = link_ip_to_carp_interface(find_interface_ip($cif));
1944
	if (empty($carpifs))
1945
		return;
1946

    
1947
	$carps = explode(" ", $carpifs);
1948
	if(is_array($config['virtualip']['vip'])) {
1949
		$viparr = &$config['virtualip']['vip'];
1950
		foreach ($viparr as $vip) {
1951
			if (in_array($vip['carpif'], $carps)) {
1952
				switch ($vip['mode']) {
1953
				case "carp":
1954
					interface_vip_bring_down($vip);
1955
					sleep(1);
1956
					interface_carp_configure($vip);
1957
					break;
1958
				case "ipalias":
1959
					interface_vip_bring_down($vip);
1960
					sleep(1);
1961
					interface_ipalias_configure($vip);
1962
					break;
1963
				}
1964
			}
1965
		}
1966
	}
1967
}
1968

    
1969
function interface_carp_configure(&$vip) {
1970
	global $config, $g;
1971
	if(isset($config['system']['developerspew'])) {
1972
		$mt = microtime();
1973
		echo "interface_carp_configure() being called $mt\n";
1974
	}
1975

    
1976
	if ($vip['mode'] != "carp")
1977
		return;
1978

    
1979
	/*
1980
	 * ensure the interface containing the VIP really exists
1981
 	 * prevents a panic if the interface is missing or invalid
1982
	 */
1983
	$realif = get_real_interface($vip['interface']);
1984
	if (!does_interface_exist($realif)) {
1985
		file_notice("CARP", sprintf(gettext("Interface specified for the virtual IP address %s does not exist. Skipping this VIP."), $vip['subnet']), "Firewall: Virtual IP", "");
1986
		return;
1987
	}
1988

    
1989
	if(is_ipaddrv4($vip['subnet'])) {
1990
		/* Ensure CARP IP really exists prior to loading up. */
1991
		$ww_subnet_ip = find_interface_ip($realif);
1992
		$ww_subnet_bits = find_interface_subnet($realif);
1993
		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'])) {
1994
			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", "");
1995
			return;
1996
		}
1997
	}
1998
	if(is_ipaddrv6($vip['subnet'])) {
1999
		/* Ensure CARP IP really exists prior to loading up. */
2000
		$ww_subnet_ip = find_interface_ipv6($realif);
2001
		$ww_subnet_bits = find_interface_subnetv6($realif);
2002
		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'])) {
2003
			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", "");
2004
			return;
2005
		}
2006
	}
2007

    
2008
	// set the vip interface to the vhid
2009
	$vipif = "{$vip['interface']}_vip{$vip['vhid']}";
2010

    
2011
	/* create the carp interface and setup */
2012
	if (does_interface_exist($vipif)) {
2013
		pfSense_interface_flags($vipif, -IFF_UP);
2014
	} else {
2015
		$carpif = pfSense_interface_create("carp");
2016
		pfSense_interface_rename($carpif, $vipif);
2017
		pfSense_ngctl_name("{$carpif}:", $vipif);
2018
	}
2019

    
2020
	/* invalidate interface cache */
2021
	get_interface_arr(true);
2022

    
2023
	$vip_password = $vip['password'];
2024
	$vip_password = escapeshellarg(addslashes(str_replace(" ", "", $vip_password)));
2025
	if ($vip['password'] != "")
2026
		$password = " pass {$vip_password}";
2027

    
2028
	$broadcast_address = gen_subnet_max($vip['subnet'], $vip['subnet_bits']);
2029
	$advbase = "";
2030
	if (!empty($vip['advbase']))
2031
		$advbase = "advbase {$vip['advbase']}";
2032

    
2033
	if(is_ipaddrv4($vip['subnet'])) {
2034
		$broadcast_address = gen_subnet_max($vip['subnet'], $vip['subnet_bits']);
2035
		mwexec("/sbin/ifconfig {$vipif} {$vip['subnet']}/{$vip['subnet_bits']} vhid {$vip['vhid']} advskew {$vip['advskew']} {$advbase} {$password}");
2036
	}
2037
	if(is_ipaddrv6($vip['subnet'])) {
2038
		$broadcast_address = gen_subnet_max($vip['subnet'], $vip['subnet_bits']);
2039
		mwexec("/sbin/ifconfig {$vipif} inet6 {$vip['subnet']} prefixlen {$vip['subnet_bits']} vhid {$vip['vhid']} advskew {$vip['advskew']} {$advbase} {$password}");
2040
	}
2041

    
2042
	interfaces_bring_up($vipif);
2043

    
2044
	return $vipif;
2045
}
2046

    
2047
function interface_wireless_clone($realif, $wlcfg) {
2048
	global $config, $g;
2049
	/*   Check to see if interface has been cloned as of yet.  
2050
	 *   If it has not been cloned then go ahead and clone it.
2051
	 */
2052
	$needs_clone = false;
2053
	if(is_array($wlcfg['wireless']))
2054
		$wlcfg_mode = $wlcfg['wireless']['mode'];
2055
	else
2056
		$wlcfg_mode = $wlcfg['mode'];
2057
	switch($wlcfg_mode) {
2058
		 case "hostap":
2059
			$mode = "wlanmode hostap";
2060
			break;
2061
		 case "adhoc":
2062
			$mode = "wlanmode adhoc";
2063
			break;
2064
		 default:
2065
			$mode = "";
2066
			break;
2067
	}
2068
	$baseif = interface_get_wireless_base($wlcfg['if']);
2069
	if(does_interface_exist($realif)) {
2070
		exec("/sbin/ifconfig {$realif}", $output, $ret);
2071
		$ifconfig_str = implode($output);
2072
		if(($wlcfg_mode == "hostap") && (! preg_match("/hostap/si", $ifconfig_str))) {
2073
			log_error(sprintf(gettext("Interface %s changed to hostap mode"), $realif));
2074
			$needs_clone = true;
2075
		}
2076
		if(($wlcfg_mode == "adhoc") && (! preg_match("/adhoc/si", $ifconfig_str))) {
2077
			log_error(sprintf(gettext("Interface %s changed to adhoc mode"), $realif));
2078
			$needs_clone = true;
2079
		}
2080
		if(($wlcfg_mode == "bss") && (preg_match("/hostap|adhoc/si", $ifconfig_str))) {
2081
			log_error(sprintf(gettext("Interface %s changed to infrastructure mode"), $realif));
2082
			$needs_clone = true;
2083
		}
2084
	} else {
2085
		$needs_clone = true;
2086
	}
2087

    
2088
	if($needs_clone == true) {
2089
		/* remove previous instance if it exists */
2090
		if(does_interface_exist($realif))
2091
			pfSense_interface_destroy($realif);
2092

    
2093
		log_error(sprintf(gettext("Cloning new wireless interface %s"), $realif));
2094
		// Create the new wlan interface. FreeBSD returns the new interface name.
2095
		// example:  wlan2
2096
		exec("/sbin/ifconfig wlan create wlandev {$baseif} {$mode} bssid 2>&1", $out, $ret);
2097
		if($ret <> 0) {
2098
			log_error(sprintf(gettext('Failed to clone interface %1$s with error code %2$s, output %3$s'), $baseif, $ret, $out[0]));
2099
			return false;
2100
		}
2101
		$newif = trim($out[0]);
2102
		// Rename the interface to {$parentnic}_wlan{$number}#: EX: ath0_wlan0
2103
		pfSense_interface_rename($newif, $realif);
2104
		// FIXME: not sure what ngctl is for. Doesn't work.
2105
		// mwexec("/usr/sbin/ngctl name {$newif}: {$realif}", false);
2106
		file_put_contents("{$g['tmp_path']}/{$realif}_oldmac", get_interface_mac($realif));
2107
	}
2108
	return true;
2109
}
2110

    
2111
function interface_sync_wireless_clones(&$ifcfg, $sync_changes = false) {
2112
	global $config, $g;
2113

    
2114
	$shared_settings = array('standard', 'turbo', 'protmode', 'txpower', 'channel',
2115
	                         'diversity', 'txantenna', 'rxantenna', 'distance',
2116
	                         'regdomain', 'regcountry', 'reglocation');
2117

    
2118
	if(!is_interface_wireless($ifcfg['if']))
2119
		return;
2120

    
2121
	$baseif = interface_get_wireless_base($ifcfg['if']);
2122

    
2123
	// Sync shared settings for assigned clones
2124
	$iflist = get_configured_interface_list(false, true);
2125
	foreach ($iflist as $if) {
2126
		if ($baseif == interface_get_wireless_base($config['interfaces'][$if]['if']) && $ifcfg['if'] != $config['interfaces'][$if]['if']) {
2127
			if (isset($config['interfaces'][$if]['wireless']['standard']) || $sync_changes) {
2128
				foreach ($shared_settings as $setting) {
2129
					if ($sync_changes) {
2130
						if (isset($ifcfg['wireless'][$setting]))
2131
							$config['interfaces'][$if]['wireless'][$setting] = $ifcfg['wireless'][$setting];
2132
						else if (isset($config['interfaces'][$if]['wireless'][$setting]))
2133
							unset($config['interfaces'][$if]['wireless'][$setting]);
2134
					} else {
2135
						if (isset($config['interfaces'][$if]['wireless'][$setting]))
2136
							$ifcfg['wireless'][$setting] = $config['interfaces'][$if]['wireless'][$setting];
2137
						else if (isset($ifcfg['wireless'][$setting]))
2138
							unset($ifcfg['wireless'][$setting]);
2139
					}
2140
				}
2141
				if (!$sync_changes)
2142
					break;
2143
			}
2144
		}
2145
	}
2146

    
2147
	// Read or write settings at shared area
2148
	if (isset($config['wireless']['interfaces'][$baseif]) && is_array($config['wireless']['interfaces'][$baseif])) {
2149
		foreach ($shared_settings as $setting) {
2150
			if ($sync_changes) {
2151
				if (isset($ifcfg['wireless'][$setting]))
2152
					$config['wireless']['interfaces'][$baseif][$setting] = $ifcfg['wireless'][$setting];
2153
				else if (isset($config['wireless']['interfaces'][$baseif][$setting]))
2154
					unset($config['wireless']['interfaces'][$baseif][$setting]);
2155
			} else if (isset($config['wireless']['interfaces'][$baseif][$setting])) {
2156
				if (isset($config['wireless']['interfaces'][$baseif][$setting]))
2157
					$ifcfg['wireless'][$setting] = $config['wireless']['interfaces'][$baseif][$setting];
2158
				else if (isset($ifcfg['wireless'][$setting]))
2159
					unset($ifcfg['wireless'][$setting]);
2160
			}
2161
		}
2162
	}
2163

    
2164
	// Sync the mode on the clone creation page with the configured mode on the interface
2165
	if (interface_is_wireless_clone($ifcfg['if']) && isset($config['wireless']['clone']) && is_array($config['wireless']['clone'])) {
2166
		foreach ($config['wireless']['clone'] as &$clone) {
2167
			if ($clone['cloneif'] == $ifcfg['if']) {
2168
				if ($sync_changes) {
2169
					$clone['mode'] = $ifcfg['wireless']['mode'];
2170
				} else {
2171
					$ifcfg['wireless']['mode'] = $clone['mode'];
2172
				}
2173
				break;
2174
			}
2175
		}
2176
		unset($clone);
2177
	}
2178
}
2179

    
2180
function interface_wireless_configure($if, &$wl, &$wlcfg) {
2181
	global $config, $g;
2182

    
2183
	/*    open up a shell script that will be used to output the commands.
2184
	 *    since wireless is changing a lot, these series of commands are fragile
2185
	 *    and will sometimes need to be verified by a operator by executing the command
2186
	 *    and returning the output of the command to the developers for inspection.  please
2187
	 *    do not change this routine from a shell script to individual exec commands.  -sullrich
2188
	 */
2189

    
2190
	// Remove script file
2191
	unlink_if_exists("{$g['tmp_path']}/{$if}_setup.sh");
2192

    
2193
	// Clone wireless nic if needed.
2194
	interface_wireless_clone($if, $wl);
2195

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

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

    
2203
	/* set values for /path/program */
2204
	$hostapd = "/usr/sbin/hostapd";
2205
	$wpa_supplicant = "/usr/sbin/wpa_supplicant";
2206
	$ifconfig = "/sbin/ifconfig";
2207
	$sysctl = "/sbin/sysctl";
2208
	$killall = "/usr/bin/killall";
2209

    
2210
	/* Set all wireless ifconfig variables (split up to get rid of needed checking) */
2211

    
2212
	$wlcmd = array();
2213
	$wl_sysctl = array();
2214
	/* Make sure it's up */
2215
	$wlcmd[] = "up";
2216
	/* Set a/b/g standard */
2217
	$standard = str_replace(" Turbo", "", $wlcfg['standard']);
2218
	$wlcmd[] = "mode " . escapeshellarg($standard);
2219

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

    
2225
	/* Set ssid */
2226
	if($wlcfg['ssid'])
2227
		$wlcmd[] = "ssid " .escapeshellarg($wlcfg['ssid']);
2228

    
2229
	/* Set 802.11g protection mode */
2230
	$wlcmd[] = "protmode " . escapeshellarg($wlcfg['protmode']);
2231

    
2232
	/* set wireless channel value */
2233
	if(isset($wlcfg['channel'])) {
2234
		if($wlcfg['channel'] == "0") {
2235
			$wlcmd[] = "channel any";
2236
		} else {
2237
			$wlcmd[] = "channel " . escapeshellarg($wlcfg['channel']);
2238
		}
2239
	}
2240

    
2241
	/* Set antenna diversity value */
2242
	if(isset($wlcfg['diversity']))
2243
		$wl_sysctl[] = "diversity=" . escapeshellarg($wlcfg['diversity']);
2244

    
2245
	/* Set txantenna value */
2246
	if(isset($wlcfg['txantenna']))
2247
		$wl_sysctl[] = "txantenna=" . escapeshellarg($wlcfg['txantenna']);
2248

    
2249
	/* Set rxantenna value */
2250
	if(isset($wlcfg['rxantenna']))
2251
		$wl_sysctl[] = "rxantenna=" . escapeshellarg($wlcfg['rxantenna']);
2252

    
2253
	/* set Distance value */
2254
	if($wlcfg['distance'])
2255
		$distance = escapeshellarg($wlcfg['distance']);
2256

    
2257
	/* Set wireless hostap mode */
2258
	if ($wlcfg['mode'] == "hostap") {
2259
		$wlcmd[] = "mediaopt hostap";
2260
	} else {
2261
		$wlcmd[] = "-mediaopt hostap";
2262
	}
2263

    
2264
	/* Set wireless adhoc mode */
2265
	if ($wlcfg['mode'] == "adhoc") {
2266
		$wlcmd[] = "mediaopt adhoc";
2267
	} else {
2268
		$wlcmd[] = "-mediaopt adhoc";
2269
	}
2270

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

    
2273
	/* handle hide ssid option */
2274
	if(isset($wlcfg['hidessid']['enable'])) {
2275
		$wlcmd[] = "hidessid";
2276
	} else {
2277
		$wlcmd[] = "-hidessid";
2278
	}
2279

    
2280
	/* handle pureg (802.11g) only option */
2281
	if(isset($wlcfg['pureg']['enable'])) {
2282
		$wlcmd[] = "mode 11g pureg";
2283
	} else {
2284
		$wlcmd[] = "-pureg";
2285
	}
2286

    
2287
	/* handle puren (802.11n) only option */
2288
	if(isset($wlcfg['puren']['enable'])) {
2289
		$wlcmd[] = "puren";
2290
	} else {
2291
		$wlcmd[] = "-puren";
2292
	}
2293

    
2294
	/* enable apbridge option */
2295
	if(isset($wlcfg['apbridge']['enable'])) {
2296
		$wlcmd[] = "apbridge";
2297
	} else {
2298
		$wlcmd[] = "-apbridge";
2299
	}
2300

    
2301
	/* handle turbo option */
2302
	if(isset($wlcfg['turbo']['enable'])) {
2303
		$wlcmd[] = "mediaopt turbo";
2304
	} else {
2305
		$wlcmd[] = "-mediaopt turbo";
2306
	}
2307

    
2308
	/* handle txpower setting */
2309
	/* if($wlcfg['txpower'] <> "")
2310
		$wlcmd[] = "txpower " . escapeshellarg($wlcfg['txpower']);
2311
	*/
2312
	/* handle wme option */
2313
	if(isset($wlcfg['wme']['enable'])) {
2314
		$wlcmd[] = "wme";
2315
	} else {
2316
		$wlcmd[] = "-wme";
2317
	}
2318

    
2319
	/* set up wep if enabled */
2320
	$wepset = "";
2321
	if (isset($wlcfg['wep']['enable']) && is_array($wlcfg['wep']['key'])) {
2322
		switch($wlcfg['wpa']['auth_algs']) {
2323
			case "1":
2324
				$wepset .= "authmode open wepmode on ";
2325
				break;
2326
			case "2":
2327
				$wepset .= "authmode shared wepmode on ";
2328
				break;
2329
			case "3":
2330
				$wepset .= "authmode mixed wepmode on ";
2331
		}
2332
		$i = 1;
2333
		foreach ($wlcfg['wep']['key'] as $wepkey) {
2334
			$wepset .= "wepkey " . escapeshellarg("{$i}:{$wepkey['value']}") . " ";
2335
			if (isset($wepkey['txkey'])) {
2336
				$wlcmd[] = "weptxkey {$i} ";
2337
			}
2338
			$i++;
2339
		}
2340
		$wlcmd[] = $wepset;
2341
	} else {
2342
		$wlcmd[] = "authmode open wepmode off ";
2343
	}
2344

    
2345
	mwexec(kill_hostapd("{$if}"));
2346
	mwexec(kill_wpasupplicant("{$if}"));
2347

    
2348
	/* generate wpa_supplicant/hostap config if wpa is enabled */
2349
	conf_mount_rw();
2350

    
2351
	switch ($wlcfg['mode']) {
2352
		case 'bss':
2353
			if (isset($wlcfg['wpa']['enable'])) {
2354
				$wpa .= <<<EOD
2355
ctrl_interface={$g['varrun_path']}/wpa_supplicant
2356
ctrl_interface_group=0
2357
ap_scan=1
2358
#fast_reauth=1
2359
network={
2360
ssid="{$wlcfg['ssid']}"
2361
scan_ssid=1
2362
priority=5
2363
key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
2364
psk="{$wlcfg['wpa']['passphrase']}"
2365
pairwise={$wlcfg['wpa']['wpa_pairwise']}
2366
group={$wlcfg['wpa']['wpa_pairwise']}
2367
}
2368
EOD;
2369

    
2370
				$fd = fopen("{$g['varetc_path']}/wpa_supplicant_{$if}.conf", "w");
2371
				fwrite($fd, "{$wpa}");
2372
				fclose($fd);
2373
			}
2374
			break;
2375
		case 'hostap':
2376
			if($wlcfg['wpa']['passphrase']) 
2377
				$wpa_passphrase = "wpa_passphrase={$wlcfg['wpa']['passphrase']}\n";
2378
			else 
2379
				$wpa_passphrase = "";
2380
			if (isset($wlcfg['wpa']['enable'])) {
2381
				$wpa .= <<<EOD
2382
interface={$if}
2383
driver=bsd
2384
logger_syslog=-1
2385
logger_syslog_level=0
2386
logger_stdout=-1
2387
logger_stdout_level=0
2388
dump_file={$g['tmp_path']}/hostapd_{$if}.dump
2389
ctrl_interface={$g['varrun_path']}/hostapd
2390
ctrl_interface_group=wheel
2391
#accept_mac_file={$g['tmp_path']}/hostapd_{$if}.accept
2392
#deny_mac_file={$g['tmp_path']}/hostapd_{$if}.deny
2393
#macaddr_acl={$wlcfg['wpa']['macaddr_acl']}
2394
ssid={$wlcfg['ssid']}
2395
debug={$wlcfg['wpa']['debug_mode']}
2396
auth_algs={$wlcfg['wpa']['auth_algs']}
2397
wpa={$wlcfg['wpa']['wpa_mode']}
2398
wpa_key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
2399
wpa_pairwise={$wlcfg['wpa']['wpa_pairwise']}
2400
wpa_group_rekey={$wlcfg['wpa']['wpa_group_rekey']}
2401
wpa_gmk_rekey={$wlcfg['wpa']['wpa_gmk_rekey']}
2402
wpa_strict_rekey={$wlcfg['wpa']['wpa_strict_rekey']}
2403
{$wpa_passphrase}
2404

    
2405
EOD;
2406

    
2407
if (isset($wlcfg['wpa']['rsn_preauth'])) {
2408
	$wpa .= <<<EOD
2409
# Enable the next lines for preauth when roaming. Interface = wired or wireless interface talking to the AP you want to roam from/to
2410
rsn_preauth=1
2411
rsn_preauth_interfaces={$if}
2412

    
2413
EOD;
2414

    
2415
}
2416
				if($wlcfg['auth_server_addr'] && $wlcfg['auth_server_shared_secret']) {
2417
					$auth_server_port = "1812";
2418
					if($wlcfg['auth_server_port']) 
2419
						$auth_server_port = $wlcfg['auth_server_port'];
2420
					$auth_server_port2 = "1812";
2421
					if($wlcfg['auth_server_port2']) 
2422
						$auth_server_port2 = $wlcfg['auth_server_port2'];
2423
					$wpa .= <<<EOD
2424

    
2425
ieee8021x=1
2426
auth_server_addr={$wlcfg['auth_server_addr']}
2427
auth_server_port={$auth_server_port}
2428
auth_server_shared_secret={$wlcfg['auth_server_shared_secret']}
2429
auth_server_addr={$wlcfg['auth_server_addr2']}
2430
auth_server_port={$auth_server_port2}
2431
auth_server_shared_secret={$wlcfg['auth_server_shared_secret2']}
2432

    
2433
EOD;
2434
				} else {
2435
					$wpa .= "ieee8021x={$wlcfg['wpa']['ieee8021x']}\n";
2436
				}
2437

    
2438
				$fd = fopen("{$g['varetc_path']}/hostapd_{$if}.conf", "w");
2439
				fwrite($fd, "{$wpa}");
2440
				fclose($fd);
2441

    
2442
			}
2443
			break;
2444
	}
2445

    
2446
	/*
2447
	 *    all variables are set, lets start up everything
2448
	 */
2449

    
2450
	$baseif = interface_get_wireless_base($if);
2451
	preg_match("/^(.*?)([0-9]*)$/", $baseif, $baseif_split);
2452
	$wl_sysctl_prefix = 'dev.' . $baseif_split[1] . '.' . $baseif_split[2];
2453

    
2454
	/* set sysctls for the wireless interface */
2455
	if (!empty($wl_sysctl)) {
2456
		fwrite($fd_set, "# sysctls for {$baseif}\n");
2457
		foreach ($wl_sysctl as $wl_sysctl_line) {
2458
			fwrite($fd_set, "{$sysctl} {$wl_sysctl_prefix}.{$wl_sysctl_line}\n");
2459
		}
2460
	}
2461

    
2462
	/* set ack timers according to users preference (if he/she has any) */
2463
	if($distance) {
2464
		fwrite($fd_set, "# Enable ATH distance settings\n");
2465
		fwrite($fd_set, "/sbin/athctrl.sh -i {$baseif} -d {$distance}\n");
2466
	}
2467

    
2468
	if (isset($wlcfg['wpa']['enable'])) {
2469
		if ($wlcfg['mode'] == "bss") {
2470
			fwrite($fd_set, "{$wpa_supplicant} -B -i {$if} -c {$g['varetc_path']}/wpa_supplicant_{$if}.conf\n");
2471
		}
2472
		if ($wlcfg['mode'] == "hostap") {
2473
			/* add line to script to restore old mac to make hostapd happy */
2474
			if (file_exists("{$g['tmp_path']}/{$if}_oldmac")) {
2475
				$if_oldmac = file_get_contents("{$g['tmp_path']}/{$if}_oldmac");
2476
				if (is_macaddr($if_oldmac))
2477
					fwrite($fd_set, "{$ifconfig} " . escapeshellarg($if) .
2478
						" link " . escapeshellarg($if_oldmac) . "\n");
2479
			}
2480

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

    
2483
			/* add line to script to restore spoofed mac after running hostapd */
2484
			if (file_exists("{$g['tmp_path']}/{$if}_oldmac")) {
2485
				if ($wl['spoofmac'])
2486
					$if_curmac = $wl['spoofmac'];
2487
				else
2488
					$if_curmac = get_interface_mac($if);
2489
				if (is_macaddr($if_curmac))
2490
					fwrite($fd_set, "{$ifconfig} " . escapeshellarg($if) .
2491
						" link " . escapeshellarg($if_curmac) . "\n");
2492
			}
2493
		}
2494
	}
2495

    
2496
	fclose($fd_set);
2497
	conf_mount_ro();
2498

    
2499
	/* Making sure regulatory settings have actually changed
2500
	 * before applying, because changing them requires bringing
2501
	 * down all wireless networks on the interface. */
2502
	exec("{$ifconfig} " . escapeshellarg($if), $output);
2503
	$ifconfig_str = implode($output);
2504
	unset($output);
2505
	$reg_changing = false;
2506

    
2507
	/* special case for the debug country code */
2508
	if ($wlcfg['regcountry'] == 'DEBUG' && !preg_match("/\sregdomain\s+DEBUG\s/si", $ifconfig_str))
2509
		$reg_changing = true;
2510
	else if ($wlcfg['regdomain'] && !preg_match("/\sregdomain\s+{$wlcfg['regdomain']}\s/si", $ifconfig_str))
2511
		$reg_changing = true;
2512
	else if ($wlcfg['regcountry'] && !preg_match("/\scountry\s+{$wlcfg['regcountry']}\s/si", $ifconfig_str))
2513
		$reg_changing = true;
2514
	else if ($wlcfg['reglocation'] == 'anywhere' && preg_match("/\s(indoor|outdoor)\s/si", $ifconfig_str))
2515
		$reg_changing = true;
2516
	else if ($wlcfg['reglocation'] && $wlcfg['reglocation'] != 'anywhere' && !preg_match("/\s{$wlcfg['reglocation']}\s/si", $ifconfig_str))
2517
		$reg_changing = true;
2518

    
2519
	if ($reg_changing) {
2520
		/* set regulatory domain */
2521
		if($wlcfg['regdomain'])
2522
			$wlregcmd[] = "regdomain " . escapeshellarg($wlcfg['regdomain']);
2523

    
2524
		/* set country */
2525
		if($wlcfg['regcountry'])
2526
			$wlregcmd[] = "country " . escapeshellarg($wlcfg['regcountry']);
2527

    
2528
		/* set location */
2529
		if($wlcfg['reglocation'])
2530
			$wlregcmd[] = escapeshellarg($wlcfg['reglocation']);
2531

    
2532
		$wlregcmd_args = implode(" ", $wlregcmd);
2533

    
2534
		/* build a complete list of the wireless clones for this interface */
2535
		$clone_list = array();
2536
		if (does_interface_exist(interface_get_wireless_clone($baseif)))
2537
			$clone_list[] = interface_get_wireless_clone($baseif);
2538
		if (isset($config['wireless']['clone']) && is_array($config['wireless']['clone'])) {
2539
			foreach ($config['wireless']['clone'] as $clone) {
2540
				if ($clone['if'] == $baseif)
2541
					$clone_list[] = $clone['cloneif'];
2542
			}
2543
		}
2544

    
2545
		/* find which clones are up and bring them down */
2546
		$clones_up = array();
2547
		foreach ($clone_list as $clone_if) {
2548
			$clone_status = pfSense_get_interface_addresses($clone_if);
2549
			if ($clone_status['status'] == 'up') {
2550
				$clones_up[] = $clone_if;
2551
				mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " down");
2552
			}
2553
		}
2554

    
2555
		/* apply the regulatory settings */
2556
		mwexec("{$ifconfig} " . escapeshellarg($if) . " {$wlregcmd_args}");
2557

    
2558
		/* bring the clones back up that were previously up */
2559
		foreach ($clones_up as $clone_if) {
2560
			mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " up");
2561

    
2562
			/*
2563
			 * Rerun the setup script for the interface if it isn't this interface, the interface
2564
			 * is in infrastructure mode, and WPA is enabled.
2565
			 * This can be removed if wpa_supplicant stops dying when you bring the interface down.
2566
			 */
2567
			if ($clone_if != $if) {
2568
				$friendly_if = convert_real_interface_to_friendly_interface_name($clone_if);
2569
				if ( !empty($friendly_if)
2570
				    && $config['interfaces'][$friendly_if]['wireless']['mode'] == "bss"
2571
				    && isset($config['interfaces'][$friendly_if]['wireless']['wpa']['enable']) ) {
2572
					mwexec("/bin/sh {$g['tmp_path']}/{$clone_if}_setup.sh");
2573
				}
2574
			}
2575
		}
2576
	}
2577

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

    
2582
	/* configure wireless */
2583
	$wlcmd_args = implode(" ", $wlcmd);
2584
	mwexec("/sbin/ifconfig {$if} $wlcmd_args", false);
2585

    
2586
	
2587
	sleep(1);
2588
	/* execute hostapd and wpa_supplicant if required in shell */
2589
	mwexec("/bin/sh {$g['tmp_path']}/{$if}_setup.sh");
2590

    
2591
	return 0;
2592

    
2593
}
2594

    
2595
function kill_hostapd($interface) {
2596
	return "/bin/pkill -f \"hostapd .*{$interface}\"\n";
2597
}
2598

    
2599
function kill_wpasupplicant($interface) {
2600
	return "/bin/pkill -f \"wpa_supplicant .*{$interface}\"\n";
2601
}
2602

    
2603
function find_dhclient_process($interface) {
2604
	if ($interface)
2605
		$pid = `/bin/pgrep -axf "dhclient: {$interface}"`;
2606
	else
2607
		$pid = 0;
2608

    
2609
	return intval($pid);
2610
}
2611

    
2612
function find_dhcp6c_process($interface) {
2613
	if ($interface)
2614
		$pid = `/bin/ps auxw|grep "[d]hcp6c" |grep "{$interface}"|awk '{print $2}'`;
2615
	else
2616
		return(false);
2617

    
2618
	return intval($pid);
2619
}
2620

    
2621
function interface_configure($interface = "wan", $reloadall = false, $linkupevent = false) {
2622
	global $config, $g;
2623
	global $interface_sn_arr_cache, $interface_ip_arr_cache;
2624
	global $interface_snv6_arr_cache, $interface_ipv6_arr_cache;
2625

    
2626
	$wancfg = $config['interfaces'][$interface];
2627

    
2628
	$realif = get_real_interface($interface);
2629
	$realhwif_array = get_parent_interface($interface);
2630
	// Need code to handle MLPPP if we ever use $realhwif for MLPPP handling
2631
	$realhwif = $realhwif_array[0];
2632

    
2633
	/* Disable Accepting router advertisements unless specifically requested */
2634
	log_error("Deny router advertisements for interface {$interface}");
2635
	mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 -accept_rtadv");
2636
			
2637
	if (!$g['booting'] && !(substr($realif, 0, 4) == "ovpn")) {
2638
		/* remove all IPv4 and IPv6 addresses */
2639
		while (mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " -alias", true) == 0);
2640
		while (mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 -alias", true) == 0);
2641

    
2642
		/* only bring down the interface when both v4 and v6 are set to NONE */
2643
		if(($wancfg['ipaddr'] <> "none") && ($wancfg['ipaddrv6'] <> "none")) {
2644
			interface_bring_down($interface);
2645
		}
2646
	}
2647

    
2648
	/* wireless configuration? */
2649
	if (is_array($wancfg['wireless']))
2650
		interface_wireless_configure($realif, $wancfg, $wancfg['wireless']);
2651

    
2652
	$mac = get_interface_mac($realhwif);
2653
	/*	Don't try to reapply the spoofed MAC if it's already applied.
2654
		When ifconfig link is used, it cycles the interface down/up, which triggers 
2655
		the interface config again, which attempts to spoof the MAC again, 
2656
		which cycles the link again... */
2657
	if ($wancfg['spoofmac'] && ($wancfg['spoofmac'] != $mac)) {
2658
		mwexec("/sbin/ifconfig " . escapeshellarg($realhwif) .
2659
			" link " . escapeshellarg($wancfg['spoofmac']));
2660

    
2661
                /*
2662
                 * All vlans need to spoof their parent mac address, too.  see
2663
                 * ticket #1514: http://cvstrac.pfsense.com/tktview?tn=1514,33
2664
                 */
2665
                if (is_array($config['vlans']['vlan'])) {
2666
                        foreach ($config['vlans']['vlan'] as $vlan) {
2667
                                if ($vlan['if'] == $realhwif)
2668
                                        mwexec("/sbin/ifconfig " . escapeshellarg($vlan['vlanif']) .
2669
                                                " link " . escapeshellarg($wancfg['spoofmac']));
2670
                        }
2671
                }
2672
	}  else {
2673

    
2674
		if ($mac == "ff:ff:ff:ff:ff:ff") {
2675
			/*   this is not a valid mac address.  generate a
2676
			 *   temporary mac address so the machine can get online.
2677
			 */
2678
			echo gettext("Generating new MAC address.");
2679
			$random_mac = generate_random_mac_address();
2680
			mwexec("/sbin/ifconfig " . escapeshellarg($realhwif) .
2681
				" link " . escapeshellarg($random_mac));
2682
			$wancfg['spoofmac'] = $random_mac;
2683
			write_config();
2684
			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");
2685
		}
2686
	}
2687

    
2688
	/* media */
2689
	if ($wancfg['media'] || $wancfg['mediaopt']) {
2690
		$cmd = "/sbin/ifconfig " . escapeshellarg($realhwif);
2691
		if ($wancfg['media'])
2692
			$cmd .= " media " . escapeshellarg($wancfg['media']);
2693
		if ($wancfg['mediaopt'])
2694
			$cmd .= " mediaopt " . escapeshellarg($wancfg['mediaopt']);
2695
		mwexec($cmd);
2696
	}
2697
	if (!empty($wancfg['mtu']))
2698
		pfSense_interface_mtu($realhwif, $wancfg['mtu']);
2699
	else {
2700
		$mtu = get_interface_default_mtu(remove_numbers($realhwif));
2701
		if ($mtu != get_interface_mtu($realhwif))
2702
			pfSense_interface_mtu($realhwif, $mtu);
2703
	}
2704

    
2705
	$options = pfSense_get_interface_addresses($realhwif);
2706
	if (is_array($options) && isset($options['caps']['polling'])) {
2707
		if (isset($config['system']['polling']))
2708
			pfSense_interface_capabilities($realif, IFCAP_POLLING);
2709
		else
2710
			pfSense_interface_capabilities($realif, -IFCAP_POLLING);
2711
	}
2712

    
2713
	/* skip vlans for checksumming and polling */
2714
        if (!stristr($realhwif, "vlan") && is_array($options)) {
2715
		$flags = 0;
2716
		if(isset($config['system']['disablechecksumoffloading'])) {
2717
			if (isset($options['encaps']['txcsum']))
2718
				$flags |= IFCAP_TXCSUM;
2719
			if (isset($options['encaps']['rxcsum']))
2720
				$flags |= IFCAP_RXCSUM;
2721
        	} else {
2722
 			if (!isset($options['caps']['txcsum']))
2723
				$flags |= IFCAP_TXCSUM;
2724
			if (!isset($options['caps']['rxcsum']))
2725
				$flags |= IFCAP_RXCSUM;
2726
        	}
2727

    
2728
        	if(isset($config['system']['disablesegmentationoffloading'])) {
2729
                	if (isset($options['encaps']['tso4']))
2730
				$flags |= IFCAP_TSO;
2731
                	if (isset($options['encaps']['tso6']))
2732
				$flags |= IFCAP_TSO;
2733
        	} else {
2734
                	if (!isset($options['caps']['tso4']))
2735
				$flags |= IFCAP_TSO;
2736
                	if (!isset($options['caps']['tso6']))
2737
				$flags |= IFCAP_TSO;
2738
        	}
2739

    
2740
        	if(isset($config['system']['disablelargereceiveoffloading'])) {
2741
                	if (isset($options['encaps']['lro']))
2742
				$flags |= IFCAP_LRO;
2743
        	} else {
2744
                	if (!isset($options['caps']['lro']))
2745
				$flags |= IFCAP_LRO;
2746
        	}
2747

    
2748
        	/* if the NIC supports polling *AND* it is enabled in the GUI */
2749
        	if (!isset($config['system']['polling']) || !isset($options['caps']['polling'])) {
2750
			$flags |= IFCAP_POLLING;
2751
		}
2752
               	pfSense_interface_capabilities($realhwif, -$flags);
2753
	}
2754

    
2755
	/* invalidate interface/ip/sn cache */
2756
	get_interface_arr(true);
2757
	unset($interface_ip_arr_cache[$realif]);
2758
	unset($interface_sn_arr_cache[$realif]);
2759
	unset($interface_ipv6_arr_cache[$realif]);
2760
	unset($interface_snv6_arr_cache[$realif]);
2761

    
2762
	switch ($wancfg['ipaddr']) {
2763
		case 'dhcp':
2764
			interface_dhcp_configure($interface);
2765
			break;
2766
		case 'pppoe':
2767
		case 'l2tp':
2768
		case 'pptp':
2769
		case 'ppp':
2770
			interface_ppps_configure($interface);
2771
			break;
2772
		default:
2773
			if (is_ipaddr($wancfg['ipaddr']) && $wancfg['subnet'] <> "") {
2774
				pfSense_interface_setaddress($realif, "{$wancfg['ipaddr']}/{$wancfg['subnet']}");
2775
			} else if (substr($realif, 0, 3) == "gre") {
2776
				if (is_array($config['gres']['gre'])) {
2777
					foreach ($config['gres']['gre'] as $gre)
2778
						if ($gre['greif'] == $realif)
2779
							interface_gre_configure($gre);
2780
				}
2781
			} else if (substr($realif, 0, 3) == "gif") {
2782
				 if (is_array($config['gifs']['gif'])) {
2783
					foreach ($config['gifs']['gif'] as $gif)
2784
						if($gif['gifif'] == $realif)
2785
							interface_gif_configure($gif);
2786
				}
2787
			} else if (substr($realif, 0, 4) == "ovpn") {
2788
				/* XXX: Should be done anything?! */
2789
			}
2790
			break;
2791
	}
2792

    
2793
	switch ($wancfg['ipaddrv6']) {
2794
		case 'slaac':
2795
		case 'dhcp6':
2796
			interface_dhcpv6_configure($interface);
2797
			break;
2798
		case '6rd':
2799
			interface_6rd_configure($interface);
2800
			break;
2801
		case '6to4':
2802
			interface_6to4_configure($interface);
2803
			break;
2804
		case 'track6':
2805
			interface_track6_configure($interface);
2806
			break;
2807
		default:
2808
			if (is_ipaddr($wancfg['ipaddrv6']) && $wancfg['subnetv6'] <> "") {
2809
				pfSense_interface_setaddress($realif, "{$wancfg['ipaddrv6']}/{$wancfg['subnetv6']}");
2810
				// FIXME: Add IPv6 Support to the pfSense module
2811
				mwexec("/sbin/ifconfig {$realif} inet6 {$wancfg['ipaddrv6']} prefixlen {$wancfg['subnetv6']} ");
2812
			}
2813
			break;
2814
	}
2815

    
2816
	if(does_interface_exist($wancfg['if']))
2817
		interfaces_bring_up($wancfg['if']);
2818

    
2819
	interface_netgraph_needed($interface);
2820
 	
2821
	if (!$g['booting']) {
2822
		link_interface_to_vips($interface, "update");
2823

    
2824
		unset($gre);
2825
		$gre = link_interface_to_gre($interface);
2826
		if (!empty($gre))
2827
			array_walk($gre, 'interface_gre_configure');
2828

    
2829
		unset($gif);
2830
		$gif = link_interface_to_gif($interface);
2831
		if (!empty($gif))
2832
			array_walk($gif, 'interface_gif_configure');
2833

    
2834
		if ($linkupevent == false || substr($realif, 0, 4) == "ovpn") {
2835
			unset($bridgetmp);
2836
			$bridgetmp = link_interface_to_bridge($interface);
2837
			if (!empty($bridgetmp))
2838
				interface_bridge_add_member($bridgetmp, $realif);
2839
		}
2840

    
2841
		$grouptmp = link_interface_to_group($interface);
2842
		if (!empty($grouptmp))
2843
			array_walk($grouptmp, 'interface_group_add_member');
2844

    
2845
		if ($interface == "lan")
2846
			/* make new hosts file */
2847
			system_hosts_generate();
2848

    
2849
		if ($reloadall == true) {
2850

    
2851
			/* reconfigure static routes (kernel may have deleted them) */
2852
			system_routing_configure($interface);
2853

    
2854
			/* reload ipsec tunnels */
2855
			vpn_ipsec_configure();
2856

    
2857
			/* restart dnsmasq */
2858
			services_dnsmasq_configure();
2859

    
2860
			/* update dyndns */
2861
			send_event("service reload dyndns {$interface}");
2862

    
2863
			/* reload captive portal */
2864
			captiveportal_init_rules();
2865
		}
2866
	}
2867

    
2868
	return 0;
2869
}
2870

    
2871
function interface_track6_configure($interface = "lan") {
2872
	global $config, $g;
2873
	$iflist = get_configured_interface_with_descr(false, true);
2874

    
2875
	$wancfg = $config['interfaces'][$interface];
2876
	$wanif = $wancfg['if'];
2877
	if (empty($wancfg))
2878
		$wancfg = array();
2879

    
2880
	$wanif = get_real_interface($interface);
2881
	
2882
	/* If the interface is not configured via another, exit */
2883
	if(!$wancfg['track6-interface'] <> "") {
2884
		return(false);
2885
	}
2886

    
2887
	/* always configure a link-local of fe80::1:1 on the track6 interfaces */
2888
	$realif = get_real_interface($interface);
2889
	mwexec("/sbin/ifconfig {$realif} inet6 fe80::1:1%{$realif}");
2890

    
2891
	$type = $config['interfaces'][$wancfg['track6-interface']]['ipaddrv6'];
2892
	switch($type) {
2893
		case "6to4":
2894
			log_error("Interface {$interface} configured via {$wancfg['track6-interface']}  type {$type}");
2895
			interface_track6_6to4_configure($interface);
2896
			break;
2897
		case "6rd":
2898
			log_error("Interface {$interface} configured via {$wancfg['track6-interface']}  type {$type}");
2899
			interface_track6_6rd_configure($interface);
2900
			break;
2901
		case "dhcp6":
2902
			log_error("Interface {$interface} configured via {$wancfg['track6-interface']}  type {$type}");
2903
			interface_track6_dhcp6_configure($interface);
2904
			break;
2905
		default:
2906
			log_error("Interface {$interface} configured via {$wancfg['track6-interface']} but unknown type {$type}");
2907
			break;
2908
	}
2909
	return 0;
2910
}
2911

    
2912

    
2913
function interface_track6_6rd_configure($interface = "lan") {
2914
	global $config, $g;
2915
	$iflist = get_configured_interface_with_descr(false, true);
2916

    
2917
	$lancfg = $config['interfaces'][$interface];
2918
	$lanif = $lancfg['if'];
2919
	if (empty($lancfg))
2920
		$lancfg = array();
2921

    
2922
	$lanif = get_real_interface($interface);
2923
	
2924
	/* If the interface is not configured via another, exit */
2925
	if(!$lancfg['track6-interface'] <> "") {
2926
		return(false);
2927
	}
2928
	if(!is_numeric($lancfg['track6-prefix-id']))
2929
		$lancfg['track6-prefix-id'] = 0;
2930
	
2931
	$wancfg = $config['interfaces'][$lancfg['track6-interface']];
2932
	$wanif = $wancfg['if'];
2933
	if (empty($wancfg))
2934
		$wancfg = array();
2935
	
2936
	$ip4address = find_interface_ip($wanif);
2937
	if((!is_ipaddrv4($ip4address)) || (is_private_ip($ip4address))) {
2938
		log_error("The interface IPv4 '{$ip4address}' address on interface '{$wanif}' is not public, not configuring 6RD tunnel");
2939
		return false;
2940
	}
2941
	$hexwanv4 = return_hex_ipv4($ip4address);
2942
	
2943
	/* create the long prefix notation for math, save the prefix length */
2944
	$rd6prefix = explode("/", $wancfg['prefix-6rd']);
2945
	$rd6prefixlen = $rd6prefix[1];
2946
	$rd6prefix = Net_IPv6::uncompress($rd6prefix[0]);
2947

    
2948
	/* binary presentation of the prefix for all 128 bits. */
2949
	$rd6lanbin = convert_ipv6_to_128bit($rd6prefix);
2950
	
2951
	/* just save the left prefix length bits */
2952
	$rd6lanbin = substr($rd6lanbin, 0, $rd6prefixlen);
2953
	/* add the v4 address, offset n bits from the left */
2954
	$rd6lanbin .= substr(sprintf("%032b", hexdec($hexwanv4)), (0 + $wancfg['prefix-6rd-v4plen']), 32);
2955

    
2956
	/* add the custom prefix id, max 32bits long? (64 bits - (prefixlen + (32 - v4plen)) */
2957
	/* 64 - (37 + (32 - 17)) = 8 == /52 */
2958
	$restbits = 64 - ($rd6prefixlen + (32 - $wancfg['prefix-6rd-v4plen']));
2959
	// echo "64 - (prefixlen {$rd6prefixlen} + v4len (32 - {$wancfg['prefix-6rd-v4plen']})) = {$restbits} \n";
2960
	$rd6lanbin .= substr(sprintf("%032b", str_pad($lancfg['track6-prefix-id'], 32, "0", STR_PAD_LEFT)), (32 - $restbits), 32);
2961
	/* fill the rest out with zeros */
2962
	$rd6lanbin = str_pad($rd6lanbin, 128, "0", STR_PAD_RIGHT);;
2963

    
2964
	/* convert the 128 bits for the lan address back into a valid IPv6 address */ 
2965
	$rd6lan = convert_128bit_to_ipv6($rd6lanbin) ."1";
2966
	
2967
	log_error("rd6 {$interface} with ipv6 address {$rd6lan} based on {$lancfg['track6-interface']} ipv4 {$ip4address}");
2968
	mwexec("/sbin/ifconfig {$lanif} inet6 {$rd6lan} prefixlen 64");
2969
	return 0;
2970
}
2971

    
2972
function interface_track6_6to4_configure($interface = "lan") {
2973
	global $config, $g;
2974
	$iflist = get_configured_interface_with_descr(false, true);
2975

    
2976
	$lancfg = $config['interfaces'][$interface];
2977
	$lanif = $lancfg['if'];
2978
	if (empty($lancfg))
2979
		$lancfg = array();
2980

    
2981
	$lanif = get_real_interface($interface);
2982
	
2983
	/* If the interface is not configured via another, exit */
2984
	if(!$lancfg['track6-interface'] <> "") {
2985
		return(false);
2986
	}
2987
	if(!is_numeric($lancfg['track6-prefix-id']))
2988
		$lancfg['track6-prefix-id'] = 0;
2989
	
2990
	$wancfg = $config['interfaces'][$lancfg['track6-interface']];
2991
	$wanif = $wancfg['if'];
2992
	if (empty($wancfg))
2993
		$wancfg = array();
2994
	
2995
	$ip4address = find_interface_ip($wanif);
2996
	if((!is_ipaddrv4($ip4address)) || (is_private_ip($ip4address))) {
2997
		log_error("The interface IPv4 '{$ip4address}' address on interface '{$wanif}' is not public, not configuring 6RD tunnel");
2998
		return false;
2999
	}
3000
	$hexwanv4 = return_hex_ipv4($ip4address);
3001
	
3002
	/* create the long prefix notation for math, save the prefix length */
3003
	$sixto4prefix = "2002::";
3004
	$sixto4prefixlen = 16;
3005
	$sixto4prefix = Net_IPv6::uncompress($sixto4prefix);
3006

    
3007
	/* binary presentation of the prefix for all 128 bits. */
3008
	$sixto4lanbin = convert_ipv6_to_128bit($sixto4prefix);
3009
	
3010
	/* just save the left prefix length bits */
3011
	$sixto4lanbin = substr($sixto4lanbin, 0, $sixto4prefixlen);
3012
	/* add the v4 address */
3013
	$sixto4lanbin .= sprintf("%032b", hexdec($hexwanv4));
3014
	/* add the custom prefix id */
3015
	$sixto4lanbin .= sprintf("%016b", $lancfg['track6-prefix-id']);
3016
	/* fill the rest out with zeros */
3017
	$sixto4lanbin = str_pad($sixto4lanbin, 128, "0", STR_PAD_RIGHT);;
3018
	
3019
	/* convert the 128 bits for the lan address back into a valid IPv6 address */ 
3020
	$sixto4lan = convert_128bit_to_ipv6($sixto4lanbin) ."1";
3021
	
3022
	log_error("sixto4 {$interface} with ipv6 address {$sixto4lan} based on {$lancfg['track6-interface']} ipv4 {$ip4address}");
3023
	mwexec("/sbin/ifconfig {$lanif} inet6 {$sixto4lan} prefixlen 64");
3024
	return 0;
3025
}
3026

    
3027
function interface_track6_dhcp6_configure($interface = "lan") {
3028
	global $config, $g;
3029
	$iflist = get_configured_interface_with_descr(false, true);
3030

    
3031
	$lancfg = $config['interfaces'][$interface];
3032
	$lanif = $lancfg['if'];
3033
	if (empty($lancfg))
3034
		$lancfg = array();
3035

    
3036
	$lanif = get_real_interface($interface);
3037
	
3038
	/* If the interface is not configured via another, exit */
3039
	if(!$lancfg['track6-interface'] <> "") {
3040
		return(false);
3041
	}
3042
	if(!is_numeric($lancfg['track6-prefix-id']))
3043
		$lancfg['track6-prefix-id'] = 0;
3044
	
3045
	$wancfg = $config['interfaces'][$lancfg['track6-interface']];
3046
	$wanif = $wancfg['if'];
3047
	if (empty($wancfg))
3048
		$wancfg = array();
3049
	
3050
	
3051
	$ifcfgipv6 = find_interface_ipv6($lanif);
3052
	if(is_ipaddrv6($ifcfgipv6)) {
3053
		$dhcp6lanarr = explode(":", Net_IPv6::uncompress($ifcfgipv6));
3054
		$dhcp6lanarr[4] = 0;
3055
		$dhcp6lanarr[5] = 0;
3056
		$dhcp6lanarr[6] = 0;
3057
		$dhcp6lanarr[7] = 1;
3058
		$dhcp6lan =  Net_IPv6::compress(implode(":", $dhcp6lanarr));
3059
		log_error("dhcp6 {$interface} with ipv6 address {$dhcp6lan} based on {$lancfg['track6-interface']}");
3060
		mwexec("/sbin/ifconfig {$lanif} inet6 {$dhcp6lan} prefixlen 64");
3061
	}
3062
	return 0;
3063
}
3064

    
3065
function interface_6rd_configure($interface = "wan") {
3066
	global $config, $g;
3067
	$iflist = get_configured_interface_with_descr(false, true);
3068

    
3069
	/* because this is a tunnel interface we can only function 
3070
	 *	with a public IPv4 address on the interface */
3071

    
3072
	$wancfg = $config['interfaces'][$interface];
3073
	$wanif = $wancfg['if'];
3074
	if (empty($wancfg))
3075
		$wancfg = array();
3076

    
3077
	$wanif = get_real_interface($interface);
3078
	
3079
	$ip4address = find_interface_ip($wanif);
3080
	$ip4gateway = get_interface_gateway($wanif);
3081
	if((!is_ipaddrv4($ip4address)) || (is_private_ip($ip4address))) {
3082
		log_error("The interface IPv4 '{$ip4address}' address on interface '{$wanif}' is not public, not configuring 6RD tunnel");
3083
		return false;
3084
	}
3085
	$hexwanv4 = return_hex_ipv4($ip4address);
3086
	
3087
	if(!is_numeric($wancfg['prefix-6rd-v4plen']))
3088
		$wancfg['prefix-6rd-v4plen'] = 0;
3089

    
3090
	/* create the long prefix notation for math, save the prefix length */
3091
	$rd6prefix = explode("/", $wancfg['prefix-6rd']);
3092
	$rd6prefixlen = $rd6prefix[1];
3093
	$rd6prefix = Net_IPv6::uncompress($rd6prefix[0]);
3094

    
3095
	/* we need the hex form of the broker IPv4 address */
3096
	$hexbrv4 = return_hex_ipv4($wancfg['gateway-6rd']);
3097
	
3098
	/* binary presentation of the prefix for all 128 bits. */
3099
	$rd6prefixbin = convert_ipv6_to_128bit($rd6prefix);
3100
		
3101
	/* just save the left prefix length bits */
3102
	$rd6brprefixbin = substr($rd6prefixbin, 0, $rd6prefixlen);
3103
	/* if the prefix length is not 32 bits we need to shave bits off from the left of the v4 address. */
3104
	$rd6brprefixbin .= substr(sprintf("%032b", hexdec($hexbrv4)), $wancfg['prefix-6rd-v4plen'], 32);
3105
	/* fill out the rest with 0's */
3106
	$rd6brprefixbin = str_pad($rd6brprefixbin, 128, "0", STR_PAD_RIGHT);;
3107

    
3108
	/* convert the 128 bits for the broker address back into a valid IPv6 address */ 
3109
	$rd6brgw = convert_128bit_to_ipv6($rd6brprefixbin);
3110

    
3111
	/* just save the left prefix length bits */
3112
	$rd6prefixbin = substr($rd6prefixbin, 0, $rd6prefixlen);
3113
	/* if the prefix length is not 32 bits we need to shave bits off from the left of the v4 address. */
3114
	$rd6prefixbin .= substr(sprintf("%032b", hexdec($hexwanv4)), $wancfg['prefix-6rd-v4plen'], 32);
3115
	/* fill out the rest with 0's */
3116
	$rd6prefixbin = str_pad($rd6prefixbin, 128, "0", STR_PAD_RIGHT);;
3117

    
3118
	/* convert the 128 bits for the broker address back into a valid IPv6 address */ 
3119
	$rd6prefix = convert_128bit_to_ipv6($rd6prefixbin);
3120

    
3121
	/* stf approach only works when embedding the entire 32 bits of the v4 */
3122
	mwexec("/sbin/ifconfig stf0 create");
3123
	pfSense_interface_flags("stf0", IFF_LINK2);
3124
	mwexec("/sbin/ifconfig stf0 inet6 {$rd6prefix}/{$rd6prefixlen}");
3125
	log_error("Created 6rd interface stf0 {$rd6prefix}/{$rd6prefixlen}");
3126

    
3127
	/* write out a default router file */
3128
	file_put_contents("{$g['tmp_path']}/{$wanif}_routerv6", "{$rd6brgw}\n");
3129
	file_put_contents("{$g['tmp_path']}/{$wanif}_defaultgwv6", "{$rd6brgw}\n");
3130

    
3131
	if (is_ipaddrv4($ip4gateway))
3132
		mwexec("route change -host " . $wancfg['gateway-6rd'] . " {$ip4gateway}");
3133

    
3134
	/* configure dependent interfaces */
3135
	foreach($iflist as $if => $ifname) {
3136
		if($config['interfaces'][$if]['track6-interface'] == $interface)
3137
			interface_track6_configure($if);
3138
	}
3139

    
3140
	return 0;
3141
}
3142

    
3143
function interface_6to4_configure($interface = "wan"){
3144
	global $config, $g;
3145
	$iflist = get_configured_interface_with_descr(false, true);
3146

    
3147
	/* because this is a tunnel interface we can only function 
3148
	 *	with a public IPv4 address on the interface */
3149

    
3150
	$wancfg = $config['interfaces'][$interface];
3151
	$wanif = $wancfg['if'];
3152
	if (empty($wancfg))
3153
		$wancfg = array();
3154

    
3155
	$wanif = get_real_interface($interface);
3156
	
3157
	$ip4address = find_interface_ip($wanif);
3158
	$ip4gateway = get_interface_gateway($wanif);
3159
	if((!is_ipaddrv4($ip4address)) || (is_private_ip($ip4address))) {
3160
		log_error("The interface IPv4 '{$ip4address}' address on interface '{$wanif}' is not public, not configuring 6RD tunnel");
3161
		return false;
3162
	}
3163
	
3164
	/* create the long prefix notation for math, save the prefix length */
3165
	$stfprefixlen = 16;
3166
	$stfprefix = Net_IPv6::uncompress("2002::");
3167
	$stfarr = explode(":", $stfprefix);
3168
	$v4prefixlen = "0";
3169
	
3170
	/* we need the hex form of the interface IPv4 address */
3171
	$ip4arr = explode(".", $ip4address);
3172
	$hexwanv4 = "";
3173
	foreach($ip4arr as $octet)
3174
		$hexwanv4 .= sprintf("%02x", $octet);
3175

    
3176
	/* we need the hex form of the broker IPv4 address */
3177
	$ip4arr = explode(".", "192.88.99.1");
3178
	$hexbrv4 = "";
3179
	foreach($ip4arr as $octet)
3180
		$hexbrv4 .= sprintf("%02x", $octet);
3181
	
3182
	/* binary presentation of the prefix for all 128 bits. */
3183
	$stfprefixbin = "";
3184
	foreach($stfarr as $element) {
3185
		$stfprefixbin .= sprintf("%016b", hexdec($element));
3186
	}
3187
	/* just save the left prefix length bits */
3188
	$stfprefixstartbin = substr($stfprefixbin, 0, $stfprefixlen);
3189

    
3190
	/* if the prefix length is not 32 bits we need to shave bits off from the left of the v4 address. */
3191
	$stfbrokerbin = substr(sprintf("%032b", hexdec($hexbrv4)), $v4prefixlen, 32);
3192
	$stfbrokerbin = str_pad($stfprefixstartbin . $stfbrokerbin, 128, "0", STR_PAD_RIGHT);;
3193

    
3194
	/* for the local subnet too. */
3195
	$stflanbin = substr(sprintf("%032b", hexdec($hexwanv4)), $v4prefixlen, 32);
3196
	$stflanbin = str_pad($stfprefixstartbin . $stflanbin, 128, "0", STR_PAD_RIGHT);;
3197

    
3198
	/* convert the 128 bits for the broker address back into a valid IPv6 address */ 
3199
	$stfbrarr = array();
3200
	$stfbrbinarr = array();
3201
	$stfbrbinarr = str_split($stfbrokerbin, 16);
3202
	foreach($stfbrbinarr as $bin)
3203
		$stfbrarr[] = dechex(bindec($bin));
3204
	$stfbrgw = Net_IPv6::compress(implode(":", $stfbrarr));
3205

    
3206
	/* convert the 128 bits for the broker address back into a valid IPv6 address */ 
3207
	$stflanarr = array();
3208
	$stflanbinarr = array();
3209
	$stflanbinarr = str_split($stflanbin, 16);
3210
	foreach($stflanbinarr as $bin)
3211
		$stflanarr[] = dechex(bindec($bin));
3212
	$stflanpr = Net_IPv6::compress(implode(":", $stflanarr));
3213
	$stflanarr[7] = 1;
3214
	$stflan = Net_IPv6::compress(implode(":", $stflanarr));
3215

    
3216
	/* setup the stf interface */
3217
	mwexec("/sbin/ifconfig stf0 destroy");
3218
	mwexec("/sbin/ifconfig stf0 create");
3219
	pfSense_interface_flags("stf0", IFF_LINK2);
3220
	mwexec("/sbin/ifconfig stf0 inet6 {$stflanpr} prefixlen 16");
3221

    
3222
	log_error("Set IPv6 address inet6 {$stflanpr} prefixlen 16 for stf0, route {$stfbrgw}");
3223
	
3224
	/* write out a default router file */
3225
	file_put_contents("{$g['tmp_path']}/{$wanif}_routerv6", "{$stfbrgw}");
3226
	file_put_contents("{$g['tmp_path']}/{$wanif}_defaultgwv6", "{$stfbrgw}");
3227

    
3228
	if (is_ipaddrv4($ip4gateway)) {
3229
		mwexec("route change -host 192.88.99.1 {$ip4gateway}");
3230
	}
3231

    
3232
	/* configure dependent interfaces */
3233
	foreach($iflist as $if => $ifname) {
3234
		if($config['interfaces'][$if]['track6-interface'] == $interface)
3235
			interface_track6_configure($if);
3236
	}
3237
	
3238
	return 0;
3239
}
3240

    
3241
function interface_dhcpv6_configure($interface = "wan") {
3242
	global $config, $g;
3243
	$iflist = get_configured_interface_with_descr(false, true);
3244

    
3245
	$wancfg = $config['interfaces'][$interface];
3246
	$wanif = $wancfg['if'];
3247
	if (empty($wancfg))
3248
		$wancfg = array();
3249

    
3250
	$wanif = get_real_interface($interface);
3251

    
3252
	/* wide-dhcp6c works for now. */
3253
	$fd = fopen("{$g['varetc_path']}/dhcp6c_{$interface}.conf", "w");
3254
	if (!$fd) {
3255
		printf("Error: cannot open dhcp6c_{$interface}.conf in interface_dhcpv6_configure() for writing.\n");
3256
		return 1;
3257
	}
3258

    
3259
	$dhcp6cconf = "";
3260
	$dhcp6cconf .= "interface {$wanif} {\n";
3261

    
3262
	/* for SLAAC interfaces we do fire off a dhcp6 client for just our name servers */
3263
	if($wancfg['ipaddrv6'] == "slaac") {
3264
		$dhcp6cconf .= "	information-only;\n";
3265
		$dhcp6cconf .= "	request domain-name-servers;\n";
3266
		$dhcp6cconf .= "	request domain-name;\n";
3267
		$dhcp6cconf .= "	script \"{$g['varetc_path']}/dhcp6c_{$interface}_script.sh\"; # we'd like some nameservers please\n";
3268
		$dhcp6cconf .= "};\n";
3269
	} else {
3270
	
3271
		$dhcp6cconf .= " 	send ia-na 0;	# request stateful address\n";
3272
		if(is_numeric($wancfg['dhcp6-ia-pd-len'])) {
3273
			$dhcp6cconf .= "	send ia-pd 0;	# request prefix delegation\n";
3274
		}
3275
		$dhcp6cconf .= "request domain-name-servers;\n";
3276
		$dhcp6cconf .= "request domain-name;\n";
3277
		$dhcp6cconf .= "script \"{$g['varetc_path']}/dhcp6c_{$interface}_script.sh\"; # we'd like some nameservers please\n";
3278

    
3279
		$dhcp6cconf .= "};\n";
3280
		$dhcp6cconf .= "id-assoc na 0 { };\n";
3281
		if(is_numeric($wancfg['dhcp6-ia-pd-len'])) {
3282
			/* Setup the prefix delegation */
3283
			$dhcp6cconf .= "id-assoc pd 0 {\n";
3284
			foreach($iflist as $friendly => $ifdescr) {
3285
				if($config['interfaces'][$friendly]['track6-interface'] != $interface)
3286
					continue;
3287
				if(is_numeric($config['interfaces'][$friendly]['track6-prefix-id'])) {
3288
					log_error("setting up $friendly - {$config['interfaces'][$friendly]['track6-prefix-id']}");
3289
					$realif = get_real_interface($friendly);
3290
					$dhcp6cconf .= "	prefix-interface {$realif} {\n";
3291
					$dhcp6cconf .= "		sla-id {$config['interfaces'][$friendly]['track6-prefix-id']};\n";
3292
					$dhcp6cconf .= "		sla-len {$wancfg['dhcp6-ia-pd-len']};\n";
3293
					$dhcp6cconf .= "	};\n";
3294
				}
3295
			}
3296
			$dhcp6cconf .= "};\n";
3297
		}
3298
	}
3299
	fwrite($fd, $dhcp6cconf);
3300
	fclose($fd);
3301

    
3302
	/* Add wide-dhcp6c shell script here. Because we can not pass a argument to it. */
3303
	$fds = fopen("{$g['varetc_path']}/dhcp6c_{$interface}_script.sh", "w");
3304
	if (!$fds) {
3305
		printf("Error: cannot open dhcp6c_{$interface}_script.sh in interface_dhcpv6_configure() for writing.\n");
3306
		return 1;
3307
	}
3308
	$dhcp6cscript = "#!/bin/sh\n";
3309
	$dhcp6cscript .= "# This shell script launches /etc/rc.newwanipv6 with a interface argument.\n";
3310
	$dhcp6cscript .= "/etc/rc.newwanipv6 $wanif \n";
3311

    
3312
	fwrite($fds, $dhcp6cscript);
3313
	fclose($fds);
3314
	chmod("{$g['varetc_path']}/dhcp6c_{$interface}_script.sh", 0755);
3315

    
3316

    
3317
	/* accept router advertisements for this interface */
3318
	mwexec("/sbin/sysctl -w net.inet6.ip6.accept_rtadv=1");
3319
	log_error("Accept router advertisements on interface {$wanif} ");
3320
	mwexec("/sbin/ifconfig {$wanif} inet6 accept_rtadv");
3321

    
3322
	/* run a filter configure sync so that the filter rules allow traffic before we launch the client */
3323
	/* there reallyt is no good way around this i'm 'fraid */
3324
	filter_configure_sync();
3325

    
3326
	/* fire up dhcp6c for IPv6 first, this backgrounds immediately */
3327
	mwexec("/usr/local/sbin/dhcp6c -d -c {$g['varetc_path']}/dhcp6c_{$interface}.conf {$wanif}");
3328
	sleep(1);
3329
	exec("/sbin/rtsol -d {$wanif} 2>&1", $out, $ret);
3330
	if(!empty($out)) {
3331
		foreach($out as $line) {
3332
			if((stristr($line, "received")) && (!stristr($line, "unexpected"))) {
3333
				$parts = explode(" ", $line);
3334
				if(is_ipaddrv6($parts[3])) {
3335
					log_error("Found IPv6 default gateway '{$parts[3]}' by RA.");
3336
					file_put_contents("{$g['tmp_path']}/{$wanif}_routerv6", "{$parts[3]}\n");
3337
					file_put_contents("{$g['tmp_path']}/{$wanif}_defaultgwv6", "{$parts[3]}\n");
3338
					break;
3339
				}
3340
			}
3341
		}
3342
	}
3343
	/* worst case is that the rc.newwanipv6 handles setting up the track6 interface */
3344
	if($wancfg['ippaddrv6'] != "slaac") {
3345
		/* configure dependent interfaces */
3346
		foreach($iflist as $if => $ifname) {
3347
			if($config['interfaces'][$if]['track6-interface'] == $interface)
3348
				interface_track6_configure($if);
3349
		}
3350
	}
3351
	return 0;
3352
}
3353

    
3354
function interface_dhcp_configure($interface = "wan") {
3355
	global $config, $g;
3356

    
3357
	$wancfg = $config['interfaces'][$interface];
3358
	$wanif = $wancfg['if'];
3359
	if (empty($wancfg))
3360
		$wancfg = array();
3361

    
3362
	/* generate dhclient_wan.conf */
3363
	$fd = fopen("{$g['varetc_path']}/dhclient_{$interface}.conf", "w");
3364
	if (!$fd) {
3365
		printf(printf(gettext("Error: cannot open dhclient_%s.conf in interface_dhcp_configure() for writing.%s"), $interface, "\n"));
3366
		return 1;
3367
	}
3368

    
3369
	if ($wancfg['dhcphostname']) {
3370
		$dhclientconf_hostname = "send dhcp-client-identifier \"{$wancfg['dhcphostname']}\";\n";
3371
		$dhclientconf_hostname .= "\tsend host-name \"{$wancfg['dhcphostname']}\";\n";
3372
	} else {
3373
		$dhclientconf_hostname = "";
3374
	}
3375

    
3376
	$wanif = get_real_interface($interface);
3377
	if (empty($wanif)) {
3378
		log_error(sprintf(gettext("Invalid interface \"%s\" in interface_dhcp_configure()"), $interface));
3379
		return 0;
3380
	}
3381
 	$dhclientconf = "";
3382
	
3383
	$dhclientconf .= <<<EOD
3384
interface "{$wanif}" {
3385
timeout 60;
3386
retry 15;
3387
select-timeout 0;
3388
initial-interval 1;
3389
	{$dhclientconf_hostname}
3390
	script "/sbin/dhclient-script";
3391
}
3392

    
3393
EOD;
3394

    
3395
if(is_ipaddr($wancfg['alias-address'])) {
3396
	$subnetmask = gen_subnet_mask($wancfg['alias-subnet']);
3397
	$dhclientconf .= <<<EOD
3398
alias {
3399
	interface  "{$wanif}";
3400
	fixed-address {$wancfg['alias-address']};
3401
	option subnet-mask {$subnetmask};
3402
}
3403

    
3404
EOD;
3405
}
3406
	fwrite($fd, $dhclientconf);
3407
	fclose($fd);
3408

    
3409
	/* bring wan interface up before starting dhclient */
3410
	if($wanif)
3411
		interfaces_bring_up($wanif);
3412
	else 
3413
		log_error(printf(gettext("Could not bring up %s interface in interface_dhcp_configure()"), $wanif));
3414

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

    
3418
	return 0;
3419
}
3420

    
3421
function interfaces_group_setup() {
3422
	global $config;
3423

    
3424
	if (!is_array($config['ifgroups']['ifgroupentry']))
3425
		return;
3426

    
3427
	foreach ($config['ifgroups']['ifgroupentry'] as $groupar)
3428
		interface_group_setup($groupar);
3429

    
3430
	return;
3431
}
3432

    
3433
function interface_group_setup(&$groupname /* The parameter is an array */) {
3434
	global $config;
3435

    
3436
	if (!is_array($groupname))
3437
		return;
3438
	$members = explode(" ", $groupname['members']);
3439
	foreach($members as $ifs) {
3440
		$realif = get_real_interface($ifs);
3441
		if ($realif)
3442
			mwexec("/sbin/ifconfig {$realif} group {$groupname['ifname']}");
3443
	}
3444

    
3445
	return;
3446
}
3447

    
3448
function interface_group_add_member($interface, $groupname) {
3449
	$interface = get_real_interface($interface);
3450
	mwexec("/sbin/ifconfig {$interface} group {$groupname}", true);
3451
}
3452
 
3453
/* COMPAT Function */
3454
function convert_friendly_interface_to_real_interface_name($interface) {
3455
	return get_real_interface($interface);
3456
}
3457

    
3458
/* COMPAT Function */
3459
function get_real_wan_interface($interface = "wan") {
3460
	return get_real_interface($interface);
3461
}
3462

    
3463
/* COMPAT Function */
3464
function get_current_wan_address($interface = "wan") {
3465
	return get_interface_ip($interface);
3466
}
3467

    
3468
/*
3469
 * convert_real_interface_to_friendly_interface_name($interface): convert fxp0 -> wan, etc.
3470
 */
3471
function convert_real_interface_to_friendly_interface_name($interface = "wan") {
3472
        global $config;
3473

    
3474
	if (stristr($interface, "_vip")) {
3475
                foreach ($config['virtualip']['vip'] as $counter => $vip) {
3476
                        if ($vip['mode'] == "carp")  {
3477
                                if ($interface == "{$vip['interface']}_vip{$vip['vhid']}")
3478
                                        return $vip['interface'];
3479
                        }
3480
                }
3481
        }
3482

    
3483
        /* XXX: For speed reasons reference directly the interface array */
3484
	$ifdescrs = &$config['interfaces'];
3485
        //$ifdescrs = get_configured_interface_list(false, true);
3486

    
3487
        foreach ($ifdescrs as $if => $ifname) {
3488
                if ($config['interfaces'][$if]['if'] == $interface)
3489
                        return $if;
3490

    
3491
                if (stristr($interface, "_wlan0") && $config['interfaces'][$if]['if'] == interface_get_wireless_base($interface))
3492
                        return $if;
3493

    
3494
		// XXX: This case doesn't work anymore (segfaults - recursion?) - should be replaced with something else or just removed.
3495
		//      Not to be replaced with get_real_interface - causes slow interface listings here because of recursion!
3496
		/*
3497
                $int = get_parent_interface($if);
3498
                if ($int[0] == $interface)
3499
                        return $ifname;
3500
		*/
3501
        }
3502
        return NULL;
3503
}
3504

    
3505
/* attempt to resolve interface to friendly descr */
3506
function convert_friendly_interface_to_friendly_descr($interface) {
3507
        global $config;
3508

    
3509
        switch ($interface) {
3510
        case "l2tp":
3511
        	$ifdesc = "L2TP";
3512
                break;
3513
	case "pptp":
3514
		$ifdesc = "PPTP";
3515
		break;
3516
	case "pppoe":
3517
		$ifdesc = "PPPoE";
3518
		break;
3519
	case "openvpn":
3520
		$ifdesc = "OpenVPN";
3521
		break;
3522
	case "enc0":
3523
	case "ipsec":
3524
		$ifdesc = "IPsec";
3525
		break;
3526
        default:
3527
                if (isset($config['interfaces'][$interface])) {
3528
                        if (empty($config['interfaces'][$interface]['descr']))
3529
                                $ifdesc = strtoupper($interface);
3530
                        else
3531
                                $ifdesc = strtoupper($config['interfaces'][$interface]['descr']);
3532
			break;
3533
		} else if (stristr($interface, "_vip")) {
3534
			if (is_array($config['virtualip']['vip'])) {
3535
				foreach ($config['virtualip']['vip'] as $counter => $vip) {
3536
					if ($vip['mode'] == "carp")  {
3537
						if ($interface == "{$vip['interface']}_vip{$vip['vhid']}")
3538
							return "{$vip['subnet']} - {$vip['descr']}";
3539
					}
3540
				}
3541
                        }
3542
                } else {
3543
			/* if list */
3544
			$ifdescrs = get_configured_interface_with_descr(false, true);
3545
			foreach ($ifdescrs as $if => $ifname) {
3546
				if ($if == $interface || $ifname == $interface)
3547
					return $ifname;
3548
			}
3549
		}
3550
                break;
3551
        }
3552

    
3553
        return $ifdesc;
3554
}
3555

    
3556
function convert_real_interface_to_friendly_descr($interface) {
3557
        global $config;
3558

    
3559
        $ifdesc = convert_real_interface_to_friendly_interface_name("{$interface}");
3560

    
3561
        if ($ifdesc) {
3562
                $iflist = get_configured_interface_with_descr(false, true);
3563
                return $iflist[$ifdesc];
3564
        }
3565

    
3566
        return $interface;
3567
}
3568

    
3569
/*
3570
 *  get_parent_interface($interface):
3571
 *			--returns the (real or virtual) parent interface(s) array for a given interface friendly name (i.e. wan)
3572
 *				or virtual interface (i.e. vlan)
3573
 *				(We need array because MLPPP and bridge interfaces have more than one parent.)
3574
 *			-- returns $interface passed in if $interface parent is not found
3575
 *			-- returns empty array if an invalid interface is passed
3576
 *	(Only handles ppps and vlans now.)
3577
 */
3578
function get_parent_interface($interface) {
3579
	global $config;
3580

    
3581
	$parents = array();
3582
	//Check that we got a valid interface passed
3583
	$realif = get_real_interface($interface);
3584
	if ($realif == NULL)
3585
		return $parents;
3586

    
3587
	// If we got a real interface, find it's friendly assigned name
3588
	$interface = convert_real_interface_to_friendly_interface_name($interface);
3589
		
3590
	if (!empty($interface) && isset($config['interfaces'][$interface])) {
3591
		$ifcfg = $config['interfaces'][$interface];
3592
		switch ($ifcfg['ipaddr']) {
3593
			case "ppp":
3594
			case "pppoe":
3595
			case "pptp":
3596
			case "l2tp":
3597
				if (empty($parents))
3598
					if (is_array($config['ppps']['ppp']))
3599
						foreach ($config['ppps']['ppp'] as $pppidx => $ppp) {
3600
							if ($ppp_if == $ppp['if']) {
3601
								$ports = explode(',', $ppp['ports']);
3602
								foreach ($ports as $pid => $parent_if) 
3603
									$parents[$pid] = get_real_interface($parent_if);
3604
								break;
3605
							}
3606
						}
3607
				break;
3608
			case "dhcp":
3609
			case "static":
3610
			default:
3611
				// Handle _vlans
3612
				if (strstr($realif,"_vlan"))
3613
					if (is_array($config['vlans']['vlan'])) 
3614
						foreach ($config['vlans']['vlan'] as $vlanidx => $vlan)
3615
							if ($ifcfg['if'] == $vlan['vlanif']){
3616
								$parents[0] = $vlan['if'];
3617
								break;
3618
							}
3619
				break;
3620
		}
3621
	}
3622
	
3623
	if (empty($parents))
3624
		$parents[0] = $realif;
3625
	
3626
	return $parents;
3627
}
3628

    
3629
function interface_is_wireless_clone($wlif) {
3630
	if(!stristr($wlif, "_wlan")) {
3631
		return false;
3632
	} else {
3633
		return true;
3634
	}
3635
}
3636

    
3637
function interface_get_wireless_base($wlif) {
3638
	if(!stristr($wlif, "_wlan")) {
3639
		return $wlif;
3640
	} else {
3641
		return substr($wlif, 0, stripos($wlif, "_wlan"));
3642
	}
3643
}
3644

    
3645
function interface_get_wireless_clone($wlif) {
3646
	if(!stristr($wlif, "_wlan")) {
3647
		return $wlif . "_wlan0";
3648
	} else {
3649
		return $wlif;
3650
	}
3651
}
3652

    
3653
function get_real_interface($interface = "wan") {
3654
    global $config;
3655

    
3656
	$wanif = NULL;
3657

    
3658
	switch ($interface) {
3659
	case "l2tp":
3660
		$wanif = "l2tp";
3661
		break;
3662
	case "pptp":
3663
		$wanif = "pptp";
3664
		break;
3665
	case "pppoe":
3666
		$wanif = "pppoe";
3667
		break;
3668
	case "openvpn":
3669
		$wanif = "openvpn";
3670
		break;
3671
	case "ipsec":
3672
	case "enc0":
3673
		$wanif = "enc0";
3674
		break;
3675
	case "ppp":
3676
		$wanif = "ppp";
3677
		break;
3678
	default:
3679
		// If a real interface was alread passed simply
3680
		// pass the real interface back.  This encourages
3681
		// the usage of this function in more cases so that
3682
		// we can combine logic for more flexibility.
3683
		if(does_interface_exist($interface)) {
3684
			$wanif = $interface;
3685
			break;
3686
		}
3687

    
3688
		if (empty($config['interfaces'][$interface]))
3689
			break;
3690

    
3691
		$cfg = &$config['interfaces'][$interface];
3692

    
3693
		// Wireless cloned NIC support (FreeBSD 8+)
3694
		// interface name format: $parentnic_wlanparentnic#
3695
		// example: ath0_wlan0
3696
		if (is_interface_wireless($cfg['if'])) {
3697
			$wanif = interface_get_wireless_clone($cfg['if']);
3698
			break;
3699
		}
3700
		/*
3701
		if (empty($cfg['if'])) {
3702
			$wancfg = $cfg['if'];
3703
			break;
3704
		}
3705
		*/
3706

    
3707
		switch ($cfg['ipaddr']) {
3708
			case "pppoe": 
3709
			case "pptp": 
3710
			case "l2tp": 
3711
			case "ppp":
3712
				$wanif = $cfg['if'];
3713
				break;
3714
			default:
3715
				$wanif = $cfg['if'];
3716
				break;
3717
		}
3718
		break;
3719
	}
3720

    
3721
    return $wanif;
3722
}
3723

    
3724
/* Guess the physical interface by providing a IP address */
3725
function guess_interface_from_ip($ipaddress) {
3726
	if(! is_ipaddr($ipaddress)) {
3727
		return false;
3728
	}
3729
	if(is_ipaddrv4($ipaddress)) {
3730
		/* create a route table we can search */
3731
		exec("netstat -rnWf inet", $output, $ret);
3732
		foreach($output as $line) {
3733
			if(preg_match("/^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\/[0-9]+[ ]+link[#]/", $line)) {
3734
				$fields = preg_split("/[ ]+/", $line);
3735
				if(ip_in_subnet($ipaddress, $fields[0])) {
3736
					return $fields[6];
3737
				}
3738
			}
3739
		}
3740
	}
3741
	/* FIXME: This works from cursory testing, regexp might need fine tuning */
3742
	if(is_ipaddrv6($ipaddress)) {
3743
		/* create a route table we can search */
3744
		exec("netstat -rnWf inet6", $output, $ret);
3745
		foreach($output as $line) {
3746
			if(preg_match("/[0-9a-f]+[:]+[0-9a-f]+[:]+[\/][0-9]+/", $line)) {
3747
				$fields = preg_split("/[ ]+/", $line);
3748
				if(ip_in_subnet($ipaddress, $fields[0])) {
3749
					return $fields[6];
3750
				}
3751
			}
3752
		}
3753
	}
3754
	$ret = exec_command("/sbin/route -n get {$ipaddress} | /usr/bin/awk '/interface/ { print \$2; };'");
3755
	if(empty($ret)) {
3756
        	return false;
3757
	}
3758
	return $ret;
3759
}
3760

    
3761
/*
3762
 * find_ip_interface($ip): return the interface where an ip is defined
3763
 *   (or if $bits is specified, where an IP within the subnet is defined)
3764
 */
3765
function find_ip_interface($ip, $bits = null)
3766
{
3767
	/* if list */
3768
	$ifdescrs = get_configured_interface_list();
3769
		
3770
	foreach ($ifdescrs as $ifdescr => $ifname) {
3771
		if ($bits === null) {
3772
			if ($ip == get_interface_ip($ifname)) {
3773
				$int = get_real_interface($ifname);
3774
				return $int;
3775
			}
3776
		}
3777
		else {
3778
			if (ip_in_subnet(get_interface_ip($ifname), $ip . "/" . $bits)) {
3779
				$int = get_real_interface($ifname);
3780
				return $int;
3781
			}
3782
		}
3783
	}
3784
	return false;
3785
}
3786

    
3787
/*
3788
 * find_virtual_ip_alias($ip): return the virtual IP alias where an IP is found
3789
 *   (or if $bits is specified, where an IP within the subnet is found)
3790
 */
3791
function find_virtual_ip_alias($ip, $bits = null) {
3792
	global $config;
3793
	if (!is_array($config['virtualip']['vip'])) {
3794
		return false;
3795
	}
3796
	foreach ($config['virtualip']['vip'] as $vip) {
3797
		if ($vip['mode'] === "ipalias") {
3798
			if ($bits === null) {
3799
				if (ip_in_subnet($ip, $vip['subnet'] . "/" . $vip['subnet_bits'])) {
3800
					return $vip;
3801
				}
3802
			}
3803
			else {
3804
				if (check_subnets_overlap($ip, $bits, $vip['subnet'], $vip['subnet_bits'])) {
3805
					return $vip;
3806
				}
3807
			}
3808
		}
3809
	}
3810
	return false;
3811
}
3812

    
3813
/*
3814
 *   find_number_of_created_carp_interfaces: return the number of carp interfaces
3815
 */
3816
function find_number_of_created_carp_interfaces() {
3817
	return `/sbin/ifconfig | grep "carp:" | wc -l`;
3818
}
3819

    
3820
function get_all_carp_interfaces() {
3821
	$ints = str_replace("\n", " ", `ifconfig | grep "carp:" -B2 | grep ": flag" | cut -d: -f1`);
3822
	$ints = explode(" ", $ints);
3823
	return $ints;
3824
}
3825

    
3826
/*
3827
 * find_carp_interface($ip): return the carp interface where an ip is defined
3828
 */
3829
function find_carp_interface($ip) {
3830
	global $config;
3831
	if (is_array($config['virtualip']['vip'])) {
3832
		foreach ($config['virtualip']['vip'] as $vip) {
3833
			if ($vip['mode'] == "carp") {
3834
				if(is_ipaddrv4($ip)) {
3835
					$carp_ip = get_interface_ip($vip['interface']);
3836
				}
3837
				if(is_ipaddrv6($ip)) {
3838
					$carp_ip = get_interface_ipv6($vip['interface']);
3839
				}
3840
				exec("/sbin/ifconfig", $output, $return);
3841
				foreach($output as $line) {
3842
					$elements = preg_split("/[ ]+/i", $line);
3843
					if(strstr($elements[0], "vip"))
3844
						$curif = str_replace(":", "", $elements[0]);
3845
					if(stristr($line, $ip)) {
3846
						$if = $curif;
3847
						continue;
3848
					}
3849
				}
3850

    
3851
				if ($if)
3852
					return $if;
3853
			}
3854
		}
3855
	}
3856
}
3857

    
3858
function link_carp_interface_to_parent($interface) {
3859
	global $config;
3860

    
3861
	if ($interface == "")
3862
		return;
3863

    
3864
	$carp_ip = get_interface_ip($interface);
3865
	$carp_ipv6 = get_interface_ipv6($interface);
3866

    
3867
	if((!is_ipaddrv4($carp_ip)) && (!is_ipaddrv6($carp_ipv6)))
3868
		return;
3869

    
3870
	/* if list */
3871
	$ifdescrs = get_configured_interface_list();
3872
	foreach ($ifdescrs as $ifdescr => $ifname) {
3873
		/* check IPv4 */
3874
		if(is_ipaddrv4($carp_ip)) {
3875
			$interfaceip = get_interface_ip($ifname);
3876
			$subnet_bits = get_interface_subnet($ifname);
3877
			$subnet_ip = gen_subnet("{$interfaceip}", "{$subnet_bits}");
3878
			if(ip_in_subnet($carp_ip, "{$subnet_ip}/{$subnet_bits}"))
3879
				return $ifname;
3880
		}
3881
		/* Check IPv6 */
3882
		if(is_ipaddrv6($carp_ipv6)) {
3883
			$interfaceipv6 = get_interface_ipv6($ifname);
3884
			$prefixlen = get_interface_subnetv6($ifname);
3885
			if(ip_in_subnet($carp_ipv6, "{$interfaceipv6}/{$prefixlen}"))
3886
				return $ifname;
3887
		}
3888
	}
3889
	return "";
3890
}
3891

    
3892

    
3893
/****f* interfaces/link_ip_to_carp_interface
3894
 * NAME
3895
 *   link_ip_to_carp_interface - Find where a CARP interface links to.
3896
 * INPUTS
3897
 *   $ip
3898
 * RESULT
3899
 *   $carp_ints
3900
 ******/
3901
function link_ip_to_carp_interface($ip) {
3902
        global $config;
3903

    
3904
        if (!is_ipaddr($ip))
3905
                return;
3906

    
3907
        $carp_ints = "";
3908
        if (is_array($config['virtualip']['vip'])) {
3909
		$first = 0;
3910
		$carp_int = array();
3911
                foreach ($config['virtualip']['vip'] as $vip) {
3912
                        if ($vip['mode'] == "carp") {
3913
                                $carp_ip = $vip['subnet'];
3914
                                $carp_sn = $vip['subnet_bits'];
3915
                                $carp_nw = gen_subnet($carp_ip, $carp_sn);
3916
                                if (ip_in_subnet($ip, "{$carp_nw}/{$carp_sn}")) {
3917
					$carp_int[] = "{$vip['interface']}_vip{$vip['vhid']}";
3918
				}
3919
                        }
3920
                }
3921
		if (!empty($carp_int))
3922
			$carp_ints = implode(" ", array_unique($carp_int));
3923
        }
3924

    
3925
        return $carp_ints;
3926
}
3927

    
3928
function link_interface_to_vlans($int, $action = "") {
3929
	global $config;
3930

    
3931
	if (empty($int))
3932
		return;
3933

    
3934
	if (is_array($config['vlans']['vlan'])) {
3935
                foreach ($config['vlans']['vlan'] as $vlan) {
3936
			if ($int == $vlan['if']) {
3937
				if ($action == "update") {
3938
					interfaces_bring_up($int);
3939
				} else if ($action == "")
3940
					return $vlan;
3941
			}
3942
		}
3943
	}
3944
}
3945

    
3946
function link_interface_to_vips($int, $action = "") {
3947
        global $config;
3948

    
3949
        if (is_array($config['virtualip']['vip'])) {
3950
		foreach ($config['virtualip']['vip'] as $vip) {
3951
			if ($int == $vip['interface']) {
3952
				if ($action == "update")
3953
					interfaces_vips_configure($int);
3954
				else
3955
					return $vip;
3956
			}
3957
		}
3958
	}
3959
}
3960

    
3961
/****f* interfaces/link_interface_to_bridge
3962
 * NAME
3963
 *   link_interface_to_bridge - Finds out a bridge group for an interface
3964
 * INPUTS
3965
 *   $ip
3966
 * RESULT
3967
 *   bridge[0-99]
3968
 ******/
3969
function link_interface_to_bridge($int) {
3970
        global $config;
3971

    
3972
        if (is_array($config['bridges']['bridged'])) {
3973
                foreach ($config['bridges']['bridged'] as $bridge) {
3974
			if (in_array($int, explode(',', $bridge['members'])))
3975
                                return "{$bridge['bridgeif']}";
3976
		}
3977
	}
3978
}
3979

    
3980
function link_interface_to_group($int) {
3981
        global $config;
3982

    
3983
	$result = array();
3984

    
3985
        if (is_array($config['ifgroups']['ifgroupentry'])) {
3986
                foreach ($config['ifgroups']['ifgroupentry'] as $group) {
3987
			if (in_array($int, explode(" ", $group['members'])))
3988
				$result[$group['ifname']] = $int;
3989
		}
3990
	}
3991

    
3992
	return $result;
3993
}
3994

    
3995
function link_interface_to_gre($interface) {
3996
        global $config;
3997

    
3998
	$result = array();
3999

    
4000
        if (is_array($config['gres']['gre'])) {
4001
                foreach ($config['gres']['gre'] as $gre)
4002
                        if($gre['if'] == $interface)
4003
				$result[] = $gre;
4004
	}
4005

    
4006
	return $result;
4007
}
4008

    
4009
function link_interface_to_gif($interface) {
4010
        global $config;
4011

    
4012
	$result = array();
4013

    
4014
        if (is_array($config['gifs']['gif'])) {
4015
                foreach ($config['gifs']['gif'] as $gif)
4016
                        if($gif['if'] == $interface)
4017
                                $result[] = $gif;
4018
	}
4019

    
4020
	return $result;
4021
}
4022

    
4023
/*
4024
 * find_interface_ip($interface): return the interface ip (first found)
4025
 */
4026
function find_interface_ip($interface, $flush = false)
4027
{
4028
	global $interface_ip_arr_cache;
4029
	global $interface_sn_arr_cache;
4030

    
4031
	$interface = str_replace("\n", "", $interface);
4032
	
4033
	if (!does_interface_exist($interface))
4034
		return;
4035

    
4036
	/* Setup IP cache */
4037
	if (!isset($interface_ip_arr_cache[$interface]) or $flush) {
4038
		$ifinfo = pfSense_get_interface_addresses($interface);
4039
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
4040
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
4041
	}
4042

    
4043
	return $interface_ip_arr_cache[$interface];
4044
}
4045

    
4046
/*
4047
 * find_interface_ipv6($interface): return the interface ip (first found)
4048
 */
4049
function find_interface_ipv6($interface, $flush = false)
4050
{
4051
	global $interface_ipv6_arr_cache;
4052
	global $interface_snv6_arr_cache;
4053
	global $config;
4054
	
4055
	$interface = trim($interface);
4056
	$interface = get_real_interface($interface);
4057
	
4058
	if (!does_interface_exist($interface))
4059
		return;
4060

    
4061
	/* Setup IP cache */
4062
	if (!isset($interface_ipv6_arr_cache[$interface]) or $flush) {
4063
		$ifinfo = pfSense_get_interface_addresses($interface);
4064
		// FIXME: Add IPv6 support to the pfSense module
4065
		exec("/sbin/ifconfig {$interface} inet6", $output);
4066
		foreach($output as $line) {
4067
			if(preg_match("/inet6/", $line)) {
4068
				$parts = explode(" ", $line);
4069
				if(! preg_match("/fe80::/", $parts[1])) {
4070
					$ifinfo['ipaddrv6'] = $parts[1];
4071
					if($parts[2] == "-->") {
4072
						$parts[5] = "126";
4073
						$ifinfo['subnetbitsv6'] = $parts[5];
4074
					} else {
4075
						$ifinfo['subnetbitsv6'] = $parts[3];
4076
					}
4077
				}
4078
			}
4079
		}
4080
		$interface_ipv6_arr_cache[$interface] = $ifinfo['ipaddrv6'];
4081
		$interface_snv6_arr_cache[$interface] = $ifinfo['subnetbitsv6'];
4082
	}
4083

    
4084
	return $interface_ipv6_arr_cache[$interface];
4085
}
4086

    
4087
/*
4088
 * find_interface_ipv6_ll($interface): return the interface ipv6 link local (first found)
4089
 */
4090
function find_interface_ipv6_ll($interface, $flush = false)
4091
{
4092
	global $interface_llv6_arr_cache;
4093
	global $config;
4094
	
4095
	$interface = str_replace("\n", "", $interface);
4096
	
4097
	if (!does_interface_exist($interface))
4098
		return;
4099

    
4100
	/* Setup IP cache */
4101
	if (!isset($interface_llv6_arr_cache[$interface]) or $flush) {
4102
		$ifinfo = pfSense_get_interface_addresses($interface);
4103
		// FIXME: Add IPv6 support to the pfSense module
4104
		exec("/sbin/ifconfig {$interface} inet6", $output);
4105
		foreach($output as $line) {
4106
			if(preg_match("/inet6/", $line)) {
4107
				$parts = explode(" ", $line);
4108
				if(preg_match("/fe80::/", $parts[1])) {
4109
					$partsaddress = explode("%", $parts[1]);
4110
					$ifinfo['linklocal'] = $partsaddress[0];
4111
				}
4112
			}
4113
		}
4114
		$interface_llv6_arr_cache[$interface] = $ifinfo['linklocal'];
4115
	}
4116
	return $interface_llv6_arr_cache[$interface];
4117
}
4118

    
4119
function find_interface_subnet($interface, $flush = false)
4120
{
4121
	global $interface_sn_arr_cache;
4122
	global $interface_ip_arr_cache;
4123

    
4124
	$interface = str_replace("\n", "", $interface);
4125
	if (does_interface_exist($interface) == false)
4126
		return;
4127

    
4128
	if (!isset($interface_sn_arr_cache[$interface]) or $flush) {
4129
		$ifinfo = pfSense_get_interface_addresses($interface);
4130
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
4131
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
4132
        }
4133

    
4134
	return $interface_sn_arr_cache[$interface];
4135
}
4136

    
4137
function find_interface_subnetv6($interface, $flush = false)
4138
{
4139
	global $interface_snv6_arr_cache;
4140
	global $interface_ipv6_arr_cache;
4141

    
4142
	$interface = str_replace("\n", "", $interface);
4143
	if (does_interface_exist($interface) == false)
4144
		return;
4145

    
4146
	if (!isset($interface_snv6_arr_cache[$interface]) or $flush) {
4147
		$ifinfo = pfSense_get_interface_addresses($interface);
4148
		// FIXME: Add IPv6 support to the pfSense module
4149
		exec("/sbin/ifconfig {$interface} inet6", $output);
4150
		foreach($output as $line) {
4151
			if(preg_match("/inet6/", $line)) {
4152
				$parts = explode(" ", $line);
4153
				if(! preg_match("/fe80::/", $parts[1])) {
4154
					$ifinfo['ipaddrv6'] = $parts[1];
4155
					if($parts[2] == "-->") {
4156
						$parts[5] = "126";
4157
						$ifinfo['subnetbitsv6'] = $parts[5];
4158
					} else {
4159
						$ifinfo['subnetbitsv6'] = $parts[3];
4160
					}
4161
				}
4162
			}
4163
		}
4164
		$interface_ipv6_arr_cache[$interface] = $ifinfo['ipaddrv6'];
4165
		$interface_snv6_arr_cache[$interface] = $ifinfo['subnetbitsv6'];
4166
        }
4167

    
4168
	return $interface_snv6_arr_cache[$interface];
4169
}
4170

    
4171
function ip_in_interface_alias_subnet($interface, $ipalias) {
4172
	global $config;
4173

    
4174
	if (empty($interface) || !is_ipaddr($ipalias))
4175
		return false;
4176
	if (is_array($config['virtualip']['vip'])) {
4177
                foreach ($config['virtualip']['vip'] as $vip) {
4178
                        switch ($vip['mode']) {
4179
                        case "ipalias":
4180
                                if ($vip['interface'] <> $interface)
4181
                                        break;
4182
				if (ip_in_subnet($ipalias, gen_subnet($vip['subnet'], $vip['subnet_bits']) . "/" . $vip['subnet_bits']))
4183
					return true;
4184
                                break;
4185
                        }
4186
                }
4187
	}
4188

    
4189
	return false;
4190
}
4191

    
4192
function get_interface_ip($interface = "wan")
4193
{
4194
	$realif = get_failover_interface($interface);
4195
	if (!$realif) {
4196
		if (preg_match("/^carp/i", $interface))
4197
			$realif = $interface;
4198
		else if (preg_match("/^[a-z0-9]+_vip/i", $interface))
4199
			$realif = $interface;
4200
		else
4201
			return null;
4202
	}
4203

    
4204
	$curip = find_interface_ip($realif);
4205
	if ($curip && is_ipaddr($curip) && ($curip != "0.0.0.0"))
4206
		return $curip;
4207
	else
4208
		return null;
4209
}
4210

    
4211
function get_interface_ipv6($interface = "wan")
4212
{
4213
	global $config;
4214
	$realif = get_failover_interface($interface);
4215
	switch($config['interfaces'][$interface]['ipaddrv6']) {
4216
		case "6rd":
4217
		case "6to4":
4218
			$realif = "stf0";
4219
			break;
4220
	}
4221
	if (!$realif) {
4222
		if (preg_match("/^carp/i", $interface))
4223
			$realif = $interface;
4224
		else if (preg_match("/^[a-z0-9]+_vip/i", $interface))
4225
			$realif = $interface;
4226
		else
4227
			return null;
4228
	}
4229

    
4230
	$curip = find_interface_ipv6($realif);
4231
	if ($curip && is_ipaddrv6($curip) && ($curip != "::"))
4232
		return $curip;
4233
	else
4234
		return null;
4235
}
4236

    
4237
function get_interface_linklocal($interface = "wan")
4238
{
4239
	$realif = get_failover_interface($interface);
4240
	if (!$realif) {
4241
		if (preg_match("/^carp/i", $interface))
4242
			$realif = $interface;
4243
		else if (preg_match("/^[a-z0-9]+_vip/i", $interface))
4244
			$realif = $interface;
4245
		else
4246
			return null;
4247
	}
4248

    
4249
	$curip = find_interface_ipv6_ll($realif);
4250
	if ($curip && is_ipaddrv6($curip) && ($curip != "::"))
4251
		return $curip;
4252
	else
4253
		return null;
4254
}
4255

    
4256
function get_interface_subnet($interface = "wan")
4257
{
4258
	$realif = get_real_interface($interface);
4259
	if (!$realif) {
4260
                if (preg_match("/^carp/i", $interface))
4261
                        $realif = $interface;
4262
                else if (preg_match("/^[a-z0-9]+_vip/i", $interface))
4263
                        $realif = $interface;
4264
                else
4265
                        return null;
4266
        }
4267

    
4268
	$cursn = find_interface_subnet($realif);
4269
	if (!empty($cursn))
4270
		return $cursn;
4271

    
4272
	return null;
4273
}
4274

    
4275
function get_interface_subnetv6($interface = "wan")
4276
{
4277
	$realif = get_real_interface($interface);
4278
	if (!$realif) {
4279
                if (preg_match("/^carp/i", $interface))
4280
                        $realif = $interface;
4281
                else if (preg_match("/^[a-z0-9]+_vip/i", $interface))
4282
                        $realif = $interface;
4283
                else
4284
                        return null;
4285
        }
4286

    
4287
	$cursn = find_interface_subnetv6($realif);
4288
	if (!empty($cursn))
4289
		return $cursn;
4290

    
4291
	return null;
4292
}
4293

    
4294
/* return outside interfaces with a gateway */
4295
function get_interfaces_with_gateway() {
4296
	global $config;
4297

    
4298
	$ints = array();
4299

    
4300
	/* loop interfaces, check config for outbound */
4301
	foreach($config['interfaces'] as $ifdescr => $ifname) {
4302
		switch ($ifname['ipaddr']) {
4303
			case "dhcp":
4304
			case "ppp";
4305
			case "pppoe":
4306
			case "pptp":
4307
			case "l2tp":
4308
			case "ppp";
4309
				$ints[$ifdescr] = $ifdescr;
4310
			break;
4311
			default:
4312
				if (substr($ifname['if'], 0, 4) ==  "ovpn" ||
4313
				    !empty($ifname['gateway']))
4314
					$ints[$ifdescr] = $ifdescr;
4315
			break;
4316
		}
4317
	}
4318
	return $ints;
4319
}
4320

    
4321
/* return true if interface has a gateway */
4322
function interface_has_gateway($friendly) {
4323
	global $config;
4324

    
4325
	if (!empty($config['interfaces'][$friendly])) {
4326
		$ifname = &$config['interfaces'][$friendly];
4327
		switch ($ifname['ipaddr']) {
4328
			case "dhcp":
4329
			case "pppoe":
4330
			case "pptp":
4331
			case "l2tp":
4332
			case "ppp";
4333
				return true;
4334
			break;
4335
			default:
4336
				if (substr($ifname['if'], 0, 4) ==  "ovpn")
4337
					return true;
4338
				if (!empty($ifname['gateway']))
4339
					return true;
4340
			break;
4341
		}
4342
	}
4343

    
4344
	return false;
4345
}
4346

    
4347
/* return true if interface has a gateway */
4348
function interface_has_gatewayv6($friendly) {
4349
	global $config;
4350

    
4351
	if (!empty($config['interfaces'][$friendly])) {
4352
		$ifname = &$config['interfaces'][$friendly];
4353
		switch ($ifname['ipaddrv6']) {
4354
			case "slaac":
4355
			case "dhcp6":
4356
				return true;
4357
				break;
4358
			case "6to4":
4359
				return true;
4360
				break;
4361
			case "6rd":
4362
				return true;
4363
				break;
4364
			default:
4365
				if (substr($ifname['if'], 0, 4) ==  "ovpn")
4366
					return true;
4367
				if (!empty($ifname['gatewayv6']))
4368
					return true;
4369
				break;
4370
		}
4371
	}
4372

    
4373
	return false;
4374
}
4375

    
4376
/****f* interfaces/is_altq_capable
4377
 * NAME
4378
 *   is_altq_capable - Test if interface is capable of using ALTQ
4379
 * INPUTS
4380
 *   $int            - string containing interface name
4381
 * RESULT
4382
 *   boolean         - true or false
4383
 ******/
4384

    
4385
function is_altq_capable($int) {
4386
        /* Per:
4387
         * http://www.freebsd.org/cgi/man.cgi?query=altq&manpath=FreeBSD+7.2-current&format=html
4388
         * Only the following drivers have ALTQ support
4389
         */
4390
	$capable = array("age", "alc", "ale", "an", "ath", "aue", "awi", "bce",
4391
			"bfe", "bge", "bridge", "cas", "dc", "de", "ed", "em", "ep", "fxp", "gem",
4392
			"hme", "igb", "ipw", "iwi", "jme", "le", "lem", "msk", "mxge", "my", "nfe",
4393
			"npe", "nve", "ral", "re", "rl", "rum", "run", "bwn", "sf", "sis", "sk",
4394
			"ste", "stge", "txp", "udav", "ural", "vge", "vr", "wi", "xl",
4395
			"ndis", "tun", "ovpns", "ovpnc", "vlan", "pppoe", "pptp", "ng",
4396
			"l2tp", "ppp", "vtnet");
4397

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

    
4400
        if (in_array($int_family[0], $capable))
4401
                return true;
4402
	else if (stristr($int, "l2tp")) /* VLANs are name $parent_$vlan now */
4403
		return true;
4404
	else if (stristr($int, "vlan")) /* VLANs are name $parent_$vlan now */
4405
		return true;
4406
	else if (stristr($int, "_wlan")) /* WLANs are name $parent_$wlan now */
4407
		return true;
4408
        else
4409
                return false;
4410
}
4411

    
4412
/****f* interfaces/is_interface_wireless
4413
 * NAME
4414
 *   is_interface_wireless - Returns if an interface is wireless
4415
 * RESULT
4416
 *   $tmp       - Returns if an interface is wireless
4417
 ******/
4418
function is_interface_wireless($interface) {
4419
        global $config, $g;
4420

    
4421
        $friendly = convert_real_interface_to_friendly_interface_name($interface);
4422
        if(!isset($config['interfaces'][$friendly]['wireless'])) {
4423
                if (preg_match($g['wireless_regex'], $interface)) {
4424
                        if (isset($config['interfaces'][$friendly]))
4425
                                $config['interfaces'][$friendly]['wireless'] = array();
4426
                        return true;
4427
                }
4428
                return false;
4429
        } else
4430
                return true;
4431
}
4432

    
4433
function get_wireless_modes($interface) {
4434
	/* return wireless modes and channels */
4435
	$wireless_modes = array();
4436

    
4437
	$cloned_interface = get_real_interface($interface);
4438

    
4439
	if($cloned_interface && is_interface_wireless($cloned_interface)) {
4440
		$chan_list = "/sbin/ifconfig {$cloned_interface} list chan";
4441
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
4442
		$format_list = "/usr/bin/awk '{print \$5 \" \" \$6 \",\" \$1}'";
4443

    
4444
		$interface_channels = "";
4445
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
4446
		$interface_channel_count = count($interface_channels);
4447

    
4448
		$c = 0;
4449
		while ($c < $interface_channel_count)
4450
		{
4451
			$channel_line = explode(",", $interface_channels["$c"]);
4452
			$wireless_mode = trim($channel_line[0]);
4453
			$wireless_channel = trim($channel_line[1]);
4454
			if(trim($wireless_mode) != "") {
4455
				/* if we only have 11g also set 11b channels */
4456
				if($wireless_mode == "11g") {
4457
					if(!isset($wireless_modes["11b"]))
4458
						$wireless_modes["11b"] = array();
4459
				} else if($wireless_mode == "11g ht") {
4460
					if(!isset($wireless_modes["11b"]))
4461
						$wireless_modes["11b"] = array();
4462
					if(!isset($wireless_modes["11g"]))
4463
						$wireless_modes["11g"] = array();
4464
					$wireless_mode = "11ng";
4465
				} else if($wireless_mode == "11a ht") {
4466
					if(!isset($wireless_modes["11a"]))
4467
						$wireless_modes["11a"] = array();
4468
					$wireless_mode = "11na";
4469
				}
4470
				$wireless_modes["$wireless_mode"]["$c"] = $wireless_channel;
4471
			}
4472
			$c++;
4473
		}
4474
	}
4475
	return($wireless_modes);
4476
}
4477

    
4478
/* return channel numbers, frequency, max txpower, and max regulation txpower */
4479
function get_wireless_channel_info($interface) {
4480
	$wireless_channels = array();
4481

    
4482
	$cloned_interface = get_real_interface($interface);
4483

    
4484
	if($cloned_interface && is_interface_wireless($cloned_interface)) {
4485
		$chan_list = "/sbin/ifconfig {$cloned_interface} list txpower";
4486
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
4487
		$format_list = "/usr/bin/awk '{print \$1 \",\" \$3 \" \" \$4 \",\" \$5 \",\" \$7}'";
4488

    
4489
		$interface_channels = "";
4490
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
4491

    
4492
		foreach ($interface_channels as $channel_line) {
4493
			$channel_line = explode(",", $channel_line);
4494
			if(!isset($wireless_channels[$channel_line[0]]))
4495
				$wireless_channels[$channel_line[0]] = $channel_line;
4496
		}
4497
	}
4498
	return($wireless_channels);
4499
}
4500

    
4501
/****f* interfaces/get_interface_mtu
4502
 * NAME
4503
 *   get_interface_mtu - Return the mtu of an interface
4504
 * RESULT
4505
 *   $tmp       - Returns the mtu of an interface
4506
 ******/
4507
function get_interface_mtu($interface) {
4508
        $mtu = pfSense_get_interface_addresses($interface);
4509
        return $mtu['mtu'];
4510
}
4511

    
4512
function get_interface_mac($interface) {
4513

    
4514
	$macinfo = pfSense_get_interface_addresses($interface);
4515
	return $macinfo["macaddr"];
4516
}
4517

    
4518
/****f* pfsense-utils/generate_random_mac_address
4519
 * NAME
4520
 *   generate_random_mac - generates a random mac address
4521
 * INPUTS
4522
 *   none
4523
 * RESULT
4524
 *   $mac - a random mac address
4525
 ******/
4526
function generate_random_mac_address() {
4527
        $mac = "02";
4528
        for($x=0; $x<5; $x++)
4529
                $mac .= ":" . dechex(rand(16, 255));
4530
        return $mac;
4531
}
4532

    
4533
/****f* interfaces/is_jumbo_capable
4534
 * NAME
4535
 *   is_jumbo_capable - Test if interface is jumbo frame capable.  Useful for determining VLAN capability.
4536
 * INPUTS
4537
 *   $int             - string containing interface name
4538
 * RESULT
4539
 *   boolean          - true or false
4540
 ******/
4541
function is_jumbo_capable($iface) {
4542

    
4543

    
4544
	$iface = trim($iface);
4545
	$capable = pfSense_get_interface_addresses($iface);
4546
	if (isset($capable['caps']['vlanmtu']))
4547
                return true;
4548

    
4549

    
4550

    
4551

    
4552

    
4553
	return false;
4554
}
4555

    
4556
function interface_setup_pppoe_reset_file($pppif, $iface="") {
4557
	global $g;
4558

    
4559
	$cron_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
4560

    
4561
	if(!empty($iface) && !empty($pppif)){
4562
		$cron_cmd = <<<EOD
4563
#!/bin/sh
4564
/usr/local/sbin/pfSctl -c 'interface reload {$iface}'
4565
/usr/bin/logger -t {$pppif} "PPPoE periodic reset executed on {$iface}"
4566

    
4567
EOD;
4568

    
4569
		@file_put_contents($cron_file, $cron_cmd);
4570
		chmod($cron_file, 0755);
4571
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
4572
	} else
4573
		unlink_if_exists($cron_file);
4574
}
4575

    
4576
function get_interface_default_mtu($type = "ethernet") {
4577
	switch ($type) {
4578
	case "gre":
4579
		return 1476;
4580
		break;
4581
	case "gif":
4582
		return 1280;
4583
		break;
4584
	case "tun":
4585
	case "vlan":
4586
	case "tap":
4587
	case "ethernet":
4588
	default:
4589
		return 1500;
4590
		break;
4591
	}
4592

    
4593
	/* Never reached */
4594
	return 1500;
4595
}
4596

    
4597
function get_vip_descr($ipaddress) {
4598
	global $config;
4599

    
4600
	foreach ($config['virtualip']['vip'] as $vip) {
4601
		if ($vip['subnet'] == $ipaddress) {
4602
			return ($vip['descr']);
4603
		}
4604
	}
4605
	return "";
4606
}
4607

    
4608
function interfaces_staticarp_configure($if) {
4609
	global $config, $g;
4610
	if(isset($config['system']['developerspew'])) {
4611
		$mt = microtime();
4612
		echo "interfaces_staticarp_configure($if) being called $mt\n";
4613
	}
4614

    
4615
	$ifcfg = $config['interfaces'][$if];
4616

    
4617
	if (empty($if) || empty($ifcfg['if']))
4618
		return 0;
4619

    
4620
	/* Enable staticarp, if enabled */
4621
	if(isset($config['dhcpd'][$if]['staticarp'])) {
4622
		mwexec("/sbin/ifconfig " . escapeshellarg($ifcfg['if']) . " staticarp " );
4623
		mwexec("/usr/sbin/arp -d -i " . escapeshellarg($ifcfg['if']) . " -a > /dev/null 2>&1 ");
4624
		if (is_array($config['dhcpd'][$if]['staticmap'])) {
4625

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

    
4629
			}
4630

    
4631
		}
4632
	} else {
4633
		mwexec("/sbin/ifconfig " . escapeshellarg($ifcfg['if']) . " -staticarp " );
4634
		mwexec("/usr/sbin/arp -d -i " . escapeshellarg($ifcfg['if']) . " -a > /dev/null 2>&1 ");
4635
		if (is_array($config['dhcpd'][$if]['staticmap'])) {
4636
			foreach ($config['dhcpd'][$if]['staticmap'] as $arpent) {
4637
				if (isset($arpent['arp_table_static_entry'])) {
4638
					mwexec("/usr/sbin/arp -s " . escapeshellarg($arpent['ipaddr']) . " " . escapeshellarg($arpent['mac']));
4639
				}
4640
			}
4641
		}
4642
	}
4643

    
4644
	return 0;
4645
}
4646

    
4647
function get_failover_interface($interface) {
4648
	global $config;
4649
	/* shortcut to get_real_interface if we find it in the config */
4650
	if(is_array($config['interfaces'][$interface])) {
4651
		$wanif = get_real_interface($interface);
4652
		return $wanif;
4653
	}
4654

    
4655
	/* compare against gateway groups */
4656
	$a_groups = return_gateway_groups_array();
4657
	if(is_array($a_groups[$interface])) {
4658
		/* we found a gateway group, fetch the interface or vip */
4659
		if($a_groups[$interface][0]['vip'] <> "")
4660
			$wanif = $a_groups[$interface][0]['vip'];
4661
		else
4662
			$wanif = $a_groups[$interface][0]['int'];
4663
		
4664
		return $wanif;
4665
	}
4666
	/* fall through to get_real_interface */
4667
	$wanif = get_real_interface($interface);
4668
	return $wanif;
4669
}
4670

    
4671
?>
(25-25/67)