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
			if (empty($ports[$pid]))
1357
				return 0;
1358
		}
1359
	}
1360
	$localips = explode(',',$ppp['localip']);
1361
	$gateways = explode(',',$ppp['gateway']);
1362
	$subnets = explode(',',$ppp['subnet']);
1363

    
1364
	/* We bring up the parent interface first because if DHCP is configured on the parent we need
1365
	 * to obtain an address first so we can write it in the mpd .conf file for PPTP and L2TP configs
1366
	 */
1367
	foreach($ports as $pid => $port){
1368
		switch ($ppp['type']) {
1369
			case "pppoe":
1370
				/* Bring the parent interface up */
1371
				interfaces_bring_up($port);
1372
				pfSense_ngctl_attach(".", $port);
1373
				/* Enable setautosrc to automatically change mac address if parent interface's changes */
1374
				mwexec("ngctl msg {$port}: setautosrc 1");
1375
				break;
1376
			case "pptp":
1377
			case "l2tp":
1378
				/* configure interface */
1379
				if(is_ipaddr($localips[$pid])){
1380
					// Manually configure interface IP/subnet
1381
					pfSense_interface_setaddress($port, "{$localips[$pid]}/{$subnets[$pid]}");
1382
					interfaces_bring_up($port);
1383
				} else if (empty($localips[$pid]))
1384
					$localips[$pid] = get_interface_ip($port); // try to get the interface IP from the port
1385

    
1386
				if(!is_ipaddr($localips[$pid])){
1387
					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!");
1388
					$localips[$pid] = "0.0.0.0";
1389
				}
1390
				/* XXX: This needs to go away soon! [It's commented out!] */
1391
				/* Configure the gateway (remote IP ) */
1392
				if (!$g['booting'] && !is_ipaddr($gateways[$pid]) && is_hostname($gateways[$pid])) {
1393
					/* XXX: Fix later
1394
					$gateways[$pid] = gethostbyname($gateways[$pid]);
1395
					if(!is_ipaddr($gateways[$pid])) {
1396
						log_error("Could not get a valid Gateway IP from {$port} via DNS in interfaces_ppps_configure.");
1397
						return 0;
1398
					}
1399
					*/
1400
				}
1401
				if(!is_ipaddr($gateways[$pid])){
1402
					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));
1403
					return 0;
1404
				}
1405
				pfSense_ngctl_attach(".", $port);
1406
				break;
1407
			case "ppp":
1408
				if (!file_exists("{$port}")) {
1409
					log_error(sprintf(gettext("Device %s does not exist. PPP link cannot start without the modem device."), $port));
1410
					return 0;
1411
				}
1412
				break;
1413
			default:
1414
				log_error(sprintf(gettext("Unkown %s configured as ppp interface."), $type));
1415
				break;
1416
		}
1417
	}
1418

    
1419
	if (is_array($ports) && count($ports) > 1)
1420
		$multilink = "enable";
1421
	else
1422
		$multilink = "disable";
1423

    
1424
	if ($type == "modem"){
1425
		if (is_ipaddr($ppp['localip']))
1426
			$localip = $ppp['localip'];
1427
		else
1428
			$localip = '0.0.0.0';
1429

    
1430
		if (is_ipaddr($ppp['gateway']))
1431
			$gateway = $ppp['gateway'];
1432
		else
1433
			$gateway = "10.64.64.{$pppid}";
1434
		$ranges = "{$localip}/0 {$gateway}/0";
1435

    
1436
		if (empty($ppp['apnum']))
1437
			$ppp['apnum'] = 1;
1438
	} else
1439
		$ranges = "0.0.0.0/0 0.0.0.0/0";
1440

    
1441
	if (isset($ppp['ondemand']))
1442
		$ondemand = "enable";
1443
	else
1444
		$ondemand = "disable";
1445
	if (!isset($ppp['idletimeout']))
1446
		$ppp['idletimeout'] = 0;
1447

    
1448
	if (empty($ppp['username']) && $type == "modem"){
1449
		$ppp['username'] = "user";
1450
		$ppp['password'] = "none";
1451
	}
1452
	if (empty($ppp['password']) && $type == "modem")
1453
		$passwd = "none";
1454
	else
1455
		$passwd = base64_decode($ppp['password']);
1456

    
1457
	$bandwidths = explode(',',$ppp['bandwidth']);
1458
	$defaultmtu = "1492";
1459
	if (!empty($ifcfg['mtu']))
1460
		$defaultmtu = intval($ifcfg['mtu']);
1461
	$mtus = explode(',',$ppp['mtu']);
1462
	$mrus = explode(',',$ppp['mru']);
1463

    
1464
	if (isset($ppp['mrru']))
1465
		$mrrus = explode(',',$ppp['mrru']);
1466

    
1467
	// Construct the mpd.conf file
1468
	$mpdconf = <<<EOD
1469
startup:
1470
	# configure the console
1471
	set console close
1472
	# configure the web server
1473
	set web close
1474

    
1475
default:
1476
{$ppp['type']}client:
1477
	create bundle static {$interface}
1478
	set bundle enable ipv6cp
1479
	set iface name {$pppif}
1480

    
1481
EOD;
1482
	$setdefaultgw = false;
1483
	$founddefaultgw = false;
1484
	if (is_array($config['gateways']['gateway_item'])) {
1485
		foreach($config['gateways']['gateway_item'] as $gateway) {
1486
			if($interface == $gateway['interface'] && isset($gateway['defaultgw'])) {
1487
				$setdefaultgw = true;
1488
				break;
1489
			} else if (isset($gateway['defaultgw']) && !empty($gateway['interface'])) {
1490
				$founddefaultgw = true;
1491
				break;
1492
			}
1493
		}
1494
	}
1495

    
1496
	if (($interface == "wan" && $founddefaultgw == false) || $setdefaultgw == true){
1497
		$setdefaultgw = true;
1498
		$mpdconf .= <<<EOD
1499
	set iface route default
1500

    
1501
EOD;
1502
	}
1503
	$mpdconf .= <<<EOD
1504
	set iface {$ondemand} on-demand
1505
	set iface idle {$ppp['idletimeout']}
1506

    
1507
EOD;
1508

    
1509
	if (isset($ppp['ondemand']))
1510
		$mpdconf .= <<<EOD
1511
	set iface addrs 10.10.1.1 10.10.1.2
1512

    
1513
EOD;
1514

    
1515
	if (isset($ppp['tcpmssfix']))
1516
		$tcpmss = "disable";
1517
	else
1518
		$tcpmss = "enable";
1519
		$mpdconf .= <<<EOD
1520
	set iface {$tcpmss} tcpmssfix
1521

    
1522
EOD;
1523

    
1524
	$mpdconf .= <<<EOD
1525
	set iface up-script /usr/local/sbin/ppp-linkup
1526
	set iface down-script /usr/local/sbin/ppp-linkdown
1527
	set ipcp ranges {$ranges}
1528

    
1529
EOD;
1530
	if (isset($ppp['vjcomp']))
1531
		$mpdconf .= <<<EOD
1532
	set ipcp no vjcomp
1533

    
1534
EOD;
1535

    
1536
	if (isset($config['system']['dnsallowoverride']))
1537
		$mpdconf .= <<<EOD
1538
	set ipcp enable req-pri-dns
1539
	set ipcp enable req-sec-dns
1540

    
1541
EOD;
1542
	if (!isset($ppp['verbose_log']))
1543
		$mpdconf .= <<<EOD
1544
	#log -bund -ccp -chat -iface -ipcp -lcp -link
1545

    
1546
EOD;
1547
	foreach($ports as $pid => $port){
1548
		$port = get_real_interface($port);
1549
		$mpdconf .= <<<EOD
1550

    
1551
	create link static {$interface}_link{$pid} {$type}
1552
	set link action bundle {$interface}
1553
	set link {$multilink} multilink
1554
	set link keep-alive 10 60
1555
	set link max-redial 0
1556

    
1557
EOD;
1558
		if (isset($ppp['shortseq']))
1559
			$mpdconf .= <<<EOD
1560
	set link no shortseq
1561

    
1562
EOD;
1563

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

    
1568
EOD;
1569

    
1570
		if (isset($ppp['protocomp']))
1571
			$mpdconf .= <<<EOD
1572
	set link no protocomp
1573

    
1574
EOD;
1575

    
1576
		$mpdconf .= <<<EOD
1577
	set link disable chap pap
1578
	set link accept chap pap eap
1579
	set link disable incoming
1580

    
1581
EOD;
1582

    
1583

    
1584
		if (!empty($bandwidths[$pid]))
1585
			$mpdconf .= <<<EOD
1586
	set link bandwidth {$bandwidths[$pid]}
1587

    
1588
EOD;
1589

    
1590
		if (empty($mtus[$pid]))
1591
			$mtus[$pid] = $defaultmtu;
1592
			$mpdconf .= <<<EOD
1593
	set link mtu {$mtus[$pid]}
1594

    
1595
EOD;
1596

    
1597
		if (!empty($mrus[$pid]))
1598
			$mpdconf .= <<<EOD
1599
	set link mru {$mrus[$pid]}
1600

    
1601
EOD;
1602

    
1603
		if (!empty($mrrus[$pid]))
1604
			$mpdconf .= <<<EOD
1605
	set link mrru {$mrrus[$pid]}
1606

    
1607
EOD;
1608

    
1609
		$mpdconf .= <<<EOD
1610
	set auth authname "{$ppp['username']}"
1611
	set auth password {$passwd}
1612

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

    
1623
EOD;
1624
		}
1625
		if (isset($ppp['connect-timeout']) && $type == "modem") {
1626
			$mpdconf .= <<<EOD
1627
	set modem var \$ConnectTimeout "{$ppp['connect-timeout']}"
1628

    
1629
EOD;
1630
		}
1631
		if (isset($ppp['initstr']) && $type == "modem") {
1632
			$initstr = base64_decode($ppp['initstr']);
1633
			$mpdconf .= <<<EOD
1634
	set modem var \$InitString "{$initstr}"
1635

    
1636
EOD;
1637
		}
1638
		if (isset($ppp['simpin']) && $type == "modem") {
1639
			if($ppp['pin-wait'] == "")
1640
				$ppp['pin-wait'] = 0;
1641
			$mpdconf .= <<<EOD
1642
	set modem var \$SimPin "{$ppp['simpin']}"
1643
	set modem var \$PinWait "{$ppp['pin-wait']}"
1644

    
1645
EOD;
1646
		}
1647
		if (isset($ppp['apn']) && $type == "modem") {
1648
			$mpdconf .= <<<EOD
1649
	set modem var \$APN "{$ppp['apn']}"
1650
	set modem var \$APNum "{$ppp['apnum']}"
1651

    
1652
EOD;
1653
		}
1654
		if ($type == "pppoe") {
1655
			// Send a null service name if none is set.
1656
			$provider = isset($ppp['provider']) ? $ppp['provider'] : "";
1657
			$mpdconf .= <<<EOD
1658
	set pppoe service "{$provider}"
1659

    
1660
EOD;
1661
		}
1662
		if ($type == "pppoe")
1663
			$mpdconf .= <<<EOD
1664
	set pppoe iface {$port}
1665

    
1666
EOD;
1667

    
1668
		if ($type == "pptp" || $type == "l2tp") {
1669
			$mpdconf .= <<<EOD
1670
	set {$type} self {$localips[$pid]}
1671
	set {$type} peer {$gateways[$pid]}
1672

    
1673
EOD;
1674
		}
1675

    
1676
		$mpdconf .= "\topen\n";
1677
	} //end foreach($port)
1678

    
1679

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

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

    
1710
	/* clean up old lock files */
1711
	foreach($ports as $port) {
1712
		if(file_exists("{$g['var_path']}/spool/lock/LCK..{$port}"))
1713
			unlink("{$g['var_path']}/spool/lock/LCK..{$port}");
1714
	}
1715

    
1716
	/* fire up mpd */
1717
	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");
1718

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

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

    
1754
	return 1;
1755
}
1756

    
1757
function interfaces_carp_setup() {
1758
	global $g, $config;
1759

    
1760
	if (isset($config['system']['developerspew'])) {
1761
		$mt = microtime();
1762
		echo "interfaces_carp_setup() being called $mt\n";
1763
	}
1764

    
1765
	if ($g['booting']) {
1766
		echo gettext("Configuring CARP settings...");
1767
		mute_kernel_msgs();
1768
	}
1769

    
1770
	/* suck in configuration items */
1771
	if ($config['hasync']) {
1772
		$pfsyncenabled = $config['hasync']['pfsyncenabled'];
1773
		$balanacing = $config['hasync']['balancing'];
1774
		$pfsyncinterface = $config['hasync']['pfsyncinterface'];
1775
		$pfsyncpeerip = $config['hasync']['pfsyncpeerip'];
1776
	} else {
1777
		unset($pfsyncinterface);
1778
		unset($balanacing);
1779
		unset($pfsyncenabled);
1780
	}
1781

    
1782
	if ($balanacing) {
1783
		mwexec("/sbin/sysctl net.inet.carp.arpbalance=1", true);
1784
		mwexec("/sbin/sysctl net.inet.carp.preempt=0", true);
1785
	} else
1786
		mwexec("/sbin/sysctl net.inet.carp.preempt=1", true);
1787

    
1788
	mwexec("sbin/sysctl net.inet.carp.log=1", true);
1789
	if (!empty($pfsyncinterface))
1790
		$carp_sync_int = get_real_interface($pfsyncinterface);
1791
	else
1792
		unset($carp_sync_int);
1793

    
1794
	/* setup pfsync interface */
1795
	if ($carp_sync_int and $pfsyncenabled) {
1796
		if (is_ipaddr($pfsyncpeerip))
1797
			mwexec("/sbin/ifconfig pfsync0 syncdev {$carp_sync_int} syncpeer {$pfsyncpeerip} up", false);
1798
		else
1799
			mwexec("/sbin/ifconfig pfsync0 syncdev {$carp_sync_int} up", false);
1800

    
1801
		sleep(1);
1802

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

    
1816
	if($config['virtualip']['vip'])
1817
		mwexec("/sbin/sysctl net.inet.carp.allow=1", true);
1818
	else
1819
		mwexec("/sbin/sysctl net.inet.carp.allow=0", true);
1820

    
1821
	if ($g['booting']) {
1822
		unmute_kernel_msgs();
1823
		echo gettext("done.") . "\n";
1824
	}
1825
}
1826

    
1827
function interface_proxyarp_configure($interface = "") {
1828
	global $config, $g;
1829
	if(isset($config['system']['developerspew'])) {
1830
		$mt = microtime();
1831
		echo "interface_proxyarp_configure() being called $mt\n";
1832
	}
1833

    
1834
	/* kill any running choparp */
1835
	if (empty($interface))
1836
		killbyname("choparp");
1837
	else {
1838
		$vipif = get_real_interface($interface);
1839
		if (file_exists("{$g['varrun_path']}/choparp_{$vipif}.pid"))
1840
			killbypid("{$g['varrun_path']}/choparp_{$vipif}.pid");
1841
	}
1842

    
1843
	$paa = array();
1844
	if (!empty($config['virtualip']) && is_array($config['virtualip']['vip'])) {
1845

    
1846
		/* group by interface */
1847
		foreach ($config['virtualip']['vip'] as $vipent) {
1848
			if ($vipent['mode'] === "proxyarp") {
1849
				if ($vipent['interface'])
1850
					$proxyif = $vipent['interface'];
1851
				else
1852
					$proxyif = "wan";
1853

    
1854
				if (!empty($interface) && $interface != $proxyif)
1855
					continue;
1856

    
1857
				if (!is_array($paa[$proxyif]))
1858
					$paa[$proxyif] = array();
1859

    
1860
				$paa[$proxyif][] = $vipent;
1861
			}
1862
		}
1863
	}
1864

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

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

    
1935
function interface_ipalias_configure(&$vip) {
1936
	if ($vip['mode'] == "ipalias") {
1937
		$if = get_real_interface($vip['interface']);
1938
		$af = "inet";
1939
		if(is_ipaddrv6($vip['subnet']))
1940
			$af = "inet6";
1941
		mwexec("/sbin/ifconfig " . escapeshellarg($if) ." {$af} ". escapeshellarg($vip['subnet']) ."/" . escapeshellarg($vip['subnet_bits']) . " alias");
1942
	}
1943
}
1944

    
1945
function interface_reload_carps($cif) {
1946
	global $config;
1947

    
1948
	$carpifs = link_ip_to_carp_interface(find_interface_ip($cif));
1949
	if (empty($carpifs))
1950
		return;
1951

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

    
1974
function interface_carp_configure(&$vip) {
1975
	global $config, $g;
1976
	if(isset($config['system']['developerspew'])) {
1977
		$mt = microtime();
1978
		echo "interface_carp_configure() being called $mt\n";
1979
	}
1980

    
1981
	if ($vip['mode'] != "carp")
1982
		return;
1983

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

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

    
2013
	// set the vip interface to the vhid
2014
	$vipif = "{$vip['interface']}_vip{$vip['vhid']}";
2015

    
2016
	/* create the carp interface and setup */
2017
	if (does_interface_exist($vipif)) {
2018
		pfSense_interface_flags($vipif, -IFF_UP);
2019
	} else {
2020
		$carpif = pfSense_interface_create("carp");
2021
		pfSense_interface_rename($carpif, $vipif);
2022
		pfSense_ngctl_name("{$carpif}:", $vipif);
2023
	}
2024

    
2025
	/* invalidate interface cache */
2026
	get_interface_arr(true);
2027

    
2028
	$vip_password = $vip['password'];
2029
	$vip_password = escapeshellarg(addslashes(str_replace(" ", "", $vip_password)));
2030
	if ($vip['password'] != "")
2031
		$password = " pass {$vip_password}";
2032

    
2033
	$broadcast_address = gen_subnet_max($vip['subnet'], $vip['subnet_bits']);
2034
	$advbase = "";
2035
	if (!empty($vip['advbase']))
2036
		$advbase = "advbase {$vip['advbase']}";
2037

    
2038
	if(is_ipaddrv4($vip['subnet'])) {
2039
		$broadcast_address = gen_subnet_max($vip['subnet'], $vip['subnet_bits']);
2040
		mwexec("/sbin/ifconfig {$vipif} {$vip['subnet']}/{$vip['subnet_bits']} vhid {$vip['vhid']} advskew {$vip['advskew']} {$advbase} {$password}");
2041
	}
2042
	if(is_ipaddrv6($vip['subnet'])) {
2043
		$broadcast_address = gen_subnet_max($vip['subnet'], $vip['subnet_bits']);
2044
		mwexec("/sbin/ifconfig {$vipif} inet6 {$vip['subnet']} prefixlen {$vip['subnet_bits']} vhid {$vip['vhid']} advskew {$vip['advskew']} {$advbase} {$password}");
2045
	}
2046

    
2047
	interfaces_bring_up($vipif);
2048

    
2049
	return $vipif;
2050
}
2051

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

    
2093
	if($needs_clone == true) {
2094
		/* remove previous instance if it exists */
2095
		if(does_interface_exist($realif))
2096
			pfSense_interface_destroy($realif);
2097

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

    
2116
function interface_sync_wireless_clones(&$ifcfg, $sync_changes = false) {
2117
	global $config, $g;
2118

    
2119
	$shared_settings = array('standard', 'turbo', 'protmode', 'txpower', 'channel',
2120
	                         'diversity', 'txantenna', 'rxantenna', 'distance',
2121
	                         'regdomain', 'regcountry', 'reglocation');
2122

    
2123
	if(!is_interface_wireless($ifcfg['if']))
2124
		return;
2125

    
2126
	$baseif = interface_get_wireless_base($ifcfg['if']);
2127

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

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

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

    
2185
function interface_wireless_configure($if, &$wl, &$wlcfg) {
2186
	global $config, $g;
2187

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

    
2195
	// Remove script file
2196
	unlink_if_exists("{$g['tmp_path']}/{$if}_setup.sh");
2197

    
2198
	// Clone wireless nic if needed.
2199
	interface_wireless_clone($if, $wl);
2200

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

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

    
2208
	/* set values for /path/program */
2209
	$hostapd = "/usr/sbin/hostapd";
2210
	$wpa_supplicant = "/usr/sbin/wpa_supplicant";
2211
	$ifconfig = "/sbin/ifconfig";
2212
	$sysctl = "/sbin/sysctl";
2213
	$killall = "/usr/bin/killall";
2214

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

    
2217
	$wlcmd = array();
2218
	$wl_sysctl = array();
2219
	/* Make sure it's up */
2220
	$wlcmd[] = "up";
2221
	/* Set a/b/g standard */
2222
	$standard = str_replace(" Turbo", "", $wlcfg['standard']);
2223
	$wlcmd[] = "mode " . escapeshellarg($standard);
2224

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

    
2230
	/* Set ssid */
2231
	if($wlcfg['ssid'])
2232
		$wlcmd[] = "ssid " .escapeshellarg($wlcfg['ssid']);
2233

    
2234
	/* Set 802.11g protection mode */
2235
	$wlcmd[] = "protmode " . escapeshellarg($wlcfg['protmode']);
2236

    
2237
	/* set wireless channel value */
2238
	if(isset($wlcfg['channel'])) {
2239
		if($wlcfg['channel'] == "0") {
2240
			$wlcmd[] = "channel any";
2241
		} else {
2242
			$wlcmd[] = "channel " . escapeshellarg($wlcfg['channel']);
2243
		}
2244
	}
2245

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

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

    
2254
	/* Set rxantenna value */
2255
	if(isset($wlcfg['rxantenna']))
2256
		$wl_sysctl[] = "rxantenna=" . escapeshellarg($wlcfg['rxantenna']);
2257

    
2258
	/* set Distance value */
2259
	if($wlcfg['distance'])
2260
		$distance = escapeshellarg($wlcfg['distance']);
2261

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

    
2269
	/* Set wireless adhoc mode */
2270
	if ($wlcfg['mode'] == "adhoc") {
2271
		$wlcmd[] = "mediaopt adhoc";
2272
	} else {
2273
		$wlcmd[] = "-mediaopt adhoc";
2274
	}
2275

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

    
2278
	/* handle hide ssid option */
2279
	if(isset($wlcfg['hidessid']['enable'])) {
2280
		$wlcmd[] = "hidessid";
2281
	} else {
2282
		$wlcmd[] = "-hidessid";
2283
	}
2284

    
2285
	/* handle pureg (802.11g) only option */
2286
	if(isset($wlcfg['pureg']['enable'])) {
2287
		$wlcmd[] = "mode 11g pureg";
2288
	} else {
2289
		$wlcmd[] = "-pureg";
2290
	}
2291

    
2292
	/* handle puren (802.11n) only option */
2293
	if(isset($wlcfg['puren']['enable'])) {
2294
		$wlcmd[] = "puren";
2295
	} else {
2296
		$wlcmd[] = "-puren";
2297
	}
2298

    
2299
	/* enable apbridge option */
2300
	if(isset($wlcfg['apbridge']['enable'])) {
2301
		$wlcmd[] = "apbridge";
2302
	} else {
2303
		$wlcmd[] = "-apbridge";
2304
	}
2305

    
2306
	/* handle turbo option */
2307
	if(isset($wlcfg['turbo']['enable'])) {
2308
		$wlcmd[] = "mediaopt turbo";
2309
	} else {
2310
		$wlcmd[] = "-mediaopt turbo";
2311
	}
2312

    
2313
	/* handle txpower setting */
2314
	/* if($wlcfg['txpower'] <> "")
2315
		$wlcmd[] = "txpower " . escapeshellarg($wlcfg['txpower']);
2316
	*/
2317
	/* handle wme option */
2318
	if(isset($wlcfg['wme']['enable'])) {
2319
		$wlcmd[] = "wme";
2320
	} else {
2321
		$wlcmd[] = "-wme";
2322
	}
2323

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

    
2350
	mwexec(kill_hostapd("{$if}"));
2351
	mwexec(kill_wpasupplicant("{$if}"));
2352

    
2353
	/* generate wpa_supplicant/hostap config if wpa is enabled */
2354
	conf_mount_rw();
2355

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

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

    
2410
EOD;
2411

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

    
2418
EOD;
2419

    
2420
}
2421
				if($wlcfg['auth_server_addr'] && $wlcfg['auth_server_shared_secret']) {
2422
					$auth_server_port = "1812";
2423
					if($wlcfg['auth_server_port'])
2424
						$auth_server_port = $wlcfg['auth_server_port'];
2425
					$auth_server_port2 = "1812";
2426
					if($wlcfg['auth_server_port2'])
2427
						$auth_server_port2 = $wlcfg['auth_server_port2'];
2428
					$wpa .= <<<EOD
2429

    
2430
ieee8021x=1
2431
auth_server_addr={$wlcfg['auth_server_addr']}
2432
auth_server_port={$auth_server_port}
2433
auth_server_shared_secret={$wlcfg['auth_server_shared_secret']}
2434
auth_server_addr={$wlcfg['auth_server_addr2']}
2435
auth_server_port={$auth_server_port2}
2436
auth_server_shared_secret={$wlcfg['auth_server_shared_secret2']}
2437

    
2438
EOD;
2439
				} else {
2440
					$wpa .= "ieee8021x={$wlcfg['wpa']['ieee8021x']}\n";
2441
				}
2442

    
2443
				$fd = fopen("{$g['varetc_path']}/hostapd_{$if}.conf", "w");
2444
				fwrite($fd, "{$wpa}");
2445
				fclose($fd);
2446

    
2447
			}
2448
			break;
2449
	}
2450

    
2451
	/*
2452
	 *    all variables are set, lets start up everything
2453
	 */
2454

    
2455
	$baseif = interface_get_wireless_base($if);
2456
	preg_match("/^(.*?)([0-9]*)$/", $baseif, $baseif_split);
2457
	$wl_sysctl_prefix = 'dev.' . $baseif_split[1] . '.' . $baseif_split[2];
2458

    
2459
	/* set sysctls for the wireless interface */
2460
	if (!empty($wl_sysctl)) {
2461
		fwrite($fd_set, "# sysctls for {$baseif}\n");
2462
		foreach ($wl_sysctl as $wl_sysctl_line) {
2463
			fwrite($fd_set, "{$sysctl} {$wl_sysctl_prefix}.{$wl_sysctl_line}\n");
2464
		}
2465
	}
2466

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

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

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

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

    
2501
	fclose($fd_set);
2502
	conf_mount_ro();
2503

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

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

    
2524
	if ($reg_changing) {
2525
		/* set regulatory domain */
2526
		if($wlcfg['regdomain'])
2527
			$wlregcmd[] = "regdomain " . escapeshellarg($wlcfg['regdomain']);
2528

    
2529
		/* set country */
2530
		if($wlcfg['regcountry'])
2531
			$wlregcmd[] = "country " . escapeshellarg($wlcfg['regcountry']);
2532

    
2533
		/* set location */
2534
		if($wlcfg['reglocation'])
2535
			$wlregcmd[] = escapeshellarg($wlcfg['reglocation']);
2536

    
2537
		$wlregcmd_args = implode(" ", $wlregcmd);
2538

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

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

    
2560
		/* apply the regulatory settings */
2561
		mwexec("{$ifconfig} " . escapeshellarg($if) . " {$wlregcmd_args}");
2562

    
2563
		/* bring the clones back up that were previously up */
2564
		foreach ($clones_up as $clone_if) {
2565
			mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " up");
2566

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

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

    
2587
	/* configure wireless */
2588
	$wlcmd_args = implode(" ", $wlcmd);
2589
	mwexec("/sbin/ifconfig {$if} $wlcmd_args", false);
2590

    
2591

    
2592
	sleep(1);
2593
	/* execute hostapd and wpa_supplicant if required in shell */
2594
	mwexec("/bin/sh {$g['tmp_path']}/{$if}_setup.sh");
2595

    
2596
	return 0;
2597

    
2598
}
2599

    
2600
function kill_hostapd($interface) {
2601
	return "/bin/pkill -f \"hostapd .*{$interface}\"\n";
2602
}
2603

    
2604
function kill_wpasupplicant($interface) {
2605
	return "/bin/pkill -f \"wpa_supplicant .*{$interface}\"\n";
2606
}
2607

    
2608
function find_dhclient_process($interface) {
2609
	if ($interface)
2610
		$pid = `/bin/pgrep -axf "dhclient: {$interface}"`;
2611
	else
2612
		$pid = 0;
2613

    
2614
	return intval($pid);
2615
}
2616

    
2617
function find_dhcp6c_process($interface) {
2618
	if ($interface)
2619
		$pid = `/bin/ps auxw|grep "[d]hcp6c" |grep "{$interface}"|awk '{print $2}'`;
2620
	else
2621
		return(false);
2622

    
2623
	return intval($pid);
2624
}
2625

    
2626
function interface_configure($interface = "wan", $reloadall = false, $linkupevent = false) {
2627
	global $config, $g;
2628
	global $interface_sn_arr_cache, $interface_ip_arr_cache;
2629
	global $interface_snv6_arr_cache, $interface_ipv6_arr_cache;
2630

    
2631
	$wancfg = $config['interfaces'][$interface];
2632

    
2633
	$realif = get_real_interface($interface);
2634
	$realhwif_array = get_parent_interface($interface);
2635
	// Need code to handle MLPPP if we ever use $realhwif for MLPPP handling
2636
	$realhwif = $realhwif_array[0];
2637

    
2638
	/* Disable Accepting router advertisements unless specifically requested */
2639
	log_error("Deny router advertisements for interface {$interface}");
2640
	mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 -accept_rtadv");
2641

    
2642
	if (!$g['booting'] && !(substr($realif, 0, 4) == "ovpn")) {
2643
		/* remove all IPv4 and IPv6 addresses */
2644
		while (mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " -alias", true) == 0);
2645
		while (mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 -alias", true) == 0);
2646

    
2647
		/* only bring down the interface when both v4 and v6 are set to NONE */
2648
		if(($wancfg['ipaddr'] <> "none") && ($wancfg['ipaddrv6'] <> "none")) {
2649
			interface_bring_down($interface);
2650
		}
2651
	}
2652

    
2653
	/* wireless configuration? */
2654
	if (is_array($wancfg['wireless']))
2655
		interface_wireless_configure($realif, $wancfg, $wancfg['wireless']);
2656

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

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

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

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

    
2710
	$options = pfSense_get_interface_addresses($realhwif);
2711
	if (is_array($options) && isset($options['caps']['polling'])) {
2712
		if (isset($config['system']['polling']))
2713
			pfSense_interface_capabilities($realif, IFCAP_POLLING);
2714
		else
2715
			pfSense_interface_capabilities($realif, -IFCAP_POLLING);
2716
	}
2717

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

    
2733
        	if(isset($config['system']['disablesegmentationoffloading'])) {
2734
                	if (isset($options['encaps']['tso4']))
2735
				$flags |= IFCAP_TSO;
2736
                	if (isset($options['encaps']['tso6']))
2737
				$flags |= IFCAP_TSO;
2738
        	} else {
2739
                	if (!isset($options['caps']['tso4']))
2740
				$flags |= IFCAP_TSO;
2741
                	if (!isset($options['caps']['tso6']))
2742
				$flags |= IFCAP_TSO;
2743
        	}
2744

    
2745
        	if(isset($config['system']['disablelargereceiveoffloading'])) {
2746
                	if (isset($options['encaps']['lro']))
2747
				$flags |= IFCAP_LRO;
2748
        	} else {
2749
                	if (!isset($options['caps']['lro']))
2750
				$flags |= IFCAP_LRO;
2751
        	}
2752

    
2753
        	/* if the NIC supports polling *AND* it is enabled in the GUI */
2754
        	if (!isset($config['system']['polling']) || !isset($options['caps']['polling'])) {
2755
			$flags |= IFCAP_POLLING;
2756
		}
2757
               	pfSense_interface_capabilities($realhwif, -$flags);
2758
	}
2759

    
2760
	/* invalidate interface/ip/sn cache */
2761
	get_interface_arr(true);
2762
	unset($interface_ip_arr_cache[$realif]);
2763
	unset($interface_sn_arr_cache[$realif]);
2764
	unset($interface_ipv6_arr_cache[$realif]);
2765
	unset($interface_snv6_arr_cache[$realif]);
2766

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

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

    
2821
	if(does_interface_exist($wancfg['if']))
2822
		interfaces_bring_up($wancfg['if']);
2823

    
2824
	interface_netgraph_needed($interface);
2825

    
2826
	if (!$g['booting']) {
2827
		link_interface_to_vips($interface, "update");
2828

    
2829
		unset($gre);
2830
		$gre = link_interface_to_gre($interface);
2831
		if (!empty($gre))
2832
			array_walk($gre, 'interface_gre_configure');
2833

    
2834
		unset($gif);
2835
		$gif = link_interface_to_gif($interface);
2836
		if (!empty($gif))
2837
			array_walk($gif, 'interface_gif_configure');
2838

    
2839
		if ($linkupevent == false || substr($realif, 0, 4) == "ovpn") {
2840
			unset($bridgetmp);
2841
			$bridgetmp = link_interface_to_bridge($interface);
2842
			if (!empty($bridgetmp))
2843
				interface_bridge_add_member($bridgetmp, $realif);
2844
		}
2845

    
2846
		$grouptmp = link_interface_to_group($interface);
2847
		if (!empty($grouptmp))
2848
			array_walk($grouptmp, 'interface_group_add_member');
2849

    
2850
		if ($interface == "lan")
2851
			/* make new hosts file */
2852
			system_hosts_generate();
2853

    
2854
		if ($reloadall == true) {
2855

    
2856
			/* reconfigure static routes (kernel may have deleted them) */
2857
			system_routing_configure($interface);
2858

    
2859
			/* reload ipsec tunnels */
2860
			vpn_ipsec_configure();
2861

    
2862
			/* restart dnsmasq */
2863
			services_dnsmasq_configure();
2864

    
2865
			/* update dyndns */
2866
			send_event("service reload dyndns {$interface}");
2867

    
2868
			/* reload captive portal */
2869
			captiveportal_init_rules();
2870
		}
2871
	}
2872

    
2873
	return 0;
2874
}
2875

    
2876
function interface_track6_configure($interface = "lan") {
2877
	global $config, $g;
2878
	$iflist = get_configured_interface_with_descr(false, true);
2879

    
2880
	$wancfg = $config['interfaces'][$interface];
2881
	$wanif = $wancfg['if'];
2882
	if (empty($wancfg))
2883
		$wancfg = array();
2884

    
2885
	$wanif = get_real_interface($interface);
2886

    
2887
	/* If the interface is not configured via another, exit */
2888
	if(!$wancfg['track6-interface'] <> "") {
2889
		return(false);
2890
	}
2891

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

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

    
2917

    
2918
function interface_track6_6rd_configure($interface = "lan") {
2919
	global $config, $g;
2920
	$iflist = get_configured_interface_with_descr(false, true);
2921

    
2922
	$lancfg = $config['interfaces'][$interface];
2923
	$lanif = $lancfg['if'];
2924
	if (empty($lancfg))
2925
		$lancfg = array();
2926

    
2927
	$lanif = get_real_interface($interface);
2928

    
2929
	/* If the interface is not configured via another, exit */
2930
	if(!$lancfg['track6-interface'] <> "") {
2931
		return(false);
2932
	}
2933
	if(!is_numeric($lancfg['track6-prefix-id']))
2934
		$lancfg['track6-prefix-id'] = 0;
2935

    
2936
	$wancfg = $config['interfaces'][$lancfg['track6-interface']];
2937
	$wanif = $wancfg['if'];
2938
	if (empty($wancfg))
2939
		$wancfg = array();
2940

    
2941
	$ip4address = find_interface_ip($wanif);
2942
	if((!is_ipaddrv4($ip4address)) || (is_private_ip($ip4address))) {
2943
		log_error("The interface IPv4 '{$ip4address}' address on interface '{$wanif}' is not public, not configuring 6RD tunnel");
2944
		return false;
2945
	}
2946
	$hexwanv4 = return_hex_ipv4($ip4address);
2947

    
2948
	/* create the long prefix notation for math, save the prefix length */
2949
	$rd6prefix = explode("/", $wancfg['prefix-6rd']);
2950
	$rd6prefixlen = $rd6prefix[1];
2951
	$rd6prefix = Net_IPv6::uncompress($rd6prefix[0]);
2952

    
2953
	/* binary presentation of the prefix for all 128 bits. */
2954
	$rd6lanbin = convert_ipv6_to_128bit($rd6prefix);
2955

    
2956
	/* just save the left prefix length bits */
2957
	$rd6lanbin = substr($rd6lanbin, 0, $rd6prefixlen);
2958
	/* add the v4 address, offset n bits from the left */
2959
	$rd6lanbin .= substr(sprintf("%032b", hexdec($hexwanv4)), (0 + $wancfg['prefix-6rd-v4plen']), 32);
2960

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

    
2969
	/* convert the 128 bits for the lan address back into a valid IPv6 address */
2970
	$rd6lan = convert_128bit_to_ipv6($rd6lanbin) ."1";
2971

    
2972
	log_error("rd6 {$interface} with ipv6 address {$rd6lan} based on {$lancfg['track6-interface']} ipv4 {$ip4address}");
2973
	mwexec("/sbin/ifconfig {$lanif} inet6 {$rd6lan} prefixlen 64");
2974
	return 0;
2975
}
2976

    
2977
function interface_track6_6to4_configure($interface = "lan") {
2978
	global $config, $g;
2979
	$iflist = get_configured_interface_with_descr(false, true);
2980

    
2981
	$lancfg = $config['interfaces'][$interface];
2982
	$lanif = $lancfg['if'];
2983
	if (empty($lancfg))
2984
		$lancfg = array();
2985

    
2986
	$lanif = get_real_interface($interface);
2987

    
2988
	/* If the interface is not configured via another, exit */
2989
	if(!$lancfg['track6-interface'] <> "") {
2990
		return(false);
2991
	}
2992
	if(!is_numeric($lancfg['track6-prefix-id']))
2993
		$lancfg['track6-prefix-id'] = 0;
2994

    
2995
	$wancfg = $config['interfaces'][$lancfg['track6-interface']];
2996
	$wanif = $wancfg['if'];
2997
	if (empty($wancfg))
2998
		$wancfg = array();
2999

    
3000
	$ip4address = find_interface_ip($wanif);
3001
	if((!is_ipaddrv4($ip4address)) || (is_private_ip($ip4address))) {
3002
		log_error("The interface IPv4 '{$ip4address}' address on interface '{$wanif}' is not public, not configuring 6RD tunnel");
3003
		return false;
3004
	}
3005
	$hexwanv4 = return_hex_ipv4($ip4address);
3006

    
3007
	/* create the long prefix notation for math, save the prefix length */
3008
	$sixto4prefix = "2002::";
3009
	$sixto4prefixlen = 16;
3010
	$sixto4prefix = Net_IPv6::uncompress($sixto4prefix);
3011

    
3012
	/* binary presentation of the prefix for all 128 bits. */
3013
	$sixto4lanbin = convert_ipv6_to_128bit($sixto4prefix);
3014

    
3015
	/* just save the left prefix length bits */
3016
	$sixto4lanbin = substr($sixto4lanbin, 0, $sixto4prefixlen);
3017
	/* add the v4 address */
3018
	$sixto4lanbin .= sprintf("%032b", hexdec($hexwanv4));
3019
	/* add the custom prefix id */
3020
	$sixto4lanbin .= sprintf("%016b", $lancfg['track6-prefix-id']);
3021
	/* fill the rest out with zeros */
3022
	$sixto4lanbin = str_pad($sixto4lanbin, 128, "0", STR_PAD_RIGHT);;
3023

    
3024
	/* convert the 128 bits for the lan address back into a valid IPv6 address */
3025
	$sixto4lan = convert_128bit_to_ipv6($sixto4lanbin) ."1";
3026

    
3027
	log_error("sixto4 {$interface} with ipv6 address {$sixto4lan} based on {$lancfg['track6-interface']} ipv4 {$ip4address}");
3028
	mwexec("/sbin/ifconfig {$lanif} inet6 {$sixto4lan} prefixlen 64");
3029
	return 0;
3030
}
3031

    
3032
function interface_track6_dhcp6_configure($interface = "lan") {
3033
	global $config, $g;
3034
	$iflist = get_configured_interface_with_descr(false, true);
3035

    
3036
	$lancfg = $config['interfaces'][$interface];
3037
	$lanif = $lancfg['if'];
3038
	if (empty($lancfg))
3039
		$lancfg = array();
3040

    
3041
	$lanif = get_real_interface($interface);
3042

    
3043
	/* If the interface is not configured via another, exit */
3044
	if(!$lancfg['track6-interface'] <> "") {
3045
		return(false);
3046
	}
3047
	if(!is_numeric($lancfg['track6-prefix-id']))
3048
		$lancfg['track6-prefix-id'] = 0;
3049

    
3050
	$wancfg = $config['interfaces'][$lancfg['track6-interface']];
3051
	$wanif = $wancfg['if'];
3052
	if (empty($wancfg))
3053
		$wancfg = array();
3054

    
3055

    
3056
	$ifcfgipv6 = find_interface_ipv6($lanif);
3057
	if(is_ipaddrv6($ifcfgipv6)) {
3058
		$dhcp6lanarr = explode(":", Net_IPv6::uncompress($ifcfgipv6));
3059
		$dhcp6lanarr[4] = 0;
3060
		$dhcp6lanarr[5] = 0;
3061
		$dhcp6lanarr[6] = 0;
3062
		$dhcp6lanarr[7] = 1;
3063
		$dhcp6lan =  Net_IPv6::compress(implode(":", $dhcp6lanarr));
3064
		log_error("dhcp6 {$interface} with ipv6 address {$dhcp6lan} based on {$lancfg['track6-interface']}");
3065
		mwexec("/sbin/ifconfig {$lanif} inet6 {$dhcp6lan} prefixlen 64");
3066
	}
3067
	return 0;
3068
}
3069

    
3070
function interface_6rd_configure($interface = "wan") {
3071
	global $config, $g;
3072
	$iflist = get_configured_interface_with_descr(false, true);
3073

    
3074
	/* because this is a tunnel interface we can only function
3075
	 *	with a public IPv4 address on the interface */
3076

    
3077
	$wancfg = $config['interfaces'][$interface];
3078
	$wanif = $wancfg['if'];
3079
	if (empty($wancfg))
3080
		$wancfg = array();
3081

    
3082
	$wanif = get_real_interface($interface);
3083

    
3084
	$ip4address = find_interface_ip($wanif);
3085
	$ip4gateway = get_interface_gateway($wanif);
3086
	if((!is_ipaddrv4($ip4address)) || (is_private_ip($ip4address))) {
3087
		log_error("The interface IPv4 '{$ip4address}' address on interface '{$wanif}' is not public, not configuring 6RD tunnel");
3088
		return false;
3089
	}
3090
	$hexwanv4 = return_hex_ipv4($ip4address);
3091

    
3092
	if(!is_numeric($wancfg['prefix-6rd-v4plen']))
3093
		$wancfg['prefix-6rd-v4plen'] = 0;
3094

    
3095
	/* create the long prefix notation for math, save the prefix length */
3096
	$rd6prefix = explode("/", $wancfg['prefix-6rd']);
3097
	$rd6prefixlen = $rd6prefix[1];
3098
	$rd6prefix = Net_IPv6::uncompress($rd6prefix[0]);
3099

    
3100
	/* we need the hex form of the broker IPv4 address */
3101
	$hexbrv4 = return_hex_ipv4($wancfg['gateway-6rd']);
3102

    
3103
	/* binary presentation of the prefix for all 128 bits. */
3104
	$rd6prefixbin = convert_ipv6_to_128bit($rd6prefix);
3105

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

    
3113
	/* convert the 128 bits for the broker address back into a valid IPv6 address */
3114
	$rd6brgw = convert_128bit_to_ipv6($rd6brprefixbin);
3115

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

    
3123
	/* convert the 128 bits for the broker address back into a valid IPv6 address */
3124
	$rd6prefix = convert_128bit_to_ipv6($rd6prefixbin);
3125

    
3126
	/* stf approach only works when embedding the entire 32 bits of the v4 */
3127
	mwexec("/sbin/ifconfig stf0 create");
3128
	pfSense_interface_flags("stf0", IFF_LINK2);
3129
	mwexec("/sbin/ifconfig stf0 inet6 {$rd6prefix}/{$rd6prefixlen}");
3130
	log_error("Created 6rd interface stf0 {$rd6prefix}/{$rd6prefixlen}");
3131

    
3132
	/* write out a default router file */
3133
	file_put_contents("{$g['tmp_path']}/{$wanif}_routerv6", "{$rd6brgw}\n");
3134
	file_put_contents("{$g['tmp_path']}/{$wanif}_defaultgwv6", "{$rd6brgw}\n");
3135

    
3136
	if (is_ipaddrv4($ip4gateway))
3137
		mwexec("route change -host " . $wancfg['gateway-6rd'] . " {$ip4gateway}");
3138

    
3139
	/* configure dependent interfaces */
3140
	foreach($iflist as $if => $ifname) {
3141
		if($config['interfaces'][$if]['track6-interface'] == $interface)
3142
			interface_track6_configure($if);
3143
	}
3144

    
3145
	return 0;
3146
}
3147

    
3148
function interface_6to4_configure($interface = "wan"){
3149
	global $config, $g;
3150
	$iflist = get_configured_interface_with_descr(false, true);
3151

    
3152
	/* because this is a tunnel interface we can only function
3153
	 *	with a public IPv4 address on the interface */
3154

    
3155
	$wancfg = $config['interfaces'][$interface];
3156
	$wanif = $wancfg['if'];
3157
	if (empty($wancfg))
3158
		$wancfg = array();
3159

    
3160
	$wanif = get_real_interface($interface);
3161

    
3162
	$ip4address = find_interface_ip($wanif);
3163
	$ip4gateway = get_interface_gateway($wanif);
3164
	if((!is_ipaddrv4($ip4address)) || (is_private_ip($ip4address))) {
3165
		log_error("The interface IPv4 '{$ip4address}' address on interface '{$wanif}' is not public, not configuring 6RD tunnel");
3166
		return false;
3167
	}
3168

    
3169
	/* create the long prefix notation for math, save the prefix length */
3170
	$stfprefixlen = 16;
3171
	$stfprefix = Net_IPv6::uncompress("2002::");
3172
	$stfarr = explode(":", $stfprefix);
3173
	$v4prefixlen = "0";
3174

    
3175
	/* we need the hex form of the interface IPv4 address */
3176
	$ip4arr = explode(".", $ip4address);
3177
	$hexwanv4 = "";
3178
	foreach($ip4arr as $octet)
3179
		$hexwanv4 .= sprintf("%02x", $octet);
3180

    
3181
	/* we need the hex form of the broker IPv4 address */
3182
	$ip4arr = explode(".", "192.88.99.1");
3183
	$hexbrv4 = "";
3184
	foreach($ip4arr as $octet)
3185
		$hexbrv4 .= sprintf("%02x", $octet);
3186

    
3187
	/* binary presentation of the prefix for all 128 bits. */
3188
	$stfprefixbin = "";
3189
	foreach($stfarr as $element) {
3190
		$stfprefixbin .= sprintf("%016b", hexdec($element));
3191
	}
3192
	/* just save the left prefix length bits */
3193
	$stfprefixstartbin = substr($stfprefixbin, 0, $stfprefixlen);
3194

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

    
3199
	/* for the local subnet too. */
3200
	$stflanbin = substr(sprintf("%032b", hexdec($hexwanv4)), $v4prefixlen, 32);
3201
	$stflanbin = str_pad($stfprefixstartbin . $stflanbin, 128, "0", STR_PAD_RIGHT);;
3202

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

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

    
3221
	/* setup the stf interface */
3222
	mwexec("/sbin/ifconfig stf0 destroy");
3223
	mwexec("/sbin/ifconfig stf0 create");
3224
	pfSense_interface_flags("stf0", IFF_LINK2);
3225
	mwexec("/sbin/ifconfig stf0 inet6 {$stflanpr} prefixlen 16");
3226

    
3227
	log_error("Set IPv6 address inet6 {$stflanpr} prefixlen 16 for stf0, route {$stfbrgw}");
3228

    
3229
	/* write out a default router file */
3230
	file_put_contents("{$g['tmp_path']}/{$wanif}_routerv6", "{$stfbrgw}");
3231
	file_put_contents("{$g['tmp_path']}/{$wanif}_defaultgwv6", "{$stfbrgw}");
3232

    
3233
	if (is_ipaddrv4($ip4gateway)) {
3234
		mwexec("route change -host 192.88.99.1 {$ip4gateway}");
3235
	}
3236

    
3237
	/* configure dependent interfaces */
3238
	foreach($iflist as $if => $ifname) {
3239
		if($config['interfaces'][$if]['track6-interface'] == $interface)
3240
			interface_track6_configure($if);
3241
	}
3242

    
3243
	return 0;
3244
}
3245

    
3246
function interface_dhcpv6_configure($interface = "wan") {
3247
	global $config, $g;
3248
	$iflist = get_configured_interface_with_descr(false, true);
3249

    
3250
	$wancfg = $config['interfaces'][$interface];
3251
	$wanif = $wancfg['if'];
3252
	if (empty($wancfg))
3253
		$wancfg = array();
3254

    
3255
	$wanif = get_real_interface($interface);
3256

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

    
3264
	$dhcp6cconf = "";
3265
	$dhcp6cconf .= "interface {$wanif} {\n";
3266

    
3267
	/* for SLAAC interfaces we do fire off a dhcp6 client for just our name servers */
3268
	if($wancfg['ipaddrv6'] == "slaac") {
3269
		$dhcp6cconf .= "	information-only;\n";
3270
		$dhcp6cconf .= "	request domain-name-servers;\n";
3271
		$dhcp6cconf .= "	request domain-name;\n";
3272
		$dhcp6cconf .= "	script \"{$g['varetc_path']}/dhcp6c_{$interface}_script.sh\"; # we'd like some nameservers please\n";
3273
		$dhcp6cconf .= "};\n";
3274
	} else {
3275

    
3276
		$dhcp6cconf .= " 	send ia-na 0;	# request stateful address\n";
3277
		if(is_numeric($wancfg['dhcp6-ia-pd-len'])) {
3278
			$dhcp6cconf .= "	send ia-pd 0;	# request prefix delegation\n";
3279
		}
3280
		$dhcp6cconf .= "request domain-name-servers;\n";
3281
		$dhcp6cconf .= "request domain-name;\n";
3282
		$dhcp6cconf .= "script \"{$g['varetc_path']}/dhcp6c_{$interface}_script.sh\"; # we'd like some nameservers please\n";
3283

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

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

    
3317
	fwrite($fds, $dhcp6cscript);
3318
	fclose($fds);
3319
	chmod("{$g['varetc_path']}/dhcp6c_{$interface}_script.sh", 0755);
3320

    
3321

    
3322
	/* accept router advertisements for this interface */
3323
	mwexec("/sbin/sysctl -w net.inet6.ip6.accept_rtadv=1");
3324
	log_error("Accept router advertisements on interface {$wanif} ");
3325
	mwexec("/sbin/ifconfig {$wanif} inet6 accept_rtadv");
3326

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

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

    
3359
function interface_dhcp_configure($interface = "wan") {
3360
	global $config, $g;
3361

    
3362
	$wancfg = $config['interfaces'][$interface];
3363
	$wanif = $wancfg['if'];
3364
	if (empty($wancfg))
3365
		$wancfg = array();
3366

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

    
3374
	if ($wancfg['dhcphostname']) {
3375
		$dhclientconf_hostname = "send dhcp-client-identifier \"{$wancfg['dhcphostname']}\";\n";
3376
		$dhclientconf_hostname .= "\tsend host-name \"{$wancfg['dhcphostname']}\";\n";
3377
	} else {
3378
		$dhclientconf_hostname = "";
3379
	}
3380

    
3381
	$wanif = get_real_interface($interface);
3382
	if (empty($wanif)) {
3383
		log_error(sprintf(gettext("Invalid interface \"%s\" in interface_dhcp_configure()"), $interface));
3384
		return 0;
3385
	}
3386
 	$dhclientconf = "";
3387

    
3388
	$dhclientconf .= <<<EOD
3389
interface "{$wanif}" {
3390
timeout 60;
3391
retry 15;
3392
select-timeout 0;
3393
initial-interval 1;
3394
	{$dhclientconf_hostname}
3395
	script "/sbin/dhclient-script";
3396
}
3397

    
3398
EOD;
3399

    
3400
if(is_ipaddr($wancfg['alias-address'])) {
3401
	$subnetmask = gen_subnet_mask($wancfg['alias-subnet']);
3402
	$dhclientconf .= <<<EOD
3403
alias {
3404
	interface  "{$wanif}";
3405
	fixed-address {$wancfg['alias-address']};
3406
	option subnet-mask {$subnetmask};
3407
}
3408

    
3409
EOD;
3410
}
3411
	fwrite($fd, $dhclientconf);
3412
	fclose($fd);
3413

    
3414
	/* bring wan interface up before starting dhclient */
3415
	if($wanif)
3416
		interfaces_bring_up($wanif);
3417
	else
3418
		log_error(printf(gettext("Could not bring up %s interface in interface_dhcp_configure()"), $wanif));
3419

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

    
3423
	return 0;
3424
}
3425

    
3426
function interfaces_group_setup() {
3427
	global $config;
3428

    
3429
	if (!is_array($config['ifgroups']['ifgroupentry']))
3430
		return;
3431

    
3432
	foreach ($config['ifgroups']['ifgroupentry'] as $groupar)
3433
		interface_group_setup($groupar);
3434

    
3435
	return;
3436
}
3437

    
3438
function interface_group_setup(&$groupname /* The parameter is an array */) {
3439
	global $config;
3440

    
3441
	if (!is_array($groupname))
3442
		return;
3443
	$members = explode(" ", $groupname['members']);
3444
	foreach($members as $ifs) {
3445
		$realif = get_real_interface($ifs);
3446
		if ($realif)
3447
			mwexec("/sbin/ifconfig {$realif} group {$groupname['ifname']}");
3448
	}
3449

    
3450
	return;
3451
}
3452

    
3453
function interface_group_add_member($interface, $groupname) {
3454
	$interface = get_real_interface($interface);
3455
	mwexec("/sbin/ifconfig {$interface} group {$groupname}", true);
3456
}
3457

    
3458
/* COMPAT Function */
3459
function convert_friendly_interface_to_real_interface_name($interface) {
3460
	return get_real_interface($interface);
3461
}
3462

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

    
3468
/* COMPAT Function */
3469
function get_current_wan_address($interface = "wan") {
3470
	return get_interface_ip($interface);
3471
}
3472

    
3473
/*
3474
 * convert_real_interface_to_friendly_interface_name($interface): convert fxp0 -> wan, etc.
3475
 */
3476
function convert_real_interface_to_friendly_interface_name($interface = "wan") {
3477
	global $config;
3478

    
3479
	if (stristr($interface, "_vip")) {
3480
		foreach ($config['virtualip']['vip'] as $counter => $vip) {
3481
			if ($vip['mode'] == "carp")  {
3482
				if ($interface == "{$vip['interface']}_vip{$vip['vhid']}")
3483
					return $vip['interface'];
3484
			}
3485
		}
3486
	}
3487

    
3488
	/* XXX: For speed reasons reference directly the interface array */
3489
	$ifdescrs = &$config['interfaces'];
3490
	//$ifdescrs = get_configured_interface_list(false, true);
3491

    
3492
	foreach ($ifdescrs as $if => $ifname) {
3493
		if ($if == $interface || $config['interfaces'][$if]['if'] == $interface)
3494
			return $if;
3495

    
3496
		if (stristr($interface, "_wlan0") && $config['interfaces'][$if]['if'] == interface_get_wireless_base($interface))
3497
			return $if;
3498

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

    
3510
/* attempt to resolve interface to friendly descr */
3511
function convert_friendly_interface_to_friendly_descr($interface) {
3512
        global $config;
3513

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

    
3558
        return $ifdesc;
3559
}
3560

    
3561
function convert_real_interface_to_friendly_descr($interface) {
3562
        global $config;
3563

    
3564
        $ifdesc = convert_real_interface_to_friendly_interface_name("{$interface}");
3565

    
3566
        if ($ifdesc) {
3567
                $iflist = get_configured_interface_with_descr(false, true);
3568
                return $iflist[$ifdesc];
3569
        }
3570

    
3571
        return $interface;
3572
}
3573

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

    
3586
	$parents = array();
3587
	//Check that we got a valid interface passed
3588
	$realif = get_real_interface($interface);
3589
	if ($realif == NULL)
3590
		return $parents;
3591

    
3592
	// If we got a real interface, find it's friendly assigned name
3593
	$interface = convert_real_interface_to_friendly_interface_name($interface);
3594

    
3595
	if (!empty($interface) && isset($config['interfaces'][$interface])) {
3596
		$ifcfg = $config['interfaces'][$interface];
3597
		switch ($ifcfg['ipaddr']) {
3598
			case "ppp":
3599
			case "pppoe":
3600
			case "pptp":
3601
			case "l2tp":
3602
				if (empty($parents))
3603
					if (is_array($config['ppps']['ppp']))
3604
						foreach ($config['ppps']['ppp'] as $pppidx => $ppp) {
3605
							if ($ifcfg['if'] == $ppp['if']) {
3606
								$ports = explode(',', $ppp['ports']);
3607
								foreach ($ports as $pid => $parent_if)
3608
									$parents[$pid] = get_real_interface($parent_if);
3609
								break;
3610
							}
3611
						}
3612
				break;
3613
			case "dhcp":
3614
			case "static":
3615
			default:
3616
				// Handle _vlans
3617
				if (strstr($realif,"_vlan"))
3618
					if (is_array($config['vlans']['vlan']))
3619
						foreach ($config['vlans']['vlan'] as $vlanidx => $vlan)
3620
							if ($ifcfg['if'] == $vlan['vlanif']){
3621
								$parents[0] = $vlan['if'];
3622
								break;
3623
							}
3624
				break;
3625
		}
3626
	}
3627

    
3628
	if (empty($parents))
3629
		$parents[0] = $realif;
3630

    
3631
	return $parents;
3632
}
3633

    
3634
function interface_is_wireless_clone($wlif) {
3635
	if(!stristr($wlif, "_wlan")) {
3636
		return false;
3637
	} else {
3638
		return true;
3639
	}
3640
}
3641

    
3642
function interface_get_wireless_base($wlif) {
3643
	if(!stristr($wlif, "_wlan")) {
3644
		return $wlif;
3645
	} else {
3646
		return substr($wlif, 0, stripos($wlif, "_wlan"));
3647
	}
3648
}
3649

    
3650
function interface_get_wireless_clone($wlif) {
3651
	if(!stristr($wlif, "_wlan")) {
3652
		return $wlif . "_wlan0";
3653
	} else {
3654
		return $wlif;
3655
	}
3656
}
3657

    
3658
function get_real_interface($interface = "wan") {
3659
    global $config;
3660

    
3661
	$wanif = NULL;
3662

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

    
3693
		if (empty($config['interfaces'][$interface]))
3694
			break;
3695

    
3696
		$cfg = &$config['interfaces'][$interface];
3697

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

    
3712
		switch ($cfg['ipaddr']) {
3713
			case "pppoe":
3714
			case "pptp":
3715
			case "l2tp":
3716
			case "ppp":
3717
				$wanif = $cfg['if'];
3718
				break;
3719
			default:
3720
				$wanif = $cfg['if'];
3721
				break;
3722
		}
3723
		break;
3724
	}
3725

    
3726
    return $wanif;
3727
}
3728

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

    
3766
/*
3767
 * find_ip_interface($ip): return the interface where an ip is defined
3768
 *   (or if $bits is specified, where an IP within the subnet is defined)
3769
 */
3770
function find_ip_interface($ip, $bits = null)
3771
{
3772
	/* if list */
3773
	$ifdescrs = get_configured_interface_list();
3774

    
3775
	foreach ($ifdescrs as $ifdescr => $ifname) {
3776
		if ($bits === null) {
3777
			if ($ip == get_interface_ip($ifname)) {
3778
				$int = get_real_interface($ifname);
3779
				return $int;
3780
			}
3781
		}
3782
		else {
3783
			if (ip_in_subnet(get_interface_ip($ifname), $ip . "/" . $bits)) {
3784
				$int = get_real_interface($ifname);
3785
				return $int;
3786
			}
3787
		}
3788
	}
3789
	return false;
3790
}
3791

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

    
3818
/*
3819
 *   find_number_of_created_carp_interfaces: return the number of carp interfaces
3820
 */
3821
function find_number_of_created_carp_interfaces() {
3822
	return `/sbin/ifconfig | grep "carp:" | wc -l`;
3823
}
3824

    
3825
function get_all_carp_interfaces() {
3826
	$ints = str_replace("\n", " ", `ifconfig | grep "carp:" -B2 | grep ": flag" | cut -d: -f1`);
3827
	$ints = explode(" ", $ints);
3828
	return $ints;
3829
}
3830

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

    
3856
				if ($if)
3857
					return $if;
3858
			}
3859
		}
3860
	}
3861
}
3862

    
3863
function link_carp_interface_to_parent($interface) {
3864
	global $config;
3865

    
3866
	if ($interface == "")
3867
		return;
3868

    
3869
	$carp_ip = get_interface_ip($interface);
3870
	$carp_ipv6 = get_interface_ipv6($interface);
3871

    
3872
	if((!is_ipaddrv4($carp_ip)) && (!is_ipaddrv6($carp_ipv6)))
3873
		return;
3874

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

    
3897

    
3898
/****f* interfaces/link_ip_to_carp_interface
3899
 * NAME
3900
 *   link_ip_to_carp_interface - Find where a CARP interface links to.
3901
 * INPUTS
3902
 *   $ip
3903
 * RESULT
3904
 *   $carp_ints
3905
 ******/
3906
function link_ip_to_carp_interface($ip) {
3907
        global $config;
3908

    
3909
        if (!is_ipaddr($ip))
3910
                return;
3911

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

    
3930
        return $carp_ints;
3931
}
3932

    
3933
function link_interface_to_vlans($int, $action = "") {
3934
	global $config;
3935

    
3936
	if (empty($int))
3937
		return;
3938

    
3939
	if (is_array($config['vlans']['vlan'])) {
3940
                foreach ($config['vlans']['vlan'] as $vlan) {
3941
			if ($int == $vlan['if']) {
3942
				if ($action == "update") {
3943
					interfaces_bring_up($int);
3944
				} else if ($action == "")
3945
					return $vlan;
3946
			}
3947
		}
3948
	}
3949
}
3950

    
3951
function link_interface_to_vips($int, $action = "") {
3952
        global $config;
3953

    
3954
        if (is_array($config['virtualip']['vip'])) {
3955
		foreach ($config['virtualip']['vip'] as $vip) {
3956
			if ($int == $vip['interface']) {
3957
				if ($action == "update")
3958
					interfaces_vips_configure($int);
3959
				else
3960
					return $vip;
3961
			}
3962
		}
3963
	}
3964
}
3965

    
3966
/****f* interfaces/link_interface_to_bridge
3967
 * NAME
3968
 *   link_interface_to_bridge - Finds out a bridge group for an interface
3969
 * INPUTS
3970
 *   $ip
3971
 * RESULT
3972
 *   bridge[0-99]
3973
 ******/
3974
function link_interface_to_bridge($int) {
3975
        global $config;
3976

    
3977
        if (is_array($config['bridges']['bridged'])) {
3978
                foreach ($config['bridges']['bridged'] as $bridge) {
3979
			if (in_array($int, explode(',', $bridge['members'])))
3980
                                return "{$bridge['bridgeif']}";
3981
		}
3982
	}
3983
}
3984

    
3985
function link_interface_to_group($int) {
3986
        global $config;
3987

    
3988
	$result = array();
3989

    
3990
        if (is_array($config['ifgroups']['ifgroupentry'])) {
3991
                foreach ($config['ifgroups']['ifgroupentry'] as $group) {
3992
			if (in_array($int, explode(" ", $group['members'])))
3993
				$result[$group['ifname']] = $int;
3994
		}
3995
	}
3996

    
3997
	return $result;
3998
}
3999

    
4000
function link_interface_to_gre($interface) {
4001
        global $config;
4002

    
4003
	$result = array();
4004

    
4005
        if (is_array($config['gres']['gre'])) {
4006
                foreach ($config['gres']['gre'] as $gre)
4007
                        if($gre['if'] == $interface)
4008
				$result[] = $gre;
4009
	}
4010

    
4011
	return $result;
4012
}
4013

    
4014
function link_interface_to_gif($interface) {
4015
        global $config;
4016

    
4017
	$result = array();
4018

    
4019
        if (is_array($config['gifs']['gif'])) {
4020
                foreach ($config['gifs']['gif'] as $gif)
4021
                        if($gif['if'] == $interface)
4022
                                $result[] = $gif;
4023
	}
4024

    
4025
	return $result;
4026
}
4027

    
4028
/*
4029
 * find_interface_ip($interface): return the interface ip (first found)
4030
 */
4031
function find_interface_ip($interface, $flush = false)
4032
{
4033
	global $interface_ip_arr_cache;
4034
	global $interface_sn_arr_cache;
4035

    
4036
	$interface = str_replace("\n", "", $interface);
4037

    
4038
	if (!does_interface_exist($interface))
4039
		return;
4040

    
4041
	/* Setup IP cache */
4042
	if (!isset($interface_ip_arr_cache[$interface]) or $flush) {
4043
		$ifinfo = pfSense_get_interface_addresses($interface);
4044
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
4045
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
4046
	}
4047

    
4048
	return $interface_ip_arr_cache[$interface];
4049
}
4050

    
4051
/*
4052
 * find_interface_ipv6($interface): return the interface ip (first found)
4053
 */
4054
function find_interface_ipv6($interface, $flush = false)
4055
{
4056
	global $interface_ipv6_arr_cache;
4057
	global $interface_snv6_arr_cache;
4058
	global $config;
4059

    
4060
	$interface = trim($interface);
4061
	$interface = get_real_interface($interface);
4062

    
4063
	if (!does_interface_exist($interface))
4064
		return;
4065

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

    
4089
	return $interface_ipv6_arr_cache[$interface];
4090
}
4091

    
4092
/*
4093
 * find_interface_ipv6_ll($interface): return the interface ipv6 link local (first found)
4094
 */
4095
function find_interface_ipv6_ll($interface, $flush = false)
4096
{
4097
	global $interface_llv6_arr_cache;
4098
	global $config;
4099

    
4100
	$interface = str_replace("\n", "", $interface);
4101

    
4102
	if (!does_interface_exist($interface))
4103
		return;
4104

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

    
4124
function find_interface_subnet($interface, $flush = false)
4125
{
4126
	global $interface_sn_arr_cache;
4127
	global $interface_ip_arr_cache;
4128

    
4129
	$interface = str_replace("\n", "", $interface);
4130
	if (does_interface_exist($interface) == false)
4131
		return;
4132

    
4133
	if (!isset($interface_sn_arr_cache[$interface]) or $flush) {
4134
		$ifinfo = pfSense_get_interface_addresses($interface);
4135
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
4136
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
4137
        }
4138

    
4139
	return $interface_sn_arr_cache[$interface];
4140
}
4141

    
4142
function find_interface_subnetv6($interface, $flush = false)
4143
{
4144
	global $interface_snv6_arr_cache;
4145
	global $interface_ipv6_arr_cache;
4146

    
4147
	$interface = str_replace("\n", "", $interface);
4148
	if (does_interface_exist($interface) == false)
4149
		return;
4150

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

    
4173
	return $interface_snv6_arr_cache[$interface];
4174
}
4175

    
4176
function ip_in_interface_alias_subnet($interface, $ipalias) {
4177
	global $config;
4178

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

    
4194
	return false;
4195
}
4196

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

    
4209
	$curip = find_interface_ip($realif);
4210
	if ($curip && is_ipaddr($curip) && ($curip != "0.0.0.0"))
4211
		return $curip;
4212
	else
4213
		return null;
4214
}
4215

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

    
4235
	$curip = find_interface_ipv6($realif);
4236
	if ($curip && is_ipaddrv6($curip) && ($curip != "::"))
4237
		return $curip;
4238
	else
4239
		return null;
4240
}
4241

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

    
4254
	$curip = find_interface_ipv6_ll($realif);
4255
	if ($curip && is_ipaddrv6($curip) && ($curip != "::"))
4256
		return $curip;
4257
	else
4258
		return null;
4259
}
4260

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

    
4273
	$cursn = find_interface_subnet($realif);
4274
	if (!empty($cursn))
4275
		return $cursn;
4276

    
4277
	return null;
4278
}
4279

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

    
4292
	$cursn = find_interface_subnetv6($realif);
4293
	if (!empty($cursn))
4294
		return $cursn;
4295

    
4296
	return null;
4297
}
4298

    
4299
/* return outside interfaces with a gateway */
4300
function get_interfaces_with_gateway() {
4301
	global $config;
4302

    
4303
	$ints = array();
4304

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

    
4326
/* return true if interface has a gateway */
4327
function interface_has_gateway($friendly) {
4328
	global $config;
4329

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

    
4349
	return false;
4350
}
4351

    
4352
/* return true if interface has a gateway */
4353
function interface_has_gatewayv6($friendly) {
4354
	global $config;
4355

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

    
4378
	return false;
4379
}
4380

    
4381
/****f* interfaces/is_altq_capable
4382
 * NAME
4383
 *   is_altq_capable - Test if interface is capable of using ALTQ
4384
 * INPUTS
4385
 *   $int            - string containing interface name
4386
 * RESULT
4387
 *   boolean         - true or false
4388
 ******/
4389

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

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

    
4405
        if (in_array($int_family[0], $capable))
4406
                return true;
4407
	else if (stristr($int, "l2tp")) /* VLANs are name $parent_$vlan now */
4408
		return true;
4409
	else if (stristr($int, "vlan")) /* VLANs are name $parent_$vlan now */
4410
		return true;
4411
	else if (stristr($int, "_wlan")) /* WLANs are name $parent_$wlan now */
4412
		return true;
4413
        else
4414
                return false;
4415
}
4416

    
4417
/****f* interfaces/is_interface_wireless
4418
 * NAME
4419
 *   is_interface_wireless - Returns if an interface is wireless
4420
 * RESULT
4421
 *   $tmp       - Returns if an interface is wireless
4422
 ******/
4423
function is_interface_wireless($interface) {
4424
        global $config, $g;
4425

    
4426
        $friendly = convert_real_interface_to_friendly_interface_name($interface);
4427
        if(!isset($config['interfaces'][$friendly]['wireless'])) {
4428
                if (preg_match($g['wireless_regex'], $interface)) {
4429
                        if (isset($config['interfaces'][$friendly]))
4430
                                $config['interfaces'][$friendly]['wireless'] = array();
4431
                        return true;
4432
                }
4433
                return false;
4434
        } else
4435
                return true;
4436
}
4437

    
4438
function get_wireless_modes($interface) {
4439
	/* return wireless modes and channels */
4440
	$wireless_modes = array();
4441

    
4442
	$cloned_interface = get_real_interface($interface);
4443

    
4444
	if($cloned_interface && is_interface_wireless($cloned_interface)) {
4445
		$chan_list = "/sbin/ifconfig {$cloned_interface} list chan";
4446
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
4447
		$format_list = "/usr/bin/awk '{print \$5 \" \" \$6 \",\" \$1}'";
4448

    
4449
		$interface_channels = "";
4450
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
4451
		$interface_channel_count = count($interface_channels);
4452

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

    
4483
/* return channel numbers, frequency, max txpower, and max regulation txpower */
4484
function get_wireless_channel_info($interface) {
4485
	$wireless_channels = array();
4486

    
4487
	$cloned_interface = get_real_interface($interface);
4488

    
4489
	if($cloned_interface && is_interface_wireless($cloned_interface)) {
4490
		$chan_list = "/sbin/ifconfig {$cloned_interface} list txpower";
4491
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
4492
		$format_list = "/usr/bin/awk '{print \$1 \",\" \$3 \" \" \$4 \",\" \$5 \",\" \$7}'";
4493

    
4494
		$interface_channels = "";
4495
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
4496

    
4497
		foreach ($interface_channels as $channel_line) {
4498
			$channel_line = explode(",", $channel_line);
4499
			if(!isset($wireless_channels[$channel_line[0]]))
4500
				$wireless_channels[$channel_line[0]] = $channel_line;
4501
		}
4502
	}
4503
	return($wireless_channels);
4504
}
4505

    
4506
/****f* interfaces/get_interface_mtu
4507
 * NAME
4508
 *   get_interface_mtu - Return the mtu of an interface
4509
 * RESULT
4510
 *   $tmp       - Returns the mtu of an interface
4511
 ******/
4512
function get_interface_mtu($interface) {
4513
        $mtu = pfSense_get_interface_addresses($interface);
4514
        return $mtu['mtu'];
4515
}
4516

    
4517
function get_interface_mac($interface) {
4518

    
4519
	$macinfo = pfSense_get_interface_addresses($interface);
4520
	return $macinfo["macaddr"];
4521
}
4522

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

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

    
4548

    
4549
	$iface = trim($iface);
4550
	$capable = pfSense_get_interface_addresses($iface);
4551
	if (isset($capable['caps']['vlanmtu']))
4552
                return true;
4553

    
4554

    
4555

    
4556

    
4557

    
4558
	return false;
4559
}
4560

    
4561
function interface_setup_pppoe_reset_file($pppif, $iface="") {
4562
	global $g;
4563

    
4564
	$cron_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
4565

    
4566
	if(!empty($iface) && !empty($pppif)){
4567
		$cron_cmd = <<<EOD
4568
#!/bin/sh
4569
/usr/local/sbin/pfSctl -c 'interface reload {$iface}'
4570
/usr/bin/logger -t {$pppif} "PPPoE periodic reset executed on {$iface}"
4571

    
4572
EOD;
4573

    
4574
		@file_put_contents($cron_file, $cron_cmd);
4575
		chmod($cron_file, 0755);
4576
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
4577
	} else
4578
		unlink_if_exists($cron_file);
4579
}
4580

    
4581
function get_interface_default_mtu($type = "ethernet") {
4582
	switch ($type) {
4583
	case "gre":
4584
		return 1476;
4585
		break;
4586
	case "gif":
4587
		return 1280;
4588
		break;
4589
	case "tun":
4590
	case "vlan":
4591
	case "tap":
4592
	case "ethernet":
4593
	default:
4594
		return 1500;
4595
		break;
4596
	}
4597

    
4598
	/* Never reached */
4599
	return 1500;
4600
}
4601

    
4602
function get_vip_descr($ipaddress) {
4603
	global $config;
4604

    
4605
	foreach ($config['virtualip']['vip'] as $vip) {
4606
		if ($vip['subnet'] == $ipaddress) {
4607
			return ($vip['descr']);
4608
		}
4609
	}
4610
	return "";
4611
}
4612

    
4613
function interfaces_staticarp_configure($if) {
4614
	global $config, $g;
4615
	if(isset($config['system']['developerspew'])) {
4616
		$mt = microtime();
4617
		echo "interfaces_staticarp_configure($if) being called $mt\n";
4618
	}
4619

    
4620
	$ifcfg = $config['interfaces'][$if];
4621

    
4622
	if (empty($if) || empty($ifcfg['if']))
4623
		return 0;
4624

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

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

    
4634
			}
4635

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

    
4649
	return 0;
4650
}
4651

    
4652
function get_failover_interface($interface) {
4653
	global $config;
4654
	/* shortcut to get_real_interface if we find it in the config */
4655
	if(is_array($config['interfaces'][$interface])) {
4656
		$wanif = get_real_interface($interface);
4657
		return $wanif;
4658
	}
4659

    
4660
	/* compare against gateway groups */
4661
	$a_groups = return_gateway_groups_array();
4662
	if(is_array($a_groups[$interface])) {
4663
		/* we found a gateway group, fetch the interface or vip */
4664
		if($a_groups[$interface][0]['vip'] <> "")
4665
			$wanif = $a_groups[$interface][0]['vip'];
4666
		else
4667
			$wanif = $a_groups[$interface][0]['int'];
4668

    
4669
		return $wanif;
4670
	}
4671
	/* fall through to get_real_interface */
4672
	$wanif = get_real_interface($interface);
4673
	return $wanif;
4674
}
4675

    
4676
?>
(25-25/67)