Project

General

Profile

Download (137 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/*
3
	interfaces.inc
4
	Copyright (C) 2004-2008 Scott Ullrich
5
	Copyright (C) 2008-2009 Ermal Lu?i
6
	All rights reserved.
7

    
8
	function interfaces_wireless_configure is
9
	Copyright (C) 2005 Espen Johansen
10
	All rights reserved.
11

    
12
	originally part of m0n0wall (http://m0n0.ch/wall)
13
	Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>.
14
	All rights reserved.
15

    
16
	Redistribution and use in source and binary forms, with or without
17
	modification, are permitted provided that the following conditions are met:
18

    
19
	1. Redistributions of source code must retain the above copyright notices,
20
	   this list of conditions and the following disclaimer.
21

    
22
	2. Redistributions in binary form must reproduce the above copyright
23
	   notices, this list of conditions and the following disclaimer in the
24
	   documentation and/or other materials provided with the distribution.
25

    
26
	THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
27
	INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
28
	AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
29
	AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
30
	OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31
	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32
	INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33
	CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34
	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35
	POSSIBILITY OF SUCH DAMAGE.
36

    
37
	pfSense_BUILDER_BINARIES:	/sbin/dhclient	/bin/sh	/usr/bin/grep	/usr/bin/xargs	/usr/bin/awk	/usr/local/sbin/choparp
38
	pfSense_BUILDER_BINARIES:	/sbin/ifconfig	/sbin/route	/usr/sbin/ngctl	/usr/sbin/arp	/bin/kill	/usr/local/sbin/mpd5
39
	pfSense_BUILDER_BINARIES:	/usr/local/sbin/dhcp6c
40
	pfSense_MODULE:	interfaces
41

    
42
*/
43

    
44
/* include all configuration functions */
45
require_once("globals.inc");
46
require_once("util.inc");
47
require_once("gwlb.inc");
48

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

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

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

    
68
	return $interface_arr_cache;
69
}
70

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

    
78
	if(!$interface)
79
		return false;
80

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

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

    
95
	if(!$vip)
96
		return false;
97

    
98

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

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

    
124
	return false;
125
}
126

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

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

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

    
170
				if ($realif == $ppp['if']) {
171
					$found = true;
172
					break;
173
				}
174
*/
175
				$ports = explode(',',$ppp['ports']);
176
				foreach($ports as $pid => $port){
177
					$port = get_real_interface($port);
178
					if ($realif == $port) {
179
						$found = true;
180
						break;
181
					}
182
					/* Find the parent interfaces of the vlans in the MLPPP configs
183
					* there should be only one element in the array here
184
					* -- this could be better . . . */
185
					$parent_if = get_parent_interface($port);
186
					if ($realif == $parent_if[0]) {
187
						$found = true;
188
						break;
189
					}
190
				}
191
			}
192
		}
193
	}
194

    
195
	if ($found == false) {
196
		$realif = get_real_interface($interface);
197
		pfSense_ngctl_detach("{$realif}:", $realif);
198
	}
199
	/* NOTE: We make sure for this on interface_ppps_configure()
200
	 *	no need to do it here agan.
201
	 *	else
202
	 *		pfSense_ngctl_attach(".", $realif);
203
	 */
204
}
205

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

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

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

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

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

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

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

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

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

    
267
	interfaces_bring_up($vlanif);
268

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

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

    
275
	return $vlanif;
276
}
277

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

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

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

    
293
	if(!does_interface_exist($qinqif)) {
294
		log_error(sprintf(gettext("interface_qinq_configure called with invalid if.%s"), "\n"));
295
		return;
296
	}
297

    
298
	$vlanif = interface_vlan_configure($vlan);
299

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

    
308
	pfSense_ngctl_attach(".", $qinqif);
309
	if (!empty($vlanif) && does_interface_exist($vlanif)) {
310
		fwrite($fd, "shutdown {$qinqif}qinq:\n");
311
		exec("/usr/sbin/ngctl msg {$qinqif}qinq: gettable", $result);
312
		if (empty($result)) {
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
	} else {
318
		fwrite($fd, "mkpeer {$qinqif}: vlan lower downstream\n");
319
		fwrite($fd, "name {$qinqif}:lower {$vlanif}qinq\n");
320
		fwrite($fd, "connect {$qinqif}: {$vlanif}qinq: upper nomatch\n");
321
	}
322

    
323
	/* invalidate interface cache */
324
	get_interface_arr(true);
325

    
326
	if (!stristr($qinqif, "vlan"))
327
		mwexec("/sbin/ifconfig {$qinqif} promisc\n");
328

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

    
344
	interfaces_bring_up($qinqif);
345
	if (!empty($vlan['members'])) {
346
		$members = explode(" ", $vlan['members']);
347
		foreach ($members as $qif)
348
			interfaces_bring_up("{$vlanif}_{$qif}");
349
	}
350

    
351
	return $vlanif;
352
}
353

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

    
368
function interface_qinq2_configure(&$qinq, $fd, $macaddr) {
369
	global $config, $g;
370

    
371
	if (!is_array($qinq)) {
372
		log_error(sprintf(gettext("QinQ compat VLAN: called with wrong options. Problems with config!%s"), "\n"));
373
		return;
374
	}
375

    
376
	$if = $qinq['if'];
377
	$tag = $qinq['tag'];
378
	$vlanif = "{$if}_{$tag}";
379
	if(empty($if)) {
380
		log_error(sprintf(gettext("interface_qinq2_configure called with if undefined.%s"), "\n"));
381
		return;
382
	}
383

    
384
	fwrite($fd, "shutdown {$if}h{$tag}:\n");
385
	fwrite($fd, "mkpeer {$if}qinq: eiface {$if}{$tag} ether\n");
386
	fwrite($fd, "name {$if}qinq:{$if}{$tag} {$if}h{$tag}\n");
387
	fwrite($fd, "msg {$if}qinq: addfilter { vlan={$tag} hook=\"{$if}{$tag}\" }\n");
388
	fwrite($fd, "msg {$if}h{$tag}: setifname \"{$vlanif}\"\n");
389
	fwrite($fd, "msg {$if}h{$tag}: set {$macaddr}\n");
390

    
391
	/* invalidate interface cache */
392
	get_interface_arr(true);
393

    
394
	return $vlanif;
395
}
396

    
397
function interfaces_create_wireless_clones() {
398
	global $config, $g;
399

    
400
	if($g['booting'])
401
		echo gettext("Creating wireless clone interfaces...");
402

    
403
	$iflist = get_configured_interface_list();
404

    
405
	foreach ($iflist as $if) {
406
		$realif = $config['interfaces'][$if]['if'];
407
		if (is_interface_wireless($realif))
408
			interface_wireless_clone(interface_get_wireless_clone($realif), $config['interfaces'][$if]);
409
	}
410

    
411
	if (isset($config['wireless']['clone']) && is_array($config['wireless']['clone']) && count($config['wireless']['clone'])) {
412
		foreach ($config['wireless']['clone'] as $clone) {
413
			if(empty($clone['cloneif']))
414
				continue;
415
			if(does_interface_exist($clone['cloneif']))
416
				continue;
417
			/* XXX: Maybe we should report any errors?! */
418
			interface_wireless_clone($clone['cloneif'], $clone);
419
		}
420
	}
421
	if($g['booting'])
422
		echo gettext("done.") . "\n";
423

    
424
}
425

    
426
function interfaces_bridge_configure($checkmember = 0) {
427
	global $config;
428

    
429
	$i = 0;
430
	if (is_array($config['bridges']['bridged']) && count($config['bridges']['bridged'])) {
431
		foreach ($config['bridges']['bridged'] as $bridge) {
432
			if(empty($bridge['bridgeif']))
433
				$bridge['bridgeif'] = "bridge{$i}";
434
			if ($checkmember == 1) {
435
				$members = explode(',', $bridge['members']);
436
				foreach ($members as $member) {
437
					if (strstr($bridge['if'], "_vip"))
438
						continue 2;
439
					if (!empty($config['interfaces'][$bridge['if']]) && $config['interfaces'][$bridge['if']]['ipaddrv6'] == "track6")  
440
						continue 2;
441
				}
442
			}
443
			else if ($checkmember == 2) {
444
				$members = explode(',', $bridge['members']);
445
				foreach ($members as $member) {
446
					if (!strstr($bridge['if'], "_vip"))
447
						continue 2;
448
					if (empty($config['interfaces'][$bridge['if']]) || $config['interfaces'][$bridge['if']]['ipaddrv6'] != "track6")  
449
						continue 2;
450
				}
451
			}
452
			/* XXX: Maybe we should report any errors?! */
453
			interface_bridge_configure($bridge, $checkmember);
454
			$i++;
455
		}
456
	}
457
}
458

    
459
function interface_bridge_configure(&$bridge, $checkmember = 0) {
460
	global $config, $g;
461

    
462
	if (!is_array($bridge))
463
		return;
464

    
465
	if (empty($bridge['members'])) {
466
		log_error(sprintf(gettext("No members found on %s"), $bridge['bridgeif']));
467
		return;
468
	}
469

    
470
	$members = explode(',', $bridge['members']);
471
	if (!count($members))
472
		return;
473

    
474
	/* Calculate smaller mtu and enforce it */
475
	$smallermtu = 0;
476
	$commonrx = true;
477
	$commontx = true;
478
	$foundgif = false;
479
	foreach ($members as $member) {
480
		$realif = get_real_interface($member);
481
		$opts = pfSense_get_interface_addresses($realif);
482
		$mtu = $opts['mtu'];
483
		if (substr($realif, 0, 3) == "gif") {
484
			$foundgif = true;
485
			if ($checkmember == 1)
486
				return;
487
			if ($mtu <= 1500)
488
				continue;
489
		}
490
		if (!isset($opts['encaps']['txcsum']))
491
			$commontx = false;
492
		if (!isset($opts['encaps']['rxcsum']))
493
			$commonrx = false;
494
		if (!isset($opts['encaps']['tso4']))
495
			$commontso4 = false;
496
		if (!isset($opts['encaps']['tso6']))
497
			$commontso6 = false;
498
		if (!isset($opts['encaps']['lro']))
499
			$commonlro = false;
500
		if ($smallermtu == 0 && !empty($mtu))
501
			$smallermtu = $mtu;
502
		else if (!empty($mtu) && $mtu < $smallermtu)
503
			$smallermtu = $mtu;
504
	}
505
	if ($foundgif == false && $checkmember == 2)
506
		return;
507

    
508
	/* Just in case anything is not working well */
509
	if ($smallermtu == 0)
510
		$smallermtu = 1500;
511

    
512
	$flags = 0;
513
	if ($commonrx === false)
514
		$flags |= IFCAP_RXCSUM;
515
	if ($commontx === false)
516
		$flags |= IFCAP_TXCSUM;
517
	if ($commontso4 === false)
518
		$flags |= IFCAP_TSO4;
519
	if ($commontso6 === false)
520
		$flags |= IFCAP_TSO6;
521
	if ($commonlro === false)
522
		$flags |= IFCAP_LRO;
523

    
524
	if ($g['booting'] || !empty($bridge['bridgeif'])) {
525
		pfSense_interface_destroy($bridge['bridgeif']);
526
		pfSense_interface_create($bridge['bridgeif']);
527
		$bridgeif = escapeshellarg($bridge['bridgeif']);
528
	} else {
529
		$bridgeif = pfSense_interface_create("bridge");
530
		$bridge['bridgeif'] = $bridgeif;
531
	}
532

    
533
	$checklist = get_configured_interface_list();
534

    
535
	/* Add interfaces to bridge */
536
	foreach ($members as $member) {
537
		if (empty($checklist[$member]))
538
			continue;
539
		$realif = get_real_interface($member);
540
		if (!$realif) {
541
			log_error(gettext("realif not defined in interfaces bridge - up"));
542
			continue;
543
		}
544
		/* make sure the parent interface is up */
545
		pfSense_interface_mtu($realif, $smallermtu);
546
		pfSense_interface_capabilities($realif, -$flags);
547
		interfaces_bring_up($realif);
548
		pfSense_bridge_add_member($bridge['bridgeif'], $realif);
549
	}
550

    
551
	if (isset($bridge['enablestp'])) {
552
		/* Choose spanning tree proto */
553
		mwexec("/sbin/ifconfig {$bridgeif} proto " . escapeshellarg($bridge['proto']));
554

    
555
		if (!empty($bridge['stp'])) {
556
			$stpifs = explode(',', $bridge['stp']);
557
			foreach ($stpifs as $stpif) {
558
				$realif = get_real_interface($stpif);
559
				mwexec("/sbin/ifconfig {$bridgeif} stp {$realif}");
560
			}
561
		}
562
		if (!empty($bridge['maxage']))
563
			mwexec("/sbin/ifconfig {$bridgeif} maxage " . escapeshellarg($bridge['maxage']));
564
		if (!empty($bridge['fwdelay']))
565
			mwexec("/sbin/ifconfig {$bridgeif} fwddelay " . escapeshellarg($bridge['fwdelay']));
566
		if (!empty($bridge['hellotime']))
567
			mwexec("/sbin/ifconfig {$bridgeif} hellotime " . escapeshellarg($bridge['hellotime']));
568
		if (!empty($bridge['priority']))
569
			mwexec("/sbin/ifconfig {$bridgeif} priority " . escapeshellarg($bridge['priority']));
570
		if (!empty($bridge['holdcnt']))
571
			mwexec("/sbin/ifconfig {$bridgeif} holdcnt " . escapeshellarg($bridge['holdcnt']));
572
		if (!empty($bridge['ifpriority'])) {
573
			$pconfig = explode(",", $bridge['ifpriority']);
574
			$ifpriority = array();
575
			foreach ($pconfig as $cfg) {
576
				$embcfg = explode_assoc(":", $cfg);
577
				foreach ($embcfg as $key => $value)
578
					$ifpriority[$key] = $value;
579
			}
580
			foreach ($ifpriority as $key => $value) {
581
				$realif = get_real_interface($key);
582
				mwexec("/sbin/ifconfig ${bridgeif} ifpriority {$realif} " . escapeshellarg($value));
583
			}
584
		}
585
		if (!empty($bridge['ifpathcost'])) {
586
			$pconfig = explode(",", $bridge['ifpathcost']);
587
			$ifpathcost = array();
588
			foreach ($pconfig as $cfg) {
589
				$embcfg = explode_assoc(":", $cfg);
590
				foreach ($embcfg as $key => $value)
591
					$ifpathcost[$key] = $value;
592
			}
593
			foreach ($ifpathcost as $key => $value) {
594
				$realif = get_real_interface($key);
595
				mwexec("/sbin/ifconfig ${bridgeif} ifpathcost {$realif} " . escapeshellarg($value));
596
			}
597
		}
598
	}
599

    
600
	if ($bridge['maxaddr'] <> "")
601
		mwexec("/sbin/ifconfig {$bridgeif} maxaddr {$bridge['maxaddr']}");
602
	if ($bridge['timeout'] <> "")
603
		mwexec("/sbin/ifconfig {$bridgeif} timeout {$bridge['timeout']}");
604
	if ($bridge['span'] <> "") {
605
		$realif = get_real_interface($bridge['span']);
606
		mwexec("/sbin/ifconfig {$bridgeif} span {$realif}");
607
	}
608
	if (!empty($bridge['edge'])) {
609
		$edgeifs = explode(',', $bridge['edge']);
610
		foreach ($edgeifs as $edgeif) {
611
			$realif = get_real_interface($edgeif);
612
			mwexec("/sbin/ifconfig {$bridgeif} edge {$realif}");
613
		}
614
	}
615
	if (!empty($bridge['autoedge'])) {
616
		$edgeifs = explode(',', $bridge['autoedge']);
617
		foreach ($edgeifs as $edgeif) {
618
			$realif = get_real_interface($edgeif);
619
			mwexec("/sbin/ifconfig {$bridgeif} -autoedge {$realif}");
620
		}
621
	}
622
	if (!empty($bridge['ptp'])) {
623
		$ptpifs = explode(',', $bridge['ptp']);
624
		foreach ($ptpifs as $ptpif) {
625
			$realif = get_real_interface($ptpif);
626
			mwexec("/sbin/ifconfig {$bridgeif} ptp {$realif}");
627
		}
628
	}
629
	if (!empty($bridge['autoptp'])) {
630
		$ptpifs = explode(',', $bridge['autoptp']);
631
		foreach ($ptpifs as $ptpif) {
632
			$realif = get_real_interface($ptpif);
633
			mwexec("/sbin/ifconfig {$bridgeif} -autoptp {$realif}");
634
		}
635
	}
636
	if (!empty($bridge['static'])) {
637
		$stickyifs = explode(',', $bridge['static']);
638
		foreach ($stickyifs as $stickyif) {
639
			$realif = get_real_interface($stickyif);
640
			mwexec("/sbin/ifconfig {$bridgeif} sticky {$realif}");
641
		}
642
	}
643
	if (!empty($bridge['private'])) {
644
		$privateifs = explode(',', $bridge['private']);
645
		foreach ($privateifs as $privateif) {
646
			$realif = get_real_interface($privateif);
647
			mwexec("/sbin/ifconfig {$bridgeif} private {$realif}");
648
		}
649
	}
650

    
651
	if ($bridge['bridgeif'])
652
		interfaces_bring_up($bridge['bridgeif']);
653
	else
654
		log_error(gettext("bridgeif not defined -- could not bring interface up"));
655
}
656

    
657
function interface_bridge_add_member($bridgeif, $interface) {
658

    
659
	if (!does_interface_exist($bridgeif) || !does_interface_exist($interface))
660
		return;
661

    
662
	$mtu = get_interface_mtu($bridgeif);
663
	$mtum = get_interface_mtu($interface);
664

    
665
	if ($mtu != $mtum && !(substr($interface, 0, 3) == "gif" && $mtu <= 1500))
666
		pfSense_interface_mtu($interface, $mtu);
667

    
668
	$options = pfSense_get_interface_addresses($bridgeif);
669
	$flags = 0;
670
	if (!isset($options['encaps']['txcsum']))
671
		$flags |= IFCAP_TXCSUM;
672

    
673
	if (!isset($options['encaps']['rxcsum']))
674
		$flags |= IFCAP_RXCSUM;
675

    
676
	pfSense_interface_capabilities($interface, -$flags);
677

    
678
	interfaces_bring_up($interface);
679
	pfSense_bridge_add_member($bridgeif, $interface);
680
}
681

    
682
function interfaces_lagg_configure() {
683
	global $config, $g;
684
	if($g['booting'])
685
		echo gettext("Configuring LAGG interfaces...");
686
	$i = 0;
687
	if (is_array($config['laggs']['lagg']) && count($config['laggs']['lagg'])) {
688
		foreach ($config['laggs']['lagg'] as $lagg) {
689
			if(empty($lagg['laggif']))
690
				$lagg['laggif'] = "lagg{$i}";
691
			/* XXX: Maybe we should report any errors?! */
692
			interface_lagg_configure($lagg);
693
			$i++;
694
		}
695
	}
696
	if($g['booting'])
697
		echo gettext("done.") . "\n";
698
}
699

    
700
function interface_lagg_configure(&$lagg) {
701
	global $config, $g;
702

    
703
	if (!is_array($lagg))
704
		return -1;
705

    
706
	$members = explode(',', $lagg['members']);
707
	if (!count($members))
708
		return -1;
709

    
710
	if ($g['booting'] || !(empty($lagg['laggif']))) {
711
		pfSense_interface_destroy($lagg['laggif']);
712
		pfSense_interface_create($lagg['laggif']);
713
		$laggif = $lagg['laggif'];
714
	} else
715
		$laggif = pfSense_interface_create("lagg");
716

    
717
	/* Calculate smaller mtu and enforce it */
718
	$smallermtu = 0;
719
	foreach ($members as $member) {
720
		$opts = pfSense_get_interface_addresses($member);
721
		$mtu = $opts['mtu'];
722
		if (!isset($opts['encaps']['txcsum']))
723
			$commontx = false;
724
		if (!isset($opts['encaps']['rxcsum']))
725
			$commonrx = false;
726
		if (!isset($opts['encaps']['tso4']))
727
			$commontso4 = false;
728
		if (!isset($opts['encaps']['tso6']))
729
			$commontso6 = false;
730
		if (!isset($opts['encaps']['lro']))
731
			$commonlro = false;
732
		if ($smallermtu == 0 && !empty($mtu))
733
			$smallermtu = $mtu;
734
		else if (!empty($mtu) && $mtu < $smallermtu)
735
			$smallermtu = $mtu;
736
	}
737

    
738
	/* Just in case anything is not working well */
739
	if ($smallermtu == 0)
740
		$smallermtu = 1500;
741

    
742
	$flags = 0;
743
	if ($commonrx === false)
744
		$flags |= IFCAP_RXCSUM;
745
	if ($commontx === false)
746
		$flags |= IFCAP_TXCSUM;
747
	if ($commontso4 === false)
748
		$flags |= IFCAP_TSO4;
749
	if ($commontso6 === false)
750
		$flags |= IFCAP_TSO6;
751
	if ($commonlro === false)
752
		$flags |= IFCAP_LRO;
753

    
754
	$checklist = get_interface_list();
755

    
756
	foreach ($members as $member) {
757
		if (!array_key_exists($member, $checklist))
758
			continue;
759
		/* make sure the parent interface is up */
760
		pfSense_interface_mtu($member, $smallermtu);
761
		pfSense_interface_capabilities($member, -$flags);
762
		interfaces_bring_up($member);
763
		mwexec("/sbin/ifconfig {$laggif} laggport {$member}");
764
	}
765

    
766
	mwexec("/sbin/ifconfig {$laggif} laggproto {$lagg['proto']}");
767

    
768
	interfaces_bring_up($laggif);
769

    
770
	return $laggif;
771
}
772

    
773
function interfaces_gre_configure($checkparent = 0) {
774
	global $config;
775

    
776
	if (is_array($config['gres']['gre']) && count($config['gres']['gre'])) {
777
		foreach ($config['gres']['gre'] as $i => $gre) {
778
			if(empty($gre['greif']))
779
				$gre['greif'] = "gre{$i}";
780
			if ($checkparent == 1) {
781
				if (strstr($gre['if'], "_vip"))
782
					continue;
783
				if (!empty($config['interfaces'][$gre['if']]) && $config['interfaces'][$gre['if']]['ipaddrv6'] == "track6")  
784
					continue;
785
			}
786
			else if ($checkparent == 2) {
787
				if (!strstr($gre['if'], "_vip"))
788
					continue;
789
				if (empty($config['interfaces'][$gre['if']]) || $config['interfaces'][$gre['if']]['ipaddrv6'] != "track6")  
790
					continue;
791
			}
792
			/* XXX: Maybe we should report any errors?! */
793
			interface_gre_configure($gre);
794
		}
795
	}
796
}
797

    
798
/* NOTE: $grekey is not used but useful for passing this function to array_walk. */
799
function interface_gre_configure(&$gre, $grekey = "") {
800
	global $config, $g;
801

    
802
	if (!is_array($gre))
803
		return -1;
804

    
805
	$realif = get_real_interface($gre['if']);
806
	$realifip = get_interface_ip($gre['if']);
807

    
808
	/* make sure the parent interface is up */
809
	interfaces_bring_up($realif);
810

    
811
	if ($g['booting'] || !(empty($gre['greif']))) {
812
		pfSense_interface_destroy($gre['greif']);
813
		pfSense_interface_create($gre['greif']);
814
		$greif = $gre['greif'];
815
	} else
816
		$greif = pfSense_interface_create("gre");
817

    
818
	/* Do not change the order here for more see gre(4) NOTES section. */
819
	mwexec("/sbin/ifconfig {$greif} tunnel {$realifip} {$gre['remote-addr']}");
820
	if((is_ipaddrv6($gre['tunnel-local-addr'])) || (is_ipaddrv6($gre['tunnel-remote-addr']))) {
821
		mwexec("/sbin/ifconfig {$greif} inet6 {$gre['tunnel-local-addr']} {$gre['tunnel-remote-addr']} prefixlen /{$gre['tunnel-remote-net']} ");
822
	} else {
823
		mwexec("/sbin/ifconfig {$greif} {$gre['tunnel-local-addr']} {$gre['tunnel-remote-addr']} netmask " . gen_subnet_mask($gre['tunnel-remote-net']));
824
	}
825
	if (isset($gre['link0']) && $gre['link0'])
826
		pfSense_interface_flags($greif, IFF_LINK0);
827
	if (isset($gre['link1']) && $gre['link1'])
828
		pfSense_interface_flags($greif, IFF_LINK1);
829
	if (isset($gre['link2']) && $gre['link2'])
830
		pfSense_interface_flags($greif, IFF_LINK2);
831

    
832
	if($greif)
833
		interfaces_bring_up($greif);
834
	else
835
		log_error(gettext("Could not bring greif up -- variable not defined."));
836

    
837
	if (isset($gre['link1']) && $gre['link1'])
838
		mwexec("/sbin/route add {$gre['tunnel-remote-addr']}/{$gre['tunnel-remote-net']} {$gre['tunnel-local-addr']}");
839
	if(is_ipaddrv4($gre['tunnel-remote-addr']))
840
		file_put_contents("{$g['tmp_path']}/{$greif}_router", $gre['tunnel-remote-addr']);
841
	if(is_ipaddrv6($gre['tunnel-remote-addr']))
842
		file_put_contents("{$g['tmp_path']}/{$greif}_routerv6", $gre['tunnel-remote-addr']);
843

    
844
	return $greif;
845
}
846

    
847
function interfaces_gif_configure($checkparent = 0) {
848
	global $config;
849

    
850
	if (is_array($config['gifs']['gif']) && count($config['gifs']['gif'])) {
851
		foreach ($config['gifs']['gif'] as $i => $gif) {
852
			if(empty($gif['gifif']))
853
				$gre['gifif'] = "gif{$i}";
854
			if ($checkparent == 1) {
855
				if (strstr($gif['if'], "_vip"))
856
					continue;
857
				if (!empty($config['interfaces'][$gif['if']]) && $config['interfaces'][$gif['if']]['ipaddrv6'] == "track6")  
858
					continue;
859
			}
860
			else if ($checkparent == 2) {
861
				if (!strstr($gre['if'], "_vip"))
862
					continue;
863
				if (empty($config['interfaces'][$gif['if']]) || $config['interfaces'][$gif['if']]['ipaddrv6'] != "track6")  
864
					continue;
865
			}
866
			/* XXX: Maybe we should report any errors?! */
867
			interface_gif_configure($gif);
868
		}
869
	}
870
}
871

    
872
/* NOTE: $gifkey is not used but useful for passing this function to array_walk. */
873
function interface_gif_configure(&$gif, $gifkey = "") {
874
	global $config, $g;
875

    
876
	if (!is_array($gif))
877
		return -1;
878

    
879
	$realif = get_real_interface($gif['if']);
880
	$ipaddr = $gif['ipaddr'];
881

    
882
	if (is_ipaddrv4($gif['remote-addr'])) {
883
		if (is_ipaddrv4($ipaddr))
884
			$realifip = $ipaddr;
885
		else
886
			$realifip = get_interface_ip($gif['if']);
887
		$realifgw = get_interface_gateway($gif['if']);
888
	} else if (is_ipaddrv6($gif['remote-addr'])) {
889
		if (is_ipaddrv6($ipaddr))
890
			$realifip = $ipaddr;
891
		else
892
			$realifip = get_interface_ipv6($gif['if']);
893
		$realifgw = get_interface_gatewayv6($gif['if']);
894
	}
895
	/* make sure the parent interface is up */
896
	if($realif)
897
		interfaces_bring_up($realif);
898
	else
899
		log_error(gettext("could not bring realif up -- variable not defined -- interface_gif_configure()"));
900

    
901
	if ($g['booting'] || !(empty($gif['gifif']))) {
902
		pfSense_interface_destroy($gif['gifif']);
903
		pfSense_interface_create($gif['gifif']);
904
		$gifif = $gif['gifif'];
905
	} else
906
		$gifif = pfSense_interface_create("gif");
907

    
908
	/* Do not change the order here for more see gif(4) NOTES section. */
909
	mwexec("/sbin/ifconfig {$gifif} tunnel {$realifip} {$gif['remote-addr']}");
910
	if((is_ipaddrv6($gif['tunnel-local-addr'])) || (is_ipaddrv6($gif['tunnel-remote-addr']))) {
911
		mwexec("/sbin/ifconfig {$gifif} inet6 {$gif['tunnel-local-addr']} {$gif['tunnel-remote-addr']} prefixlen /{$gif['tunnel-remote-net']} ");
912
	} else {
913
		mwexec("/sbin/ifconfig {$gifif} {$gif['tunnel-local-addr']} {$gif['tunnel-remote-addr']} netmask " . gen_subnet_mask($gif['tunnel-remote-net']));
914
	}
915
	if (isset($gif['link0']) && $gif['link0'])
916
		pfSense_interface_flags($gifif, IFF_LINK0);
917
	if (isset($gif['link1']) && $gif['link1'])
918
		pfSense_interface_flags($gifif, IFF_LINK1);
919
	if($gifif)
920
		interfaces_bring_up($gifif);
921
	else
922
		log_error(gettext("could not bring gifif up -- variable not defined"));
923

    
924
	$iflist = get_configured_interface_list();
925
	foreach($iflist as $ifname) {
926
		if($config['interfaces'][$ifname]['if'] == $gifif) {
927
			if(get_interface_gateway($ifname)) {
928
				system_routing_configure($ifname);
929
				break;
930
			}
931
			if(get_interface_gateway_v6($ifname)) {
932
				system_routing_configure($ifname);
933
				break;
934
			}
935
		}
936
	}
937

    
938

    
939
	if(is_ipaddrv4($gif['tunnel-remote-addr']))
940
		file_put_contents("{$g['tmp_path']}/{$gifif}_router", $gif['tunnel-remote-addr']);
941
	if(is_ipaddrv6($gif['tunnel-remote-addr']))
942
		file_put_contents("{$g['tmp_path']}/{$gifif}_routerv6", $gif['tunnel-remote-addr']);
943

    
944
	if (is_ipaddrv4($realifgw)) {
945
		mwexec("route change -host {$gif['remote-addr']} {$realifgw}");
946
	}
947
	if (is_ipaddrv6($realifgw)) {
948
		mwexec("route change -host -inet6 {$gif['remote-addr']} {$realifgw}");
949
	}
950

    
951
	return $gifif;
952
}
953

    
954
function interfaces_configure() {
955
	global $config, $g;
956

    
957
	if ($g['platform'] == 'jail')
958
		return;
959

    
960
	/* Set up our loopback interface */
961
	interfaces_loopback_configure();
962

    
963
	/* create the unconfigured wireless clones */
964
	interfaces_create_wireless_clones();
965

    
966
	/* set up LAGG virtual interfaces */
967
	interfaces_lagg_configure();
968

    
969
	/* set up VLAN virtual interfaces */
970
	interfaces_vlan_configure();
971

    
972
	interfaces_qinq_configure();
973

    
974
	$iflist = get_configured_interface_with_descr();
975
	$delayed_list = array();
976
	$bridge_list = array();
977
	$track6_list = array();
978

    
979
	/* This is needed to speedup interfaces on bootup. */
980
	$reload = false;
981
	if (!$g['booting'])
982
		$reload = true;
983

    
984
	foreach($iflist as $if => $ifname) {
985
		$realif = $config['interfaces'][$if]['if'];
986
		if (strstr($realif, "bridge"))
987
			$bridge_list[$if] = $ifname;
988
		else if (strstr($realif, "gre"))
989
			$delayed_list[$if] = $ifname;
990
		else if (strstr($realif, "gif"))
991
			$delayed_list[$if] = $ifname;
992
		else if (strstr($realif, "ovpn")) {
993
			//echo "Delaying OpenVPN interface configuration...done.\n";
994
			continue;
995
		} else if (!empty($config['interfaces'][$if]['ipaddrv6']) && $config['interfaces'][$if]['ipaddrv6'] == "track6") {
996
			$track6_list[$if] = $ifname;
997
		} else {
998
			if ($g['booting'])
999
				printf(gettext("Configuring %s interface..."), $ifname);
1000

    
1001
			if($g['debug'])
1002
				log_error(sprintf(gettext("Configuring %s"), $ifname));
1003
			interface_configure($if, $reload);
1004
			if ($g['booting'])
1005
				echo gettext( "done.") . "\n";
1006
		}
1007
	}
1008

    
1009
	/*
1010
	 * NOTE: The following function parameter consists of
1011
	 *	1 - Do not load gre/gif/bridge with parent/member as vip
1012
	 *	2 - Do load gre/gif/bridge with parent/member as vip
1013
	 */
1014

    
1015
	/* set up GRE virtual interfaces */
1016
	interfaces_gre_configure(1);
1017

    
1018
	/* set up GIF virtual interfaces */
1019
	interfaces_gif_configure(1);
1020

    
1021
	/* set up BRIDGe virtual interfaces */
1022
	interfaces_bridge_configure(1);
1023

    
1024
	foreach ($track6_list as $if => $ifname) {
1025
		if ($g['booting'])
1026
			printf(gettext("Configuring %s interface..."), $ifname);
1027
		if ($g['debug'])
1028
			log_error(sprintf(gettext("Configuring %s"), $ifname));
1029

    
1030
		interface_configure($if, $reload);
1031

    
1032
		if ($g['booting'])
1033
			echo gettext("done.") . "\n";
1034
	}
1035

    
1036
	/* bring up vip interfaces */
1037
	interfaces_vips_configure();
1038

    
1039
	/* set up GRE virtual interfaces */
1040
	interfaces_gre_configure(2);
1041

    
1042
	/* set up GIF virtual interfaces */
1043
	interfaces_gif_configure(2);
1044

    
1045
	foreach ($delayed_list as $if => $ifname) {
1046
		if ($g['booting'])
1047
			printf(gettext("Configuring %s interface..."), $ifname);
1048
		if ($g['debug'])
1049
			log_error(sprintf(gettext("Configuring %s"), $ifname));
1050

    
1051
		interface_configure($if, $reload);
1052

    
1053
		if ($g['booting'])
1054
			echo gettext("done.") . "\n";
1055
	}
1056

    
1057
	/* set up BRIDGe virtual interfaces */
1058
	interfaces_bridge_configure(2);
1059

    
1060
	foreach ($bridge_list as $if => $ifname) {
1061
		if ($g['booting'])
1062
			printf(gettext("Configuring %s interface..."), $ifname);
1063
		if($g['debug'])
1064
			log_error(sprintf(gettext("Configuring %s"), $ifname));
1065

    
1066
		interface_configure($if, $reload);
1067

    
1068
		if ($g['booting'])
1069
			echo gettext("done.") . "\n";
1070
	}
1071

    
1072
	/* configure interface groups */
1073
	interfaces_group_setup();
1074

    
1075
	if (!$g['booting']) {
1076
		/* reconfigure static routes (kernel may have deleted them) */
1077
		system_routing_configure();
1078

    
1079
		/* reload IPsec tunnels */
1080
		vpn_ipsec_configure();
1081

    
1082
		/* reload dhcpd (interface enabled/disabled status may have changed) */
1083
		services_dhcpd_configure();
1084

    
1085
		/* restart dnsmasq */
1086
		services_dnsmasq_configure();
1087

    
1088
		/* reload captive portal */
1089
		if (function_exists('captiveportal_init_rules'))
1090
			captiveportal_init_rules();
1091
	}
1092

    
1093
	return 0;
1094
}
1095

    
1096
function interface_reconfigure($interface = "wan", $reloadall = false) {
1097
	interface_bring_down($interface);
1098
	interface_configure($interface, $reloadall);
1099
}
1100

    
1101
function interface_vip_bring_down($vip) {
1102
	global $g;
1103

    
1104
	switch ($vip['mode']) {
1105
	case "proxyarp":
1106
		$vipif = get_real_interface($vip['interface']);
1107
		if (file_exists("{$g['varrun_path']}/choparp_{$vipif}.pid"))
1108
			killbypid("{$g['varrun_path']}/choparp_{$vipif}.pid");
1109
		break;
1110
	case "ipalias":
1111
		$vipif = get_real_interface($vip['interface']);
1112
		if (does_interface_exist($vipif)) {
1113
			if (is_ipaddrv6($vip['subnet']))
1114
				mwexec("/sbin/ifconfig {$vipif} inet6 {$vip['subnet']} -alias");
1115
			else
1116
				pfSense_interface_deladdress($vipif, $vip['subnet']);
1117
		}
1118
		break;
1119
	case "carp":
1120
		$vipif = "{$vip['interface']}_vip{$vip['vhid']}";
1121
		if (does_interface_exist($vipif))
1122
			pfSense_interface_destroy($vipif);
1123
		break;
1124
	}
1125
}
1126

    
1127
function interface_bring_down($interface = "wan", $destroy = false, $ifacecfg = false) {
1128
	global $config, $g;
1129

    
1130
	if (!isset($config['interfaces'][$interface]))
1131
		return;
1132

    
1133
	if ($g['debug'])
1134
		log_error("Calling interface down for interface {$interface}, destroy is " . (($destroy) ? 'true' : 'false'));
1135

    
1136
	if ($ifacecfg === false)
1137
		$ifcfg = $config['interfaces'][$interface];
1138
	else if (!is_array($ifacecfg))
1139
		log_error(gettext("Wrong parameters used during interface_bring_down"));
1140
	else
1141
		$ifcfg = $ifacecfg;
1142
		
1143

    
1144
	$realif = get_real_interface($interface);
1145

    
1146
	switch ($ifcfg['ipaddr']) {
1147
	case "ppp":
1148
	case "pppoe":
1149
	case "pptp":
1150
	case "l2tp":
1151
		if (is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) {
1152
			foreach ($config['ppps']['ppp'] as $pppid => $ppp) {
1153
				if ($realif == $ppp['if']) {
1154
					if (isset($ppp['ondemand']) && !$destroy){
1155
						send_event("interface reconfigure {$interface}");
1156
						break;
1157
					}
1158
					if (file_exists("{$g['varrun_path']}/{$ppp['type']}_{$interface}.pid")) {
1159
						killbypid("{$g['varrun_path']}/{$ppp['type']}_{$interface}.pid");
1160
						sleep(2);
1161
					}
1162
					unlink_if_exists("{$g['varetc_path']}/mpd_{$interface}.conf");
1163
					break;
1164
				}
1165
			}
1166
		}
1167
		break;
1168
	case "dhcp":
1169
		$pid = find_dhclient_process($realif);
1170
		if($pid)
1171
			mwexec("/bin/kill {$pid}");
1172
		sleep(1);
1173
		unlink_if_exists("{$g['varetc_path']}/dhclient_{$interface}.conf");
1174
		if(does_interface_exist("$realif")) {
1175
			mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete", true);
1176
			if ($destroy == true)
1177
				pfSense_interface_flags($realif, -IFF_UP);
1178
			mwexec("/usr/sbin/arp -d -i {$realif} -a");
1179
		}
1180
		break;
1181
	default:
1182
		if(does_interface_exist("$realif")) {
1183
			mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete", true);
1184
			if ($destroy == true)
1185
				pfSense_interface_flags($realif, -IFF_UP);
1186
			mwexec("/usr/sbin/arp -d -i {$realif} -a");
1187
		}
1188
		break;
1189
	}
1190

    
1191
	switch ($ifcfg['ipaddrv6']) {
1192
	case "slaac":
1193
	case "dhcp6":
1194
		$pidv6 = find_dhcp6c_process($realif);
1195
		if($pidv6)
1196
			mwexec("/bin/kill {$pidv6}");
1197
		sleep(3);
1198
		unlink_if_exists("{$g['varetc_path']}/dhcp6c_{$interface}.conf");
1199
		if (does_interface_exist("$realif")) {
1200
			$ip6 = get_interface_ipv6($interface);
1201
			if (is_ipaddrv6($ip6))
1202
				mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 {$ip6} delete", true);
1203
			if ($destroy == true)
1204
				pfSense_interface_flags($realif, -IFF_UP);
1205
			mwexec("/usr/sbin/arp -d -i {$realif} -a");
1206
		}
1207
		break;
1208
	case "6rd":
1209
	case "6to4":
1210
		$realif = "{$interface}_stf";
1211
		if(does_interface_exist("$realif")) {
1212
			$ip6 = get_interface_ipv6($interface);
1213
			if (is_ipaddrv6($ip6))
1214
				mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 {$ip6} delete", true);
1215
			if ($destroy == true)
1216
				pfSense_interface_flags($realif, -IFF_UP);
1217
		}
1218
		break;
1219
	default:
1220
		if(does_interface_exist("$realif")) {
1221
			$ip6 = get_interface_ipv6($interface);
1222
			if (is_ipaddrv6($ip6))
1223
				mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 {$ip6} delete", true);
1224
			if (!empty($ifcfg['ipaddrv6']) && is_ipaddrv6($ifcfg['ipaddrv6']))
1225
				mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 {$ifcfg['ipaddrv6']} delete", true);
1226
			if ($destroy == true)
1227
				pfSense_interface_flags($realif, -IFF_UP);
1228
			mwexec("/usr/sbin/arp -d -i {$realif} -a");
1229
		}
1230
		break;
1231
	}
1232

    
1233
	if (file_exists("{$g['tmp_path']}/{$realif}_router"))
1234
		$old_router = trim(file_get_contents("{$g['tmp_path']}/{$realif}_router"));
1235
//	log_error("Checking for old router states: {$g['tmp_path']}/{$realif}_router = {$old_router}");
1236
	if (!empty($old_router)) {
1237
		log_error("Clearing states to old gateway {$old_router}.");
1238
		mwexec("/sbin/pfctl -i {$realif} -Fs");
1239
	}
1240

    
1241
	/* remove interface up file if it exists */
1242
	unlink_if_exists("{$g['tmp_path']}/{$realif}up");
1243
	unlink_if_exists("{$g['vardb_path']}/{$interface}ip");
1244
	unlink_if_exists("{$g['vardb_path']}/{$interface}ipv6");
1245
	unlink_if_exists("{$g['tmp_path']}/{$realif}_router");
1246
	unlink_if_exists("{$g['tmp_path']}/{$realif}_routerv6");
1247
	unlink_if_exists("{$g['varetc_path']}/nameserver_{$realif}");
1248
	unlink_if_exists("{$g['varetc_path']}/searchdomain_{$realif}");
1249

    
1250
	/* hostapd and wpa_supplicant do not need to be running when the interface is down.
1251
	 * They will also use 100% CPU if running after the wireless clone gets deleted. */
1252
	if (is_array($ifcfg['wireless'])) {
1253
		kill_hostapd($realif);
1254
		mwexec(kill_wpasupplicant($realif));
1255
	}
1256

    
1257
	if ($destroy == true) {
1258
		if (preg_match("/^[a-z0-9]+_vip|^tun|^ovpn|^gif|^gre|^lagg|^bridge|vlan|_stf$/i", $realif))
1259
			pfSense_interface_destroy($realif);
1260
	}
1261

    
1262
	return;
1263
}
1264

    
1265
function interfaces_ptpid_used($ptpid) {
1266
	global $config;
1267

    
1268
	if (is_array($config['ppps']['ppp']))
1269
		foreach ($config['ppps']['ppp'] as & $settings)
1270
			if ($ptpid == $settings['ptpid'])
1271
				return true;
1272

    
1273
	return false;
1274
}
1275

    
1276
function interfaces_ptpid_next() {
1277

    
1278
	$ptpid = 0;
1279
	while(interfaces_ptpid_used($ptpid))
1280
		$ptpid++;
1281

    
1282
	return $ptpid;
1283
}
1284

    
1285
function getMPDCRONSettings($pppif) {
1286
	global $config;
1287

    
1288
	$cron_cmd_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
1289
	if (is_array($config['cron']['item'])) {
1290
		foreach ($config['cron']['item'] as $i => $item) {
1291
			if (stripos($item['command'], $cron_cmd_file) !== false)
1292
				return array("ID" => $i, "ITEM" => $item);
1293
		}
1294
	}
1295

    
1296
	return NULL;
1297
}
1298

    
1299
function handle_pppoe_reset($post_array) {
1300
	global $config, $g;
1301

    
1302
	$pppif = "{$post_array['type']}{$post_array['ptpid']}";
1303
	$cron_cmd_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
1304

    
1305
	if (!is_array($config['cron']['item']))
1306
		$config['cron']['item'] = array();
1307

    
1308
	$itemhash = getMPDCRONSettings($pppif);
1309

    
1310
	// reset cron items if necessary and return
1311
	if (empty($post_array['pppoe-reset-type'])) {
1312
		if (isset($itemhash))
1313
			unset($config['cron']['item'][$itemhash['ID']]);
1314
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
1315
		return;
1316
	}
1317

    
1318
	if (empty($itemhash))
1319
		$itemhash = array();
1320
	$item = array();
1321
	if (isset($post_array['pppoe-reset-type']) && $post_array['pppoe-reset-type'] == "custom") {
1322
		$item['minute'] = $post_array['pppoe_resetminute'];
1323
		$item['hour'] = $post_array['pppoe_resethour'];
1324
		if (isset($post_array['pppoe_resetdate']) && $post_array['pppoe_resetdate'] <> "") {
1325
			$date = explode("/", $post_array['pppoe_resetdate']);
1326
			$item['mday'] = $date[1];
1327
			$item['month'] = $date[0];
1328
		} else {
1329
			$item['mday'] = "*";
1330
			$item['month'] = "*";
1331
		}
1332
		$item['wday'] = "*";
1333
		$item['who'] = "root";
1334
		$item['command'] = $cron_cmd_file;
1335
	} else if (isset($post_array['pppoe-reset-type']) && $post_array['pppoe-reset-type'] == "preset") {
1336
		switch ($post_array['pppoe_pr_preset_val']) {
1337
		case "monthly":
1338
			$item['minute'] = "0";
1339
			$item['hour'] = "0";
1340
			$item['mday'] = "1";
1341
			$item['month'] = "*";
1342
			$item['wday'] = "*";
1343
			break;
1344
	        case "weekly":
1345
			$item['minute'] = "0";
1346
			$item['hour'] = "0";
1347
			$item['mday'] = "*";
1348
			$item['month'] = "*";
1349
			$item['wday'] = "0";
1350
			break;
1351
		case "daily":
1352
			$item['minute'] = "0";
1353
			$item['hour'] = "0";
1354
			$item['mday'] = "*";
1355
			$item['month'] = "*";
1356
			$item['wday'] = "*";
1357
			break;
1358
		case "hourly":
1359
			$item['minute'] = "0";
1360
			$item['hour'] = "*";
1361
			$item['mday'] = "*";
1362
			$item['month'] = "*";
1363
			$item['wday'] = "*";
1364
			break;
1365
		} // end switch
1366
		$item['who'] = "root";
1367
		$item['command'] = $cron_cmd_file;
1368
	}
1369
	if (empty($item))
1370
		return;
1371
	if (isset($item['ID']))
1372
		$config['cron']['item'][$item['ID']] = $item;
1373
	else
1374
		$config['cron']['item'][] = $item;
1375
}
1376

    
1377
/*
1378
 * This function can configure PPPoE, MLPPP (PPPoE), PPTP.
1379
 * It writes the mpd config file to /var/etc every time the link is opened.
1380
 */
1381
function interface_ppps_configure($interface) {
1382
	global $config, $g;
1383

    
1384
	/* Return for unassigned interfaces. This is a minimum requirement. */
1385
	if (empty($config['interfaces'][$interface]))
1386
		return 0;
1387
	$ifcfg = $config['interfaces'][$interface];
1388
	if (!isset($ifcfg['enable']))
1389
		return 0;
1390

    
1391
	// mpd5 requires a /var/spool/lock directory for PPP modem links.
1392
	if(!is_dir("/var/spool/lock")) {
1393
		exec("/bin/mkdir -p /var/spool/lock");
1394
		exec("/bin/chmod a+rw /var/spool/lock/.");
1395
	}
1396
	// mpd5 modem chat script expected in the same directory as the mpd_xxx.conf files
1397
	if (!file_exists("{$g['varetc_path']}/mpd.script"))
1398
		mwexec("/bin/ln -s /usr/local/sbin/mpd.script {$g['varetc_path']}/.");
1399

    
1400
	if (is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) {
1401
		foreach ($config['ppps']['ppp'] as $pppid => $ppp) {
1402
			if ($ifcfg['if'] == $ppp['if'])
1403
				break;
1404
		}
1405
	}
1406
	if (!$ppp || $ifcfg['if'] != $ppp['if']){
1407
		log_error(sprintf(gettext("Can't find PPP config for %s in interface_ppps_configure()."), $ifcfg['if']));
1408
		return 0;
1409
	}
1410
	$pppif = $ifcfg['if'];
1411
	if ($ppp['type'] == "ppp")
1412
		$type = "modem";
1413
	else
1414
		$type = $ppp['type'];
1415
	$upper_type = strtoupper($ppp['type']);
1416

    
1417
	if($g['booting']) {
1418
		$descr = isset($ifcfg['descr']) ? $ifcfg['descr'] : strtoupper($interface);
1419
		echo "starting {$pppif} link...";
1420
		// Do not re-configure the interface if we are booting and it's already been started
1421
		if(file_exists("{$g['varrun_path']}/{$ppp['type']}_{$interface}.pid"))
1422
			return 0;
1423
	}
1424

    
1425
	$ports = explode(',',$ppp['ports']);
1426
	if ($type != "modem") {
1427
		foreach ($ports as $pid => $port) {
1428
			$ports[$pid] = get_real_interface($port);
1429
			if (empty($ports[$pid]))
1430
				return 0;
1431
		}
1432
	}
1433
	$localips = explode(',',$ppp['localip']);
1434
	$gateways = explode(',',$ppp['gateway']);
1435
	$subnets = explode(',',$ppp['subnet']);
1436

    
1437
	/* We bring up the parent interface first because if DHCP is configured on the parent we need
1438
	 * to obtain an address first so we can write it in the mpd .conf file for PPTP and L2TP configs
1439
	 */
1440
	foreach($ports as $pid => $port){
1441
		switch ($ppp['type']) {
1442
			case "pppoe":
1443
				/* Bring the parent interface up */
1444
				interfaces_bring_up($port);
1445
				pfSense_ngctl_attach(".", $port);
1446
				/* Enable setautosrc to automatically change mac address if parent interface's changes */
1447
				mwexec("ngctl msg {$port}: setautosrc 1");
1448
				break;
1449
			case "pptp":
1450
			case "l2tp":
1451
				/* configure interface */
1452
				if(is_ipaddr($localips[$pid])){
1453
					// Manually configure interface IP/subnet
1454
					pfSense_interface_setaddress($port, "{$localips[$pid]}/{$subnets[$pid]}");
1455
					interfaces_bring_up($port);
1456
				} else if (empty($localips[$pid]))
1457
					$localips[$pid] = get_interface_ip($port); // try to get the interface IP from the port
1458

    
1459
				if(!is_ipaddr($localips[$pid])){
1460
					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!");
1461
					$localips[$pid] = "0.0.0.0";
1462
				}
1463
				/* XXX: This needs to go away soon! [It's commented out!] */
1464
				/* Configure the gateway (remote IP ) */
1465
				if (!$g['booting'] && !is_ipaddr($gateways[$pid]) && is_hostname($gateways[$pid])) {
1466
					/* XXX: Fix later
1467
					$gateways[$pid] = gethostbyname($gateways[$pid]);
1468
					if(!is_ipaddr($gateways[$pid])) {
1469
						log_error("Could not get a valid Gateway IP from {$port} via DNS in interfaces_ppps_configure.");
1470
						return 0;
1471
					}
1472
					*/
1473
				}
1474
				if(!is_ipaddr($gateways[$pid])){
1475
					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));
1476
					return 0;
1477
				}
1478
				pfSense_ngctl_attach(".", $port);
1479
				break;
1480
			case "ppp":
1481
				if (!file_exists("{$port}")) {
1482
					log_error(sprintf(gettext("Device %s does not exist. PPP link cannot start without the modem device."), $port));
1483
					return 0;
1484
				}
1485
				break;
1486
			default:
1487
				log_error(sprintf(gettext("Unkown %s configured as ppp interface."), $type));
1488
				break;
1489
		}
1490
	}
1491

    
1492
	if (is_array($ports) && count($ports) > 1)
1493
		$multilink = "enable";
1494
	else
1495
		$multilink = "disable";
1496

    
1497
	if ($type == "modem"){
1498
		if (is_ipaddr($ppp['localip']))
1499
			$localip = $ppp['localip'];
1500
		else
1501
			$localip = '0.0.0.0';
1502

    
1503
		if (is_ipaddr($ppp['gateway']))
1504
			$gateway = $ppp['gateway'];
1505
		else
1506
			$gateway = "10.64.64.{$pppid}";
1507
		$ranges = "{$localip}/0 {$gateway}/0";
1508

    
1509
		if (empty($ppp['apnum']))
1510
			$ppp['apnum'] = 1;
1511
	} else
1512
		$ranges = "0.0.0.0/0 0.0.0.0/0";
1513

    
1514
	if (isset($ppp['ondemand']))
1515
		$ondemand = "enable";
1516
	else
1517
		$ondemand = "disable";
1518
	if (!isset($ppp['idletimeout']))
1519
		$ppp['idletimeout'] = 0;
1520

    
1521
	if (empty($ppp['username']) && $type == "modem"){
1522
		$ppp['username'] = "user";
1523
		$ppp['password'] = "none";
1524
	}
1525
	if (empty($ppp['password']) && $type == "modem")
1526
		$passwd = "none";
1527
	else
1528
		$passwd = base64_decode($ppp['password']);
1529

    
1530
	$bandwidths = explode(',',$ppp['bandwidth']);
1531
	$defaultmtu = "1492";
1532
	if (!empty($ifcfg['mtu']))
1533
		$defaultmtu = intval($ifcfg['mtu']);
1534
	$mtus = explode(',',$ppp['mtu']);
1535
	$mrus = explode(',',$ppp['mru']);
1536

    
1537
	if (isset($ppp['mrru']))
1538
		$mrrus = explode(',',$ppp['mrru']);
1539

    
1540
	// Construct the mpd.conf file
1541
	$mpdconf = <<<EOD
1542
startup:
1543
	# configure the console
1544
	set console close
1545
	# configure the web server
1546
	set web close
1547

    
1548
default:
1549
{$ppp['type']}client:
1550
	create bundle static {$interface}
1551
	set bundle enable ipv6cp
1552
	set iface name {$pppif}
1553

    
1554
EOD;
1555
	$setdefaultgw = false;
1556
	$founddefaultgw = false;
1557
	if (is_array($config['gateways']['gateway_item'])) {
1558
		foreach($config['gateways']['gateway_item'] as $gateway) {
1559
			if($interface == $gateway['interface'] && isset($gateway['defaultgw'])) {
1560
				$setdefaultgw = true;
1561
				break;
1562
			} else if (isset($gateway['defaultgw']) && !empty($gateway['interface'])) {
1563
				$founddefaultgw = true;
1564
				break;
1565
			}
1566
		}
1567
	}
1568

    
1569
	if (($interface == "wan" && $founddefaultgw == false) || $setdefaultgw == true){
1570
		$setdefaultgw = true;
1571
		$mpdconf .= <<<EOD
1572
	set iface route default
1573

    
1574
EOD;
1575
	}
1576
	$mpdconf .= <<<EOD
1577
	set iface {$ondemand} on-demand
1578
	set iface idle {$ppp['idletimeout']}
1579

    
1580
EOD;
1581

    
1582
	if (isset($ppp['ondemand']))
1583
		$mpdconf .= <<<EOD
1584
	set iface addrs 10.10.1.1 10.10.1.2
1585

    
1586
EOD;
1587

    
1588
	if (isset($ppp['tcpmssfix']))
1589
		$tcpmss = "disable";
1590
	else
1591
		$tcpmss = "enable";
1592
		$mpdconf .= <<<EOD
1593
	set iface {$tcpmss} tcpmssfix
1594

    
1595
EOD;
1596

    
1597
	$mpdconf .= <<<EOD
1598
	set iface up-script /usr/local/sbin/ppp-linkup
1599
	set iface down-script /usr/local/sbin/ppp-linkdown
1600
	set ipcp ranges {$ranges}
1601

    
1602
EOD;
1603
	if (isset($ppp['vjcomp']))
1604
		$mpdconf .= <<<EOD
1605
	set ipcp no vjcomp
1606

    
1607
EOD;
1608

    
1609
	if (isset($config['system']['dnsallowoverride']))
1610
		$mpdconf .= <<<EOD
1611
	set ipcp enable req-pri-dns
1612
	set ipcp enable req-sec-dns
1613

    
1614
EOD;
1615
	if (!isset($ppp['verbose_log']))
1616
		$mpdconf .= <<<EOD
1617
	#log -bund -ccp -chat -iface -ipcp -lcp -link
1618

    
1619
EOD;
1620
	foreach($ports as $pid => $port){
1621
		$port = get_real_interface($port);
1622
		$mpdconf .= <<<EOD
1623

    
1624
	create link static {$interface}_link{$pid} {$type}
1625
	set link action bundle {$interface}
1626
	set link {$multilink} multilink
1627
	set link keep-alive 10 60
1628
	set link max-redial 0
1629

    
1630
EOD;
1631
		if (isset($ppp['shortseq']))
1632
			$mpdconf .= <<<EOD
1633
	set link no shortseq
1634

    
1635
EOD;
1636

    
1637
		if (isset($ppp['acfcomp']))
1638
			$mpdconf .= <<<EOD
1639
	set link no acfcomp
1640

    
1641
EOD;
1642

    
1643
		if (isset($ppp['protocomp']))
1644
			$mpdconf .= <<<EOD
1645
	set link no protocomp
1646

    
1647
EOD;
1648

    
1649
		$mpdconf .= <<<EOD
1650
	set link disable chap pap
1651
	set link accept chap pap eap
1652
	set link disable incoming
1653

    
1654
EOD;
1655

    
1656

    
1657
		if (!empty($bandwidths[$pid]))
1658
			$mpdconf .= <<<EOD
1659
	set link bandwidth {$bandwidths[$pid]}
1660

    
1661
EOD;
1662

    
1663
		if (empty($mtus[$pid]))
1664
			$mtus[$pid] = $defaultmtu;
1665
			$mpdconf .= <<<EOD
1666
	set link mtu {$mtus[$pid]}
1667

    
1668
EOD;
1669

    
1670
		if (!empty($mrus[$pid]))
1671
			$mpdconf .= <<<EOD
1672
	set link mru {$mrus[$pid]}
1673

    
1674
EOD;
1675

    
1676
		if (!empty($mrrus[$pid]))
1677
			$mpdconf .= <<<EOD
1678
	set link mrru {$mrrus[$pid]}
1679

    
1680
EOD;
1681

    
1682
		$mpdconf .= <<<EOD
1683
	set auth authname "{$ppp['username']}"
1684
	set auth password {$passwd}
1685

    
1686
EOD;
1687
		if ($type == "modem") {
1688
			$mpdconf .= <<<EOD
1689
	set modem device {$ppp['ports']}
1690
	set modem script DialPeer
1691
	set modem idle-script Ringback
1692
	set modem watch -cd
1693
	set modem var \$DialPrefix "DT"
1694
	set modem var \$Telephone "{$ppp['phone']}"
1695

    
1696
EOD;
1697
		}
1698
		if (isset($ppp['connect-timeout']) && $type == "modem") {
1699
			$mpdconf .= <<<EOD
1700
	set modem var \$ConnectTimeout "{$ppp['connect-timeout']}"
1701

    
1702
EOD;
1703
		}
1704
		if (isset($ppp['initstr']) && $type == "modem") {
1705
			$initstr = base64_decode($ppp['initstr']);
1706
			$mpdconf .= <<<EOD
1707
	set modem var \$InitString "{$initstr}"
1708

    
1709
EOD;
1710
		}
1711
		if (isset($ppp['simpin']) && $type == "modem") {
1712
			if($ppp['pin-wait'] == "")
1713
				$ppp['pin-wait'] = 0;
1714
			$mpdconf .= <<<EOD
1715
	set modem var \$SimPin "{$ppp['simpin']}"
1716
	set modem var \$PinWait "{$ppp['pin-wait']}"
1717

    
1718
EOD;
1719
		}
1720
		if (isset($ppp['apn']) && $type == "modem") {
1721
			$mpdconf .= <<<EOD
1722
	set modem var \$APN "{$ppp['apn']}"
1723
	set modem var \$APNum "{$ppp['apnum']}"
1724

    
1725
EOD;
1726
		}
1727
		if ($type == "pppoe") {
1728
			// Send a null service name if none is set.
1729
			$provider = isset($ppp['provider']) ? $ppp['provider'] : "";
1730
			$mpdconf .= <<<EOD
1731
	set pppoe service "{$provider}"
1732

    
1733
EOD;
1734
		}
1735
		if ($type == "pppoe")
1736
			$mpdconf .= <<<EOD
1737
	set pppoe iface {$port}
1738

    
1739
EOD;
1740

    
1741
		if ($type == "pptp" || $type == "l2tp") {
1742
			$mpdconf .= <<<EOD
1743
	set {$type} self {$localips[$pid]}
1744
	set {$type} peer {$gateways[$pid]}
1745

    
1746
EOD;
1747
		}
1748

    
1749
		$mpdconf .= "\topen\n";
1750
	} //end foreach($port)
1751

    
1752

    
1753
	/* Generate mpd.conf. If mpd_[interface].conf exists in the conf path, then link to it instead of generating a fresh conf file. */
1754
	if (file_exists("{$g['conf_path']}/mpd_{$interface}.conf"))
1755
		mwexec("/bin/ln -s {$g['conf_path']}/mpd_{$interface}.conf {$g['varetc_path']}/.");
1756
	else {
1757
		$fd = fopen("{$g['varetc_path']}/mpd_{$interface}.conf", "w");
1758
		if (!$fd) {
1759
			log_error(sprintf(gettext("Error: cannot open mpd_%s.conf in interface_ppps_configure().%s"), $interface, "\n"));
1760
			return 0;
1761
		}
1762
		// Write out mpd_ppp.conf
1763
		fwrite($fd, $mpdconf);
1764
		fclose($fd);
1765
		unset($mpdconf);
1766
	}
1767

    
1768
	// Create the uptime log if requested and if it doesn't exist already, or delete it if it is no longer requested.
1769
	if (isset($ppp['uptime'])) {
1770
		if (!file_exists("/conf/{$pppif}.log")) {
1771
			conf_mount_rw();
1772
			mwexec("echo /dev/null > /conf/{$pppif}.log");
1773
			conf_mount_ro();
1774
		}
1775
	} else {
1776
		if (file_exists("/conf/{$pppif}.log")) {
1777
			conf_mount_rw();
1778
			mwexec("rm -f /conf/{$pppif}.log");
1779
			conf_mount_ro();
1780
		}
1781
	}
1782

    
1783
	/* clean up old lock files */
1784
	foreach($ports as $port) {
1785
		if(file_exists("{$g['var_path']}/spool/lock/LCK..{$port}"))
1786
			unlink("{$g['var_path']}/spool/lock/LCK..{$port}");
1787
	}
1788

    
1789
	/* fire up mpd */
1790
	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");
1791

    
1792
	// Check for PPPoE periodic reset request
1793
	if ($type == "pppoe") {
1794
		if (!empty($ppp['pppoe-reset-type']))
1795
			interface_setup_pppoe_reset_file($ppp['if'], $interface);
1796
		else
1797
			interface_setup_pppoe_reset_file($ppp['if']);
1798
	}
1799
	/* wait for upto 10 seconds for the interface to appear (ppp(oe)) */
1800
	$i = 0;
1801
	while($i < 10) {
1802
		exec("/sbin/ifconfig {$ppp['if']} 2>&1", $out, $ret);
1803
		if($ret == 0)
1804
			break;
1805
		sleep(1);
1806
		$i++;
1807
	}
1808

    
1809
	/* we only support the 3gstats.php for huawei modems for now. Will add more later. */
1810
	/* We should be able to launch the right version for each modem */
1811
	/* We can also guess the mondev from the manufacturer */
1812
	exec("usbconfig | egrep -ie '(huawei)'", $usbmodemoutput);
1813
	mwexec("/bin/ps auxww|grep \"{$interface}\" |grep \"[3]gstats\" | awk '{print $2}' |xargs kill");
1814
	foreach($ports as $port) {
1815
		if(preg_match("/huawei/i", implode("\n", $usbmodemoutput))) {
1816
			$mondev  = substr(basename($port), 0, -1);
1817
			$devlist = glob("/dev/{$mondev}?");
1818
			$mondev = basename(end($devlist));
1819
		}
1820
		if(preg_match("/zte/i", implode("\n", $usbmodemoutput))) {
1821
			$mondev  = substr(basename($port), 0, -1) . "1";
1822
		}
1823
		log_error("Starting 3gstats.php on device '{$mondev}' for interface '{$interface}'");
1824
		mwexec_bg("/usr/local/bin/3gstats.php {$mondev} {$interface}");
1825
	}
1826

    
1827
	return 1;
1828
}
1829

    
1830
function interfaces_carp_setup() {
1831
	global $g, $config;
1832

    
1833
	if (isset($config['system']['developerspew'])) {
1834
		$mt = microtime();
1835
		echo "interfaces_carp_setup() being called $mt\n";
1836
	}
1837

    
1838
	if ($g['booting']) {
1839
		echo gettext("Configuring CARP settings...");
1840
		mute_kernel_msgs();
1841
	}
1842

    
1843
	/* suck in configuration items */
1844
	if ($config['hasync']) {
1845
		$pfsyncenabled = $config['hasync']['pfsyncenabled'];
1846
		$balanacing = $config['hasync']['balancing'];
1847
		$pfsyncinterface = $config['hasync']['pfsyncinterface'];
1848
		$pfsyncpeerip = $config['hasync']['pfsyncpeerip'];
1849
	} else {
1850
		unset($pfsyncinterface);
1851
		unset($balanacing);
1852
		unset($pfsyncenabled);
1853
	}
1854

    
1855
	if ($balanacing) {
1856
		mwexec("/sbin/sysctl net.inet.carp.arpbalance=1", true);
1857
		mwexec("/sbin/sysctl net.inet.carp.preempt=0", true);
1858
	} else
1859
		mwexec("/sbin/sysctl net.inet.carp.preempt=1", true);
1860

    
1861
	mwexec("sbin/sysctl net.inet.carp.log=1", true);
1862
	if (!empty($pfsyncinterface))
1863
		$carp_sync_int = get_real_interface($pfsyncinterface);
1864
	else
1865
		unset($carp_sync_int);
1866

    
1867
	/* setup pfsync interface */
1868
	if ($carp_sync_int and $pfsyncenabled) {
1869
		if (is_ipaddr($pfsyncpeerip))
1870
			mwexec("/sbin/ifconfig pfsync0 syncdev {$carp_sync_int} syncpeer {$pfsyncpeerip} up", false);
1871
		else
1872
			mwexec("/sbin/ifconfig pfsync0 syncdev {$carp_sync_int} up", false);
1873

    
1874
		sleep(1);
1875

    
1876
		/* 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
1877
		 * for existing sessions.
1878
		 */
1879
		log_error("waiting for pfsync...");
1880
		$i = 0;
1881
		while (intval(trim(`/sbin/ifconfig pfsync0 | /usr/bin/grep 'syncok: 0' | /usr/bin/grep -v grep | /usr/bin/wc -l`)) == 0 && $i < 30) {
1882
			$i++;
1883
			sleep(1);
1884
		}
1885
		log_error("pfsync done in $i seconds.");
1886
		log_error("Configuring CARP settings finalize...");
1887
	}
1888

    
1889
	if($config['virtualip']['vip'])
1890
		mwexec("/sbin/sysctl net.inet.carp.allow=1", true);
1891
	else
1892
		mwexec("/sbin/sysctl net.inet.carp.allow=0", true);
1893

    
1894
	if ($g['booting']) {
1895
		unmute_kernel_msgs();
1896
		echo gettext("done.") . "\n";
1897
	}
1898
}
1899

    
1900
function interface_proxyarp_configure($interface = "") {
1901
	global $config, $g;
1902
	if(isset($config['system']['developerspew'])) {
1903
		$mt = microtime();
1904
		echo "interface_proxyarp_configure() being called $mt\n";
1905
	}
1906

    
1907
	/* kill any running choparp */
1908
	if (empty($interface))
1909
		killbyname("choparp");
1910
	else {
1911
		$vipif = get_real_interface($interface);
1912
		if (file_exists("{$g['varrun_path']}/choparp_{$vipif}.pid"))
1913
			killbypid("{$g['varrun_path']}/choparp_{$vipif}.pid");
1914
	}
1915

    
1916
	$paa = array();
1917
	if (!empty($config['virtualip']) && is_array($config['virtualip']['vip'])) {
1918

    
1919
		/* group by interface */
1920
		foreach ($config['virtualip']['vip'] as $vipent) {
1921
			if ($vipent['mode'] === "proxyarp") {
1922
				if ($vipent['interface'])
1923
					$proxyif = $vipent['interface'];
1924
				else
1925
					$proxyif = "wan";
1926

    
1927
				if (!empty($interface) && $interface != $proxyif)
1928
					continue;
1929

    
1930
				if (!is_array($paa[$proxyif]))
1931
					$paa[$proxyif] = array();
1932

    
1933
				$paa[$proxyif][] = $vipent;
1934
			}
1935
		}
1936
	}
1937

    
1938
	if (!empty($interface)) {
1939
		if (is_array($paa[$interface])) {
1940
			$paaifip = get_interface_ip($interface);
1941
			if (!is_ipaddr($paaifip))
1942
				return;
1943
			$args = get_real_interface($interface) . " auto";
1944
			foreach ($paa[$interface] as $paent) {
1945
				if (isset($paent['subnet']))
1946
					$args .= " " . escapeshellarg("{$paent['subnet']}/{$paent['subnet_bits']}");
1947
				else if (isset($paent['range']))
1948
					$args .= " " . escapeshellarg($paent['range']['from'] . "-" . $paent['range']['to']);
1949
			}
1950
			mwexec_bg("/usr/local/sbin/choparp " . $args);
1951
		}
1952
	} else if (count($paa) > 0) {
1953
		foreach ($paa as $paif => $paents)  {
1954
			$paaifip = get_interface_ip($paif);
1955
			if (!is_ipaddr($paaifip))
1956
				continue;
1957
			$args = get_real_interface($paif) . " auto";
1958
			foreach ($paents as $paent) {
1959
				if (isset($paent['subnet']))
1960
					$args .= " " . escapeshellarg("{$paent['subnet']}/{$paent['subnet_bits']}");
1961
				else if (isset($paent['range']))
1962
					$args .= " " . escapeshellarg($paent['range']['from'] . "-" . $paent['range']['to']);
1963
			}
1964
			mwexec_bg("/usr/local/sbin/choparp " . $args);
1965
		}
1966
	}
1967
}
1968

    
1969
function interfaces_vips_configure($interface = "") {
1970
	global $g, $config;
1971
	if(isset($config['system']['developerspew'])) {
1972
		$mt = microtime();
1973
		echo "interfaces_vips_configure() being called $mt\n";
1974
	}
1975
	$paa = array();
1976
	if(is_array($config['virtualip']['vip'])) {
1977
		$carp_setuped = false;
1978
		$anyproxyarp = false;
1979
		foreach ($config['virtualip']['vip'] as $vip) {
1980
			switch ($vip['mode']) {
1981
			case "proxyarp":
1982
				/* nothing it is handled on interface_proxyarp_configure() */
1983
				if ($interface <> "" && $vip['interface'] <> $interface)
1984
					continue;
1985
				$anyproxyarp = true;
1986
				break;
1987
			case "ipalias":
1988
				if ($interface <> "" && $vip['interface'] <> $interface)
1989
					continue;
1990
				interface_ipalias_configure($vip);
1991
				break;
1992
			case "carp":
1993
				if ($interface <> "" && $vip['interface'] <> $interface)
1994
					continue;
1995
				if ($carp_setuped == false)
1996
					$carp_setuped = true;
1997
				interface_carp_configure($vip);
1998
				break;
1999
			}
2000
		}
2001
		if ($carp_setuped == true)
2002
			interfaces_carp_setup();
2003
		if ($anyproxyarp == true)
2004
			interface_proxyarp_configure();
2005
	}
2006
}
2007

    
2008
function interface_ipalias_configure(&$vip) {
2009
	if ($vip['mode'] == "ipalias") {
2010
		$if = get_real_interface($vip['interface']);
2011
		$af = "inet";
2012
		if(is_ipaddrv6($vip['subnet']))
2013
			$af = "inet6";
2014
		mwexec("/sbin/ifconfig " . escapeshellarg($if) ." {$af} ". escapeshellarg($vip['subnet']) ."/" . escapeshellarg($vip['subnet_bits']) . " alias");
2015
	}
2016
}
2017

    
2018
function interface_reload_carps($cif) {
2019
	global $config;
2020

    
2021
	$carpifs = link_ip_to_carp_interface(find_interface_ip($cif));
2022
	if (empty($carpifs))
2023
		return;
2024

    
2025
	$carps = explode(" ", $carpifs);
2026
	if(is_array($config['virtualip']['vip'])) {
2027
		$viparr = &$config['virtualip']['vip'];
2028
		foreach ($viparr as $vip) {
2029
			if (in_array($vip['carpif'], $carps)) {
2030
				switch ($vip['mode']) {
2031
				case "carp":
2032
					interface_vip_bring_down($vip);
2033
					sleep(1);
2034
					interface_carp_configure($vip);
2035
					break;
2036
				case "ipalias":
2037
					interface_vip_bring_down($vip);
2038
					sleep(1);
2039
					interface_ipalias_configure($vip);
2040
					break;
2041
				}
2042
			}
2043
		}
2044
	}
2045
}
2046

    
2047
function interface_carp_configure(&$vip) {
2048
	global $config, $g;
2049
	if(isset($config['system']['developerspew'])) {
2050
		$mt = microtime();
2051
		echo "interface_carp_configure() being called $mt\n";
2052
	}
2053

    
2054
	if ($vip['mode'] != "carp")
2055
		return;
2056

    
2057
	/*
2058
	 * ensure the interface containing the VIP really exists
2059
	 * prevents a panic if the interface is missing or invalid
2060
	 */
2061
	$realif = get_real_interface($vip['interface']);
2062
	if (!does_interface_exist($realif)) {
2063
		file_notice("CARP", sprintf(gettext("Interface specified for the virtual IP address %s does not exist. Skipping this VIP."), $vip['subnet']), "Firewall: Virtual IP", "");
2064
		return;
2065
	}
2066

    
2067
	if(is_ipaddrv4($vip['subnet'])) {
2068
		/* Ensure CARP IP really exists prior to loading up. */
2069
		$ww_subnet_ip = find_interface_ip($realif);
2070
		$ww_subnet_bits = find_interface_subnet($realif);
2071
		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'])) {
2072
			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", "");
2073
			return;
2074
		}
2075
	}
2076
	if(is_ipaddrv6($vip['subnet'])) {
2077
		/* Ensure CARP IP really exists prior to loading up. */
2078
		$ww_subnet_ip = find_interface_ipv6($realif);
2079
		$ww_subnet_bits = find_interface_subnetv6($realif);
2080
		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'])) {
2081
			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", "");
2082
			return;
2083
		}
2084
	}
2085

    
2086
	// set the vip interface to the vhid
2087
	$vipif = "{$vip['interface']}_vip{$vip['vhid']}";
2088

    
2089
	/* create the carp interface and setup */
2090
	if (does_interface_exist($vipif)) {
2091
		pfSense_interface_flags($vipif, -IFF_UP);
2092
	} else {
2093
		$carpif = pfSense_interface_create("carp");
2094
		pfSense_interface_rename($carpif, $vipif);
2095
		pfSense_ngctl_name("{$carpif}:", $vipif);
2096
	}
2097

    
2098
	/* invalidate interface cache */
2099
	get_interface_arr(true);
2100

    
2101
	$vip_password = $vip['password'];
2102
	$vip_password = escapeshellarg(addslashes(str_replace(" ", "", $vip_password)));
2103
	if ($vip['password'] != "")
2104
		$password = " pass {$vip_password}";
2105

    
2106
	$broadcast_address = gen_subnet_max($vip['subnet'], $vip['subnet_bits']);
2107
	$advbase = "";
2108
	if (!empty($vip['advbase']))
2109
		$advbase = "advbase {$vip['advbase']}";
2110

    
2111
	if(is_ipaddrv4($vip['subnet'])) {
2112
		$broadcast_address = gen_subnet_max($vip['subnet'], $vip['subnet_bits']);
2113
		mwexec("/sbin/ifconfig {$vipif} {$vip['subnet']}/{$vip['subnet_bits']} vhid {$vip['vhid']} advskew {$vip['advskew']} {$advbase} {$password}");
2114
	}
2115
	if(is_ipaddrv6($vip['subnet'])) {
2116
		$broadcast_address = gen_subnet_max($vip['subnet'], $vip['subnet_bits']);
2117
		mwexec("/sbin/ifconfig {$vipif} inet6 {$vip['subnet']} prefixlen {$vip['subnet_bits']} vhid {$vip['vhid']} advskew {$vip['advskew']} {$advbase} {$password}");
2118
	}
2119

    
2120
	interfaces_bring_up($vipif);
2121

    
2122
	return $vipif;
2123
}
2124

    
2125
function interface_wireless_clone($realif, $wlcfg) {
2126
	global $config, $g;
2127
	/*   Check to see if interface has been cloned as of yet.
2128
	 *   If it has not been cloned then go ahead and clone it.
2129
	 */
2130
	$needs_clone = false;
2131
	if(is_array($wlcfg['wireless']))
2132
		$wlcfg_mode = $wlcfg['wireless']['mode'];
2133
	else
2134
		$wlcfg_mode = $wlcfg['mode'];
2135
	switch($wlcfg_mode) {
2136
		 case "hostap":
2137
			$mode = "wlanmode hostap";
2138
			break;
2139
		 case "adhoc":
2140
			$mode = "wlanmode adhoc";
2141
			break;
2142
		 default:
2143
			$mode = "";
2144
			break;
2145
	}
2146
	$baseif = interface_get_wireless_base($wlcfg['if']);
2147
	if(does_interface_exist($realif)) {
2148
		exec("/sbin/ifconfig {$realif}", $output, $ret);
2149
		$ifconfig_str = implode($output);
2150
		if(($wlcfg_mode == "hostap") && (! preg_match("/hostap/si", $ifconfig_str))) {
2151
			log_error(sprintf(gettext("Interface %s changed to hostap mode"), $realif));
2152
			$needs_clone = true;
2153
		}
2154
		if(($wlcfg_mode == "adhoc") && (! preg_match("/adhoc/si", $ifconfig_str))) {
2155
			log_error(sprintf(gettext("Interface %s changed to adhoc mode"), $realif));
2156
			$needs_clone = true;
2157
		}
2158
		if(($wlcfg_mode == "bss") && (preg_match("/hostap|adhoc/si", $ifconfig_str))) {
2159
			log_error(sprintf(gettext("Interface %s changed to infrastructure mode"), $realif));
2160
			$needs_clone = true;
2161
		}
2162
	} else {
2163
		$needs_clone = true;
2164
	}
2165

    
2166
	if($needs_clone == true) {
2167
		/* remove previous instance if it exists */
2168
		if(does_interface_exist($realif))
2169
			pfSense_interface_destroy($realif);
2170

    
2171
		log_error(sprintf(gettext("Cloning new wireless interface %s"), $realif));
2172
		// Create the new wlan interface. FreeBSD returns the new interface name.
2173
		// example:  wlan2
2174
		exec("/sbin/ifconfig wlan create wlandev {$baseif} {$mode} bssid 2>&1", $out, $ret);
2175
		if($ret <> 0) {
2176
			log_error(sprintf(gettext('Failed to clone interface %1$s with error code %2$s, output %3$s'), $baseif, $ret, $out[0]));
2177
			return false;
2178
		}
2179
		$newif = trim($out[0]);
2180
		// Rename the interface to {$parentnic}_wlan{$number}#: EX: ath0_wlan0
2181
		pfSense_interface_rename($newif, $realif);
2182
		// FIXME: not sure what ngctl is for. Doesn't work.
2183
		// mwexec("/usr/sbin/ngctl name {$newif}: {$realif}", false);
2184
		file_put_contents("{$g['tmp_path']}/{$realif}_oldmac", get_interface_mac($realif));
2185
	}
2186
	return true;
2187
}
2188

    
2189
function interface_sync_wireless_clones(&$ifcfg, $sync_changes = false) {
2190
	global $config, $g;
2191

    
2192
	$shared_settings = array('standard', 'turbo', 'protmode', 'txpower', 'channel',
2193
	                         'diversity', 'txantenna', 'rxantenna', 'distance',
2194
	                         'regdomain', 'regcountry', 'reglocation');
2195

    
2196
	if(!is_interface_wireless($ifcfg['if']))
2197
		return;
2198

    
2199
	$baseif = interface_get_wireless_base($ifcfg['if']);
2200

    
2201
	// Sync shared settings for assigned clones
2202
	$iflist = get_configured_interface_list(false, true);
2203
	foreach ($iflist as $if) {
2204
		if ($baseif == interface_get_wireless_base($config['interfaces'][$if]['if']) && $ifcfg['if'] != $config['interfaces'][$if]['if']) {
2205
			if (isset($config['interfaces'][$if]['wireless']['standard']) || $sync_changes) {
2206
				foreach ($shared_settings as $setting) {
2207
					if ($sync_changes) {
2208
						if (isset($ifcfg['wireless'][$setting]))
2209
							$config['interfaces'][$if]['wireless'][$setting] = $ifcfg['wireless'][$setting];
2210
						else if (isset($config['interfaces'][$if]['wireless'][$setting]))
2211
							unset($config['interfaces'][$if]['wireless'][$setting]);
2212
					} else {
2213
						if (isset($config['interfaces'][$if]['wireless'][$setting]))
2214
							$ifcfg['wireless'][$setting] = $config['interfaces'][$if]['wireless'][$setting];
2215
						else if (isset($ifcfg['wireless'][$setting]))
2216
							unset($ifcfg['wireless'][$setting]);
2217
					}
2218
				}
2219
				if (!$sync_changes)
2220
					break;
2221
			}
2222
		}
2223
	}
2224

    
2225
	// Read or write settings at shared area
2226
	if (isset($config['wireless']['interfaces'][$baseif]) && is_array($config['wireless']['interfaces'][$baseif])) {
2227
		foreach ($shared_settings as $setting) {
2228
			if ($sync_changes) {
2229
				if (isset($ifcfg['wireless'][$setting]))
2230
					$config['wireless']['interfaces'][$baseif][$setting] = $ifcfg['wireless'][$setting];
2231
				else if (isset($config['wireless']['interfaces'][$baseif][$setting]))
2232
					unset($config['wireless']['interfaces'][$baseif][$setting]);
2233
			} else if (isset($config['wireless']['interfaces'][$baseif][$setting])) {
2234
				if (isset($config['wireless']['interfaces'][$baseif][$setting]))
2235
					$ifcfg['wireless'][$setting] = $config['wireless']['interfaces'][$baseif][$setting];
2236
				else if (isset($ifcfg['wireless'][$setting]))
2237
					unset($ifcfg['wireless'][$setting]);
2238
			}
2239
		}
2240
	}
2241

    
2242
	// Sync the mode on the clone creation page with the configured mode on the interface
2243
	if (interface_is_wireless_clone($ifcfg['if']) && isset($config['wireless']['clone']) && is_array($config['wireless']['clone'])) {
2244
		foreach ($config['wireless']['clone'] as &$clone) {
2245
			if ($clone['cloneif'] == $ifcfg['if']) {
2246
				if ($sync_changes) {
2247
					$clone['mode'] = $ifcfg['wireless']['mode'];
2248
				} else {
2249
					$ifcfg['wireless']['mode'] = $clone['mode'];
2250
				}
2251
				break;
2252
			}
2253
		}
2254
		unset($clone);
2255
	}
2256
}
2257

    
2258
function interface_wireless_configure($if, &$wl, &$wlcfg) {
2259
	global $config, $g;
2260

    
2261
	/*    open up a shell script that will be used to output the commands.
2262
	 *    since wireless is changing a lot, these series of commands are fragile
2263
	 *    and will sometimes need to be verified by a operator by executing the command
2264
	 *    and returning the output of the command to the developers for inspection.  please
2265
	 *    do not change this routine from a shell script to individual exec commands.  -sullrich
2266
	 */
2267

    
2268
	// Remove script file
2269
	unlink_if_exists("{$g['tmp_path']}/{$if}_setup.sh");
2270

    
2271
	// Clone wireless nic if needed.
2272
	interface_wireless_clone($if, $wl);
2273

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

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

    
2281
	/* set values for /path/program */
2282
	$hostapd = "/usr/sbin/hostapd";
2283
	$wpa_supplicant = "/usr/sbin/wpa_supplicant";
2284
	$ifconfig = "/sbin/ifconfig";
2285
	$sysctl = "/sbin/sysctl";
2286
	$killall = "/usr/bin/killall";
2287

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

    
2290
	$wlcmd = array();
2291
	$wl_sysctl = array();
2292
	/* Make sure it's up */
2293
	$wlcmd[] = "up";
2294
	/* Set a/b/g standard */
2295
	$standard = str_replace(" Turbo", "", $wlcfg['standard']);
2296
	$wlcmd[] = "mode " . escapeshellarg($standard);
2297

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

    
2303
	/* Set ssid */
2304
	if($wlcfg['ssid'])
2305
		$wlcmd[] = "ssid " .escapeshellarg($wlcfg['ssid']);
2306

    
2307
	/* Set 802.11g protection mode */
2308
	$wlcmd[] = "protmode " . escapeshellarg($wlcfg['protmode']);
2309

    
2310
	/* set wireless channel value */
2311
	if(isset($wlcfg['channel'])) {
2312
		if($wlcfg['channel'] == "0") {
2313
			$wlcmd[] = "channel any";
2314
		} else {
2315
			$wlcmd[] = "channel " . escapeshellarg($wlcfg['channel']);
2316
		}
2317
	}
2318

    
2319
	/* Set antenna diversity value */
2320
	if(isset($wlcfg['diversity']))
2321
		$wl_sysctl[] = "diversity=" . escapeshellarg($wlcfg['diversity']);
2322

    
2323
	/* Set txantenna value */
2324
	if(isset($wlcfg['txantenna']))
2325
		$wl_sysctl[] = "txantenna=" . escapeshellarg($wlcfg['txantenna']);
2326

    
2327
	/* Set rxantenna value */
2328
	if(isset($wlcfg['rxantenna']))
2329
		$wl_sysctl[] = "rxantenna=" . escapeshellarg($wlcfg['rxantenna']);
2330

    
2331
	/* set Distance value */
2332
	if($wlcfg['distance'])
2333
		$distance = escapeshellarg($wlcfg['distance']);
2334

    
2335
	/* Set wireless hostap mode */
2336
	if ($wlcfg['mode'] == "hostap") {
2337
		$wlcmd[] = "mediaopt hostap";
2338
	} else {
2339
		$wlcmd[] = "-mediaopt hostap";
2340
	}
2341

    
2342
	/* Set wireless adhoc mode */
2343
	if ($wlcfg['mode'] == "adhoc") {
2344
		$wlcmd[] = "mediaopt adhoc";
2345
	} else {
2346
		$wlcmd[] = "-mediaopt adhoc";
2347
	}
2348

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

    
2351
	/* handle hide ssid option */
2352
	if(isset($wlcfg['hidessid']['enable'])) {
2353
		$wlcmd[] = "hidessid";
2354
	} else {
2355
		$wlcmd[] = "-hidessid";
2356
	}
2357

    
2358
	/* handle pureg (802.11g) only option */
2359
	if(isset($wlcfg['pureg']['enable'])) {
2360
		$wlcmd[] = "mode 11g pureg";
2361
	} else {
2362
		$wlcmd[] = "-pureg";
2363
	}
2364

    
2365
	/* handle puren (802.11n) only option */
2366
	if(isset($wlcfg['puren']['enable'])) {
2367
		$wlcmd[] = "puren";
2368
	} else {
2369
		$wlcmd[] = "-puren";
2370
	}
2371

    
2372
	/* enable apbridge option */
2373
	if(isset($wlcfg['apbridge']['enable'])) {
2374
		$wlcmd[] = "apbridge";
2375
	} else {
2376
		$wlcmd[] = "-apbridge";
2377
	}
2378

    
2379
	/* handle turbo option */
2380
	if(isset($wlcfg['turbo']['enable'])) {
2381
		$wlcmd[] = "mediaopt turbo";
2382
	} else {
2383
		$wlcmd[] = "-mediaopt turbo";
2384
	}
2385

    
2386
	/* handle txpower setting */
2387
	/* if($wlcfg['txpower'] <> "")
2388
		$wlcmd[] = "txpower " . escapeshellarg($wlcfg['txpower']);
2389
	*/
2390
	/* handle wme option */
2391
	if(isset($wlcfg['wme']['enable'])) {
2392
		$wlcmd[] = "wme";
2393
	} else {
2394
		$wlcmd[] = "-wme";
2395
	}
2396

    
2397
	/* set up wep if enabled */
2398
	$wepset = "";
2399
	if (isset($wlcfg['wep']['enable']) && is_array($wlcfg['wep']['key'])) {
2400
		switch($wlcfg['wpa']['auth_algs']) {
2401
			case "1":
2402
				$wepset .= "authmode open wepmode on ";
2403
				break;
2404
			case "2":
2405
				$wepset .= "authmode shared wepmode on ";
2406
				break;
2407
			case "3":
2408
				$wepset .= "authmode mixed wepmode on ";
2409
		}
2410
		$i = 1;
2411
		foreach ($wlcfg['wep']['key'] as $wepkey) {
2412
			$wepset .= "wepkey " . escapeshellarg("{$i}:{$wepkey['value']}") . " ";
2413
			if (isset($wepkey['txkey'])) {
2414
				$wlcmd[] = "weptxkey {$i} ";
2415
			}
2416
			$i++;
2417
		}
2418
		$wlcmd[] = $wepset;
2419
	} else {
2420
		$wlcmd[] = "authmode open wepmode off ";
2421
	}
2422

    
2423
	kill_hostapd($if);
2424
	mwexec(kill_wpasupplicant("{$if}"));
2425

    
2426
	/* generate wpa_supplicant/hostap config if wpa is enabled */
2427
	conf_mount_rw();
2428

    
2429
	switch ($wlcfg['mode']) {
2430
		case 'bss':
2431
			if (isset($wlcfg['wpa']['enable'])) {
2432
				$wpa .= <<<EOD
2433
ctrl_interface={$g['varrun_path']}/wpa_supplicant
2434
ctrl_interface_group=0
2435
ap_scan=1
2436
#fast_reauth=1
2437
network={
2438
ssid="{$wlcfg['ssid']}"
2439
scan_ssid=1
2440
priority=5
2441
key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
2442
psk="{$wlcfg['wpa']['passphrase']}"
2443
pairwise={$wlcfg['wpa']['wpa_pairwise']}
2444
group={$wlcfg['wpa']['wpa_pairwise']}
2445
}
2446
EOD;
2447

    
2448
				$fd = fopen("{$g['varetc_path']}/wpa_supplicant_{$if}.conf", "w");
2449
				fwrite($fd, "{$wpa}");
2450
				fclose($fd);
2451
			}
2452
			break;
2453
		case 'hostap':
2454
			if($wlcfg['wpa']['passphrase'])
2455
				$wpa_passphrase = "wpa_passphrase={$wlcfg['wpa']['passphrase']}\n";
2456
			else
2457
				$wpa_passphrase = "";
2458
			if (isset($wlcfg['wpa']['enable'])) {
2459
				$wpa .= <<<EOD
2460
interface={$if}
2461
driver=bsd
2462
logger_syslog=-1
2463
logger_syslog_level=0
2464
logger_stdout=-1
2465
logger_stdout_level=0
2466
dump_file={$g['tmp_path']}/hostapd_{$if}.dump
2467
ctrl_interface={$g['varrun_path']}/hostapd
2468
ctrl_interface_group=wheel
2469
#accept_mac_file={$g['tmp_path']}/hostapd_{$if}.accept
2470
#deny_mac_file={$g['tmp_path']}/hostapd_{$if}.deny
2471
#macaddr_acl={$wlcfg['wpa']['macaddr_acl']}
2472
ssid={$wlcfg['ssid']}
2473
debug={$wlcfg['wpa']['debug_mode']}
2474
auth_algs={$wlcfg['wpa']['auth_algs']}
2475
wpa={$wlcfg['wpa']['wpa_mode']}
2476
wpa_key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
2477
wpa_pairwise={$wlcfg['wpa']['wpa_pairwise']}
2478
wpa_group_rekey={$wlcfg['wpa']['wpa_group_rekey']}
2479
wpa_gmk_rekey={$wlcfg['wpa']['wpa_gmk_rekey']}
2480
wpa_strict_rekey={$wlcfg['wpa']['wpa_strict_rekey']}
2481
{$wpa_passphrase}
2482

    
2483
EOD;
2484

    
2485
if (isset($wlcfg['wpa']['rsn_preauth'])) {
2486
	$wpa .= <<<EOD
2487
# Enable the next lines for preauth when roaming. Interface = wired or wireless interface talking to the AP you want to roam from/to
2488
rsn_preauth=1
2489
rsn_preauth_interfaces={$if}
2490

    
2491
EOD;
2492

    
2493
}
2494
				if($wlcfg['auth_server_addr'] && $wlcfg['auth_server_shared_secret']) {
2495
					$auth_server_port = "1812";
2496
					if($wlcfg['auth_server_port'])
2497
						$auth_server_port = $wlcfg['auth_server_port'];
2498
					$auth_server_port2 = "1812";
2499
					if($wlcfg['auth_server_port2'])
2500
						$auth_server_port2 = $wlcfg['auth_server_port2'];
2501
					$wpa .= <<<EOD
2502

    
2503
ieee8021x=1
2504
auth_server_addr={$wlcfg['auth_server_addr']}
2505
auth_server_port={$auth_server_port}
2506
auth_server_shared_secret={$wlcfg['auth_server_shared_secret']}
2507
auth_server_addr={$wlcfg['auth_server_addr2']}
2508
auth_server_port={$auth_server_port2}
2509
auth_server_shared_secret={$wlcfg['auth_server_shared_secret2']}
2510

    
2511
EOD;
2512
				} else {
2513
					$wpa .= "ieee8021x={$wlcfg['wpa']['ieee8021x']}\n";
2514
				}
2515

    
2516
				$fd = fopen("{$g['varetc_path']}/hostapd_{$if}.conf", "w");
2517
				fwrite($fd, "{$wpa}");
2518
				fclose($fd);
2519

    
2520
			}
2521
			break;
2522
	}
2523

    
2524
	/*
2525
	 *    all variables are set, lets start up everything
2526
	 */
2527

    
2528
	$baseif = interface_get_wireless_base($if);
2529
	preg_match("/^(.*?)([0-9]*)$/", $baseif, $baseif_split);
2530
	$wl_sysctl_prefix = 'dev.' . $baseif_split[1] . '.' . $baseif_split[2];
2531

    
2532
	/* set sysctls for the wireless interface */
2533
	if (!empty($wl_sysctl)) {
2534
		fwrite($fd_set, "# sysctls for {$baseif}\n");
2535
		foreach ($wl_sysctl as $wl_sysctl_line) {
2536
			fwrite($fd_set, "{$sysctl} {$wl_sysctl_prefix}.{$wl_sysctl_line}\n");
2537
		}
2538
	}
2539

    
2540
	/* set ack timers according to users preference (if he/she has any) */
2541
	if($distance) {
2542
		fwrite($fd_set, "# Enable ATH distance settings\n");
2543
		fwrite($fd_set, "/sbin/athctrl.sh -i {$baseif} -d {$distance}\n");
2544
	}
2545

    
2546
	if (isset($wlcfg['wpa']['enable'])) {
2547
		if ($wlcfg['mode'] == "bss") {
2548
			fwrite($fd_set, "{$wpa_supplicant} -B -i {$if} -c {$g['varetc_path']}/wpa_supplicant_{$if}.conf\n");
2549
		}
2550
		if ($wlcfg['mode'] == "hostap") {
2551
			/* add line to script to restore old mac to make hostapd happy */
2552
			if (file_exists("{$g['tmp_path']}/{$if}_oldmac")) {
2553
				$if_oldmac = file_get_contents("{$g['tmp_path']}/{$if}_oldmac");
2554
				if (is_macaddr($if_oldmac))
2555
					fwrite($fd_set, "{$ifconfig} " . escapeshellarg($if) .
2556
						" link " . escapeshellarg($if_oldmac) . "\n");
2557
			}
2558

    
2559
			fwrite($fd_set, "{$hostapd} -B -P {$g['varrun_path']}/hostapd_{$if}.pid {$g['varetc_path']}/hostapd_{$if}.conf\n");
2560

    
2561
			/* add line to script to restore spoofed mac after running hostapd */
2562
			if (file_exists("{$g['tmp_path']}/{$if}_oldmac")) {
2563
				if ($wl['spoofmac'])
2564
					$if_curmac = $wl['spoofmac'];
2565
				else
2566
					$if_curmac = get_interface_mac($if);
2567
				if (is_macaddr($if_curmac))
2568
					fwrite($fd_set, "{$ifconfig} " . escapeshellarg($if) .
2569
						" link " . escapeshellarg($if_curmac) . "\n");
2570
			}
2571
		}
2572
	}
2573

    
2574
	fclose($fd_set);
2575
	conf_mount_ro();
2576

    
2577
	/* Making sure regulatory settings have actually changed
2578
	 * before applying, because changing them requires bringing
2579
	 * down all wireless networks on the interface. */
2580
	exec("{$ifconfig} " . escapeshellarg($if), $output);
2581
	$ifconfig_str = implode($output);
2582
	unset($output);
2583
	$reg_changing = false;
2584

    
2585
	/* special case for the debug country code */
2586
	if ($wlcfg['regcountry'] == 'DEBUG' && !preg_match("/\sregdomain\s+DEBUG\s/si", $ifconfig_str))
2587
		$reg_changing = true;
2588
	else if ($wlcfg['regdomain'] && !preg_match("/\sregdomain\s+{$wlcfg['regdomain']}\s/si", $ifconfig_str))
2589
		$reg_changing = true;
2590
	else if ($wlcfg['regcountry'] && !preg_match("/\scountry\s+{$wlcfg['regcountry']}\s/si", $ifconfig_str))
2591
		$reg_changing = true;
2592
	else if ($wlcfg['reglocation'] == 'anywhere' && preg_match("/\s(indoor|outdoor)\s/si", $ifconfig_str))
2593
		$reg_changing = true;
2594
	else if ($wlcfg['reglocation'] && $wlcfg['reglocation'] != 'anywhere' && !preg_match("/\s{$wlcfg['reglocation']}\s/si", $ifconfig_str))
2595
		$reg_changing = true;
2596

    
2597
	if ($reg_changing) {
2598
		/* set regulatory domain */
2599
		if($wlcfg['regdomain'])
2600
			$wlregcmd[] = "regdomain " . escapeshellarg($wlcfg['regdomain']);
2601

    
2602
		/* set country */
2603
		if($wlcfg['regcountry'])
2604
			$wlregcmd[] = "country " . escapeshellarg($wlcfg['regcountry']);
2605

    
2606
		/* set location */
2607
		if($wlcfg['reglocation'])
2608
			$wlregcmd[] = escapeshellarg($wlcfg['reglocation']);
2609

    
2610
		$wlregcmd_args = implode(" ", $wlregcmd);
2611

    
2612
		/* build a complete list of the wireless clones for this interface */
2613
		$clone_list = array();
2614
		if (does_interface_exist(interface_get_wireless_clone($baseif)))
2615
			$clone_list[] = interface_get_wireless_clone($baseif);
2616
		if (isset($config['wireless']['clone']) && is_array($config['wireless']['clone'])) {
2617
			foreach ($config['wireless']['clone'] as $clone) {
2618
				if ($clone['if'] == $baseif)
2619
					$clone_list[] = $clone['cloneif'];
2620
			}
2621
		}
2622

    
2623
		/* find which clones are up and bring them down */
2624
		$clones_up = array();
2625
		foreach ($clone_list as $clone_if) {
2626
			$clone_status = pfSense_get_interface_addresses($clone_if);
2627
			if ($clone_status['status'] == 'up') {
2628
				$clones_up[] = $clone_if;
2629
				mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " down");
2630
			}
2631
		}
2632

    
2633
		/* apply the regulatory settings */
2634
		mwexec("{$ifconfig} " . escapeshellarg($if) . " {$wlregcmd_args}");
2635

    
2636
		/* bring the clones back up that were previously up */
2637
		foreach ($clones_up as $clone_if) {
2638
			mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " up");
2639

    
2640
			/*
2641
			 * Rerun the setup script for the interface if it isn't this interface, the interface
2642
			 * is in infrastructure mode, and WPA is enabled.
2643
			 * This can be removed if wpa_supplicant stops dying when you bring the interface down.
2644
			 */
2645
			if ($clone_if != $if) {
2646
				$friendly_if = convert_real_interface_to_friendly_interface_name($clone_if);
2647
				if ( !empty($friendly_if)
2648
				    && $config['interfaces'][$friendly_if]['wireless']['mode'] == "bss"
2649
				    && isset($config['interfaces'][$friendly_if]['wireless']['wpa']['enable']) ) {
2650
					mwexec("/bin/sh {$g['tmp_path']}/{$clone_if}_setup.sh");
2651
				}
2652
			}
2653
		}
2654
	}
2655

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

    
2660
	/* configure wireless */
2661
	$wlcmd_args = implode(" ", $wlcmd);
2662
	mwexec("/sbin/ifconfig {$if} $wlcmd_args", false);
2663

    
2664

    
2665
	sleep(1);
2666
	/* execute hostapd and wpa_supplicant if required in shell */
2667
	mwexec("/bin/sh {$g['tmp_path']}/{$if}_setup.sh");
2668

    
2669
	return 0;
2670

    
2671
}
2672

    
2673
function kill_hostapd($interface) {
2674
	global $g;
2675

    
2676
	if (isvalidpid("{$g['varrun_path']}/hostapd_{$interface}.pid"))
2677
		return killbypid("{$g['varrun_path']}/hostapd_{$interface}.pid");
2678
}
2679

    
2680
function kill_wpasupplicant($interface) {
2681
	return "/bin/pkill -f \"wpa_supplicant .*{$interface}\\.conf\"\n";
2682
}
2683

    
2684
function find_dhclient_process($interface) {
2685
	if ($interface)
2686
		$pid = `/bin/pgrep -axf "dhclient: {$interface}"`;
2687
	else
2688
		$pid = 0;
2689

    
2690
	return intval($pid);
2691
}
2692

    
2693
function find_dhcp6c_process($interface) {
2694
	global $g;
2695

    
2696
	if ($interface)
2697
		if (isvalidpid("{$g['varrun_path']}/dhcp6c_{$interface}.pid"))
2698
			$pid = trim(file_get_contents("{$g['varrun_path']}/dhcp6c_{$interface}.pid"), " \n");
2699
	else
2700
		return(false);
2701

    
2702
	return intval($pid);
2703
}
2704

    
2705
function interface_configure($interface = "wan", $reloadall = false, $linkupevent = false) {
2706
	global $config, $g;
2707
	global $interface_sn_arr_cache, $interface_ip_arr_cache;
2708
	global $interface_snv6_arr_cache, $interface_ipv6_arr_cache;
2709

    
2710
	$wancfg = $config['interfaces'][$interface];
2711

    
2712
	if (!isset($wancfg['enable']))
2713
		return;
2714

    
2715
	$realif = get_real_interface($interface);
2716
	$realhwif_array = get_parent_interface($interface);
2717
	// Need code to handle MLPPP if we ever use $realhwif for MLPPP handling
2718
	$realhwif = $realhwif_array[0];
2719

    
2720
	/* Disable Accepting router advertisements unless specifically requested */
2721
	if ($g['debug'])
2722
		log_error("Deny router advertisements for interface {$interface}");
2723
	mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 -accept_rtadv");
2724

    
2725
	if (!$g['booting'] && !(substr($realif, 0, 4) == "ovpn")) {
2726
		/* remove all IPv4 and IPv6 addresses */
2727
		while (mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " -alias", true) == 0);
2728
		while (mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 -alias", true) == 0);
2729

    
2730
		/* only bring down the interface when both v4 and v6 are set to NONE */
2731
		if(empty($wancfg['ipaddr']) && empty($wancfg['ipaddrv6'])) {
2732
			interface_bring_down($interface);
2733
		}
2734
	}
2735

    
2736
	/* wireless configuration? */
2737
	if (is_array($wancfg['wireless']))
2738
		interface_wireless_configure($realif, $wancfg, $wancfg['wireless']);
2739

    
2740
	$mac = get_interface_mac($realhwif);
2741
	/*
2742
	 * Don't try to reapply the spoofed MAC if it's already applied.
2743
	 * When ifconfig link is used, it cycles the interface down/up, which triggers
2744
	 * the interface config again, which attempts to spoof the MAC again,
2745
	 * which cycles the link again...
2746
	 */
2747
	if ($wancfg['spoofmac'] && ($wancfg['spoofmac'] != $mac)) {
2748
		mwexec("/sbin/ifconfig " . escapeshellarg($realhwif) .
2749
			" link " . escapeshellarg($wancfg['spoofmac']));
2750

    
2751
		/*
2752
		 * All vlans need to spoof their parent mac address, too.  see
2753
		 * ticket #1514: http://cvstrac.pfsense.com/tktview?tn=1514,33
2754
		 */
2755
		if (is_array($config['vlans']['vlan'])) {
2756
			foreach ($config['vlans']['vlan'] as $vlan) {
2757
				if ($vlan['if'] == $realhwif)
2758
					mwexec("/sbin/ifconfig " . escapeshellarg($vlan['vlanif']) .
2759
					" link " . escapeshellarg($wancfg['spoofmac']));
2760
			}
2761
		}
2762
	}  else {
2763

    
2764
		if ($mac == "ff:ff:ff:ff:ff:ff") {
2765
			/*   this is not a valid mac address.  generate a
2766
			 *   temporary mac address so the machine can get online.
2767
			 */
2768
			echo gettext("Generating new MAC address.");
2769
			$random_mac = generate_random_mac_address();
2770
			mwexec("/sbin/ifconfig " . escapeshellarg($realhwif) .
2771
				" link " . escapeshellarg($random_mac));
2772
			$wancfg['spoofmac'] = $random_mac;
2773
			write_config();
2774
			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");
2775
		}
2776
	}
2777

    
2778
	/* media */
2779
	if ($wancfg['media'] || $wancfg['mediaopt']) {
2780
		$cmd = "/sbin/ifconfig " . escapeshellarg($realhwif);
2781
		if ($wancfg['media'])
2782
			$cmd .= " media " . escapeshellarg($wancfg['media']);
2783
		if ($wancfg['mediaopt'])
2784
			$cmd .= " mediaopt " . escapeshellarg($wancfg['mediaopt']);
2785
		mwexec($cmd);
2786
	}
2787
	if (!empty($wancfg['mtu']))
2788
		pfSense_interface_mtu($realhwif, $wancfg['mtu']);
2789
	else {
2790
		$mtu = get_interface_default_mtu(remove_numbers($realhwif));
2791
		if ($mtu != get_interface_mtu($realhwif))
2792
			pfSense_interface_mtu($realhwif, $mtu);
2793
	}
2794

    
2795
	$options = pfSense_get_interface_addresses($realhwif);
2796
	if (is_array($options) && isset($options['caps']['polling'])) {
2797
		if (isset($config['system']['polling']))
2798
			pfSense_interface_capabilities($realif, IFCAP_POLLING);
2799
		else
2800
			pfSense_interface_capabilities($realif, -IFCAP_POLLING);
2801
	}
2802

    
2803
	/* skip vlans for checksumming and polling */
2804
	if (!stristr($realhwif, "vlan") && is_array($options)) {
2805
		$flags = 0;
2806
		if(isset($config['system']['disablechecksumoffloading'])) {
2807
			if (isset($options['encaps']['txcsum']))
2808
				$flags |= IFCAP_TXCSUM;
2809
			if (isset($options['encaps']['rxcsum']))
2810
				$flags |= IFCAP_RXCSUM;
2811
		} else {
2812
			if (!isset($options['caps']['txcsum']))
2813
				$flags |= IFCAP_TXCSUM;
2814
			if (!isset($options['caps']['rxcsum']))
2815
				$flags |= IFCAP_RXCSUM;
2816
		}
2817

    
2818
		if(isset($config['system']['disablesegmentationoffloading'])) {
2819
			if (isset($options['encaps']['tso4']))
2820
				$flags |= IFCAP_TSO;
2821
			if (isset($options['encaps']['tso6']))
2822
				$flags |= IFCAP_TSO;
2823
		} else {
2824
			if (!isset($options['caps']['tso4']))
2825
				$flags |= IFCAP_TSO;
2826
			if (!isset($options['caps']['tso6']))
2827
				$flags |= IFCAP_TSO;
2828
		}
2829

    
2830
		if(isset($config['system']['disablelargereceiveoffloading'])) {
2831
			if (isset($options['encaps']['lro']))
2832
				$flags |= IFCAP_LRO;
2833
		} else {
2834
			if (!isset($options['caps']['lro']))
2835
				$flags |= IFCAP_LRO;
2836
		}
2837

    
2838
		/* if the NIC supports polling *AND* it is enabled in the GUI */
2839
		if (!isset($config['system']['polling']) || !isset($options['caps']['polling'])) {
2840
			$flags |= IFCAP_POLLING;
2841
		}
2842
		pfSense_interface_capabilities($realhwif, -$flags);
2843
	}
2844

    
2845
	/* invalidate interface/ip/sn cache */
2846
	get_interface_arr(true);
2847
	unset($interface_ip_arr_cache[$realif]);
2848
	unset($interface_sn_arr_cache[$realif]);
2849
	unset($interface_ipv6_arr_cache[$realif]);
2850
	unset($interface_snv6_arr_cache[$realif]);
2851

    
2852
	switch ($wancfg['ipaddr']) {
2853
		case 'dhcp':
2854
			interface_dhcp_configure($interface);
2855
			break;
2856
		case 'pppoe':
2857
		case 'l2tp':
2858
		case 'pptp':
2859
		case 'ppp':
2860
			interface_ppps_configure($interface);
2861
			break;
2862
		default:
2863
			if (is_ipaddr($wancfg['ipaddr']) && $wancfg['subnet'] <> "") {
2864
				pfSense_interface_setaddress($realif, "{$wancfg['ipaddr']}/{$wancfg['subnet']}");
2865
			} else if (substr($realif, 0, 3) == "gre") {
2866
				if (is_array($config['gres']['gre'])) {
2867
					foreach ($config['gres']['gre'] as $gre)
2868
						if ($gre['greif'] == $realif)
2869
							interface_gre_configure($gre);
2870
				}
2871
			} else if (substr($realif, 0, 3) == "gif") {
2872
				if (is_array($config['gifs']['gif'])) {
2873
					foreach ($config['gifs']['gif'] as $gif)
2874
						if($gif['gifif'] == $realif)
2875
							interface_gif_configure($gif);
2876
				}
2877
			} else if (substr($realif, 0, 4) == "ovpn") {
2878
				/* XXX: Should be done anything?! */
2879
			}
2880
			break;
2881
	}
2882

    
2883
	switch ($wancfg['ipaddrv6']) {
2884
		case 'slaac':
2885
		case 'dhcp6':
2886
			interface_dhcpv6_configure($interface, $wancfg);
2887
			break;
2888
		case '6rd':
2889
			interface_6rd_configure($interface, $wancfg);
2890
			break;
2891
		case '6to4':
2892
			interface_6to4_configure($interface, $wancfg);
2893
			break;
2894
		case 'track6':
2895
			interface_track6_configure($interface, $wancfg);
2896
			break;
2897
		default:
2898
			if (is_ipaddr($wancfg['ipaddrv6']) && $wancfg['subnetv6'] <> "") {
2899
				pfSense_interface_setaddress($realif, "{$wancfg['ipaddrv6']}/{$wancfg['subnetv6']}");
2900
				// FIXME: Add IPv6 Support to the pfSense module
2901
				mwexec("/sbin/ifconfig {$realif} inet6 {$wancfg['ipaddrv6']} prefixlen {$wancfg['subnetv6']} ");
2902
			}
2903
			break;
2904
	}
2905

    
2906
	if(does_interface_exist($wancfg['if']))
2907
		interfaces_bring_up($wancfg['if']);
2908

    
2909
	interface_netgraph_needed($interface);
2910

    
2911
	if (!$g['booting']) {
2912
		link_interface_to_vips($interface, "update");
2913

    
2914
		unset($gre);
2915
		$gre = link_interface_to_gre($interface);
2916
		if (!empty($gre))
2917
			array_walk($gre, 'interface_gre_configure');
2918

    
2919
		unset($gif);
2920
		$gif = link_interface_to_gif($interface);
2921
		if (!empty($gif))
2922
			array_walk($gif, 'interface_gif_configure');
2923

    
2924
		if ($linkupevent == false || substr($realif, 0, 4) == "ovpn") {
2925
			unset($bridgetmp);
2926
			$bridgetmp = link_interface_to_bridge($interface);
2927
			if (!empty($bridgetmp))
2928
				interface_bridge_add_member($bridgetmp, $realif);
2929
		}
2930

    
2931
		$grouptmp = link_interface_to_group($interface);
2932
		if (!empty($grouptmp))
2933
			array_walk($grouptmp, 'interface_group_add_member');
2934

    
2935
		if ($interface == "lan")
2936
			/* make new hosts file */
2937
			system_hosts_generate();
2938

    
2939
		if ($reloadall == true) {
2940

    
2941
			/* reconfigure static routes (kernel may have deleted them) */
2942
			system_routing_configure($interface);
2943

    
2944
			/* reload ipsec tunnels */
2945
			vpn_ipsec_configure();
2946

    
2947
			/* restart dnsmasq */
2948
			services_dnsmasq_configure();
2949

    
2950
			/* update dyndns */
2951
			send_event("service reload dyndns {$interface}");
2952

    
2953
			/* reload captive portal */
2954
			captiveportal_init_rules();
2955
		}
2956
	}
2957

    
2958
	return 0;
2959
}
2960

    
2961
function interface_track6_configure($interface = "lan", $wancfg) {
2962
	global $config, $g;
2963

    
2964
	if (!is_array($wancfg))
2965
		return;
2966

    
2967
	if (!isset($wancfg['enable']))
2968
		return;
2969

    
2970
	/* If the interface is not configured via another, exit */
2971
	if (empty($wancfg['track6-interface']))
2972
		return;
2973

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

    
2978
	$trackcfg = $config['interfaces'][$wancfg['track6-interface']];
2979
	if (!isset($trackcfg['enable'])) {
2980
		log_error("Interface {$interface} tracking non-existant interface {$wancfg['track6-interface']}");
2981
		return;
2982
	}
2983

    
2984
	switch($trackcfg['ipaddrv6']) {
2985
		case "6to4":
2986
			if ($g['debug'])
2987
				log_error("Interface {$interface} configured via {$wancfg['track6-interface']}  type {$type}");
2988
			interface_track6_6to4_configure($interface, $wancfg);
2989
			break;
2990
		case "6rd":
2991
			if ($g['debug'])
2992
				log_error("Interface {$interface} configured via {$wancfg['track6-interface']}  type {$type}");
2993
			interface_track6_6rd_configure($interface, $wancfg);
2994
			break;
2995
		case "dhcp6":
2996
			if ($g['debug'])
2997
				log_error("Interface {$interface} configured via {$wancfg['track6-interface']}  type {$type}");
2998
			interface_track6_dhcp6_configure($interface, $wancfg);
2999
			break;
3000
	}
3001

    
3002
	return 0;
3003
}
3004

    
3005

    
3006
function interface_track6_6rd_configure($interface = "lan", $lancfg) {
3007
	global $config, $g;
3008

    
3009
	if (!is_array($lancfg))
3010
		return;
3011

    
3012
	/* If the interface is not configured via another, exit */
3013
	if (empty($lancfg['track6-interface']))
3014
		return;
3015

    
3016
	if (!is_numeric($lancfg['track6-prefix-id']))
3017
		$lancfg['track6-prefix-id'] = 0;
3018

    
3019
	$wancfg = $config['interfaces'][$lancfg['track6-interface']];
3020
	if (empty($wancfg)) {
3021
		log_error("Interface {$interface} tracking non-existant interface {$lancfg['track6-interface']}");
3022
		return;
3023
	}
3024

    
3025
	$wanif = get_real_interface($lancfg['track6-interface']);
3026
	$ip4address = find_interface_ip($wanif);
3027
	if (!is_ipaddrv4($ip4address)) { /* XXX: This should not be needed by 6rd || (is_private_ip($ip4address))) { */
3028
		log_error("The interface IPv4 '{$ip4address}' address on interface '{$wanif}' is not public, not configuring 6RD tunnel");
3029
		return;
3030
	}
3031
	$hexwanv4 = return_hex_ipv4($ip4address);
3032

    
3033
	/* create the long prefix notation for math, save the prefix length */
3034
	$rd6prefix = explode("/", $wancfg['prefix-6rd']);
3035
	$rd6prefixlen = $rd6prefix[1];
3036
	$rd6prefix = Net_IPv6::uncompress($rd6prefix[0]);
3037

    
3038
	/* binary presentation of the prefix for all 128 bits. */
3039
	$rd6lanbin = convert_ipv6_to_128bit($rd6prefix);
3040

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

    
3046
	/* add the custom prefix id, max 32bits long? (64 bits - (prefixlen + (32 - v4plen)) */
3047
	/* 64 - (37 + (32 - 17)) = 8 == /52 */
3048
	$restbits = 64 - ($rd6prefixlen + (32 - $wancfg['prefix-6rd-v4plen']));
3049
	// echo "64 - (prefixlen {$rd6prefixlen} + v4len (32 - {$wancfg['prefix-6rd-v4plen']})) = {$restbits} \n";
3050
	$rd6lanbin .= substr(sprintf("%032b", str_pad($lancfg['track6-prefix-id'], 32, "0", STR_PAD_LEFT)), (32 - $restbits), 32);
3051
	/* fill the rest out with zeros */
3052
	$rd6lanbin = str_pad($rd6lanbin, 128, "0", STR_PAD_RIGHT);;
3053

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

    
3057
	$lanif = get_real_interface($interface);
3058
	$oip = find_interface_ipv6($lanif);
3059
	if (is_ipaddrv6($oip))
3060
		mwexec("/sbin/ifconfig {$lanif} inet6 {$oip} delete");
3061
	log_error("rd6 {$interface} with ipv6 address {$rd6lan} based on {$lancfg['track6-interface']} ipv4 {$ip4address}");
3062
	mwexec("/sbin/ifconfig {$lanif} inet6 {$rd6lan} prefixlen 64");
3063

    
3064
	return 0;
3065
}
3066

    
3067
function interface_track6_6to4_configure($interface = "lan", $lancfg) {
3068
	global $config, $g;
3069

    
3070
	if (!is_array($lancfg))
3071
		return;
3072

    
3073
	/* If the interface is not configured via another, exit */
3074
	if (empty($lancfg['track6-interface']))
3075
		return;
3076

    
3077
	$wancfg = $config['interfaces'][$lancfg['track6-interface']];
3078
	if (empty($wancfg)) {
3079
		log_error("Interface {$interface} tracking non-existant interface {$lancfg['track6-interface']}");
3080
		return;
3081
	}
3082

    
3083
	if (!is_numeric($lancfg['track6-prefix-id']))
3084
		$lancfg['track6-prefix-id'] = 0;
3085

    
3086
	$wanif = get_real_interface($lancfg['track6-interface']);
3087
	$ip4address = find_interface_ip($wanif);
3088
	if (!is_ipaddrv4($ip4address) || is_private_ip($ip4address)) {
3089
		log_error("The interface IPv4 '{$ip4address}' address on interface '{$wanif}' is not public, not configuring 6RD tunnel");
3090
		return;
3091
	}
3092
	$hexwanv4 = return_hex_ipv4($ip4address);
3093

    
3094
	/* create the long prefix notation for math, save the prefix length */
3095
	$sixto4prefix = "2002::";
3096
	$sixto4prefixlen = 16;
3097
	$sixto4prefix = Net_IPv6::uncompress($sixto4prefix);
3098

    
3099
	/* binary presentation of the prefix for all 128 bits. */
3100
	$sixto4lanbin = convert_ipv6_to_128bit($sixto4prefix);
3101

    
3102
	/* just save the left prefix length bits */
3103
	$sixto4lanbin = substr($sixto4lanbin, 0, $sixto4prefixlen);
3104
	/* add the v4 address */
3105
	$sixto4lanbin .= sprintf("%032b", hexdec($hexwanv4));
3106
	/* add the custom prefix id */
3107
	$sixto4lanbin .= sprintf("%016b", $lancfg['track6-prefix-id']);
3108
	/* fill the rest out with zeros */
3109
	$sixto4lanbin = str_pad($sixto4lanbin, 128, "0", STR_PAD_RIGHT);;
3110

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

    
3114
	$lanif = get_real_interface($interface);
3115
	$oip = find_interface_ipv6($lanif);
3116
	if (is_ipaddrv6($oip))
3117
		mwexec("/sbin/ifconfig {$lanif} inet6 {$oip} delete");
3118
	log_error("sixto4 {$interface} with ipv6 address {$sixto4lan} based on {$lancfg['track6-interface']} ipv4 {$ip4address}");
3119
	mwexec("/sbin/ifconfig {$lanif} inet6 {$sixto4lan} prefixlen 64");
3120

    
3121
	return 0;
3122
}
3123

    
3124
function interface_track6_dhcp6_configure($interface = "lan", $lancfg) {
3125
	global $config, $g;
3126

    
3127
	if (!is_array($lancfg))
3128
		return;
3129

    
3130
	/* If the interface is not configured via another, exit */
3131
	if (empty($lancfg['track6-interface']))
3132
		return;
3133

    
3134
	if (!is_numeric($lancfg['track6-prefix-id']))
3135
		$lancfg['track6-prefix-id'] = 0;
3136

    
3137
	$wancfg = $config['interfaces'][$lancfg['track6-interface']];
3138
	if (empty($wancfg)) {
3139
		log_error("Interface {$interface} tracking non-existant interface {$lancfg['track6-interface']}");
3140
		return;
3141
	}
3142

    
3143
	$wanif = get_real_interface($lancfg['track6-interface']);
3144
	$ifcfgipv6 = find_interface_ipv6($wanif);
3145
	if (is_ipaddrv6($ifcfgipv6)) {
3146
		$dhcp6lanarr = explode(":", Net_IPv6::uncompress($ifcfgipv6));
3147
		$dhcp6lanarr[4] = 0;
3148
		$dhcp6lanarr[5] = 0;
3149
		$dhcp6lanarr[6] = 0;
3150
		$dhcp6lanarr[7] = 1;
3151
		$dhcp6lan =  Net_IPv6::compress(implode(":", $dhcp6lanarr));
3152
		$lanif = get_real_interface($interface);
3153
		$oip = find_interface_ipv6($lanif);
3154
		if (is_ipaddrv6($oip))
3155
			mwexec("/sbin/ifconfig {$lanif} inet6 {$oip} delete");
3156
		log_error("dhcp6 {$interface} with ipv6 address {$dhcp6lan} based on {$lancfg['track6-interface']}");
3157
		mwexec("/sbin/ifconfig {$lanif} inet6 {$dhcp6lan} prefixlen 64");
3158
	}
3159

    
3160
	return 0;
3161
}
3162

    
3163
function interface_6rd_configure($interface = "wan", $wancfg) {
3164
	global $config, $g;
3165

    
3166
	/* because this is a tunnel interface we can only function
3167
	 *	with a public IPv4 address on the interface */
3168

    
3169
	if (!is_array($wancfg))
3170
		return;
3171

    
3172
	$wanif = get_real_interface($interface);
3173
	$ip4address = find_interface_ip($wanif);
3174
	if ((!is_ipaddrv4($ip4address)) || (is_private_ip($ip4address))) {
3175
		log_error("The interface IPv4 '{$ip4address}' address on interface '{$wanif}' is not public, not configuring 6RD tunnel");
3176
		return false;
3177
	}
3178
	$hexwanv4 = return_hex_ipv4($ip4address);
3179

    
3180
	if (!is_numeric($wancfg['prefix-6rd-v4plen']))
3181
		$wancfg['prefix-6rd-v4plen'] = 0;
3182

    
3183
	/* create the long prefix notation for math, save the prefix length */
3184
	$rd6prefix = explode("/", $wancfg['prefix-6rd']);
3185
	$rd6prefixlen = $rd6prefix[1];
3186
	$rd6prefix = Net_IPv6::uncompress($rd6prefix[0]);
3187

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

    
3191
	/* binary presentation of the prefix for all 128 bits. */
3192
	$rd6prefixbin = convert_ipv6_to_128bit($rd6prefix);
3193

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

    
3201
	/* convert the 128 bits for the broker address back into a valid IPv6 address */
3202
	$rd6brgw = convert_128bit_to_ipv6($rd6brprefixbin);
3203

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

    
3211
	/* convert the 128 bits for the broker address back into a valid IPv6 address */
3212
	$rd6prefix = convert_128bit_to_ipv6($rd6prefixbin);
3213

    
3214
	/* XXX: need to extend to support variable prefix size for v4 */
3215
	if (!is_module_loaded("if_stf"))
3216
		mwexec("/sbin/kldload if_stf.ko");
3217
	$stfiface = "{$interface}_stf";
3218
	if (does_interface_exist($stfiface))
3219
		pfSense_interface_destroy($stfiface);
3220
	$tmpstfiface = pfSense_interface_create("stf");
3221
	pfSense_interface_rename($tmpstfiface, $stfiface);
3222
	pfSense_interface_flags($stfiface, IFF_LINK2);
3223
	mwexec("/sbin/ifconfig {$stfiface} inet6 {$rd6prefix}/{$rd6prefixlen}");
3224
	if ($g['debug'])
3225
		log_error("Created 6rd interface {$stfiface} {$rd6prefix}/{$rd6prefixlen}");
3226

    
3227
	/* write out a default router file */
3228
	file_put_contents("{$g['tmp_path']}/{$wanif}_routerv6", "{$rd6brgw}\n");
3229
	file_put_contents("{$g['tmp_path']}/{$wanif}_defaultgwv6", "{$rd6brgw}\n");
3230

    
3231
	$ip4gateway = get_interface_gateway($interface);
3232
	if (is_ipaddrv4($ip4gateway))
3233
		mwexec("/sbin/route change -host " . $wancfg['gateway-6rd'] . " {$ip4gateway}");
3234

    
3235
	/* configure dependent interfaces */
3236
	if (!$g['booting'])
3237
		link_interface_to_track6($interface, "update");
3238

    
3239
	return 0;
3240
}
3241

    
3242
function interface_6to4_configure($interface = "wan", $wancfg){
3243
	global $config, $g;
3244

    
3245
	/* because this is a tunnel interface we can only function
3246
	 *	with a public IPv4 address on the interface */
3247

    
3248
	if (!is_array($wancfg))
3249
		return;
3250

    
3251
	$wanif = get_real_interface($interface);
3252
	$ip4address = find_interface_ip($wanif);
3253
	if((!is_ipaddrv4($ip4address)) || (is_private_ip($ip4address))) {
3254
		log_error("The interface IPv4 '{$ip4address}' address on interface '{$wanif}' is not public, not configuring 6RD tunnel");
3255
		return false;
3256
	}
3257

    
3258
	/* create the long prefix notation for math, save the prefix length */
3259
	$stfprefixlen = 16;
3260
	$stfprefix = Net_IPv6::uncompress("2002::");
3261
	$stfarr = explode(":", $stfprefix);
3262
	$v4prefixlen = "0";
3263

    
3264
	/* we need the hex form of the interface IPv4 address */
3265
	$ip4arr = explode(".", $ip4address);
3266
	$hexwanv4 = "";
3267
	foreach($ip4arr as $octet)
3268
		$hexwanv4 .= sprintf("%02x", $octet);
3269

    
3270
	/* we need the hex form of the broker IPv4 address */
3271
	$ip4arr = explode(".", "192.88.99.1");
3272
	$hexbrv4 = "";
3273
	foreach($ip4arr as $octet)
3274
		$hexbrv4 .= sprintf("%02x", $octet);
3275

    
3276
	/* binary presentation of the prefix for all 128 bits. */
3277
	$stfprefixbin = "";
3278
	foreach($stfarr as $element) {
3279
		$stfprefixbin .= sprintf("%016b", hexdec($element));
3280
	}
3281
	/* just save the left prefix length bits */
3282
	$stfprefixstartbin = substr($stfprefixbin, 0, $stfprefixlen);
3283

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

    
3288
	/* for the local subnet too. */
3289
	$stflanbin = substr(sprintf("%032b", hexdec($hexwanv4)), $v4prefixlen, 32);
3290
	$stflanbin = str_pad($stfprefixstartbin . $stflanbin, 128, "0", STR_PAD_RIGHT);;
3291

    
3292
	/* convert the 128 bits for the broker address back into a valid IPv6 address */
3293
	$stfbrarr = array();
3294
	$stfbrbinarr = array();
3295
	$stfbrbinarr = str_split($stfbrokerbin, 16);
3296
	foreach($stfbrbinarr as $bin)
3297
		$stfbrarr[] = dechex(bindec($bin));
3298
	$stfbrgw = Net_IPv6::compress(implode(":", $stfbrarr));
3299

    
3300
	/* convert the 128 bits for the broker address back into a valid IPv6 address */
3301
	$stflanarr = array();
3302
	$stflanbinarr = array();
3303
	$stflanbinarr = str_split($stflanbin, 16);
3304
	foreach($stflanbinarr as $bin)
3305
		$stflanarr[] = dechex(bindec($bin));
3306
	$stflanpr = Net_IPv6::compress(implode(":", $stflanarr));
3307
	$stflanarr[7] = 1;
3308
	$stflan = Net_IPv6::compress(implode(":", $stflanarr));
3309

    
3310
	/* setup the stf interface */
3311
	if (!is_module_loaded("if_stf"))
3312
		mwexec("/sbin/kldload if_stf.ko");
3313
	$stfiface = "{$interface}_stf";
3314
	if (does_interface_exist($stfiface))
3315
		pfSense_interface_destroy($stfiface);
3316
	$tmpstfiface = pfSense_interface_create("stf");
3317
	pfSense_interface_rename($tmpstfiface, $stfiface);
3318
	pfSense_interface_flags($stfiface, IFF_LINK2);
3319
	mwexec("/sbin/ifconfig {$stfiface} inet6 {$stflanpr} prefixlen 16");
3320

    
3321
	if ($g['debug'])
3322
		log_error("Set IPv6 address inet6 {$stflanpr} prefixlen 16 for {$stfiface}, route {$stfbrgw}");
3323

    
3324
	/* write out a default router file */
3325
	file_put_contents("{$g['tmp_path']}/{$wanif}_routerv6", "{$stfbrgw}");
3326
	file_put_contents("{$g['tmp_path']}/{$wanif}_defaultgwv6", "{$stfbrgw}");
3327

    
3328
	$ip4gateway = get_interface_gateway($interface);
3329
	if (is_ipaddrv4($ip4gateway))
3330
		mwexec("route change -host 192.88.99.1 {$ip4gateway}");
3331

    
3332
	if (!$g['booting'])
3333
		link_interface_to_track6($interface, "update");
3334

    
3335
	return 0;
3336
}
3337

    
3338
function interface_dhcpv6_configure($interface = "wan", $wancfg) {
3339
	global $config, $g;
3340

    
3341
	if (!is_array($wancfg))
3342
		return;
3343

    
3344
	$wanif = get_real_interface($interface);
3345
	$dhcp6cconf = "";
3346
	$dhcp6cconf .= "interface {$wanif} {\n";
3347

    
3348
	/* for SLAAC interfaces we do fire off a dhcp6 client for just our name servers */
3349
	if($wancfg['ipaddrv6'] == "slaac") {
3350
		$dhcp6cconf .= "	information-only;\n";
3351
		$dhcp6cconf .= "	request domain-name-servers;\n";
3352
		$dhcp6cconf .= "	request domain-name;\n";
3353
		$dhcp6cconf .= "	script \"{$g['varetc_path']}/dhcp6c_{$interface}_script.sh\"; # we'd like some nameservers please\n";
3354
		$dhcp6cconf .= "};\n";
3355
	} else {
3356

    
3357
		$dhcp6cconf .= " 	send ia-na 0;	# request stateful address\n";
3358
		if(is_numeric($wancfg['dhcp6-ia-pd-len']))
3359
			$dhcp6cconf .= "	send ia-pd 0;	# request prefix delegation\n";
3360
		$dhcp6cconf .= "request domain-name-servers;\n";
3361
		$dhcp6cconf .= "request domain-name;\n";
3362
		$dhcp6cconf .= "script \"{$g['varetc_path']}/dhcp6c_{$interface}_script.sh\"; # we'd like some nameservers please\n";
3363

    
3364
		$dhcp6cconf .= "};\n";
3365
		$dhcp6cconf .= "id-assoc na 0 { };\n";
3366
		if(is_numeric($wancfg['dhcp6-ia-pd-len'])) {
3367
			/* Setup the prefix delegation */
3368
			$dhcp6cconf .= "id-assoc pd 0 {\n";
3369
			$iflist = get_configured_interface_with_descr(false, true);
3370
			$iflist = link_interface_to_track6($interface);
3371
			foreach ($iflist as $friendly => $ifcfg) {
3372
				if (is_numeric($ifcfg['track6-prefix-id'])) {
3373
					if ($g['debug'])
3374
						log_error("setting up $ifdescr - {$ifcfg['track6-prefix-id']}");
3375
					$realif = get_real_interface($friendly);
3376
					$dhcp6cconf .= "	prefix-interface {$realif} {\n";
3377
					$dhcp6cconf .= "		sla-id {$ifcfg['track6-prefix-id']};\n";
3378
					$dhcp6cconf .= "		sla-len {$wancfg['dhcp6-ia-pd-len']};\n";
3379
					$dhcp6cconf .= "	};\n";
3380
				}
3381
			}
3382
			unset($iflist, $ifcfg);
3383
			$dhcp6cconf .= "};\n";
3384
		}
3385
	}
3386
	/* wide-dhcp6c works for now. */
3387
	if (!@file_put_contents("{$g['varetc_path']}/dhcp6c_{$interface}.conf", $dhcp6cconf)) {
3388
		printf("Error: cannot open dhcp6c_{$interface}.conf in interface_dhcpv6_configure() for writing.\n");
3389
		unset($dhcp6cconf);
3390
		return 1;
3391
	}
3392
	unset($dhcp6cconf);
3393

    
3394
	$dhcp6cscript = "#!/bin/sh\n";
3395
	$dhcp6cscript .= "# This shell script launches /etc/rc.newwanipv6 with a interface argument.\n";
3396
	$dhcp6cscript .= "/etc/rc.newwanipv6 {$wanif} \n";
3397
	/* Add wide-dhcp6c shell script here. Because we can not pass a argument to it. */
3398
	if (!@file_put_contents("{$g['varetc_path']}/dhcp6c_{$interface}_script.sh", $dhcp6cscript)) {
3399
		printf("Error: cannot open dhcp6c_{$interface}_script.sh in interface_dhcpv6_configure() for writing.\n");
3400
		unset($dhcp6cscript);
3401
		return 1;
3402
	}
3403
	unset($dhcp6cscript);
3404
	@chmod("{$g['varetc_path']}/dhcp6c_{$interface}_script.sh", 0755);
3405

    
3406

    
3407
	/* accept router advertisements for this interface */
3408
	mwexec("/sbin/sysctl -w net.inet6.ip6.accept_rtadv=1");
3409
	log_error("Accept router advertisements on interface {$wanif} ");
3410
	mwexec("/sbin/ifconfig {$wanif} inet6 accept_rtadv");
3411

    
3412
	/* run a filter configure sync so that the filter rules allow traffic before we launch the client */
3413
	/* there reallyt is no good way around this i'm 'fraid */
3414
	if (!$g['booting'])
3415
		filter_configure_sync();
3416

    
3417
	/* fire up dhcp6c for IPv6 first, this backgrounds immediately */
3418
	mwexec("/usr/local/sbin/dhcp6c -d -c {$g['varetc_path']}/dhcp6c_{$interface}.conf -p {$g['varrun_path']}/dhcp6c_{$interface}.pid {$wanif}");
3419
	sleep(1);
3420
	unset($out);
3421
	exec("/sbin/rtsol -d {$wanif} 2>&1", $out, $ret);
3422
	if (!empty($out)) {
3423
		foreach($out as $line) {
3424
			if((stristr($line, "received")) && (!stristr($line, "unexpected"))) {
3425
				$parts = explode(" ", $line);
3426
				if(is_ipaddrv6($parts[3])) {
3427
					log_error("Found IPv6 default gateway '{$parts[3]}' by RA.");
3428
					file_put_contents("{$g['tmp_path']}/{$wanif}_routerv6", "{$parts[3]}\n");
3429
					file_put_contents("{$g['tmp_path']}/{$wanif}_defaultgwv6", "{$parts[3]}\n");
3430
					break;
3431
				}
3432
			}
3433
		}
3434
		unset($out);
3435
	}
3436
	/* worst case is that the rc.newwanipv6 handles setting up the track6 interface */
3437
	if (!$g['booting'] && $wancfg['ipaddrv6'] != "slaac")
3438
		link_interface_to_track6($interface, "update");
3439

    
3440
	return 0;
3441
}
3442

    
3443
function interface_dhcp_configure($interface = "wan") {
3444
	global $config, $g;
3445

    
3446
	$wancfg = $config['interfaces'][$interface];
3447
	$wanif = $wancfg['if'];
3448
	if (empty($wancfg))
3449
		$wancfg = array();
3450

    
3451
	/* generate dhclient_wan.conf */
3452
	$fd = fopen("{$g['varetc_path']}/dhclient_{$interface}.conf", "w");
3453
	if (!$fd) {
3454
		printf(printf(gettext("Error: cannot open dhclient_%s.conf in interface_dhcp_configure() for writing.%s"), $interface, "\n"));
3455
		return 1;
3456
	}
3457

    
3458
	if ($wancfg['dhcphostname']) {
3459
		$dhclientconf_hostname = "send dhcp-client-identifier \"{$wancfg['dhcphostname']}\";\n";
3460
		$dhclientconf_hostname .= "\tsend host-name \"{$wancfg['dhcphostname']}\";\n";
3461
	} else {
3462
		$dhclientconf_hostname = "";
3463
	}
3464

    
3465
	$wanif = get_real_interface($interface);
3466
	if (empty($wanif)) {
3467
		log_error(sprintf(gettext("Invalid interface \"%s\" in interface_dhcp_configure()"), $interface));
3468
		return 0;
3469
	}
3470
	$dhclientconf = "";
3471

    
3472
	$dhclientconf .= <<<EOD
3473
interface "{$wanif}" {
3474
timeout 60;
3475
retry 15;
3476
select-timeout 0;
3477
initial-interval 1;
3478
	{$dhclientconf_hostname}
3479
	script "/sbin/dhclient-script";
3480
}
3481

    
3482
EOD;
3483

    
3484
if(is_ipaddr($wancfg['alias-address'])) {
3485
	$subnetmask = gen_subnet_mask($wancfg['alias-subnet']);
3486
	$dhclientconf .= <<<EOD
3487
alias {
3488
	interface  "{$wanif}";
3489
	fixed-address {$wancfg['alias-address']};
3490
	option subnet-mask {$subnetmask};
3491
}
3492

    
3493
EOD;
3494
}
3495
	fwrite($fd, $dhclientconf);
3496
	fclose($fd);
3497

    
3498
	/* bring wan interface up before starting dhclient */
3499
	if($wanif)
3500
		interfaces_bring_up($wanif);
3501
	else
3502
		log_error(printf(gettext("Could not bring up %s interface in interface_dhcp_configure()"), $wanif));
3503

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

    
3507
	return 0;
3508
}
3509

    
3510
function interfaces_group_setup() {
3511
	global $config;
3512

    
3513
	if (!is_array($config['ifgroups']['ifgroupentry']))
3514
		return;
3515

    
3516
	foreach ($config['ifgroups']['ifgroupentry'] as $groupar)
3517
		interface_group_setup($groupar);
3518

    
3519
	return;
3520
}
3521

    
3522
function interface_group_setup(&$groupname /* The parameter is an array */) {
3523
	global $config;
3524

    
3525
	if (!is_array($groupname))
3526
		return;
3527
	$members = explode(" ", $groupname['members']);
3528
	foreach($members as $ifs) {
3529
		$realif = get_real_interface($ifs);
3530
		if ($realif)
3531
			mwexec("/sbin/ifconfig {$realif} group {$groupname['ifname']}");
3532
	}
3533

    
3534
	return;
3535
}
3536

    
3537
function interface_group_add_member($interface, $groupname) {
3538
	$interface = get_real_interface($interface);
3539
	mwexec("/sbin/ifconfig {$interface} group {$groupname}", true);
3540
}
3541

    
3542
/* COMPAT Function */
3543
function convert_friendly_interface_to_real_interface_name($interface) {
3544
	return get_real_interface($interface);
3545
}
3546

    
3547
/* COMPAT Function */
3548
function get_real_wan_interface($interface = "wan") {
3549
	return get_real_interface($interface);
3550
}
3551

    
3552
/* COMPAT Function */
3553
function get_current_wan_address($interface = "wan") {
3554
	return get_interface_ip($interface);
3555
}
3556

    
3557
/*
3558
 * convert_real_interface_to_friendly_interface_name($interface): convert fxp0 -> wan, etc.
3559
 */
3560
function convert_real_interface_to_friendly_interface_name($interface = "wan") {
3561
	global $config;
3562

    
3563
	if (stristr($interface, "_vip")) {
3564
		foreach ($config['virtualip']['vip'] as $counter => $vip) {
3565
			if ($vip['mode'] == "carp")  {
3566
				if ($interface == "{$vip['interface']}_vip{$vip['vhid']}")
3567
					return $vip['interface'];
3568
			}
3569
		}
3570
	}
3571

    
3572
	/* XXX: For speed reasons reference directly the interface array */
3573
	$ifdescrs = &$config['interfaces'];
3574
	//$ifdescrs = get_configured_interface_list(false, true);
3575

    
3576
	foreach ($ifdescrs as $if => $ifname) {
3577
		if ($if == $interface || $config['interfaces'][$if]['if'] == $interface)
3578
			return $if;
3579

    
3580
		if (stristr($interface, "_wlan0") && $config['interfaces'][$if]['if'] == interface_get_wireless_base($interface))
3581
			return $if;
3582

    
3583
		// XXX: This case doesn't work anymore (segfaults - recursion?) - should be replaced with something else or just removed.
3584
		//      Not to be replaced with get_real_interface - causes slow interface listings here because of recursion!
3585
		/*
3586
		$int = get_parent_interface($if);
3587
		if ($int[0] == $interface)
3588
			return $ifname;
3589
		 */
3590
	}
3591
	return NULL;
3592
}
3593

    
3594
/* attempt to resolve interface to friendly descr */
3595
function convert_friendly_interface_to_friendly_descr($interface) {
3596
	global $config;
3597

    
3598
	switch ($interface) {
3599
	case "l2tp":
3600
		$ifdesc = "L2TP";
3601
		break;
3602
	case "pptp":
3603
		$ifdesc = "PPTP";
3604
		break;
3605
	case "pppoe":
3606
		$ifdesc = "PPPoE";
3607
		break;
3608
	case "openvpn":
3609
		$ifdesc = "OpenVPN";
3610
		break;
3611
	case "enc0":
3612
	case "ipsec":
3613
		$ifdesc = "IPsec";
3614
		break;
3615
	default:
3616
		if (isset($config['interfaces'][$interface])) {
3617
			if (empty($config['interfaces'][$interface]['descr']))
3618
				$ifdesc = strtoupper($interface);
3619
			else
3620
				$ifdesc = strtoupper($config['interfaces'][$interface]['descr']);
3621
			break;
3622
		} else if (stristr($interface, "_vip")) {
3623
			if (is_array($config['virtualip']['vip'])) {
3624
				foreach ($config['virtualip']['vip'] as $counter => $vip) {
3625
					if ($vip['mode'] == "carp")  {
3626
						if ($interface == "{$vip['interface']}_vip{$vip['vhid']}")
3627
							return "{$vip['subnet']} - {$vip['descr']}";
3628
					}
3629
				}
3630
			}
3631
		} else {
3632
			/* if list */
3633
			$ifdescrs = get_configured_interface_with_descr(false, true);
3634
			foreach ($ifdescrs as $if => $ifname) {
3635
				if ($if == $interface || $ifname == $interface)
3636
					return $ifname;
3637
			}
3638
		}
3639
		break;
3640
	}
3641

    
3642
	return $ifdesc;
3643
}
3644

    
3645
function convert_real_interface_to_friendly_descr($interface) {
3646
	global $config;
3647

    
3648
	$ifdesc = convert_real_interface_to_friendly_interface_name("{$interface}");
3649

    
3650
	if ($ifdesc) {
3651
		$iflist = get_configured_interface_with_descr(false, true);
3652
		return $iflist[$ifdesc];
3653
	}
3654

    
3655
	return $interface;
3656
}
3657

    
3658
/*
3659
 *  get_parent_interface($interface):
3660
 *			--returns the (real or virtual) parent interface(s) array for a given interface friendly name (i.e. wan)
3661
 *				or virtual interface (i.e. vlan)
3662
 *				(We need array because MLPPP and bridge interfaces have more than one parent.)
3663
 *			-- returns $interface passed in if $interface parent is not found
3664
 *			-- returns empty array if an invalid interface is passed
3665
 *	(Only handles ppps and vlans now.)
3666
 */
3667
function get_parent_interface($interface) {
3668
	global $config;
3669

    
3670
	$parents = array();
3671
	//Check that we got a valid interface passed
3672
	$realif = get_real_interface($interface);
3673
	if ($realif == NULL)
3674
		return $parents;
3675

    
3676
	// If we got a real interface, find it's friendly assigned name
3677
	$interface = convert_real_interface_to_friendly_interface_name($interface);
3678

    
3679
	if (!empty($interface) && isset($config['interfaces'][$interface])) {
3680
		$ifcfg = $config['interfaces'][$interface];
3681
		switch ($ifcfg['ipaddr']) {
3682
			case "ppp":
3683
			case "pppoe":
3684
			case "pptp":
3685
			case "l2tp":
3686
				if (empty($parents))
3687
					if (is_array($config['ppps']['ppp']))
3688
						foreach ($config['ppps']['ppp'] as $pppidx => $ppp) {
3689
							if ($ifcfg['if'] == $ppp['if']) {
3690
								$ports = explode(',', $ppp['ports']);
3691
								foreach ($ports as $pid => $parent_if)
3692
									$parents[$pid] = get_real_interface($parent_if);
3693
								break;
3694
							}
3695
						}
3696
				break;
3697
			case "dhcp":
3698
			case "static":
3699
			default:
3700
				// Handle _vlans
3701
				if (strstr($realif,"_vlan"))
3702
					if (is_array($config['vlans']['vlan']))
3703
						foreach ($config['vlans']['vlan'] as $vlanidx => $vlan)
3704
							if ($ifcfg['if'] == $vlan['vlanif']){
3705
								$parents[0] = $vlan['if'];
3706
								break;
3707
							}
3708
				break;
3709
		}
3710
	}
3711

    
3712
	if (empty($parents))
3713
		$parents[0] = $realif;
3714

    
3715
	return $parents;
3716
}
3717

    
3718
function interface_is_wireless_clone($wlif) {
3719
	if(!stristr($wlif, "_wlan")) {
3720
		return false;
3721
	} else {
3722
		return true;
3723
	}
3724
}
3725

    
3726
function interface_get_wireless_base($wlif) {
3727
	if(!stristr($wlif, "_wlan")) {
3728
		return $wlif;
3729
	} else {
3730
		return substr($wlif, 0, stripos($wlif, "_wlan"));
3731
	}
3732
}
3733

    
3734
function interface_get_wireless_clone($wlif) {
3735
	if(!stristr($wlif, "_wlan")) {
3736
		return $wlif . "_wlan0";
3737
	} else {
3738
		return $wlif;
3739
	}
3740
}
3741

    
3742
function get_real_interface($interface = "wan") {
3743
	global $config;
3744

    
3745
	$wanif = NULL;
3746

    
3747
	switch ($interface) {
3748
	case "l2tp":
3749
		$wanif = "l2tp";
3750
		break;
3751
	case "pptp":
3752
		$wanif = "pptp";
3753
		break;
3754
	case "pppoe":
3755
		$wanif = "pppoe";
3756
		break;
3757
	case "openvpn":
3758
		$wanif = "openvpn";
3759
		break;
3760
	case "ipsec":
3761
	case "enc0":
3762
		$wanif = "enc0";
3763
		break;
3764
	case "ppp":
3765
		$wanif = "ppp";
3766
		break;
3767
	default:
3768
		// If a real interface was alread passed simply
3769
		// pass the real interface back.  This encourages
3770
		// the usage of this function in more cases so that
3771
		// we can combine logic for more flexibility.
3772
		if(does_interface_exist($interface)) {
3773
			$wanif = $interface;
3774
			break;
3775
		}
3776

    
3777
		if (empty($config['interfaces'][$interface]))
3778
			break;
3779

    
3780
		$cfg = &$config['interfaces'][$interface];
3781

    
3782
		// Wireless cloned NIC support (FreeBSD 8+)
3783
		// interface name format: $parentnic_wlanparentnic#
3784
		// example: ath0_wlan0
3785
		if (is_interface_wireless($cfg['if'])) {
3786
			$wanif = interface_get_wireless_clone($cfg['if']);
3787
			break;
3788
		}
3789

    
3790
		$wanif = $cfg['if'];
3791
		break;
3792
	}
3793

    
3794
	return $wanif;
3795
}
3796

    
3797
/* Guess the physical interface by providing a IP address */
3798
function guess_interface_from_ip($ipaddress) {
3799
	if(! is_ipaddr($ipaddress)) {
3800
		return false;
3801
	}
3802
	if(is_ipaddrv4($ipaddress)) {
3803
		/* create a route table we can search */
3804
		exec("netstat -rnWf inet", $output, $ret);
3805
		foreach($output as $line) {
3806
			if(preg_match("/^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\/[0-9]+[ ]+link[#]/", $line)) {
3807
				$fields = preg_split("/[ ]+/", $line);
3808
				if(ip_in_subnet($ipaddress, $fields[0])) {
3809
					return $fields[6];
3810
				}
3811
			}
3812
		}
3813
	}
3814
	/* FIXME: This works from cursory testing, regexp might need fine tuning */
3815
	if(is_ipaddrv6($ipaddress)) {
3816
		/* create a route table we can search */
3817
		exec("netstat -rnWf inet6", $output, $ret);
3818
		foreach($output as $line) {
3819
			if(preg_match("/[0-9a-f]+[:]+[0-9a-f]+[:]+[\/][0-9]+/", $line)) {
3820
				$fields = preg_split("/[ ]+/", $line);
3821
				if(ip_in_subnet($ipaddress, $fields[0])) {
3822
					return $fields[6];
3823
				}
3824
			}
3825
		}
3826
	}
3827
	$ret = exec_command("/sbin/route -n get {$ipaddress} | /usr/bin/awk '/interface/ { print \$2; };'");
3828
	if(empty($ret)) {
3829
		return false;
3830
	}
3831
	return $ret;
3832
}
3833

    
3834
/*
3835
 * find_ip_interface($ip): return the interface where an ip is defined
3836
 *   (or if $bits is specified, where an IP within the subnet is defined)
3837
 */
3838
function find_ip_interface($ip, $bits = null)
3839
{
3840
	/* if list */
3841
	$ifdescrs = get_configured_interface_list();
3842

    
3843
	foreach ($ifdescrs as $ifdescr => $ifname) {
3844
		if ($bits === null) {
3845
			if ($ip == get_interface_ip($ifname)) {
3846
				$int = get_real_interface($ifname);
3847
				return $int;
3848
			}
3849
		}
3850
		else {
3851
			if (ip_in_subnet(get_interface_ip($ifname), $ip . "/" . $bits)) {
3852
				$int = get_real_interface($ifname);
3853
				return $int;
3854
			}
3855
		}
3856
	}
3857
	return false;
3858
}
3859

    
3860
/*
3861
 * find_virtual_ip_alias($ip): return the virtual IP alias where an IP is found
3862
 *   (or if $bits is specified, where an IP within the subnet is found)
3863
 */
3864
function find_virtual_ip_alias($ip, $bits = null) {
3865
	global $config;
3866
	if (!is_array($config['virtualip']['vip'])) {
3867
		return false;
3868
	}
3869
	foreach ($config['virtualip']['vip'] as $vip) {
3870
		if ($vip['mode'] === "ipalias") {
3871
			if ($bits === null) {
3872
				if (ip_in_subnet($ip, $vip['subnet'] . "/" . $vip['subnet_bits'])) {
3873
					return $vip;
3874
				}
3875
			}
3876
			else {
3877
				if (check_subnets_overlap($ip, $bits, $vip['subnet'], $vip['subnet_bits'])) {
3878
					return $vip;
3879
				}
3880
			}
3881
		}
3882
	}
3883
	return false;
3884
}
3885

    
3886
/*
3887
 *   find_number_of_created_carp_interfaces: return the number of carp interfaces
3888
 */
3889
function find_number_of_created_carp_interfaces() {
3890
	return `/sbin/ifconfig | grep "carp:" | wc -l`;
3891
}
3892

    
3893
function get_all_carp_interfaces() {
3894
	$ints = str_replace("\n", " ", `ifconfig | grep "carp:" -B2 | grep ": flag" | cut -d: -f1`);
3895
	$ints = explode(" ", $ints);
3896
	return $ints;
3897
}
3898

    
3899
/*
3900
 * find_carp_interface($ip): return the carp interface where an ip is defined
3901
 */
3902
function find_carp_interface($ip) {
3903
	global $config;
3904
	if (is_array($config['virtualip']['vip'])) {
3905
		foreach ($config['virtualip']['vip'] as $vip) {
3906
			if ($vip['mode'] == "carp") {
3907
				if(is_ipaddrv4($ip)) {
3908
					$carp_ip = get_interface_ip($vip['interface']);
3909
				}
3910
				if(is_ipaddrv6($ip)) {
3911
					$carp_ip = get_interface_ipv6($vip['interface']);
3912
				}
3913
				exec("/sbin/ifconfig", $output, $return);
3914
				foreach($output as $line) {
3915
					$elements = preg_split("/[ ]+/i", $line);
3916
					if(strstr($elements[0], "vip"))
3917
						$curif = str_replace(":", "", $elements[0]);
3918
					if(stristr($line, $ip)) {
3919
						$if = $curif;
3920
						continue;
3921
					}
3922
				}
3923

    
3924
				if ($if)
3925
					return $if;
3926
			}
3927
		}
3928
	}
3929
}
3930

    
3931
function link_carp_interface_to_parent($interface) {
3932
	global $config;
3933

    
3934
	if ($interface == "")
3935
		return;
3936

    
3937
	$carp_ip = get_interface_ip($interface);
3938
	$carp_ipv6 = get_interface_ipv6($interface);
3939

    
3940
	if((!is_ipaddrv4($carp_ip)) && (!is_ipaddrv6($carp_ipv6)))
3941
		return;
3942

    
3943
	/* if list */
3944
	$ifdescrs = get_configured_interface_list();
3945
	foreach ($ifdescrs as $ifdescr => $ifname) {
3946
		/* check IPv4 */
3947
		if(is_ipaddrv4($carp_ip)) {
3948
			$interfaceip = get_interface_ip($ifname);
3949
			$subnet_bits = get_interface_subnet($ifname);
3950
			$subnet_ip = gen_subnet("{$interfaceip}", "{$subnet_bits}");
3951
			if(ip_in_subnet($carp_ip, "{$subnet_ip}/{$subnet_bits}"))
3952
				return $ifname;
3953
		}
3954
		/* Check IPv6 */
3955
		if(is_ipaddrv6($carp_ipv6)) {
3956
			$interfaceipv6 = get_interface_ipv6($ifname);
3957
			$prefixlen = get_interface_subnetv6($ifname);
3958
			if(ip_in_subnet($carp_ipv6, "{$interfaceipv6}/{$prefixlen}"))
3959
				return $ifname;
3960
		}
3961
	}
3962
	return "";
3963
}
3964

    
3965

    
3966
/****f* interfaces/link_ip_to_carp_interface
3967
 * NAME
3968
 *   link_ip_to_carp_interface - Find where a CARP interface links to.
3969
 * INPUTS
3970
 *   $ip
3971
 * RESULT
3972
 *   $carp_ints
3973
 ******/
3974
function link_ip_to_carp_interface($ip) {
3975
	global $config;
3976

    
3977
	if (!is_ipaddr($ip))
3978
		return;
3979

    
3980
	$carp_ints = "";
3981
	if (is_array($config['virtualip']['vip'])) {
3982
		$first = 0;
3983
		$carp_int = array();
3984
		foreach ($config['virtualip']['vip'] as $vip) {
3985
			if ($vip['mode'] == "carp") {
3986
				$carp_ip = $vip['subnet'];
3987
				$carp_sn = $vip['subnet_bits'];
3988
				$carp_nw = gen_subnet($carp_ip, $carp_sn);
3989
				if (ip_in_subnet($ip, "{$carp_nw}/{$carp_sn}")) {
3990
					$carp_int[] = "{$vip['interface']}_vip{$vip['vhid']}";
3991
				}
3992
			}
3993
		}
3994
		if (!empty($carp_int))
3995
			$carp_ints = implode(" ", array_unique($carp_int));
3996
	}
3997

    
3998
	return $carp_ints;
3999
}
4000

    
4001
function link_interface_to_track6($int, $action = "") {
4002
	global $config;
4003

    
4004
	if (empty($int))
4005
		return;
4006

    
4007
	if (is_array($config['interfaces'])) {
4008
		$list = array();
4009
		foreach ($config['interfaces'] as $ifname => $ifcfg) {
4010
			if (!isset($ifcfg['enable']))
4011
				continue;
4012
			if (!empty($ifcfg['ipaddrv6']) && $ifcfg['track6-interface'] == $int) {
4013
				if ($action == "update")
4014
					interface_track6_configure($ifname, $ifcfg);
4015
				else if ($action == "")
4016
					$list[$ifname] = $ifcfg;
4017
			}
4018
		}
4019
		return $list;
4020
	}
4021
}
4022

    
4023
function link_interface_to_vlans($int, $action = "") {
4024
	global $config;
4025

    
4026
	if (empty($int))
4027
		return;
4028

    
4029
	if (is_array($config['vlans']['vlan'])) {
4030
		foreach ($config['vlans']['vlan'] as $vlan) {
4031
			if ($int == $vlan['if']) {
4032
				if ($action == "update") {
4033
					interfaces_bring_up($int);
4034
				} else if ($action == "")
4035
					return $vlan;
4036
			}
4037
		}
4038
	}
4039
}
4040

    
4041
function link_interface_to_vips($int, $action = "") {
4042
	global $config;
4043

    
4044
	if (is_array($config['virtualip']['vip'])) {
4045
		$result = array();
4046
		foreach ($config['virtualip']['vip'] as $vip) {
4047
			if ($int == $vip['interface']) {
4048
				if ($action == "update")
4049
					interfaces_vips_configure($int);
4050
				else
4051
					$result[] = $vip;
4052
			}
4053
		}
4054
		return $result;
4055
	}
4056
}
4057

    
4058
/****f* interfaces/link_interface_to_bridge
4059
 * NAME
4060
 *   link_interface_to_bridge - Finds out a bridge group for an interface
4061
 * INPUTS
4062
 *   $ip
4063
 * RESULT
4064
 *   bridge[0-99]
4065
 ******/
4066
function link_interface_to_bridge($int) {
4067
	global $config;
4068

    
4069
	if (is_array($config['bridges']['bridged'])) {
4070
		foreach ($config['bridges']['bridged'] as $bridge) {
4071
			if (in_array($int, explode(',', $bridge['members'])))
4072
				return "{$bridge['bridgeif']}";
4073
		}
4074
	}
4075
}
4076

    
4077
function link_interface_to_group($int) {
4078
	global $config;
4079

    
4080
	$result = array();
4081

    
4082
	if (is_array($config['ifgroups']['ifgroupentry'])) {
4083
		foreach ($config['ifgroups']['ifgroupentry'] as $group) {
4084
			if (in_array($int, explode(" ", $group['members'])))
4085
				$result[$group['ifname']] = $int;
4086
		}
4087
	}
4088

    
4089
	return $result;
4090
}
4091

    
4092
function link_interface_to_gre($interface) {
4093
	global $config;
4094

    
4095
	$result = array();
4096

    
4097
	if (is_array($config['gres']['gre'])) {
4098
		foreach ($config['gres']['gre'] as $gre)
4099
			if($gre['if'] == $interface)
4100
				$result[] = $gre;
4101
	}
4102

    
4103
	return $result;
4104
}
4105

    
4106
function link_interface_to_gif($interface) {
4107
	global $config;
4108

    
4109
	$result = array();
4110

    
4111
	if (is_array($config['gifs']['gif'])) {
4112
		foreach ($config['gifs']['gif'] as $gif)
4113
			if($gif['if'] == $interface)
4114
				$result[] = $gif;
4115
	}
4116

    
4117
	return $result;
4118
}
4119

    
4120
/*
4121
 * find_interface_ip($interface): return the interface ip (first found)
4122
 */
4123
function find_interface_ip($interface, $flush = false)
4124
{
4125
	global $interface_ip_arr_cache;
4126
	global $interface_sn_arr_cache;
4127

    
4128
	$interface = str_replace("\n", "", $interface);
4129

    
4130
	if (!does_interface_exist($interface))
4131
		return;
4132

    
4133
	/* Setup IP cache */
4134
	if (!isset($interface_ip_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_ip_arr_cache[$interface];
4141
}
4142

    
4143
/*
4144
 * find_interface_ipv6($interface): return the interface ip (first found)
4145
 */
4146
function find_interface_ipv6($interface, $flush = false)
4147
{
4148
	global $interface_ipv6_arr_cache;
4149
	global $interface_snv6_arr_cache;
4150
	global $config;
4151

    
4152
	$interface = trim($interface);
4153
	$interface = get_real_interface($interface);
4154

    
4155
	if (!does_interface_exist($interface))
4156
		return;
4157

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

    
4181
	return $interface_ipv6_arr_cache[$interface];
4182
}
4183

    
4184
/*
4185
 * find_interface_ipv6_ll($interface): return the interface ipv6 link local (first found)
4186
 */
4187
function find_interface_ipv6_ll($interface, $flush = false)
4188
{
4189
	global $interface_llv6_arr_cache;
4190
	global $config;
4191

    
4192
	$interface = str_replace("\n", "", $interface);
4193

    
4194
	if (!does_interface_exist($interface))
4195
		return;
4196

    
4197
	/* Setup IP cache */
4198
	if (!isset($interface_llv6_arr_cache[$interface]) or $flush) {
4199
		$ifinfo = pfSense_get_interface_addresses($interface);
4200
		// FIXME: Add IPv6 support to the pfSense module
4201
		exec("/sbin/ifconfig {$interface} inet6", $output);
4202
		foreach($output as $line) {
4203
			if(preg_match("/inet6/", $line)) {
4204
				$parts = explode(" ", $line);
4205
				if(preg_match("/fe80::/", $parts[1])) {
4206
					$partsaddress = explode("%", $parts[1]);
4207
					$ifinfo['linklocal'] = $partsaddress[0];
4208
				}
4209
			}
4210
		}
4211
		$interface_llv6_arr_cache[$interface] = $ifinfo['linklocal'];
4212
	}
4213
	return $interface_llv6_arr_cache[$interface];
4214
}
4215

    
4216
function find_interface_subnet($interface, $flush = false)
4217
{
4218
	global $interface_sn_arr_cache;
4219
	global $interface_ip_arr_cache;
4220

    
4221
	$interface = str_replace("\n", "", $interface);
4222
	if (does_interface_exist($interface) == false)
4223
		return;
4224

    
4225
	if (!isset($interface_sn_arr_cache[$interface]) or $flush) {
4226
		$ifinfo = pfSense_get_interface_addresses($interface);
4227
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
4228
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
4229
	}
4230

    
4231
	return $interface_sn_arr_cache[$interface];
4232
}
4233

    
4234
function find_interface_subnetv6($interface, $flush = false)
4235
{
4236
	global $interface_snv6_arr_cache;
4237
	global $interface_ipv6_arr_cache;
4238

    
4239
	$interface = str_replace("\n", "", $interface);
4240
	if (does_interface_exist($interface) == false)
4241
		return;
4242

    
4243
	$foundv6 = false;
4244
	if (!isset($interface_snv6_arr_cache[$interface]) or $flush) {
4245
		$ifinfo = pfSense_get_interface_addresses($interface);
4246
		// FIXME: Add IPv6 support to the pfSense module
4247
		unset($output);
4248
		exec("/sbin/ifconfig {$interface} inet6", $output);
4249
		foreach($output as $line) {
4250
			$line = trim($line);
4251
			if(preg_match("/inet6/", $line)) {
4252
				$parts = explode(" ", $line);
4253
				if(! preg_match("/fe80::/", $parts[1])) {
4254
					$ifinfo['ipaddrv6'] = $parts[1];
4255
					if($parts[2] == "-->") {
4256
						$parts[5] = "126";
4257
						$ifinfo['subnetbitsv6'] = $parts[5];
4258
					} else {
4259
						$ifinfo['subnetbitsv6'] = $parts[3];
4260
					}
4261
					$foundv6 = true;
4262
					break;
4263
				}
4264
			}
4265
		}
4266
		if ($foundv6 === true) {
4267
			$interface_ipv6_arr_cache[$interface] = $ifinfo['ipaddrv6'];
4268
			$interface_snv6_arr_cache[$interface] = $ifinfo['subnetbitsv6'];
4269
		} else
4270
			unset($interface_ipv6_arr_cache[$interface], $interface_snv6_arr_cache[$interface]);
4271
	}
4272

    
4273
	return $interface_snv6_arr_cache[$interface];
4274
}
4275

    
4276
function ip_in_interface_alias_subnet($interface, $ipalias) {
4277
	global $config;
4278

    
4279
	if (empty($interface) || !is_ipaddr($ipalias))
4280
		return false;
4281
	if (is_array($config['virtualip']['vip'])) {
4282
		foreach ($config['virtualip']['vip'] as $vip) {
4283
			switch ($vip['mode']) {
4284
			case "ipalias":
4285
				if ($vip['interface'] <> $interface)
4286
					break;
4287
				if (ip_in_subnet($ipalias, gen_subnet($vip['subnet'], $vip['subnet_bits']) . "/" . $vip['subnet_bits']))
4288
					return true;
4289
				break;
4290
			}
4291
		}
4292
	}
4293

    
4294
	return false;
4295
}
4296

    
4297
function get_interface_ip($interface = "wan")
4298
{
4299
	$realif = get_failover_interface($interface);
4300
	if (!$realif) {
4301
		if (preg_match("/^carp/i", $interface))
4302
			$realif = $interface;
4303
		else if (preg_match("/^[a-z0-9]+_vip/i", $interface))
4304
			$realif = $interface;
4305
		else
4306
			return null;
4307
	}
4308

    
4309
	$curip = find_interface_ip($realif);
4310
	if ($curip && is_ipaddr($curip) && ($curip != "0.0.0.0"))
4311
		return $curip;
4312
	else
4313
		return null;
4314
}
4315

    
4316
function get_interface_ipv6($interface = "wan")
4317
{
4318
	global $config;
4319

    
4320
	$realif = get_failover_interface($interface);
4321
	if (is_array($config['interfaces'][$interface])) {
4322
		switch($config['interfaces'][$interface]['ipaddrv6']) {
4323
			case "6rd":
4324
			case "6to4":
4325
				$realif = "{$interface}_stf";
4326
				break;
4327
		}
4328
	}
4329
	if (!$realif) {
4330
		if (preg_match("/^[a-z0-9]+_vip/i", $interface))
4331
			$realif = $interface;
4332
		else
4333
			return null;
4334
	}
4335

    
4336
	$curip = find_interface_ipv6($realif);
4337
	if ($curip && is_ipaddrv6($curip) && ($curip != "::"))
4338
		return $curip;
4339
	else
4340
		return null;
4341
}
4342

    
4343
function get_interface_linklocal($interface = "wan")
4344
{
4345
	$realif = get_failover_interface($interface);
4346
	if (!$realif) {
4347
		if (preg_match("/^carp/i", $interface))
4348
			$realif = $interface;
4349
		else if (preg_match("/^[a-z0-9]+_vip/i", $interface))
4350
			$realif = $interface;
4351
		else
4352
			return null;
4353
	}
4354

    
4355
	$curip = find_interface_ipv6_ll($realif);
4356
	if ($curip && is_ipaddrv6($curip) && ($curip != "::"))
4357
		return $curip;
4358
	else
4359
		return null;
4360
}
4361

    
4362
function get_interface_subnet($interface = "wan")
4363
{
4364
	$realif = get_real_interface($interface);
4365
	if (!$realif) {
4366
		if (preg_match("/^carp/i", $interface))
4367
			$realif = $interface;
4368
		else if (preg_match("/^[a-z0-9]+_vip/i", $interface))
4369
			$realif = $interface;
4370
		else
4371
			return null;
4372
	}
4373

    
4374
	$cursn = find_interface_subnet($realif);
4375
	if (!empty($cursn))
4376
		return $cursn;
4377

    
4378
	return null;
4379
}
4380

    
4381
function get_interface_subnetv6($interface = "wan")
4382
{
4383
	global $config;
4384

    
4385
	if (is_array($config['interfaces'][$interface])) {
4386
		switch($config['interfaces'][$interface]['ipaddrv6']) {
4387
			case "6rd":
4388
			case "6to4":
4389
				$realif = "{$interface}_stf";
4390
				break;
4391
			default:
4392
				$realif = get_real_interface($interface);
4393
				break;
4394
		}
4395
	}
4396
	if (!$realif) {
4397
		if (preg_match("/^[a-z0-9]+_vip/i", $interface))
4398
			$realif = $interface;
4399
		else
4400
			return null;
4401
	}
4402

    
4403
	$cursn = find_interface_subnetv6($realif);
4404
	if (!empty($cursn))
4405
		return $cursn;
4406

    
4407
	return null;
4408
}
4409

    
4410
/* return outside interfaces with a gateway */
4411
function get_interfaces_with_gateway() {
4412
	global $config;
4413

    
4414
	$ints = array();
4415

    
4416
	/* loop interfaces, check config for outbound */
4417
	foreach($config['interfaces'] as $ifdescr => $ifname) {
4418
		switch ($ifname['ipaddr']) {
4419
			case "dhcp":
4420
			case "ppp";
4421
			case "pppoe":
4422
			case "pptp":
4423
			case "l2tp":
4424
			case "ppp";
4425
				$ints[$ifdescr] = $ifdescr;
4426
			break;
4427
			default:
4428
				if (substr($ifname['if'], 0, 4) ==  "ovpn" ||
4429
				    !empty($ifname['gateway']))
4430
					$ints[$ifdescr] = $ifdescr;
4431
			break;
4432
		}
4433
	}
4434
	return $ints;
4435
}
4436

    
4437
/* return true if interface has a gateway */
4438
function interface_has_gateway($friendly) {
4439
	global $config;
4440

    
4441
	if (!empty($config['interfaces'][$friendly])) {
4442
		$ifname = &$config['interfaces'][$friendly];
4443
		switch ($ifname['ipaddr']) {
4444
			case "dhcp":
4445
			case "pppoe":
4446
			case "pptp":
4447
			case "l2tp":
4448
			case "ppp";
4449
				return true;
4450
			break;
4451
			default:
4452
				if (substr($ifname['if'], 0, 4) ==  "ovpn")
4453
					return true;
4454
				if (!empty($ifname['gateway']))
4455
					return true;
4456
			break;
4457
		}
4458
	}
4459

    
4460
	return false;
4461
}
4462

    
4463
/* return true if interface has a gateway */
4464
function interface_has_gatewayv6($friendly) {
4465
	global $config;
4466

    
4467
	if (!empty($config['interfaces'][$friendly])) {
4468
		$ifname = &$config['interfaces'][$friendly];
4469
		switch ($ifname['ipaddrv6']) {
4470
			case "slaac":
4471
			case "dhcp6":
4472
				return true;
4473
				break;
4474
			case "6to4":
4475
				return true;
4476
				break;
4477
			case "6rd":
4478
				return true;
4479
				break;
4480
			default:
4481
				if (substr($ifname['if'], 0, 4) ==  "ovpn")
4482
					return true;
4483
				if (!empty($ifname['gatewayv6']))
4484
					return true;
4485
				break;
4486
		}
4487
	}
4488

    
4489
	return false;
4490
}
4491

    
4492
/****f* interfaces/is_altq_capable
4493
 * NAME
4494
 *   is_altq_capable - Test if interface is capable of using ALTQ
4495
 * INPUTS
4496
 *   $int            - string containing interface name
4497
 * RESULT
4498
 *   boolean         - true or false
4499
 ******/
4500

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

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

    
4516
	if (in_array($int_family[0], $capable))
4517
		return true;
4518
	else if (stristr($int, "l2tp")) /* VLANs are name $parent_$vlan now */
4519
		return true;
4520
	else if (stristr($int, "vlan")) /* VLANs are name $parent_$vlan now */
4521
		return true;
4522
	else if (stristr($int, "_wlan")) /* WLANs are name $parent_$wlan now */
4523
		return true;
4524
	else
4525
		return false;
4526
}
4527

    
4528
/****f* interfaces/is_interface_wireless
4529
 * NAME
4530
 *   is_interface_wireless - Returns if an interface is wireless
4531
 * RESULT
4532
 *   $tmp       - Returns if an interface is wireless
4533
 ******/
4534
function is_interface_wireless($interface) {
4535
	global $config, $g;
4536

    
4537
	$friendly = convert_real_interface_to_friendly_interface_name($interface);
4538
	if(!isset($config['interfaces'][$friendly]['wireless'])) {
4539
		if (preg_match($g['wireless_regex'], $interface)) {
4540
			if (isset($config['interfaces'][$friendly]))
4541
				$config['interfaces'][$friendly]['wireless'] = array();
4542
			return true;
4543
		}
4544
		return false;
4545
	} else
4546
		return true;
4547
}
4548

    
4549
function get_wireless_modes($interface) {
4550
	/* return wireless modes and channels */
4551
	$wireless_modes = array();
4552

    
4553
	$cloned_interface = get_real_interface($interface);
4554

    
4555
	if($cloned_interface && is_interface_wireless($cloned_interface)) {
4556
		$chan_list = "/sbin/ifconfig {$cloned_interface} list chan";
4557
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
4558
		$format_list = "/usr/bin/awk '{print \$5 \" \" \$6 \",\" \$1}'";
4559

    
4560
		$interface_channels = "";
4561
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
4562
		$interface_channel_count = count($interface_channels);
4563

    
4564
		$c = 0;
4565
		while ($c < $interface_channel_count)
4566
		{
4567
			$channel_line = explode(",", $interface_channels["$c"]);
4568
			$wireless_mode = trim($channel_line[0]);
4569
			$wireless_channel = trim($channel_line[1]);
4570
			if(trim($wireless_mode) != "") {
4571
				/* if we only have 11g also set 11b channels */
4572
				if($wireless_mode == "11g") {
4573
					if(!isset($wireless_modes["11b"]))
4574
						$wireless_modes["11b"] = array();
4575
				} else if($wireless_mode == "11g ht") {
4576
					if(!isset($wireless_modes["11b"]))
4577
						$wireless_modes["11b"] = array();
4578
					if(!isset($wireless_modes["11g"]))
4579
						$wireless_modes["11g"] = array();
4580
					$wireless_mode = "11ng";
4581
				} else if($wireless_mode == "11a ht") {
4582
					if(!isset($wireless_modes["11a"]))
4583
						$wireless_modes["11a"] = array();
4584
					$wireless_mode = "11na";
4585
				}
4586
				$wireless_modes["$wireless_mode"]["$c"] = $wireless_channel;
4587
			}
4588
			$c++;
4589
		}
4590
	}
4591
	return($wireless_modes);
4592
}
4593

    
4594
/* return channel numbers, frequency, max txpower, and max regulation txpower */
4595
function get_wireless_channel_info($interface) {
4596
	$wireless_channels = array();
4597

    
4598
	$cloned_interface = get_real_interface($interface);
4599

    
4600
	if($cloned_interface && is_interface_wireless($cloned_interface)) {
4601
		$chan_list = "/sbin/ifconfig {$cloned_interface} list txpower";
4602
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
4603
		$format_list = "/usr/bin/awk '{print \$1 \",\" \$3 \" \" \$4 \",\" \$5 \",\" \$7}'";
4604

    
4605
		$interface_channels = "";
4606
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
4607

    
4608
		foreach ($interface_channels as $channel_line) {
4609
			$channel_line = explode(",", $channel_line);
4610
			if(!isset($wireless_channels[$channel_line[0]]))
4611
				$wireless_channels[$channel_line[0]] = $channel_line;
4612
		}
4613
	}
4614
	return($wireless_channels);
4615
}
4616

    
4617
/****f* interfaces/get_interface_mtu
4618
 * NAME
4619
 *   get_interface_mtu - Return the mtu of an interface
4620
 * RESULT
4621
 *   $tmp       - Returns the mtu of an interface
4622
 ******/
4623
function get_interface_mtu($interface) {
4624
	$mtu = pfSense_get_interface_addresses($interface);
4625
	return $mtu['mtu'];
4626
}
4627

    
4628
function get_interface_mac($interface) {
4629

    
4630
	$macinfo = pfSense_get_interface_addresses($interface);
4631
	return $macinfo["macaddr"];
4632
}
4633

    
4634
/****f* pfsense-utils/generate_random_mac_address
4635
 * NAME
4636
 *   generate_random_mac - generates a random mac address
4637
 * INPUTS
4638
 *   none
4639
 * RESULT
4640
 *   $mac - a random mac address
4641
 ******/
4642
function generate_random_mac_address() {
4643
	$mac = "02";
4644
	for($x=0; $x<5; $x++)
4645
		$mac .= ":" . dechex(rand(16, 255));
4646
	return $mac;
4647
}
4648

    
4649
/****f* interfaces/is_jumbo_capable
4650
 * NAME
4651
 *   is_jumbo_capable - Test if interface is jumbo frame capable.  Useful for determining VLAN capability.
4652
 * INPUTS
4653
 *   $int             - string containing interface name
4654
 * RESULT
4655
 *   boolean          - true or false
4656
 ******/
4657
function is_jumbo_capable($iface) {
4658
	$iface = trim($iface);
4659
	$capable = pfSense_get_interface_addresses($iface);
4660

    
4661
	if (isset($capable['caps']['vlanmtu']))
4662
		return true;
4663

    
4664
	return false;
4665
}
4666

    
4667
function interface_setup_pppoe_reset_file($pppif, $iface="") {
4668
	global $g;
4669

    
4670
	$cron_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
4671

    
4672
	if(!empty($iface) && !empty($pppif)){
4673
		$cron_cmd = <<<EOD
4674
#!/bin/sh
4675
/usr/local/sbin/pfSctl -c 'interface reload {$iface}'
4676
/usr/bin/logger -t {$pppif} "PPPoE periodic reset executed on {$iface}"
4677

    
4678
EOD;
4679

    
4680
		@file_put_contents($cron_file, $cron_cmd);
4681
		chmod($cron_file, 0755);
4682
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
4683
	} else
4684
		unlink_if_exists($cron_file);
4685
}
4686

    
4687
function get_interface_default_mtu($type = "ethernet") {
4688
	switch ($type) {
4689
	case "gre":
4690
		return 1476;
4691
		break;
4692
	case "gif":
4693
		return 1280;
4694
		break;
4695
	case "tun":
4696
	case "vlan":
4697
	case "tap":
4698
	case "ethernet":
4699
	default:
4700
		return 1500;
4701
		break;
4702
	}
4703

    
4704
	/* Never reached */
4705
	return 1500;
4706
}
4707

    
4708
function get_vip_descr($ipaddress) {
4709
	global $config;
4710

    
4711
	foreach ($config['virtualip']['vip'] as $vip) {
4712
		if ($vip['subnet'] == $ipaddress) {
4713
			return ($vip['descr']);
4714
		}
4715
	}
4716
	return "";
4717
}
4718

    
4719
function interfaces_staticarp_configure($if) {
4720
	global $config, $g;
4721
	if(isset($config['system']['developerspew'])) {
4722
		$mt = microtime();
4723
		echo "interfaces_staticarp_configure($if) being called $mt\n";
4724
	}
4725

    
4726
	$ifcfg = $config['interfaces'][$if];
4727

    
4728
	if (empty($if) || empty($ifcfg['if']))
4729
		return 0;
4730

    
4731
	/* Enable staticarp, if enabled */
4732
	if(isset($config['dhcpd'][$if]['staticarp'])) {
4733
		mwexec("/sbin/ifconfig " . escapeshellarg($ifcfg['if']) . " staticarp " );
4734
		mwexec("/usr/sbin/arp -d -i " . escapeshellarg($ifcfg['if']) . " -a > /dev/null 2>&1 ");
4735
		if (is_array($config['dhcpd'][$if]['staticmap'])) {
4736

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

    
4740
			}
4741

    
4742
		}
4743
	} else {
4744
		mwexec("/sbin/ifconfig " . escapeshellarg($ifcfg['if']) . " -staticarp " );
4745
		mwexec("/usr/sbin/arp -d -i " . escapeshellarg($ifcfg['if']) . " -a > /dev/null 2>&1 ");
4746
		if (is_array($config['dhcpd'][$if]['staticmap'])) {
4747
			foreach ($config['dhcpd'][$if]['staticmap'] as $arpent) {
4748
				if (isset($arpent['arp_table_static_entry'])) {
4749
					mwexec("/usr/sbin/arp -s " . escapeshellarg($arpent['ipaddr']) . " " . escapeshellarg($arpent['mac']));
4750
				}
4751
			}
4752
		}
4753
	}
4754

    
4755
	return 0;
4756
}
4757

    
4758
function get_failover_interface($interface) {
4759
	global $config;
4760
	/* shortcut to get_real_interface if we find it in the config */
4761
	if(is_array($config['interfaces'][$interface])) {
4762
		$wanif = get_real_interface($interface);
4763
		return $wanif;
4764
	}
4765

    
4766
	/* compare against gateway groups */
4767
	$a_groups = return_gateway_groups_array();
4768
	if(is_array($a_groups[$interface])) {
4769
		/* we found a gateway group, fetch the interface or vip */
4770
		if($a_groups[$interface][0]['vip'] <> "")
4771
			$wanif = $a_groups[$interface][0]['vip'];
4772
		else
4773
			$wanif = $a_groups[$interface][0]['int'];
4774

    
4775
		return $wanif;
4776
	}
4777
	/* fall through to get_real_interface */
4778
	$wanif = get_real_interface($interface);
4779
	return $wanif;
4780
}
4781

    
4782
?>
(25-25/67)