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
				break;
1374
			case "pptp":
1375
			case "l2tp":
1376
				/* configure interface */
1377
				if(is_ipaddr($localips[$pid])){
1378
					// Manually configure interface IP/subnet
1379
					pfSense_interface_setaddress($port, "{$localips[$pid]}/{$subnets[$pid]}");
1380
					interfaces_bring_up($port);
1381
				} else if (empty($localips[$pid]))
1382
					$localips[$pid] = get_interface_ip($port); // try to get the interface IP from the port
1383

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1505
EOD;
1506

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

    
1511
EOD;
1512

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

    
1520
EOD;
1521

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

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

    
1532
EOD;
1533

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

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

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

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

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

    
1560
EOD;
1561

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

    
1566
EOD;
1567

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

    
1572
EOD;
1573

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

    
1579
EOD;
1580

    
1581

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

    
1586
EOD;
1587

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

    
1593
EOD;
1594

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

    
1599
EOD;
1600

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

    
1605
EOD;
1606

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

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

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

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

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

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

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

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

    
1664
EOD;
1665

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

    
1671
EOD;
1672
		}
1673

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

    
1677

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

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

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

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

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

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

    
1752
	return 1;
1753
}
1754

    
1755
function interfaces_carp_setup() {
1756
	global $g, $config;
1757

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

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

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

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

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

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

    
1799
		sleep(1);
1800

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

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

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

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

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

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

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

    
1852
				if (!empty($interface) && $interface != $proxyif)
1853
					continue;
1854

    
1855
				if (!is_array($paa[$proxyif]))
1856
					$paa[$proxyif] = array();
1857

    
1858
				$paa[$proxyif][] = $vipent;
1859
			}
1860
		}
1861
	}
1862

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

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

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

    
1943
function interface_reload_carps($cif) {
1944
	global $config;
1945

    
1946
	$carpifs = link_ip_to_carp_interface(find_interface_ip($cif));
1947
	if (empty($carpifs))
1948
		return;
1949

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

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

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

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

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

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

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

    
2023
	/* invalidate interface cache */
2024
	get_interface_arr(true);
2025

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

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

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

    
2045
	interfaces_bring_up($vipif);
2046

    
2047
	return $vipif;
2048
}
2049

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

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

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

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

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

    
2121
	if(!is_interface_wireless($ifcfg['if']))
2122
		return;
2123

    
2124
	$baseif = interface_get_wireless_base($ifcfg['if']);
2125

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

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

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

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

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

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

    
2196
	// Clone wireless nic if needed.
2197
	interface_wireless_clone($if, $wl);
2198

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2348
	mwexec(kill_hostapd("{$if}"));
2349
	mwexec(kill_wpasupplicant("{$if}"));
2350

    
2351
	/* generate wpa_supplicant/hostap config if wpa is enabled */
2352
	conf_mount_rw();
2353

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

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

    
2408
EOD;
2409

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

    
2416
EOD;
2417

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

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

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

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

    
2445
			}
2446
			break;
2447
	}
2448

    
2449
	/*
2450
	 *    all variables are set, lets start up everything
2451
	 */
2452

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

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

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

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

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

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

    
2499
	fclose($fd_set);
2500
	conf_mount_ro();
2501

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

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

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

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

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

    
2535
		$wlregcmd_args = implode(" ", $wlregcmd);
2536

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

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

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

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

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

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

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

    
2589

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

    
2594
	return 0;
2595

    
2596
}
2597

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

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

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

    
2612
	return intval($pid);
2613
}
2614

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

    
2621
	return intval($pid);
2622
}
2623

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

    
2629
	$wancfg = $config['interfaces'][$interface];
2630

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

    
2636
	if (!does_interface_exist($realhwif))
2637
		return 0;
2638

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2825
	interface_netgraph_needed($interface);
2826

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

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

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

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

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

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

    
2855
		if ($reloadall == true) {
2856

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

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

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

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

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

    
2874
	return 0;
2875
}
2876

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

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

    
2886
	$wanif = get_real_interface($interface);
2887

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

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

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

    
2918

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

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

    
2928
	$lanif = get_real_interface($interface);
2929

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

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

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

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

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

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

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

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

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

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

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

    
2987
	$lanif = get_real_interface($interface);
2988

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

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

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

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

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

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

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

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

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

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

    
3042
	$lanif = get_real_interface($interface);
3043

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

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

    
3056

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

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

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

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

    
3083
	$wanif = get_real_interface($interface);
3084

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

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

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

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

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

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

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

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

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

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

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

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

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

    
3146
	return 0;
3147
}
3148

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

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

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

    
3161
	$wanif = get_real_interface($interface);
3162

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
3244
	return 0;
3245
}
3246

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

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

    
3256
	$wanif = get_real_interface($interface);
3257

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

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

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

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

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

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

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

    
3322

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

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

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

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

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

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

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

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

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

    
3399
EOD;
3400

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

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

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

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

    
3424
	return 0;
3425
}
3426

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

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

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

    
3436
	return;
3437
}
3438

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

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

    
3451
	return;
3452
}
3453

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

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

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

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

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

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

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

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

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

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

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

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

    
3559
        return $ifdesc;
3560
}
3561

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

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

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

    
3572
        return $interface;
3573
}
3574

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

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

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

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

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

    
3632
	return $parents;
3633
}
3634

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

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

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

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

    
3662
	$wanif = NULL;
3663

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

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

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

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

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

    
3727
    return $wanif;
3728
}
3729

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

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

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

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

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

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

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

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

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

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

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

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

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

    
3898

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

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

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

    
3931
        return $carp_ints;
3932
}
3933

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

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

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

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

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

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

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

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

    
3989
	$result = array();
3990

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

    
3998
	return $result;
3999
}
4000

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

    
4004
	$result = array();
4005

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

    
4012
	return $result;
4013
}
4014

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

    
4018
	$result = array();
4019

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

    
4026
	return $result;
4027
}
4028

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
4195
	return false;
4196
}
4197

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

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

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

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

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

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

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

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

    
4278
	return null;
4279
}
4280

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

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

    
4297
	return null;
4298
}
4299

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

    
4304
	$ints = array();
4305

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

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

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

    
4350
	return false;
4351
}
4352

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

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

    
4379
	return false;
4380
}
4381

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

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

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

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

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

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

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

    
4443
	$cloned_interface = get_real_interface($interface);
4444

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

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

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

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

    
4488
	$cloned_interface = get_real_interface($interface);
4489

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

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

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

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

    
4518
function get_interface_mac($interface) {
4519

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

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

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

    
4549

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

    
4555

    
4556

    
4557

    
4558

    
4559
	return false;
4560
}
4561

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

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

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

    
4573
EOD;
4574

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

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

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

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

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

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

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

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

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

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

    
4635
			}
4636

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

    
4650
	return 0;
4651
}
4652

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

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

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

    
4677
?>
(25-25/67)