Project

General

Profile

Download (155 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']))
826
		pfSense_interface_flags($greif, IFF_LINK0);
827
	if (isset($gre['link1']))
828
		pfSense_interface_flags($greif, IFF_LINK1);
829
	if (isset($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']))
916
		pfSense_interface_flags($gifif, IFF_LINK0);
917
	if (isset($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("/sbin/route change -host {$gif['remote-addr']} {$realifgw}");
946
	}
947
	if (is_ipaddrv6($realifgw)) {
948
		mwexec("/sbin/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
		$ppps = $config['ppps']['ppp'];
1139
		$realif = get_real_interface($interface);
1140
	} elseif (!is_array($ifacecfg)) {
1141
		log_error(gettext("Wrong parameters used during interface_bring_down"));
1142
	} else {
1143
		$ifcfg = $ifacecfg['ifcfg'];
1144
		$ppps = $ifacecfg['ppps'];
1145
		if (isset($ifacecfg['ifcfg']['realif']))
1146
			$realif = $ifacecfg['ifcfg']['realif'];
1147
		else
1148
			$realif = get_real_interface($interface);
1149
	}
1150

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

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

    
1238
	if (file_exists("{$g['tmp_path']}/{$realif}_router"))
1239
		$old_router = trim(file_get_contents("{$g['tmp_path']}/{$realif}_router"));
1240
//	log_error("Checking for old router states: {$g['tmp_path']}/{$realif}_router = {$old_router}");
1241
	if (!empty($old_router)) {
1242
		log_error("Clearing states to old gateway {$old_router}.");
1243
		mwexec("/sbin/pfctl -i {$realif} -Fs -G {$old_router}");
1244
	}
1245

    
1246
	/* remove interface up file if it exists */
1247
	unlink_if_exists("{$g['tmp_path']}/{$realif}up");
1248
	unlink_if_exists("{$g['vardb_path']}/{$interface}ip");
1249
	unlink_if_exists("{$g['vardb_path']}/{$interface}ipv6");
1250
	unlink_if_exists("{$g['tmp_path']}/{$realif}_router");
1251
	unlink_if_exists("{$g['tmp_path']}/{$realif}_routerv6");
1252
	unlink_if_exists("{$g['varetc_path']}/nameserver_{$realif}");
1253
	unlink_if_exists("{$g['varetc_path']}/searchdomain_{$realif}");
1254

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

    
1262
	if ($destroy == true) {
1263
		if (preg_match("/^[a-z0-9]+_vip|^tun|^ovpn|^gif|^gre|^lagg|^bridge|vlan|_stf$/i", $realif))
1264
			pfSense_interface_destroy($realif);
1265
	}
1266

    
1267
	return;
1268
}
1269

    
1270
function interfaces_ptpid_used($ptpid) {
1271
	global $config;
1272

    
1273
	if (is_array($config['ppps']['ppp']))
1274
		foreach ($config['ppps']['ppp'] as & $settings)
1275
			if ($ptpid == $settings['ptpid'])
1276
				return true;
1277

    
1278
	return false;
1279
}
1280

    
1281
function interfaces_ptpid_next() {
1282

    
1283
	$ptpid = 0;
1284
	while(interfaces_ptpid_used($ptpid))
1285
		$ptpid++;
1286

    
1287
	return $ptpid;
1288
}
1289

    
1290
function getMPDCRONSettings($pppif) {
1291
	global $config;
1292

    
1293
	$cron_cmd_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
1294
	if (is_array($config['cron']['item'])) {
1295
		foreach ($config['cron']['item'] as $i => $item) {
1296
			if (stripos($item['command'], $cron_cmd_file) !== false)
1297
				return array("ID" => $i, "ITEM" => $item);
1298
		}
1299
	}
1300

    
1301
	return NULL;
1302
}
1303

    
1304
function handle_pppoe_reset($post_array) {
1305
	global $config, $g;
1306

    
1307
	$pppif = "{$post_array['type']}{$post_array['ptpid']}";
1308
	$cron_cmd_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
1309

    
1310
	if (!is_array($config['cron']['item']))
1311
		$config['cron']['item'] = array();
1312

    
1313
	$itemhash = getMPDCRONSettings($pppif);
1314

    
1315
	// reset cron items if necessary and return
1316
	if (empty($post_array['pppoe-reset-type'])) {
1317
		if (isset($itemhash))
1318
			unset($config['cron']['item'][$itemhash['ID']]);
1319
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
1320
		return;
1321
	}
1322

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

    
1382
/*
1383
 * This function can configure PPPoE, MLPPP (PPPoE), PPTP.
1384
 * It writes the mpd config file to /var/etc every time the link is opened.
1385
 */
1386
function interface_ppps_configure($interface) {
1387
	global $config, $g;
1388

    
1389
	/* Return for unassigned interfaces. This is a minimum requirement. */
1390
	if (empty($config['interfaces'][$interface]))
1391
		return 0;
1392
	$ifcfg = $config['interfaces'][$interface];
1393
	if (!isset($ifcfg['enable']))
1394
		return 0;
1395

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

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

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

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

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

    
1464
				if(!is_ipaddr($localips[$pid])){
1465
					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!");
1466
					$localips[$pid] = "0.0.0.0";
1467
				}
1468
				if(!is_ipaddr($gateways[$pid])){
1469
					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));
1470
					return 0;
1471
				}
1472
				pfSense_ngctl_attach(".", $port);
1473
				break;
1474
			case "ppp":
1475
				if (!file_exists("{$port}")) {
1476
					log_error(sprintf(gettext("Device %s does not exist. PPP link cannot start without the modem device."), $port));
1477
					return 0;
1478
				}
1479
				break;
1480
			default:
1481
				log_error(sprintf(gettext("Unkown %s configured as ppp interface."), $type));
1482
				break;
1483
		}
1484
	}
1485

    
1486
	if (is_array($ports) && count($ports) > 1)
1487
		$multilink = "enable";
1488
	else
1489
		$multilink = "disable";
1490

    
1491
	if ($type == "modem"){
1492
		if (is_ipaddr($ppp['localip']))
1493
			$localip = $ppp['localip'];
1494
		else
1495
			$localip = '0.0.0.0';
1496

    
1497
		if (is_ipaddr($ppp['gateway']))
1498
			$gateway = $ppp['gateway'];
1499
		else
1500
			$gateway = "10.64.64.{$pppid}";
1501
		$ranges = "{$localip}/0 {$gateway}/0";
1502

    
1503
		if (empty($ppp['apnum']))
1504
			$ppp['apnum'] = 1;
1505
	} else
1506
		$ranges = "0.0.0.0/0 0.0.0.0/0";
1507

    
1508
	if (isset($ppp['ondemand']))
1509
		$ondemand = "enable";
1510
	else
1511
		$ondemand = "disable";
1512
	if (!isset($ppp['idletimeout']))
1513
		$ppp['idletimeout'] = 0;
1514

    
1515
	if (empty($ppp['username']) && $type == "modem"){
1516
		$ppp['username'] = "user";
1517
		$ppp['password'] = "none";
1518
	}
1519
	if (empty($ppp['password']) && $type == "modem")
1520
		$passwd = "none";
1521
	else
1522
		$passwd = base64_decode($ppp['password']);
1523

    
1524
	$bandwidths = explode(',',$ppp['bandwidth']);
1525
	$defaultmtu = "1492";
1526
	if (!empty($ifcfg['mtu']))
1527
		$defaultmtu = intval($ifcfg['mtu']);
1528
	$mtus = explode(',',$ppp['mtu']);
1529
	$mrus = explode(',',$ppp['mru']);
1530

    
1531
	if (isset($ppp['mrru']))
1532
		$mrrus = explode(',',$ppp['mrru']);
1533

    
1534
	// Construct the mpd.conf file
1535
	$mpdconf = <<<EOD
1536
startup:
1537
	# configure the console
1538
	set console close
1539
	# configure the web server
1540
	set web close
1541

    
1542
default:
1543
{$ppp['type']}client:
1544
	create bundle static {$interface}
1545
	set bundle enable ipv6cp
1546
	set iface name {$pppif}
1547

    
1548
EOD;
1549
	$setdefaultgw = false;
1550
	$founddefaultgw = false;
1551
	if (is_array($config['gateways']['gateway_item'])) {
1552
		foreach($config['gateways']['gateway_item'] as $gateway) {
1553
			if($interface == $gateway['interface'] && isset($gateway['defaultgw'])) {
1554
				$setdefaultgw = true;
1555
				break;
1556
			} else if (isset($gateway['defaultgw']) && !empty($gateway['interface'])) {
1557
				$founddefaultgw = true;
1558
				break;
1559
			}
1560
		}
1561
	}
1562

    
1563
	if (($interface == "wan" && $founddefaultgw == false) || $setdefaultgw == true){
1564
		$setdefaultgw = true;
1565
		$mpdconf .= <<<EOD
1566
	set iface route default
1567

    
1568
EOD;
1569
	}
1570
	$mpdconf .= <<<EOD
1571
	set iface {$ondemand} on-demand
1572
	set iface idle {$ppp['idletimeout']}
1573

    
1574
EOD;
1575

    
1576
	if (isset($ppp['ondemand']))
1577
		$mpdconf .= <<<EOD
1578
	set iface addrs 10.10.1.1 10.10.1.2
1579

    
1580
EOD;
1581

    
1582
	if (isset($ppp['tcpmssfix']))
1583
		$tcpmss = "disable";
1584
	else
1585
		$tcpmss = "enable";
1586
		$mpdconf .= <<<EOD
1587
	set iface {$tcpmss} tcpmssfix
1588

    
1589
EOD;
1590

    
1591
	$mpdconf .= <<<EOD
1592
	set iface up-script /usr/local/sbin/ppp-linkup
1593
	set iface down-script /usr/local/sbin/ppp-linkdown
1594
	set ipcp ranges {$ranges}
1595

    
1596
EOD;
1597
	if (isset($ppp['vjcomp']))
1598
		$mpdconf .= <<<EOD
1599
	set ipcp no vjcomp
1600

    
1601
EOD;
1602

    
1603
	if (isset($config['system']['dnsallowoverride']))
1604
		$mpdconf .= <<<EOD
1605
	set ipcp enable req-pri-dns
1606
	set ipcp enable req-sec-dns
1607

    
1608
EOD;
1609
	if (!isset($ppp['verbose_log']))
1610
		$mpdconf .= <<<EOD
1611
	#log -bund -ccp -chat -iface -ipcp -lcp -link
1612

    
1613
EOD;
1614
	foreach($ports as $pid => $port){
1615
		$port = get_real_interface($port);
1616
		$mpdconf .= <<<EOD
1617

    
1618
	create link static {$interface}_link{$pid} {$type}
1619
	set link action bundle {$interface}
1620
	set link {$multilink} multilink
1621
	set link keep-alive 10 60
1622
	set link max-redial 0
1623

    
1624
EOD;
1625
		if (isset($ppp['shortseq']))
1626
			$mpdconf .= <<<EOD
1627
	set link no shortseq
1628

    
1629
EOD;
1630

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

    
1635
EOD;
1636

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

    
1641
EOD;
1642

    
1643
		$mpdconf .= <<<EOD
1644
	set link disable chap pap
1645
	set link accept chap pap eap
1646
	set link disable incoming
1647

    
1648
EOD;
1649

    
1650

    
1651
		if (!empty($bandwidths[$pid]))
1652
			$mpdconf .= <<<EOD
1653
	set link bandwidth {$bandwidths[$pid]}
1654

    
1655
EOD;
1656

    
1657
		if (empty($mtus[$pid]))
1658
			$mtus[$pid] = $defaultmtu;
1659
			$mpdconf .= <<<EOD
1660
	set link mtu {$mtus[$pid]}
1661

    
1662
EOD;
1663

    
1664
		if (!empty($mrus[$pid]))
1665
			$mpdconf .= <<<EOD
1666
	set link mru {$mrus[$pid]}
1667

    
1668
EOD;
1669

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

    
1674
EOD;
1675

    
1676
		$mpdconf .= <<<EOD
1677
	set auth authname "{$ppp['username']}"
1678
	set auth password {$passwd}
1679

    
1680
EOD;
1681
		if ($type == "modem") {
1682
			$mpdconf .= <<<EOD
1683
	set modem device {$ppp['ports']}
1684
	set modem script DialPeer
1685
	set modem idle-script Ringback
1686
	set modem watch -cd
1687
	set modem var \$DialPrefix "DT"
1688
	set modem var \$Telephone "{$ppp['phone']}"
1689

    
1690
EOD;
1691
		}
1692
		if (isset($ppp['connect-timeout']) && $type == "modem") {
1693
			$mpdconf .= <<<EOD
1694
	set modem var \$ConnectTimeout "{$ppp['connect-timeout']}"
1695

    
1696
EOD;
1697
		}
1698
		if (isset($ppp['initstr']) && $type == "modem") {
1699
			$initstr = base64_decode($ppp['initstr']);
1700
			$mpdconf .= <<<EOD
1701
	set modem var \$InitString "{$initstr}"
1702

    
1703
EOD;
1704
		}
1705
		if (isset($ppp['simpin']) && $type == "modem") {
1706
			if($ppp['pin-wait'] == "")
1707
				$ppp['pin-wait'] = 0;
1708
			$mpdconf .= <<<EOD
1709
	set modem var \$SimPin "{$ppp['simpin']}"
1710
	set modem var \$PinWait "{$ppp['pin-wait']}"
1711

    
1712
EOD;
1713
		}
1714
		if (isset($ppp['apn']) && $type == "modem") {
1715
			$mpdconf .= <<<EOD
1716
	set modem var \$APN "{$ppp['apn']}"
1717
	set modem var \$APNum "{$ppp['apnum']}"
1718

    
1719
EOD;
1720
		}
1721
		if ($type == "pppoe") {
1722
			// Send a null service name if none is set.
1723
			$provider = isset($ppp['provider']) ? $ppp['provider'] : "";
1724
			$mpdconf .= <<<EOD
1725
	set pppoe service "{$provider}"
1726

    
1727
EOD;
1728
		}
1729
		if ($type == "pppoe")
1730
			$mpdconf .= <<<EOD
1731
	set pppoe iface {$port}
1732

    
1733
EOD;
1734

    
1735
		if ($type == "pptp" || $type == "l2tp") {
1736
			$mpdconf .= <<<EOD
1737
	set {$type} self {$localips[$pid]}
1738
	set {$type} peer {$gateways[$pid]}
1739

    
1740
EOD;
1741
		}
1742

    
1743
		$mpdconf .= "\topen\n";
1744
	} //end foreach($port)
1745

    
1746

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

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

    
1777
	/* clean up old lock files */
1778
	foreach($ports as $port) {
1779
		if(file_exists("{$g['var_path']}/spool/lock/LCK..{$port}"))
1780
			unlink("{$g['var_path']}/spool/lock/LCK..{$port}");
1781
	}
1782

    
1783
	/* fire up mpd */
1784
	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");
1785

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

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

    
1821
	return 1;
1822
}
1823

    
1824
function interfaces_carp_setup() {
1825
	global $g, $config;
1826

    
1827
	if (isset($config['system']['developerspew'])) {
1828
		$mt = microtime();
1829
		echo "interfaces_carp_setup() being called $mt\n";
1830
	}
1831

    
1832
	if ($g['booting']) {
1833
		echo gettext("Configuring CARP settings...");
1834
		mute_kernel_msgs();
1835
	}
1836

    
1837
	/* suck in configuration items */
1838
	if ($config['hasync']) {
1839
		$pfsyncenabled = $config['hasync']['pfsyncenabled'];
1840
		$balanacing = $config['hasync']['balancing'];
1841
		$pfsyncinterface = $config['hasync']['pfsyncinterface'];
1842
		$pfsyncpeerip = $config['hasync']['pfsyncpeerip'];
1843
	} else {
1844
		unset($pfsyncinterface);
1845
		unset($balanacing);
1846
		unset($pfsyncenabled);
1847
	}
1848

    
1849
	if ($balanacing) {
1850
		mwexec("/sbin/sysctl net.inet.carp.arpbalance=1", true);
1851
		mwexec("/sbin/sysctl net.inet.carp.preempt=0", true);
1852
	} else
1853
		mwexec("/sbin/sysctl net.inet.carp.preempt=1", true);
1854

    
1855
	mwexec("sbin/sysctl net.inet.carp.log=1", true);
1856
	if (!empty($pfsyncinterface))
1857
		$carp_sync_int = get_real_interface($pfsyncinterface);
1858
	else
1859
		unset($carp_sync_int);
1860

    
1861
	/* setup pfsync interface */
1862
	if ($carp_sync_int and $pfsyncenabled) {
1863
		if (is_ipaddr($pfsyncpeerip))
1864
			$syncpeer = "syncpeer {$pfsyncpeerip}";
1865
		else
1866
			$syncpeer = "-syncpeer";
1867

    
1868
		mwexec("/sbin/ifconfig pfsync0 syncdev {$carp_sync_int} {$syncpeer} up", false);
1869

    
1870
		sleep(1);
1871

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

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

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

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

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

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

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

    
1925
				if (!empty($interface) && $interface != $proxyif)
1926
					continue;
1927

    
1928
				if (!is_array($paa[$proxyif]))
1929
					$paa[$proxyif] = array();
1930

    
1931
				$paa[$proxyif][] = $vipent;
1932
			}
1933
		}
1934
	}
1935

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

    
1967
function interface_ipalias_cleanup($interface, $inet = "inet4") {
1968
	global $g, $config;
1969

    
1970
	if (is_array($config['virtualip']['vip'])) {
1971
		foreach ($config['virtualip']['vip'] as $vip) {
1972
			if ($vip['mode'] == "ipalias" && $vip['interface'] == $interface) {
1973
				if ($inet == "inet6" && is_ipaddrv6($vip['subnet']))
1974
					interface_vip_bring_down($vip);
1975
				else if ($inet == "inet4" && is_ipaddrv4($vip['subnet']))
1976
					interface_vip_bring_down($vip);
1977
			}
1978
		}
1979
	}
1980
}
1981

    
1982
function interfaces_vips_configure($interface = "") {
1983
	global $g, $config;
1984
	if(isset($config['system']['developerspew'])) {
1985
		$mt = microtime();
1986
		echo "interfaces_vips_configure() being called $mt\n";
1987
	}
1988
	$paa = array();
1989
	if(is_array($config['virtualip']['vip'])) {
1990
		$carp_setuped = false;
1991
		$anyproxyarp = false;
1992
		foreach ($config['virtualip']['vip'] as $vip) {
1993
			switch ($vip['mode']) {
1994
			case "proxyarp":
1995
				/* nothing it is handled on interface_proxyarp_configure() */
1996
				if ($interface <> "" && $vip['interface'] <> $interface)
1997
					continue;
1998
				$anyproxyarp = true;
1999
				break;
2000
			case "ipalias":
2001
				if ($interface <> "" && $vip['interface'] <> $interface)
2002
					continue;
2003
				interface_ipalias_configure($vip);
2004
				break;
2005
			case "carp":
2006
				if ($interface <> "" && $vip['interface'] <> $interface)
2007
					continue;
2008
				if ($carp_setuped == false)
2009
					$carp_setuped = true;
2010
				interface_carp_configure($vip);
2011
				break;
2012
			}
2013
		}
2014
		if ($carp_setuped == true)
2015
			interfaces_carp_setup();
2016
		if ($anyproxyarp == true)
2017
			interface_proxyarp_configure();
2018
	}
2019
}
2020

    
2021
function interface_ipalias_configure(&$vip) {
2022
	if ($vip['mode'] == "ipalias") {
2023
		$if = get_real_interface($vip['interface']);
2024
		$af = "inet";
2025
		if(is_ipaddrv6($vip['subnet']))
2026
			$af = "inet6";
2027
		mwexec("/sbin/ifconfig " . escapeshellarg($if) ." {$af} ". escapeshellarg($vip['subnet']) ."/" . escapeshellarg($vip['subnet_bits']) . " alias");
2028
	}
2029
}
2030

    
2031
function interface_reload_carps($cif) {
2032
	global $config;
2033

    
2034
	$carpifs = link_ip_to_carp_interface(find_interface_ip($cif));
2035
	if (empty($carpifs))
2036
		return;
2037

    
2038
	$carps = explode(" ", $carpifs);
2039
	if(is_array($config['virtualip']['vip'])) {
2040
		$viparr = &$config['virtualip']['vip'];
2041
		foreach ($viparr as $vip) {
2042
			if (in_array($vip['carpif'], $carps)) {
2043
				switch ($vip['mode']) {
2044
				case "carp":
2045
					interface_vip_bring_down($vip);
2046
					sleep(1);
2047
					interface_carp_configure($vip);
2048
					break;
2049
				case "ipalias":
2050
					interface_vip_bring_down($vip);
2051
					sleep(1);
2052
					interface_ipalias_configure($vip);
2053
					break;
2054
				}
2055
			}
2056
		}
2057
	}
2058
}
2059

    
2060
function interface_carp_configure(&$vip) {
2061
	global $config, $g;
2062
	if(isset($config['system']['developerspew'])) {
2063
		$mt = microtime();
2064
		echo "interface_carp_configure() being called $mt\n";
2065
	}
2066

    
2067
	if ($vip['mode'] != "carp")
2068
		return;
2069

    
2070
	/*
2071
	 * ensure the interface containing the VIP really exists
2072
	 * prevents a panic if the interface is missing or invalid
2073
	 */
2074
	$realif = get_real_interface($vip['interface']);
2075
	if (!does_interface_exist($realif)) {
2076
		file_notice("CARP", sprintf(gettext("Interface specified for the virtual IP address %s does not exist. Skipping this VIP."), $vip['subnet']), "Firewall: Virtual IP", "");
2077
		return;
2078
	}
2079

    
2080
	if(is_ipaddrv4($vip['subnet'])) {
2081
		/* Ensure CARP IP really exists prior to loading up. */
2082
		$ww_subnet_ip = find_interface_ip($realif);
2083
		$ww_subnet_bits = find_interface_subnet($realif);
2084
		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'])) {
2085
			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", "");
2086
			return;
2087
		}
2088
	}
2089
	if(is_ipaddrv6($vip['subnet'])) {
2090
		/* Ensure CARP IP really exists prior to loading up. */
2091
		$ww_subnet_ip = find_interface_ipv6($realif);
2092
		$ww_subnet_bits = find_interface_subnetv6($realif);
2093
		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'])) {
2094
			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", "");
2095
			return;
2096
		}
2097
	}
2098

    
2099
	// set the vip interface to the vhid
2100
	$vipif = "{$vip['interface']}_vip{$vip['vhid']}";
2101

    
2102
	/* create the carp interface and setup */
2103
	if (does_interface_exist($vipif)) {
2104
		pfSense_interface_flags($vipif, -IFF_UP);
2105
	} else {
2106
		$carpif = pfSense_interface_create("carp");
2107
		pfSense_interface_rename($carpif, $vipif);
2108
		pfSense_ngctl_name("{$carpif}:", $vipif);
2109
	}
2110

    
2111
	/* invalidate interface cache */
2112
	get_interface_arr(true);
2113

    
2114
	$vip_password = $vip['password'];
2115
	$vip_password = escapeshellarg(addslashes(str_replace(" ", "", $vip_password)));
2116
	if ($vip['password'] != "")
2117
		$password = " pass {$vip_password}";
2118

    
2119
	$broadcast_address = gen_subnet_max($vip['subnet'], $vip['subnet_bits']);
2120
	$advbase = "";
2121
	if (!empty($vip['advbase']))
2122
		$advbase = "advbase {$vip['advbase']}";
2123

    
2124
	if(is_ipaddrv4($vip['subnet'])) {
2125
		$broadcast_address = gen_subnet_max($vip['subnet'], $vip['subnet_bits']);
2126
		mwexec("/sbin/ifconfig {$vipif} {$vip['subnet']}/{$vip['subnet_bits']} vhid {$vip['vhid']} advskew {$vip['advskew']} {$advbase} {$password}");
2127
	}
2128
	if(is_ipaddrv6($vip['subnet'])) {
2129
		$broadcast_address = gen_subnet_max($vip['subnet'], $vip['subnet_bits']);
2130
		mwexec("/sbin/ifconfig {$vipif} inet6 {$vip['subnet']} prefixlen {$vip['subnet_bits']} vhid {$vip['vhid']} advskew {$vip['advskew']} {$advbase} {$password}");
2131
	}
2132

    
2133
	interfaces_bring_up($vipif);
2134

    
2135
	return $vipif;
2136
}
2137

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

    
2179
	if($needs_clone == true) {
2180
		/* remove previous instance if it exists */
2181
		if(does_interface_exist($realif))
2182
			pfSense_interface_destroy($realif);
2183

    
2184
		log_error(sprintf(gettext("Cloning new wireless interface %s"), $realif));
2185
		// Create the new wlan interface. FreeBSD returns the new interface name.
2186
		// example:  wlan2
2187
		exec("/sbin/ifconfig wlan create wlandev {$baseif} {$mode} bssid 2>&1", $out, $ret);
2188
		if($ret <> 0) {
2189
			log_error(sprintf(gettext('Failed to clone interface %1$s with error code %2$s, output %3$s'), $baseif, $ret, $out[0]));
2190
			return false;
2191
		}
2192
		$newif = trim($out[0]);
2193
		// Rename the interface to {$parentnic}_wlan{$number}#: EX: ath0_wlan0
2194
		pfSense_interface_rename($newif, $realif);
2195
		// FIXME: not sure what ngctl is for. Doesn't work.
2196
		// mwexec("/usr/sbin/ngctl name {$newif}: {$realif}", false);
2197
		file_put_contents("{$g['tmp_path']}/{$realif}_oldmac", get_interface_mac($realif));
2198
	}
2199
	return true;
2200
}
2201

    
2202
function interface_sync_wireless_clones(&$ifcfg, $sync_changes = false) {
2203
	global $config, $g;
2204

    
2205
	$shared_settings = array('standard', 'turbo', 'protmode', 'txpower', 'channel',
2206
				 'diversity', 'txantenna', 'rxantenna', 'distance',
2207
				 'regdomain', 'regcountry', 'reglocation');
2208

    
2209
	if(!is_interface_wireless($ifcfg['if']))
2210
		return;
2211

    
2212
	$baseif = interface_get_wireless_base($ifcfg['if']);
2213

    
2214
	// Sync shared settings for assigned clones
2215
	$iflist = get_configured_interface_list(false, true);
2216
	foreach ($iflist as $if) {
2217
		if ($baseif == interface_get_wireless_base($config['interfaces'][$if]['if']) && $ifcfg['if'] != $config['interfaces'][$if]['if']) {
2218
			if (isset($config['interfaces'][$if]['wireless']['standard']) || $sync_changes) {
2219
				foreach ($shared_settings as $setting) {
2220
					if ($sync_changes) {
2221
						if (isset($ifcfg['wireless'][$setting]))
2222
							$config['interfaces'][$if]['wireless'][$setting] = $ifcfg['wireless'][$setting];
2223
						else if (isset($config['interfaces'][$if]['wireless'][$setting]))
2224
							unset($config['interfaces'][$if]['wireless'][$setting]);
2225
					} else {
2226
						if (isset($config['interfaces'][$if]['wireless'][$setting]))
2227
							$ifcfg['wireless'][$setting] = $config['interfaces'][$if]['wireless'][$setting];
2228
						else if (isset($ifcfg['wireless'][$setting]))
2229
							unset($ifcfg['wireless'][$setting]);
2230
					}
2231
				}
2232
				if (!$sync_changes)
2233
					break;
2234
			}
2235
		}
2236
	}
2237

    
2238
	// Read or write settings at shared area
2239
	if (isset($config['wireless']['interfaces'][$baseif]) && is_array($config['wireless']['interfaces'][$baseif])) {
2240
		foreach ($shared_settings as $setting) {
2241
			if ($sync_changes) {
2242
				if (isset($ifcfg['wireless'][$setting]))
2243
					$config['wireless']['interfaces'][$baseif][$setting] = $ifcfg['wireless'][$setting];
2244
				else if (isset($config['wireless']['interfaces'][$baseif][$setting]))
2245
					unset($config['wireless']['interfaces'][$baseif][$setting]);
2246
			} else if (isset($config['wireless']['interfaces'][$baseif][$setting])) {
2247
				if (isset($config['wireless']['interfaces'][$baseif][$setting]))
2248
					$ifcfg['wireless'][$setting] = $config['wireless']['interfaces'][$baseif][$setting];
2249
				else if (isset($ifcfg['wireless'][$setting]))
2250
					unset($ifcfg['wireless'][$setting]);
2251
			}
2252
		}
2253
	}
2254

    
2255
	// Sync the mode on the clone creation page with the configured mode on the interface
2256
	if (interface_is_wireless_clone($ifcfg['if']) && isset($config['wireless']['clone']) && is_array($config['wireless']['clone'])) {
2257
		foreach ($config['wireless']['clone'] as &$clone) {
2258
			if ($clone['cloneif'] == $ifcfg['if']) {
2259
				if ($sync_changes) {
2260
					$clone['mode'] = $ifcfg['wireless']['mode'];
2261
				} else {
2262
					$ifcfg['wireless']['mode'] = $clone['mode'];
2263
				}
2264
				break;
2265
			}
2266
		}
2267
		unset($clone);
2268
	}
2269
}
2270

    
2271
function interface_wireless_configure($if, &$wl, &$wlcfg) {
2272
	global $config, $g;
2273

    
2274
	/*    open up a shell script that will be used to output the commands.
2275
	 *    since wireless is changing a lot, these series of commands are fragile
2276
	 *    and will sometimes need to be verified by a operator by executing the command
2277
	 *    and returning the output of the command to the developers for inspection.  please
2278
	 *    do not change this routine from a shell script to individual exec commands.  -sullrich
2279
	 */
2280

    
2281
	// Remove script file
2282
	unlink_if_exists("{$g['tmp_path']}/{$if}_setup.sh");
2283

    
2284
	// Clone wireless nic if needed.
2285
	interface_wireless_clone($if, $wl);
2286

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

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

    
2294
	/* set values for /path/program */
2295
	$hostapd = "/usr/sbin/hostapd";
2296
	$wpa_supplicant = "/usr/sbin/wpa_supplicant";
2297
	$ifconfig = "/sbin/ifconfig";
2298
	$sysctl = "/sbin/sysctl";
2299
	$killall = "/usr/bin/killall";
2300

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

    
2303
	$wlcmd = array();
2304
	$wl_sysctl = array();
2305
	/* Make sure it's up */
2306
	$wlcmd[] = "up";
2307
	/* Set a/b/g standard */
2308
	$standard = str_replace(" Turbo", "", $wlcfg['standard']);
2309
	$wlcmd[] = "mode " . escapeshellarg($standard);
2310

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

    
2316
	/* Set ssid */
2317
	if($wlcfg['ssid'])
2318
		$wlcmd[] = "ssid " .escapeshellarg($wlcfg['ssid']);
2319

    
2320
	/* Set 802.11g protection mode */
2321
	$wlcmd[] = "protmode " . escapeshellarg($wlcfg['protmode']);
2322

    
2323
	/* set wireless channel value */
2324
	if(isset($wlcfg['channel'])) {
2325
		if($wlcfg['channel'] == "0") {
2326
			$wlcmd[] = "channel any";
2327
		} else {
2328
			$wlcmd[] = "channel " . escapeshellarg($wlcfg['channel']);
2329
		}
2330
	}
2331

    
2332
	/* Set antenna diversity value */
2333
	if(isset($wlcfg['diversity']))
2334
		$wl_sysctl[] = "diversity=" . escapeshellarg($wlcfg['diversity']);
2335

    
2336
	/* Set txantenna value */
2337
	if(isset($wlcfg['txantenna']))
2338
		$wl_sysctl[] = "txantenna=" . escapeshellarg($wlcfg['txantenna']);
2339

    
2340
	/* Set rxantenna value */
2341
	if(isset($wlcfg['rxantenna']))
2342
		$wl_sysctl[] = "rxantenna=" . escapeshellarg($wlcfg['rxantenna']);
2343

    
2344
	/* set Distance value */
2345
	if($wlcfg['distance'])
2346
		$distance = escapeshellarg($wlcfg['distance']);
2347

    
2348
	/* Set wireless hostap mode */
2349
	if ($wlcfg['mode'] == "hostap") {
2350
		$wlcmd[] = "mediaopt hostap";
2351
	} else {
2352
		$wlcmd[] = "-mediaopt hostap";
2353
	}
2354

    
2355
	/* Set wireless adhoc mode */
2356
	if ($wlcfg['mode'] == "adhoc") {
2357
		$wlcmd[] = "mediaopt adhoc";
2358
	} else {
2359
		$wlcmd[] = "-mediaopt adhoc";
2360
	}
2361

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

    
2364
	/* handle hide ssid option */
2365
	if(isset($wlcfg['hidessid']['enable'])) {
2366
		$wlcmd[] = "hidessid";
2367
	} else {
2368
		$wlcmd[] = "-hidessid";
2369
	}
2370

    
2371
	/* handle pureg (802.11g) only option */
2372
	if(isset($wlcfg['pureg']['enable'])) {
2373
		$wlcmd[] = "mode 11g pureg";
2374
	} else {
2375
		$wlcmd[] = "-pureg";
2376
	}
2377

    
2378
	/* handle puren (802.11n) only option */
2379
	if(isset($wlcfg['puren']['enable'])) {
2380
		$wlcmd[] = "puren";
2381
	} else {
2382
		$wlcmd[] = "-puren";
2383
	}
2384

    
2385
	/* enable apbridge option */
2386
	if(isset($wlcfg['apbridge']['enable'])) {
2387
		$wlcmd[] = "apbridge";
2388
	} else {
2389
		$wlcmd[] = "-apbridge";
2390
	}
2391

    
2392
	/* handle turbo option */
2393
	if(isset($wlcfg['turbo']['enable'])) {
2394
		$wlcmd[] = "mediaopt turbo";
2395
	} else {
2396
		$wlcmd[] = "-mediaopt turbo";
2397
	}
2398

    
2399
	/* handle txpower setting */
2400
	/* if($wlcfg['txpower'] <> "")
2401
		$wlcmd[] = "txpower " . escapeshellarg($wlcfg['txpower']);
2402
	*/
2403
	/* handle wme option */
2404
	if(isset($wlcfg['wme']['enable'])) {
2405
		$wlcmd[] = "wme";
2406
	} else {
2407
		$wlcmd[] = "-wme";
2408
	}
2409

    
2410
	/* set up wep if enabled */
2411
	$wepset = "";
2412
	if (isset($wlcfg['wep']['enable']) && is_array($wlcfg['wep']['key'])) {
2413
		switch($wlcfg['wpa']['auth_algs']) {
2414
			case "1":
2415
				$wepset .= "authmode open wepmode on ";
2416
				break;
2417
			case "2":
2418
				$wepset .= "authmode shared wepmode on ";
2419
				break;
2420
			case "3":
2421
				$wepset .= "authmode mixed wepmode on ";
2422
		}
2423
		$i = 1;
2424
		foreach ($wlcfg['wep']['key'] as $wepkey) {
2425
			$wepset .= "wepkey " . escapeshellarg("{$i}:{$wepkey['value']}") . " ";
2426
			if (isset($wepkey['txkey'])) {
2427
				$wlcmd[] = "weptxkey {$i} ";
2428
			}
2429
			$i++;
2430
		}
2431
		$wlcmd[] = $wepset;
2432
	} else {
2433
		$wlcmd[] = "authmode open wepmode off ";
2434
	}
2435

    
2436
	kill_hostapd($if);
2437
	mwexec(kill_wpasupplicant("{$if}"));
2438

    
2439
	/* generate wpa_supplicant/hostap config if wpa is enabled */
2440
	conf_mount_rw();
2441

    
2442
	switch ($wlcfg['mode']) {
2443
		case 'bss':
2444
			if (isset($wlcfg['wpa']['enable'])) {
2445
				$wpa .= <<<EOD
2446
ctrl_interface={$g['varrun_path']}/wpa_supplicant
2447
ctrl_interface_group=0
2448
ap_scan=1
2449
#fast_reauth=1
2450
network={
2451
ssid="{$wlcfg['ssid']}"
2452
scan_ssid=1
2453
priority=5
2454
key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
2455
psk="{$wlcfg['wpa']['passphrase']}"
2456
pairwise={$wlcfg['wpa']['wpa_pairwise']}
2457
group={$wlcfg['wpa']['wpa_pairwise']}
2458
}
2459
EOD;
2460

    
2461
				$fd = fopen("{$g['varetc_path']}/wpa_supplicant_{$if}.conf", "w");
2462
				fwrite($fd, "{$wpa}");
2463
				fclose($fd);
2464
			}
2465
			break;
2466
		case 'hostap':
2467
			if($wlcfg['wpa']['passphrase'])
2468
				$wpa_passphrase = "wpa_passphrase={$wlcfg['wpa']['passphrase']}\n";
2469
			else
2470
				$wpa_passphrase = "";
2471
			if (isset($wlcfg['wpa']['enable'])) {
2472
				$wpa .= <<<EOD
2473
interface={$if}
2474
driver=bsd
2475
logger_syslog=-1
2476
logger_syslog_level=0
2477
logger_stdout=-1
2478
logger_stdout_level=0
2479
dump_file={$g['tmp_path']}/hostapd_{$if}.dump
2480
ctrl_interface={$g['varrun_path']}/hostapd
2481
ctrl_interface_group=wheel
2482
#accept_mac_file={$g['tmp_path']}/hostapd_{$if}.accept
2483
#deny_mac_file={$g['tmp_path']}/hostapd_{$if}.deny
2484
#macaddr_acl={$wlcfg['wpa']['macaddr_acl']}
2485
ssid={$wlcfg['ssid']}
2486
debug={$wlcfg['wpa']['debug_mode']}
2487
auth_algs={$wlcfg['wpa']['auth_algs']}
2488
wpa={$wlcfg['wpa']['wpa_mode']}
2489
wpa_key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
2490
wpa_pairwise={$wlcfg['wpa']['wpa_pairwise']}
2491
wpa_group_rekey={$wlcfg['wpa']['wpa_group_rekey']}
2492
wpa_gmk_rekey={$wlcfg['wpa']['wpa_gmk_rekey']}
2493
wpa_strict_rekey={$wlcfg['wpa']['wpa_strict_rekey']}
2494
{$wpa_passphrase}
2495

    
2496
EOD;
2497

    
2498
if (isset($wlcfg['wpa']['rsn_preauth'])) {
2499
	$wpa .= <<<EOD
2500
# Enable the next lines for preauth when roaming. Interface = wired or wireless interface talking to the AP you want to roam from/to
2501
rsn_preauth=1
2502
rsn_preauth_interfaces={$if}
2503

    
2504
EOD;
2505

    
2506
}
2507
				if($wlcfg['auth_server_addr'] && $wlcfg['auth_server_shared_secret']) {
2508
					$auth_server_port = "1812";
2509
					if($wlcfg['auth_server_port'])
2510
						$auth_server_port = $wlcfg['auth_server_port'];
2511
					$auth_server_port2 = "1812";
2512
					if($wlcfg['auth_server_port2'])
2513
						$auth_server_port2 = $wlcfg['auth_server_port2'];
2514
					$wpa .= <<<EOD
2515

    
2516
ieee8021x=1
2517
auth_server_addr={$wlcfg['auth_server_addr']}
2518
auth_server_port={$auth_server_port}
2519
auth_server_shared_secret={$wlcfg['auth_server_shared_secret']}
2520
auth_server_addr={$wlcfg['auth_server_addr2']}
2521
auth_server_port={$auth_server_port2}
2522
auth_server_shared_secret={$wlcfg['auth_server_shared_secret2']}
2523

    
2524
EOD;
2525
				} else {
2526
					$wpa .= "ieee8021x={$wlcfg['wpa']['ieee8021x']}\n";
2527
				}
2528

    
2529
				$fd = fopen("{$g['varetc_path']}/hostapd_{$if}.conf", "w");
2530
				fwrite($fd, "{$wpa}");
2531
				fclose($fd);
2532

    
2533
			}
2534
			break;
2535
	}
2536

    
2537
	/*
2538
	 *    all variables are set, lets start up everything
2539
	 */
2540

    
2541
	$baseif = interface_get_wireless_base($if);
2542
	preg_match("/^(.*?)([0-9]*)$/", $baseif, $baseif_split);
2543
	$wl_sysctl_prefix = 'dev.' . $baseif_split[1] . '.' . $baseif_split[2];
2544

    
2545
	/* set sysctls for the wireless interface */
2546
	if (!empty($wl_sysctl)) {
2547
		fwrite($fd_set, "# sysctls for {$baseif}\n");
2548
		foreach ($wl_sysctl as $wl_sysctl_line) {
2549
			fwrite($fd_set, "{$sysctl} {$wl_sysctl_prefix}.{$wl_sysctl_line}\n");
2550
		}
2551
	}
2552

    
2553
	/* set ack timers according to users preference (if he/she has any) */
2554
	if($distance) {
2555
		fwrite($fd_set, "# Enable ATH distance settings\n");
2556
		fwrite($fd_set, "/sbin/athctrl.sh -i {$baseif} -d {$distance}\n");
2557
	}
2558

    
2559
	if (isset($wlcfg['wpa']['enable'])) {
2560
		if ($wlcfg['mode'] == "bss") {
2561
			fwrite($fd_set, "{$wpa_supplicant} -B -i {$if} -c {$g['varetc_path']}/wpa_supplicant_{$if}.conf\n");
2562
		}
2563
		if ($wlcfg['mode'] == "hostap") {
2564
			/* add line to script to restore old mac to make hostapd happy */
2565
			if (file_exists("{$g['tmp_path']}/{$if}_oldmac")) {
2566
				$if_oldmac = file_get_contents("{$g['tmp_path']}/{$if}_oldmac");
2567
				if (is_macaddr($if_oldmac))
2568
					fwrite($fd_set, "{$ifconfig} " . escapeshellarg($if) .
2569
						" link " . escapeshellarg($if_oldmac) . "\n");
2570
			}
2571

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

    
2574
			/* add line to script to restore spoofed mac after running hostapd */
2575
			if (file_exists("{$g['tmp_path']}/{$if}_oldmac")) {
2576
				if ($wl['spoofmac'])
2577
					$if_curmac = $wl['spoofmac'];
2578
				else
2579
					$if_curmac = get_interface_mac($if);
2580
				if (is_macaddr($if_curmac))
2581
					fwrite($fd_set, "{$ifconfig} " . escapeshellarg($if) .
2582
						" link " . escapeshellarg($if_curmac) . "\n");
2583
			}
2584
		}
2585
	}
2586

    
2587
	fclose($fd_set);
2588
	conf_mount_ro();
2589

    
2590
	/* Making sure regulatory settings have actually changed
2591
	 * before applying, because changing them requires bringing
2592
	 * down all wireless networks on the interface. */
2593
	exec("{$ifconfig} " . escapeshellarg($if), $output);
2594
	$ifconfig_str = implode($output);
2595
	unset($output);
2596
	$reg_changing = false;
2597

    
2598
	/* special case for the debug country code */
2599
	if ($wlcfg['regcountry'] == 'DEBUG' && !preg_match("/\sregdomain\s+DEBUG\s/si", $ifconfig_str))
2600
		$reg_changing = true;
2601
	else if ($wlcfg['regdomain'] && !preg_match("/\sregdomain\s+{$wlcfg['regdomain']}\s/si", $ifconfig_str))
2602
		$reg_changing = true;
2603
	else if ($wlcfg['regcountry'] && !preg_match("/\scountry\s+{$wlcfg['regcountry']}\s/si", $ifconfig_str))
2604
		$reg_changing = true;
2605
	else if ($wlcfg['reglocation'] == 'anywhere' && preg_match("/\s(indoor|outdoor)\s/si", $ifconfig_str))
2606
		$reg_changing = true;
2607
	else if ($wlcfg['reglocation'] && $wlcfg['reglocation'] != 'anywhere' && !preg_match("/\s{$wlcfg['reglocation']}\s/si", $ifconfig_str))
2608
		$reg_changing = true;
2609

    
2610
	if ($reg_changing) {
2611
		/* set regulatory domain */
2612
		if($wlcfg['regdomain'])
2613
			$wlregcmd[] = "regdomain " . escapeshellarg($wlcfg['regdomain']);
2614

    
2615
		/* set country */
2616
		if($wlcfg['regcountry'])
2617
			$wlregcmd[] = "country " . escapeshellarg($wlcfg['regcountry']);
2618

    
2619
		/* set location */
2620
		if($wlcfg['reglocation'])
2621
			$wlregcmd[] = escapeshellarg($wlcfg['reglocation']);
2622

    
2623
		$wlregcmd_args = implode(" ", $wlregcmd);
2624

    
2625
		/* build a complete list of the wireless clones for this interface */
2626
		$clone_list = array();
2627
		if (does_interface_exist(interface_get_wireless_clone($baseif)))
2628
			$clone_list[] = interface_get_wireless_clone($baseif);
2629
		if (isset($config['wireless']['clone']) && is_array($config['wireless']['clone'])) {
2630
			foreach ($config['wireless']['clone'] as $clone) {
2631
				if ($clone['if'] == $baseif)
2632
					$clone_list[] = $clone['cloneif'];
2633
			}
2634
		}
2635

    
2636
		/* find which clones are up and bring them down */
2637
		$clones_up = array();
2638
		foreach ($clone_list as $clone_if) {
2639
			$clone_status = pfSense_get_interface_addresses($clone_if);
2640
			if ($clone_status['status'] == 'up') {
2641
				$clones_up[] = $clone_if;
2642
				mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " down");
2643
			}
2644
		}
2645

    
2646
		/* apply the regulatory settings */
2647
		mwexec("{$ifconfig} " . escapeshellarg($if) . " {$wlregcmd_args}");
2648

    
2649
		/* bring the clones back up that were previously up */
2650
		foreach ($clones_up as $clone_if) {
2651
			mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " up");
2652

    
2653
			/*
2654
			 * Rerun the setup script for the interface if it isn't this interface, the interface
2655
			 * is in infrastructure mode, and WPA is enabled.
2656
			 * This can be removed if wpa_supplicant stops dying when you bring the interface down.
2657
			 */
2658
			if ($clone_if != $if) {
2659
				$friendly_if = convert_real_interface_to_friendly_interface_name($clone_if);
2660
				if ( !empty($friendly_if)
2661
				    && $config['interfaces'][$friendly_if]['wireless']['mode'] == "bss"
2662
				    && isset($config['interfaces'][$friendly_if]['wireless']['wpa']['enable']) ) {
2663
					mwexec("/bin/sh {$g['tmp_path']}/{$clone_if}_setup.sh");
2664
				}
2665
			}
2666
		}
2667
	}
2668

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

    
2673
	/* configure wireless */
2674
	$wlcmd_args = implode(" ", $wlcmd);
2675
	mwexec("/sbin/ifconfig {$if} $wlcmd_args", false);
2676

    
2677

    
2678
	sleep(1);
2679
	/* execute hostapd and wpa_supplicant if required in shell */
2680
	mwexec("/bin/sh {$g['tmp_path']}/{$if}_setup.sh");
2681

    
2682
	return 0;
2683

    
2684
}
2685

    
2686
function kill_hostapd($interface) {
2687
	global $g;
2688

    
2689
	if (isvalidpid("{$g['varrun_path']}/hostapd_{$interface}.pid"))
2690
		return killbypid("{$g['varrun_path']}/hostapd_{$interface}.pid");
2691
}
2692

    
2693
function kill_wpasupplicant($interface) {
2694
	return "/bin/pkill -f \"wpa_supplicant .*{$interface}\\.conf\"\n";
2695
}
2696

    
2697
function find_dhclient_process($interface) {
2698
	if ($interface)
2699
		$pid = `/bin/pgrep -axf "dhclient: {$interface}"`;
2700
	else
2701
		$pid = 0;
2702

    
2703
	return intval($pid);
2704
}
2705

    
2706
function find_dhcp6c_process($interface) {
2707
	global $g;
2708

    
2709
	if ($interface && isvalidpid("{$g['varrun_path']}/dhcp6c_{$interface}.pid"))
2710
		$pid = trim(file_get_contents("{$g['varrun_path']}/dhcp6c_{$interface}.pid"), " \n");
2711
	else
2712
		return(false);
2713

    
2714
	return intval($pid);
2715
}
2716

    
2717
function interface_vlan_mtu_configured($realhwif, $mtu) {
2718
	global $config;
2719

    
2720
	if (is_array($config['vlans']['vlan'])) {
2721
		foreach ($config['vlans']['vlan'] as $vlan) {
2722
			if ($vlan['if'] != $realhwif)
2723
				continue;
2724
			$assignedport = convert_real_interface_to_friendly_interface_name($vlan['vlanif']);
2725
			if (!empty($assignedport)) {
2726
				$portmtu = $config['interfaces'][$assignedport]['mtu'];
2727
				if (!empty($portmtu) && $portmtu > $mtu)
2728
					$mtu = $portmtu;
2729
			}
2730
		}
2731
	}
2732

    
2733
	return $mtu;
2734
}
2735

    
2736
function interface_configure($interface = "wan", $reloadall = false, $linkupevent = false) {
2737
	global $config, $g;
2738
	global $interface_sn_arr_cache, $interface_ip_arr_cache;
2739
	global $interface_snv6_arr_cache, $interface_ipv6_arr_cache;
2740

    
2741
	$wancfg = $config['interfaces'][$interface];
2742

    
2743
	if (!isset($wancfg['enable']))
2744
		return;
2745

    
2746
	$realif = get_real_interface($interface);
2747
	$realhwif_array = get_parent_interface($interface);
2748
	// Need code to handle MLPPP if we ever use $realhwif for MLPPP handling
2749
	$realhwif = $realhwif_array[0];
2750

    
2751
	/* Disable Accepting router advertisements unless specifically requested */
2752
	if ($g['debug'])
2753
		log_error("Deny router advertisements for interface {$interface}");
2754
	mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 -accept_rtadv");
2755

    
2756
	if (!$g['booting'] && !(substr($realif, 0, 4) == "ovpn")) {
2757
		/* remove all IPv4 and IPv6 addresses */
2758
		while (mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " -alias", true) == 0);
2759
		while (mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 -alias", true) == 0);
2760

    
2761
		/* only bring down the interface when both v4 and v6 are set to NONE */
2762
		if(empty($wancfg['ipaddr']) && empty($wancfg['ipaddrv6'])) {
2763
			interface_bring_down($interface);
2764
		}
2765
	}
2766

    
2767
	/* wireless configuration? */
2768
	if (is_array($wancfg['wireless']))
2769
		interface_wireless_configure($realif, $wancfg, $wancfg['wireless']);
2770

    
2771
	$mac = get_interface_mac($realhwif);
2772
	/*
2773
	 * Don't try to reapply the spoofed MAC if it's already applied.
2774
	 * When ifconfig link is used, it cycles the interface down/up, which triggers
2775
	 * the interface config again, which attempts to spoof the MAC again,
2776
	 * which cycles the link again...
2777
	 */
2778
	if ($wancfg['spoofmac'] && ($wancfg['spoofmac'] != $mac)) {
2779
		mwexec("/sbin/ifconfig " . escapeshellarg($realhwif) .
2780
			" link " . escapeshellarg($wancfg['spoofmac']));
2781

    
2782
		/*
2783
		 * All vlans need to spoof their parent mac address, too.  see
2784
		 * ticket #1514: http://cvstrac.pfsense.com/tktview?tn=1514,33
2785
		 */
2786
		if (is_array($config['vlans']['vlan'])) {
2787
			foreach ($config['vlans']['vlan'] as $vlan) {
2788
				if ($vlan['if'] == $realhwif)
2789
					mwexec("/sbin/ifconfig " . escapeshellarg($vlan['vlanif']) .
2790
					" link " . escapeshellarg($wancfg['spoofmac']));
2791
			}
2792
		}
2793
	}  else {
2794

    
2795
		if ($mac == "ff:ff:ff:ff:ff:ff") {
2796
			/*   this is not a valid mac address.  generate a
2797
			 *   temporary mac address so the machine can get online.
2798
			 */
2799
			echo gettext("Generating new MAC address.");
2800
			$random_mac = generate_random_mac_address();
2801
			mwexec("/sbin/ifconfig " . escapeshellarg($realhwif) .
2802
				" link " . escapeshellarg($random_mac));
2803
			$wancfg['spoofmac'] = $random_mac;
2804
			write_config();
2805
			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");
2806
		}
2807
	}
2808

    
2809
	/* media */
2810
	if ($wancfg['media'] || $wancfg['mediaopt']) {
2811
		$cmd = "/sbin/ifconfig " . escapeshellarg($realhwif);
2812
		if ($wancfg['media'])
2813
			$cmd .= " media " . escapeshellarg($wancfg['media']);
2814
		if ($wancfg['mediaopt'])
2815
			$cmd .= " mediaopt " . escapeshellarg($wancfg['mediaopt']);
2816
		mwexec($cmd);
2817
	}
2818
	$options = pfSense_get_interface_addresses($realhwif);
2819
	if (is_array($options) && isset($options['caps']['polling'])) {
2820
		if (isset($config['system']['polling']))
2821
			pfSense_interface_capabilities($realif, IFCAP_POLLING);
2822
		else
2823
			pfSense_interface_capabilities($realif, -IFCAP_POLLING);
2824
	}
2825

    
2826
	/* skip vlans for checksumming and polling */
2827
	if (!stristr($realif, "_vlan") && is_array($options)) {
2828
		$flags = 0;
2829
		if(isset($config['system']['disablechecksumoffloading'])) {
2830
			if (isset($options['encaps']['txcsum']))
2831
				$flags |= IFCAP_TXCSUM;
2832
			if (isset($options['encaps']['rxcsum']))
2833
				$flags |= IFCAP_RXCSUM;
2834
		} else {
2835
			if (!isset($options['caps']['txcsum']))
2836
				$flags |= IFCAP_TXCSUM;
2837
			if (!isset($options['caps']['rxcsum']))
2838
				$flags |= IFCAP_RXCSUM;
2839
		}
2840

    
2841
		if(isset($config['system']['disablesegmentationoffloading'])) {
2842
			if (isset($options['encaps']['tso4']))
2843
				$flags |= IFCAP_TSO;
2844
			if (isset($options['encaps']['tso6']))
2845
				$flags |= IFCAP_TSO;
2846
		} else {
2847
			if (!isset($options['caps']['tso4']))
2848
				$flags |= IFCAP_TSO;
2849
			if (!isset($options['caps']['tso6']))
2850
				$flags |= IFCAP_TSO;
2851
		}
2852

    
2853
		if(isset($config['system']['disablelargereceiveoffloading'])) {
2854
			if (isset($options['encaps']['lro']))
2855
				$flags |= IFCAP_LRO;
2856
		} else {
2857
			if (!isset($options['caps']['lro']))
2858
				$flags |= IFCAP_LRO;
2859
		}
2860

    
2861
		/* if the NIC supports polling *AND* it is enabled in the GUI */
2862
		if (!isset($config['system']['polling']) || !isset($options['caps']['polling'])) {
2863
			$flags |= IFCAP_POLLING;
2864
		}
2865
		pfSense_interface_capabilities($realhwif, -$flags);
2866
	}
2867

    
2868
	/* invalidate interface/ip/sn cache */
2869
	get_interface_arr(true);
2870
	unset($interface_ip_arr_cache[$realif]);
2871
	unset($interface_sn_arr_cache[$realif]);
2872
	unset($interface_ipv6_arr_cache[$realif]);
2873
	unset($interface_snv6_arr_cache[$realif]);
2874

    
2875
	switch ($wancfg['ipaddr']) {
2876
		case 'dhcp':
2877
			interface_dhcp_configure($interface);
2878
			break;
2879
		case 'pppoe':
2880
		case 'l2tp':
2881
		case 'pptp':
2882
		case 'ppp':
2883
			interface_ppps_configure($interface);
2884
			break;
2885
		default:
2886
			if (is_ipaddr($wancfg['ipaddr']) && $wancfg['subnet'] <> "") {
2887
				pfSense_interface_setaddress($realif, "{$wancfg['ipaddr']}/{$wancfg['subnet']}");
2888
			} else if (substr($realif, 0, 3) == "gre") {
2889
				if (is_array($config['gres']['gre'])) {
2890
					foreach ($config['gres']['gre'] as $gre)
2891
						if ($gre['greif'] == $realif)
2892
							interface_gre_configure($gre);
2893
				}
2894
			} else if (substr($realif, 0, 3) == "gif") {
2895
				if (is_array($config['gifs']['gif'])) {
2896
					foreach ($config['gifs']['gif'] as $gif)
2897
						if($gif['gifif'] == $realif)
2898
							interface_gif_configure($gif);
2899
				}
2900
			} else if (substr($realif, 0, 4) == "ovpn") {
2901
				/* XXX: Should be done anything?! */
2902
			}
2903
			break;
2904
	}
2905

    
2906
	switch ($wancfg['ipaddrv6']) {
2907
		case 'slaac':
2908
		case 'dhcp6':
2909
			interface_dhcpv6_configure($interface, $wancfg);
2910
			break;
2911
		case '6rd':
2912
			interface_6rd_configure($interface, $wancfg);
2913
			break;
2914
		case '6to4':
2915
			interface_6to4_configure($interface, $wancfg);
2916
			break;
2917
		case 'track6':
2918
			interface_track6_configure($interface, $wancfg);
2919
			break;
2920
		default:
2921
			if (is_ipaddr($wancfg['ipaddrv6']) && $wancfg['subnetv6'] <> "") {
2922
				pfSense_interface_setaddress($realif, "{$wancfg['ipaddrv6']}/{$wancfg['subnetv6']}");
2923
				// FIXME: Add IPv6 Support to the pfSense module
2924
				mwexec("/sbin/ifconfig {$realif} inet6 {$wancfg['ipaddrv6']} prefixlen {$wancfg['subnetv6']} ");
2925
			}
2926
			break;
2927
	}
2928

    
2929
	$mtu = get_interface_default_mtu(remove_ifindex($realhwif));
2930
	$assignedparent = convert_real_interface_to_friendly_interface_name($realhwif);
2931
	if (!empty($assignedparent) && !empty($config['interfaces'][$assignedparent]['mtu']))
2932
		$mtu = $config['interfaces'][$assignedparent]['mtu'];
2933

    
2934
	$vlanifs = link_interface_to_vlans($realhwif);
2935
	if (empty($vlanifs))
2936
		$vlanifs = array();
2937

    
2938
	if (!empty($wancfg['mtu'])) {
2939
		if (stristr($realif, "_vlan")) {
2940
			if (!empty($assignedparent)) {
2941
				$parentmtu = $config['interfaces'][$assignedparent]['mtu'];
2942
				if (empty($parentmtu))
2943
					$parentmtu = interface_vlan_mtu_configured($realhwif, $wancfg['mtu']);
2944
				if ($wancfg['mtu'] > $parentmtu) {
2945
					if (get_interface_mtu($realhwif) != $wancfg['mtu'])
2946
						pfSense_interface_mtu($realhwif, $wancfg['mtu']);
2947

    
2948
					/* All vlans need to use the same mtu value as their parent. */
2949
					foreach ($vlanifs as $vlan) {
2950
						if ($vlan['vlanif'] == $realif)
2951
							continue;
2952
						$assignedport = convert_real_interface_to_friendly_interface_name($vlan['vlanif']);
2953
						if (!empty($assignedport)) {
2954
							$portmtu = $config['interfaces'][$assignedport]['mtu'];
2955
							if (empty($portmtu) && (get_interface_mtu($vlan['vlanif']) != $wancfg['mtu']))
2956
								pfSense_interface_mtu($vlan['vlanif'], $wancfg['mtu']);
2957
						} else if (get_interface_mtu($vlan['vlanif']) != $wancfg['mtu'])
2958
							pfSense_interface_mtu($vlan['vlanif'], $wancfg['mtu']);
2959
					}
2960
				}
2961
			} else {
2962
				/* Parent is not assigned, back to default */
2963
				if (get_interface_mtu($realhwif) != $mtu)
2964
					pfSense_interface_mtu($realhwif, $mtu);
2965

    
2966
				/* All vlans need to use the same mtu value as their parent. */
2967
				foreach ($vlanifs as $vlan) {
2968
					if ($vlan['vlanif'] == $realif)
2969
						continue;
2970
					$assignedport = convert_real_interface_to_friendly_interface_name($vlan['vlanif']);
2971
					if (!empty($assignedport)) {
2972
						$portmtu = $config['interfaces'][$assignedport]['mtu'];
2973
						if (empty($portmtu) && (get_interface_mtu($vlan['vlanif']) != $mtu))
2974
							pfSense_interface_mtu($vlan['vlanif'], $mtu);
2975
					} else if (get_interface_mtu($vlan['vlanif']) != $mtu)
2976
						pfSense_interface_mtu($vlan['vlanif'], $mtu);
2977
				}
2978

    
2979
				if (get_interface_mtu($realif) != $wancfg['mtu'])
2980
					pfSense_interface_mtu($realif, $wancfg['mtu']);
2981
			}
2982
		} else {
2983
			foreach ($vlanifs as $vlan) {
2984
				$assignedport = convert_real_interface_to_friendly_interface_name($vlan['vlanif']);
2985
				if (empty($assignedport)) {
2986
					if (get_interface_mtu($vlan['vlanif']) != $wancfg['mtu'])
2987
						pfSense_interface_mtu($vlan['vlanif'], $wancfg['mtu']);
2988
				} else {
2989
					$vlanmtu = $config['interfaces'][$assignedport]['mtu'];
2990
					if ((empty($vlanmtu) || ($vlanmtu >= $wancfg['mtu'])) && (get_interface_mtu($vlan['vlanif']) != $wancfg['mtu']))
2991
						pfSense_interface_mtu($vlan['vlanif'], $wancfg['mtu']);
2992
				}
2993
			}
2994
		}
2995
		if ($wancfg['mtu'] != get_interface_mtu($realif))
2996
			pfSense_interface_mtu($realif, $wancfg['mtu']);
2997
	} else if (stristr($realif, "_vlan")) {
2998
		/* XXX: This is really dangerous for example with vlans changing their parent mtu! */
2999
		$bigmtu = interface_vlan_mtu_configured($realhwif, $mtu);
3000
		if ($mtu < $bigmtu)
3001
			$mtu = $bigmtu;
3002

    
3003
		if (get_interface_mtu($realhwif) != $mtu)
3004
			pfSense_interface_mtu($realhwif, $mtu);
3005

    
3006
		/* All vlans need to use the same mtu value as their parent. */
3007
		foreach ($vlanifs as $vlan) {
3008
			if ($vlan['vlanif'] == $realif)
3009
				continue;
3010
			$assignedport = convert_real_interface_to_friendly_interface_name($vlan['vlanif']);
3011
			if (!empty($assignedport)) {
3012
				$portmtu = $config['interfaces'][$assignedport]['mtu'];
3013
				if (empty($portmtu) && (get_interface_mtu($vlan['vlanif']) != $mtu))
3014
					pfSense_interface_mtu($vlan['vlanif'], $mtu);
3015
			} else if (get_interface_mtu($vlan['vlanif']) != $mtu)
3016
				pfSense_interface_mtu($vlan['vlanif'], $mtu);
3017
		}
3018
		if (get_interface_mtu($realif) != $mtu)
3019
			pfSense_interface_mtu($realif, $mtu);
3020
	} else {
3021
		/* All vlans need to use the same mtu value as their parent. */
3022
		foreach ($vlanifs as $vlan) {
3023
			$assignedport = convert_real_interface_to_friendly_interface_name($vlan['vlanif']);
3024
			if (!empty($assignedport)) {
3025
				$portmtu = $config['interfaces'][$assignedport]['mtu'];
3026
				if (empty($portmtu) && (get_interface_mtu($vlan['vlanif']) != $mtu))
3027
					pfSense_interface_mtu($vlan['vlanif'], $mtu);
3028
			} else if (get_interface_mtu($vlan['vlanif']) != $mtu)
3029
				pfSense_interface_mtu($vlan['vlanif'], $mtu);
3030
		}
3031
		if ($mtu != get_interface_mtu($realhwif))
3032
			pfSense_interface_mtu($realhwif, $mtu);
3033
	}
3034

    
3035
	unset($vlanifs);
3036

    
3037
	if(does_interface_exist($wancfg['if']))
3038
		interfaces_bring_up($wancfg['if']);
3039

    
3040
	interface_netgraph_needed($interface);
3041

    
3042
	if (!$g['booting']) {
3043
		link_interface_to_vips($interface, "update");
3044

    
3045
		unset($gre);
3046
		$gre = link_interface_to_gre($interface);
3047
		if (!empty($gre))
3048
			array_walk($gre, 'interface_gre_configure');
3049

    
3050
		unset($gif);
3051
		$gif = link_interface_to_gif($interface);
3052
		if (!empty($gif))
3053
			array_walk($gif, 'interface_gif_configure');
3054

    
3055
		if ($linkupevent == false || substr($realif, 0, 4) == "ovpn") {
3056
			unset($bridgetmp);
3057
			$bridgetmp = link_interface_to_bridge($interface);
3058
			if (!empty($bridgetmp))
3059
				interface_bridge_add_member($bridgetmp, $realif);
3060
		}
3061

    
3062
		$grouptmp = link_interface_to_group($interface);
3063
		if (!empty($grouptmp))
3064
			array_walk($grouptmp, 'interface_group_add_member');
3065

    
3066
		if ($interface == "lan")
3067
			/* make new hosts file */
3068
			system_hosts_generate();
3069

    
3070
		if ($reloadall == true) {
3071

    
3072
			/* reconfigure static routes (kernel may have deleted them) */
3073
			system_routing_configure($interface);
3074

    
3075
			/* reload ipsec tunnels */
3076
			vpn_ipsec_configure();
3077

    
3078
			/* restart dnsmasq */
3079
			services_dnsmasq_configure();
3080

    
3081
			/* update dyndns */
3082
			send_event("service reload dyndns {$interface}");
3083

    
3084
			/* reload captive portal */
3085
			captiveportal_init_rules();
3086
		}
3087
	}
3088

    
3089
	interfaces_staticarp_configure($interface);
3090
	return 0;
3091
}
3092

    
3093
function interface_track6_configure($interface = "lan", $wancfg) {
3094
	global $config, $g;
3095

    
3096
	if (!is_array($wancfg))
3097
		return;
3098

    
3099
	if (!isset($wancfg['enable']))
3100
		return;
3101

    
3102
	/* If the interface is not configured via another, exit */
3103
	if (empty($wancfg['track6-interface']))
3104
		return;
3105

    
3106
	/* always configure a link-local of fe80::1:1 on the track6 interfaces */
3107
	$realif = get_real_interface($interface);
3108
	$linklocal = find_interface_ipv6_ll($realif);
3109
	if (!empty($linklocal))
3110
		mwexec("/sbin/ifconfig {$realif} inet6 {$linklocal} delete");
3111
	mwexec("/sbin/ifconfig {$realif} inet6 fe80::1:1%{$realif}");
3112

    
3113
	$trackcfg = $config['interfaces'][$wancfg['track6-interface']];
3114
	if (!isset($trackcfg['enable'])) {
3115
		log_error("Interface {$interface} tracking non-existant interface {$wancfg['track6-interface']}");
3116
		return;
3117
	}
3118

    
3119
	switch($trackcfg['ipaddrv6']) {
3120
	case "6to4":
3121
		if ($g['debug'])
3122
			log_error("Interface {$interface} configured via {$wancfg['track6-interface']}  type {$type}");
3123
		interface_track6_6to4_configure($interface, $wancfg);
3124
		break;
3125
	case "6rd":
3126
		if ($g['debug'])
3127
			log_error("Interface {$interface} configured via {$wancfg['track6-interface']}  type {$type}");
3128
		interface_track6_6rd_configure($interface, $wancfg);
3129
		break;
3130
	}
3131

    
3132
	if (!$g['booting']) {
3133
		if (!function_exists('services_dhcpd_configure'))
3134
			require_once("services.inc");
3135

    
3136
		services_dhcpd_configure("inet6");
3137
	}
3138

    
3139
	return 0;
3140
}
3141

    
3142
function interface_track6_6rd_configure($interface = "lan", $lancfg) {
3143
	global $config, $g;
3144
	global $interface_ipv6_arr_cache;
3145
	global $interface_snv6_arr_cache;
3146

    
3147
	if (!is_array($lancfg))
3148
		return;
3149

    
3150
	/* If the interface is not configured via another, exit */
3151
	if (empty($lancfg['track6-interface']))
3152
		return;
3153

    
3154
	$wancfg = $config['interfaces'][$lancfg['track6-interface']];
3155
	if (empty($wancfg)) {
3156
		log_error("Interface {$interface} tracking non-existant interface {$lancfg['track6-interface']}");
3157
		return;
3158
	}
3159

    
3160
	$ip4address = get_interface_ip($lancfg['track6-interface']);
3161
	if (!is_ipaddrv4($ip4address)) { /* XXX: This should not be needed by 6rd || (is_private_ip($ip4address))) { */
3162
		log_error("The interface IPv4 '{$ip4address}' address on interface '{$lancfg['track6-interface']}' is not public, not configuring 6RD tunnel");
3163
		return;
3164
	}
3165
	$hexwanv4 = return_hex_ipv4($ip4address);
3166

    
3167
	/* create the long prefix notation for math, save the prefix length */
3168
	$rd6prefix = explode("/", $wancfg['prefix-6rd']);
3169
	$rd6prefixlen = $rd6prefix[1];
3170
	$rd6prefix = Net_IPv6::uncompress($rd6prefix[0]);
3171

    
3172
	/* binary presentation of the prefix for all 128 bits. */
3173
	$rd6lanbin = convert_ipv6_to_128bit($rd6prefix);
3174

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

    
3180
	/* add the custom prefix id, max 32bits long? (64 bits - (prefixlen + (32 - v4plen)) */
3181
	/* 64 - (37 + (32 - 17)) = 8 == /52 */
3182
	$restbits = 64 - ($rd6prefixlen + (32 - $wancfg['prefix-6rd-v4plen']));
3183
	// echo "64 - (prefixlen {$rd6prefixlen} + v4len (32 - {$wancfg['prefix-6rd-v4plen']})) = {$restbits} \n";
3184
	$rd6lanbin .= substr(sprintf("%032b", str_pad($lancfg['track6-prefix-id'], 32, "0", STR_PAD_LEFT)), (32 - $restbits), 32);
3185
	/* fill the rest out with zeros */
3186
	$rd6lanbin = str_pad($rd6lanbin, 128, "0", STR_PAD_RIGHT);;
3187

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

    
3191
	$lanif = get_real_interface($interface);
3192
	$oip = find_interface_ipv6($lanif);
3193
	if (is_ipaddrv6($oip))
3194
		mwexec("/sbin/ifconfig {$lanif} inet6 {$oip} delete");
3195
	unset($interface_ipv6_arr_cache[$lanif]);
3196
	unset($interface_snv6_arr_cache[$lanif]);
3197
	log_error("rd6 {$interface} with ipv6 address {$rd6lan} based on {$lancfg['track6-interface']} ipv4 {$ip4address}");
3198
	mwexec("/sbin/ifconfig {$lanif} inet6 {$rd6lan} prefixlen 64");
3199

    
3200
	return 0;
3201
}
3202

    
3203
function interface_track6_6to4_configure($interface = "lan", $lancfg) {
3204
	global $config, $g;
3205
	global $interface_ipv6_arr_cache;
3206
	global $interface_snv6_arr_cache;
3207

    
3208
	if (!is_array($lancfg))
3209
		return;
3210

    
3211
	/* If the interface is not configured via another, exit */
3212
	if (empty($lancfg['track6-interface']))
3213
		return;
3214

    
3215
	$wancfg = $config['interfaces'][$lancfg['track6-interface']];
3216
	if (empty($wancfg)) {
3217
		log_error("Interface {$interface} tracking non-existant interface {$lancfg['track6-interface']}");
3218
		return;
3219
	}
3220

    
3221
	$ip4address = get_interface_ip($lancfg['track6-interface']);
3222
	if (!is_ipaddrv4($ip4address) || is_private_ip($ip4address)) {
3223
		log_error("The interface IPv4 '{$ip4address}' address on interface '{$lancfg['track6-interface']}' is not public, not configuring 6RD tunnel");
3224
		return;
3225
	}
3226
	$hexwanv4 = return_hex_ipv4($ip4address);
3227

    
3228
	/* create the long prefix notation for math, save the prefix length */
3229
	$sixto4prefix = "2002::";
3230
	$sixto4prefixlen = 16;
3231
	$sixto4prefix = Net_IPv6::uncompress($sixto4prefix);
3232

    
3233
	/* binary presentation of the prefix for all 128 bits. */
3234
	$sixto4lanbin = convert_ipv6_to_128bit($sixto4prefix);
3235

    
3236
	/* just save the left prefix length bits */
3237
	$sixto4lanbin = substr($sixto4lanbin, 0, $sixto4prefixlen);
3238
	/* add the v4 address */
3239
	$sixto4lanbin .= sprintf("%032b", hexdec($hexwanv4));
3240
	/* add the custom prefix id */
3241
	$sixto4lanbin .= sprintf("%016b", $lancfg['track6-prefix-id']);
3242
	/* fill the rest out with zeros */
3243
	$sixto4lanbin = str_pad($sixto4lanbin, 128, "0", STR_PAD_RIGHT);;
3244

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

    
3248
	$lanif = get_real_interface($interface);
3249
	$oip = find_interface_ipv6($lanif);
3250
	if (is_ipaddrv6($oip))
3251
		mwexec("/sbin/ifconfig {$lanif} inet6 {$oip} delete");
3252
	unset($interface_ipv6_arr_cache[$lanif]);
3253
	unset($interface_snv6_arr_cache[$lanif]);
3254
	log_error("sixto4 {$interface} with ipv6 address {$sixto4lan} based on {$lancfg['track6-interface']} ipv4 {$ip4address}");
3255
	mwexec("/sbin/ifconfig {$lanif} inet6 {$sixto4lan} prefixlen 64");
3256

    
3257
	return 0;
3258
}
3259

    
3260
function interface_6rd_configure($interface = "wan", $wancfg) {
3261
	global $config, $g;
3262

    
3263
	/* because this is a tunnel interface we can only function
3264
	 *	with a public IPv4 address on the interface */
3265

    
3266
	if (!is_array($wancfg))
3267
		return;
3268

    
3269
	$wanif = get_real_interface($interface);
3270
	$ip4address = find_interface_ip($wanif);
3271
	if ((!is_ipaddrv4($ip4address)) || (is_private_ip($ip4address))) {
3272
		log_error("The interface IPv4 '{$ip4address}' address on interface '{$wanif}' is not public, not configuring 6RD tunnel");
3273
		return false;
3274
	}
3275
	$hexwanv4 = return_hex_ipv4($ip4address);
3276

    
3277
	if (!is_numeric($wancfg['prefix-6rd-v4plen']))
3278
		$wancfg['prefix-6rd-v4plen'] = 0;
3279

    
3280
	/* create the long prefix notation for math, save the prefix length */
3281
	$rd6prefix = explode("/", $wancfg['prefix-6rd']);
3282
	$rd6prefixlen = $rd6prefix[1];
3283
	$rd6prefix = Net_IPv6::uncompress($rd6prefix[0]);
3284

    
3285
	/* binary presentation of the prefix for all 128 bits. */
3286
	$rd6prefixbin = convert_ipv6_to_128bit($rd6prefix);
3287

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

    
3295
	/* convert the 128 bits for the broker address back into a valid IPv6 address */
3296
	$rd6prefix = convert_128bit_to_ipv6($rd6prefixbin);
3297

    
3298
	$rd6brgw = "{$rd6prefix}{$wancfg['gateway-6rd']}";
3299

    
3300
	/* XXX: need to extend to support variable prefix size for v4 */
3301
	if (!is_module_loaded("if_stf"))
3302
		mwexec("/sbin/kldload if_stf.ko");
3303
	$stfiface = "{$interface}_stf";
3304
	if (does_interface_exist($stfiface))
3305
		pfSense_interface_destroy($stfiface);
3306
	$tmpstfiface = pfSense_interface_create("stf");
3307
	pfSense_interface_rename($tmpstfiface, $stfiface);
3308
	pfSense_interface_flags($stfiface, IFF_LINK2);
3309
	mwexec("/sbin/ifconfig {$stfiface} inet6 {$rd6prefix}/{$rd6prefixlen}");
3310
	mwexec("/sbin/ifconfig {$stfiface} stfv4br " . escapeshellarg($wancfg['gateway-6rd']));
3311
	if ($wancfg['prefix-6rd-v4plen'] > 0 && $wancfg['prefix-6rd-v4plen'] < 32)
3312
		mwexec("/sbin/ifconfig {$stfiface} stfv4net {$ip4address}/{$wancfg['prefix-6rd-v4plen']}");
3313
	if ($g['debug'])
3314
		log_error("Created 6rd interface {$stfiface} {$rd6prefix}/{$rd6prefixlen}");
3315

    
3316
	/* write out a default router file */
3317
	file_put_contents("{$g['tmp_path']}/{$wanif}_routerv6", "{$rd6brgw}\n");
3318
	file_put_contents("{$g['tmp_path']}/{$wanif}_defaultgwv6", "{$rd6brgw}\n");
3319

    
3320
	$ip4gateway = get_interface_gateway($interface);
3321
	if (is_ipaddrv4($ip4gateway))
3322
		mwexec("/sbin/route change -host " . escapeshellarg($wancfg['gateway-6rd']) . " {$ip4gateway}");
3323

    
3324
	/* configure dependent interfaces */
3325
	if (!$g['booting'])
3326
		link_interface_to_track6($interface, "update");
3327

    
3328
	return 0;
3329
}
3330

    
3331
function interface_6to4_configure($interface = "wan", $wancfg){
3332
	global $config, $g;
3333

    
3334
	/* because this is a tunnel interface we can only function
3335
	 *	with a public IPv4 address on the interface */
3336

    
3337
	if (!is_array($wancfg))
3338
		return;
3339

    
3340
	$wanif = get_real_interface($interface);
3341
	$ip4address = find_interface_ip($wanif);
3342
	if((!is_ipaddrv4($ip4address)) || (is_private_ip($ip4address))) {
3343
		log_error("The interface IPv4 '{$ip4address}' address on interface '{$wanif}' is not public, not configuring 6RD tunnel");
3344
		return false;
3345
	}
3346

    
3347
	/* create the long prefix notation for math, save the prefix length */
3348
	$stfprefixlen = 16;
3349
	$stfprefix = Net_IPv6::uncompress("2002::");
3350
	$stfarr = explode(":", $stfprefix);
3351
	$v4prefixlen = "0";
3352

    
3353
	/* we need the hex form of the interface IPv4 address */
3354
	$ip4arr = explode(".", $ip4address);
3355
	$hexwanv4 = "";
3356
	foreach($ip4arr as $octet)
3357
		$hexwanv4 .= sprintf("%02x", $octet);
3358

    
3359
	/* we need the hex form of the broker IPv4 address */
3360
	$ip4arr = explode(".", "192.88.99.1");
3361
	$hexbrv4 = "";
3362
	foreach($ip4arr as $octet)
3363
		$hexbrv4 .= sprintf("%02x", $octet);
3364

    
3365
	/* binary presentation of the prefix for all 128 bits. */
3366
	$stfprefixbin = "";
3367
	foreach($stfarr as $element) {
3368
		$stfprefixbin .= sprintf("%016b", hexdec($element));
3369
	}
3370
	/* just save the left prefix length bits */
3371
	$stfprefixstartbin = substr($stfprefixbin, 0, $stfprefixlen);
3372

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

    
3377
	/* for the local subnet too. */
3378
	$stflanbin = substr(sprintf("%032b", hexdec($hexwanv4)), $v4prefixlen, 32);
3379
	$stflanbin = str_pad($stfprefixstartbin . $stflanbin, 128, "0", STR_PAD_RIGHT);;
3380

    
3381
	/* convert the 128 bits for the broker address back into a valid IPv6 address */
3382
	$stfbrarr = array();
3383
	$stfbrbinarr = array();
3384
	$stfbrbinarr = str_split($stfbrokerbin, 16);
3385
	foreach($stfbrbinarr as $bin)
3386
		$stfbrarr[] = dechex(bindec($bin));
3387
	$stfbrgw = Net_IPv6::compress(implode(":", $stfbrarr));
3388

    
3389
	/* convert the 128 bits for the broker address back into a valid IPv6 address */
3390
	$stflanarr = array();
3391
	$stflanbinarr = array();
3392
	$stflanbinarr = str_split($stflanbin, 16);
3393
	foreach($stflanbinarr as $bin)
3394
		$stflanarr[] = dechex(bindec($bin));
3395
	$stflanpr = Net_IPv6::compress(implode(":", $stflanarr));
3396
	$stflanarr[7] = 1;
3397
	$stflan = Net_IPv6::compress(implode(":", $stflanarr));
3398

    
3399
	/* setup the stf interface */
3400
	if (!is_module_loaded("if_stf"))
3401
		mwexec("/sbin/kldload if_stf.ko");
3402
	$stfiface = "{$interface}_stf";
3403
	if (does_interface_exist($stfiface))
3404
		pfSense_interface_destroy($stfiface);
3405
	$tmpstfiface = pfSense_interface_create("stf");
3406
	pfSense_interface_rename($tmpstfiface, $stfiface);
3407
	pfSense_interface_flags($stfiface, IFF_LINK2);
3408
	mwexec("/sbin/ifconfig {$stfiface} inet6 {$stflanpr} prefixlen 16");
3409

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

    
3413
	/* write out a default router file */
3414
	file_put_contents("{$g['tmp_path']}/{$wanif}_routerv6", "{$stfbrgw}");
3415
	file_put_contents("{$g['tmp_path']}/{$wanif}_defaultgwv6", "{$stfbrgw}");
3416

    
3417
	$ip4gateway = get_interface_gateway($interface);
3418
	if (is_ipaddrv4($ip4gateway))
3419
		mwexec("/sbin/route change -host 192.88.99.1 {$ip4gateway}");
3420

    
3421
	if (!$g['booting'])
3422
		link_interface_to_track6($interface, "update");
3423

    
3424
	return 0;
3425
}
3426

    
3427
function interface_dhcpv6_configure($interface = "wan", $wancfg) {
3428
	global $config, $g;
3429

    
3430
	if (!is_array($wancfg))
3431
		return;
3432

    
3433
	$wanif = get_real_interface($interface, "inet6");
3434
	$dhcp6cconf = "";
3435
	$dhcp6cconf .= "interface {$wanif} {\n";
3436

    
3437
	/* for SLAAC interfaces we do fire off a dhcp6 client for just our name servers */
3438
	if($wancfg['ipaddrv6'] == "slaac") {
3439
		$dhcp6cconf .= "	information-only;\n";
3440
		$dhcp6cconf .= "	request domain-name-servers;\n";
3441
		$dhcp6cconf .= "	request domain-name;\n";
3442
		$dhcp6cconf .= "	script \"{$g['varetc_path']}/dhcp6c_{$interface}_script.sh\"; # we'd like some nameservers please\n";
3443
		$dhcp6cconf .= "};\n";
3444
	} else {
3445
		/* skip address request if this is set */
3446
		if(!isset($wancfg['dhcp6prefixonly']))
3447
			$dhcp6cconf .= "        send ia-na 0;   # request stateful address\n";
3448
		if(is_numeric($wancfg['dhcp6-ia-pd-len']))
3449
			$dhcp6cconf .= "	send ia-pd 0;	# request prefix delegation\n";
3450

    
3451
		$dhcp6cconf .= "\trequest domain-name-servers;\n";
3452
		$dhcp6cconf .= "\trequest domain-name;\n";
3453
		$dhcp6cconf .= "\tscript \"{$g['varetc_path']}/dhcp6c_{$interface}_script.sh\"; # we'd like some nameservers please\n";
3454

    
3455
		$dhcp6cconf .= "};\n";
3456

    
3457
		if(!isset($wancfg['dhcp6prefixonly']))
3458
			$dhcp6cconf .= "id-assoc na 0 { };\n";
3459

    
3460
		if(is_numeric($wancfg['dhcp6-ia-pd-len'])) {
3461
			/* Setup the prefix delegation */
3462
			$dhcp6cconf .= "id-assoc pd 0 {\n";
3463
			$iflist = link_interface_to_track6($interface);
3464
			foreach ($iflist as $friendly => $ifcfg) {
3465
				if (is_numeric($ifcfg['track6-prefix-id'])) {
3466
					if ($g['debug'])
3467
						log_error("setting up $ifdescr - {$ifcfg['track6-prefix-id']}");
3468
					$realif = get_real_interface($friendly);
3469
					$dhcp6cconf .= "	prefix-interface {$realif} {\n";
3470
					$dhcp6cconf .= "		sla-id {$ifcfg['track6-prefix-id']};\n";
3471
					$dhcp6cconf .= "		sla-len {$wancfg['dhcp6-ia-pd-len']};\n";
3472
					$dhcp6cconf .= "	};\n";
3473
				}
3474
			}
3475
			unset($iflist, $ifcfg);
3476
			$dhcp6cconf .= "};\n";
3477
		}
3478
	}
3479

    
3480
	// DHCP6 Config File Advanced
3481
	if ($wancfg['adv_dhcp6_config_advanced']) { $dhcp6cconf = DHCP6_Config_File_Advanced($interface, $wancfg, $wanif); }
3482

    
3483
	// DHCP6 Config File Override
3484
	if ($wancfg['adv_dhcp6_config_file_override']) { $dhcp6cconf = DHCP6_Config_File_Override($wancfg, $wanif); }
3485

    
3486
	/* wide-dhcp6c works for now. */
3487
	if (!@file_put_contents("{$g['varetc_path']}/dhcp6c_{$interface}.conf", $dhcp6cconf)) {
3488
		printf("Error: cannot open dhcp6c_{$interface}.conf in interface_dhcpv6_configure() for writing.\n");
3489
		unset($dhcp6cconf);
3490
		return 1;
3491
	}
3492
	unset($dhcp6cconf);
3493

    
3494
	$dhcp6cscript = "#!/bin/sh\n";
3495
	$dhcp6cscript .= "# This shell script launches /etc/rc.newwanipv6 with a interface argument.\n";
3496
	$dhcp6cscript .= "/etc/rc.newwanipv6 {$wanif} \n";
3497
	/* Add wide-dhcp6c shell script here. Because we can not pass a argument to it. */
3498
	if (!@file_put_contents("{$g['varetc_path']}/dhcp6c_{$interface}_script.sh", $dhcp6cscript)) {
3499
		printf("Error: cannot open dhcp6c_{$interface}_script.sh in interface_dhcpv6_configure() for writing.\n");
3500
		unset($dhcp6cscript);
3501
		return 1;
3502
	}
3503
	unset($dhcp6cscript);
3504
	@chmod("{$g['varetc_path']}/dhcp6c_{$interface}_script.sh", 0755);
3505

    
3506
	$rtsoldscript = "#!/bin/sh\n";
3507
	$rtsoldscript .= "# This shell script launches dhcp6c and configured gateways for this interface.\n";
3508
	$rtsoldscript .= "echo $2 > {$g['tmp_path']}/{$wanif}_routerv6\n";
3509
	$rtsoldscript .= "echo $2 > {$g['tmp_path']}/{$wanif}_defaultgwv6\n";
3510
	$rtsoldscript .= "if [ -f {$g['varrun_path']}/dhcp6c_{$wanif}.pid ]; then\n";
3511
	$rtsoldscript .= "\t/bin/pkill -F {$g['varrun_path']}/dhcp6c_{$wanif}.pid\n";
3512
	$rtsoldscript .= "\t/bin/sleep 1\n";
3513
	$rtsoldscript .= "fi\n";
3514
	$rtsoldscript .= "/usr/local/sbin/dhcp6c -d -c {$g['varetc_path']}/dhcp6c_{$interface}.conf -p {$g['varrun_path']}/dhcp6c_{$wanif}.pid {$wanif}\n";
3515
	/* Add wide-dhcp6c shell script here. Because we can not pass a argument to it. */
3516
	if (!@file_put_contents("{$g['varetc_path']}/rtsold_{$wanif}_script.sh", $rtsoldscript)) {
3517
		printf("Error: cannot open rtsold_{$interface}_script.sh in interface_dhcpv6_configure() for writing.\n");
3518
		unset($rtsoldscript);
3519
		return 1;
3520
	}
3521
	unset($rtsoldscript);
3522
	@chmod("{$g['varetc_path']}/rtsold_{$wanif}_script.sh", 0755);
3523

    
3524
	/* accept router advertisements for this interface */
3525
	mwexec("/sbin/sysctl -w net.inet6.ip6.accept_rtadv=1");
3526
	log_error("Accept router advertisements on interface {$wanif} ");
3527
	mwexec("/sbin/ifconfig {$wanif} inet6 accept_rtadv");
3528

    
3529
	/* fire up rtsold for IPv6 RAs first, this backgrounds immediately. It will call dhcp6c */
3530
	if (isvalidpid("{$g['varrun_path']}/rtsold_{$wanif}.pid")) {
3531
		killbypid("{$g['varrun_path']}/rtsold_{$wanif}.pid");
3532
		sleep(2);
3533
	}
3534
	mwexec("/usr/sbin/rtsold -1 -p {$g['varrun_path']}/rtsold_{$wanif}.pid -O {$g['varetc_path']}/rtsold_{$wanif}_script.sh {$wanif}");
3535

    
3536
	/* NOTE: will be called from rtsold invoked script
3537
	 * link_interface_to_track6($interface, "update");
3538
	 */
3539

    
3540
	return 0;
3541
}
3542

    
3543
function DHCP6_Config_File_Advanced($interface, $wancfg, $wanif) {
3544
	global $g;
3545

    
3546
	$send_options = "";
3547
	if ($wancfg['adv_dhcp6_interface_statement_send_options'] != '') {
3548
		$options = split(",", $wancfg['adv_dhcp6_interface_statement_send_options']);
3549
		foreach ($options as $option) {
3550
			$send_options .= "\tsend " . trim($option) . ";\n";
3551
		}
3552
	}
3553

    
3554
	$request_options = "";
3555
	if ($wancfg['adv_dhcp6_interface_statement_request_options'] != '') {
3556
		$options = split(",", $wancfg['adv_dhcp6_interface_statement_request_options']);
3557
		foreach ($options as $option) {
3558
			$request_options .= "\trequest " . trim($option) . ";\n";
3559
		}
3560
	}
3561

    
3562
	$information_only = "";
3563
	if ($wancfg['adv_dhcp6_interface_statement_information_only_enable'] != '') 
3564
		$information_only = "\tinformation-only;\n";
3565

    
3566
	$script = "\tscript \"{$g['varetc_path']}/dhcp6c_{$interface}_script.sh\";\n";
3567
	if ($wancfg['adv_dhcp6_interface_statement_script'] != '')
3568
		$script = "\tscript \"{$wancfg['adv_dhcp6_interface_statement_script']}\";\n";
3569

    
3570
	$interface_statement  = "interface";
3571
	$interface_statement .= " {$wanif}";
3572
	$interface_statement .= " {\n";
3573
	$interface_statement .= "$send_options";
3574
	$interface_statement .= "$request_options";
3575
	$interface_statement .= "$information_only";
3576
	$interface_statement .= "$script";
3577
	$interface_statement .= "};\n";
3578

    
3579
	$id_assoc_statement_address = "";
3580
	if ($wancfg['adv_dhcp6_id_assoc_statement_address_enable'] != '') {
3581
		$id_assoc_statement_address .= "id-assoc";
3582
		$id_assoc_statement_address .= " na";
3583
		if (is_numeric($wancfg['adv_dhcp6_id_assoc_statement_address_id'])) 
3584
			$id_assoc_statement_address .= " {$wancfg['adv_dhcp6_id_assoc_statement_address_id']}";
3585
		$id_assoc_statement_address .= " { ";
3586

    
3587
		if ( ($wancfg['adv_dhcp6_id_assoc_statement_address'] != '') && 
3588
			 (is_numeric($wancfg['adv_dhcp6_id_assoc_statement_address_pltime']) || 
3589
			 ($wancfg['adv_dhcp6_id_assoc_statement_address_pltime'] == 'infinity')) ) {
3590
			$id_assoc_statement_address .= "\n\taddress";
3591
			$id_assoc_statement_address .= " {$wancfg['adv_dhcp6_id_assoc_statement_address']}";
3592
			$id_assoc_statement_address .= " {$wancfg['adv_dhcp6_id_assoc_statement_address_pltime']}";
3593
			if ( (is_numeric($wancfg['adv_dhcp6_id_assoc_statement_address_vltime'])) || 
3594
							($wancfg['adv_dhcp6_id_assoc_statement_address_vltime'] == 'infinity') ) 
3595
				$id_assoc_statement_address .= " {$wancfg['adv_dhcp6_id_assoc_statement_address_vltime']}";
3596
			$id_assoc_statement_address .= ";\n";
3597
		}
3598

    
3599
		$id_assoc_statement_address  .= "};\n";
3600
	}
3601

    
3602
	$id_assoc_statement_prefix = "";
3603
	if ($wancfg['adv_dhcp6_id_assoc_statement_prefix_enable'] != '') {
3604
		$id_assoc_statement_prefix .= "id-assoc";
3605
		$id_assoc_statement_prefix .= " pd";
3606
		if (is_numeric($wancfg['adv_dhcp6_id_assoc_statement_prefix_id'])) 
3607
			$id_assoc_statement_prefix .= " {$wancfg['adv_dhcp6_id_assoc_statement_prefix_id']}";
3608
		$id_assoc_statement_prefix .= " { ";
3609

    
3610
		if ( ($wancfg['adv_dhcp6_id_assoc_statement_prefix'] != '') && 
3611
			 (is_numeric($wancfg['adv_dhcp6_id_assoc_statement_prefix_pltime']) || 
3612
			 ($wancfg['adv_dhcp6_id_assoc_statement_prefix_pltime'] == 'infinity')) ) {
3613
			$id_assoc_statement_prefix .= "\n\tprefix";
3614
			$id_assoc_statement_prefix .= " {$wancfg['adv_dhcp6_id_assoc_statement_prefix']}";
3615
			$id_assoc_statement_prefix .= " {$wancfg['adv_dhcp6_id_assoc_statement_prefix_pltime']}";
3616
			if ( (is_numeric($wancfg['adv_dhcp6_id_assoc_statement_prefix_vltime'])) || 
3617
						  ($wancfg['adv_dhcp6_id_assoc_statement_prefix_vltime'] == 'infinity') ) 
3618
				$id_assoc_statement_prefix .= " {$wancfg['adv_dhcp6_id_assoc_statement_prefix_vltime']}";
3619
			$id_assoc_statement_prefix .= ";";
3620
		}
3621

    
3622
		if (is_numeric($wancfg['adv_dhcp6_prefix_interface_statement_sla_id'])) {
3623
			$id_assoc_statement_prefix .= "\n\tprefix-interface";
3624
			$id_assoc_statement_prefix .= " {$wanif}";
3625
			$id_assoc_statement_prefix .= " {\n";
3626
			$id_assoc_statement_prefix .= "\t\tsla-id {$wancfg['adv_dhcp6_prefix_interface_statement_sla_id']};\n";
3627
			if ( ($wancfg['adv_dhcp6_prefix_interface_statement_sla_len'] >= 0) && 
3628
				 ($wancfg['adv_dhcp6_prefix_interface_statement_sla_len'] <= 128) ) 
3629
				 $id_assoc_statement_prefix .= "\t\tsla-len {$wancfg['adv_dhcp6_prefix_interface_statement_sla_len']};\n";
3630
			$id_assoc_statement_prefix .= "\t};";
3631
		}
3632

    
3633
		if ( ($wancfg['adv_dhcp6_id_assoc_statement_prefix'] != '') || 
3634
			 (is_numeric($wancfg['adv_dhcp6_prefix_interface_statement_sla_id'])) ) { 
3635
			$id_assoc_statement_prefix .= "\n";
3636
		}
3637

    
3638
		$id_assoc_statement_prefix  .= "};\n";
3639
	}
3640

    
3641
	$authentication_statement = "";
3642
	if ( ($wancfg['adv_dhcp6_authentication_statement_authname'] != '') && 
3643
		 ($wancfg['adv_dhcp6_authentication_statement_protocol'] == 'delayed') ) {
3644
		$authentication_statement .= "authentication";
3645
		$authentication_statement .= " {$wancfg['adv_dhcp6_authentication_statement_authname']}";
3646
		$authentication_statement .= " {\n";
3647
		$authentication_statement .= "\tprotocol {$wancfg['adv_dhcp6_authentication_statement_protocol']};\n";
3648
		if (preg_match("/(hmac(-)?md5)||(HMAC(-)?MD5)/", $wancfg['adv_dhcp6_authentication_statement_algorithm'])) 
3649
			$authentication_statement .= "\talgorithm {$wancfg['adv_dhcp6_authentication_statement_algorithm']};\n";
3650
		if ($wancfg['adv_dhcp6_authentication_statement_rdm'] == 'monocounter') 
3651
			$authentication_statement .= "\trdm {$wancfg['adv_dhcp6_authentication_statement_rdm']};\n";
3652
		$authentication_statement .= "};\n";
3653
	}
3654

    
3655
	$key_info_statement = "";
3656
	if ( ($wancfg['adv_dhcp6_key_info_statement_keyname'] != '') && 
3657
		 ($wancfg['adv_dhcp6_key_info_statement_realm'] != '') && 
3658
		 (is_numeric($wancfg['adv_dhcp6_key_info_statement_keyid'])) && 
3659
		 ($wancfg['adv_dhcp6_key_info_statement_secret'] != '') ) {
3660
		$key_info_statement .= "keyinfo";
3661
		$key_info_statement .= " {$wancfg['adv_dhcp6_key_info_statement_keyname']}";
3662
		$key_info_statement .= " {\n";
3663
		$key_info_statement .= "\trealm \"{$wancfg['adv_dhcp6_key_info_statement_realm']}\";\n";
3664
		$key_info_statement .= "\tkeyid {$wancfg['adv_dhcp6_key_info_statement_keyid']};\n";
3665
		$key_info_statement .= "\tsecret \"{$wancfg['adv_dhcp6_key_info_statement_secret']}\";\n";
3666
		if (preg_match("/((([0-9]{4}-)?[0-9]{2}[0-9]{2} )?[0-9]{2}:[0-9]{2})||(foreever)/", $wancfg['adv_dhcp6_key_info_statement_expire'])) 
3667
			$key_info_statement .= "\texpire \"{$wancfg['adv_dhcp6_key_info_statement_expire']}\";\n";
3668
		$key_info_statement .= "};\n";
3669
	}
3670

    
3671
	$dhcp6cconf  = $interface_statement;
3672
	$dhcp6cconf .= $id_assoc_statement_address;
3673
	$dhcp6cconf .= $id_assoc_statement_prefix;
3674
	$dhcp6cconf .= $authentication_statement;
3675
	$dhcp6cconf .= $key_info_statement;
3676

    
3677
	$dhcp6cconf = DHCP6_Config_File_Substitutions($wancfg, $wanif, $dhcp6cconf);
3678

    
3679
	return $dhcp6cconf;
3680
}
3681

    
3682

    
3683
function DHCP6_Config_File_Override($wancfg, $wanif) {
3684

    
3685
	$dhcp6cconf = file_get_contents($wancfg['adv_dhcp6_config_file_override_path']);
3686
	$dhcp6cconf = DHCP6_Config_File_Substitutions($wancfg, $wanif, $dhcp6cconf);
3687

    
3688
	return $dhcp6cconf;
3689
}
3690

    
3691

    
3692
function DHCP6_Config_File_Substitutions($wancfg, $wanif, $dhcp6cconf) {
3693

    
3694
	$dhcp6cconf = DHCP_Config_File_Substitutions($wancfg, $wanif, $dhcp6cconf);
3695

    
3696
	return $dhcp6cconf;
3697
}
3698

    
3699

    
3700
function interface_dhcp_configure($interface = "wan") {
3701
	global $config, $g;
3702

    
3703
	$wancfg = $config['interfaces'][$interface];
3704
	$wanif = $wancfg['if'];
3705
	if (empty($wancfg))
3706
		$wancfg = array();
3707

    
3708
	/* generate dhclient_wan.conf */
3709
	$fd = fopen("{$g['varetc_path']}/dhclient_{$interface}.conf", "w");
3710
	if (!$fd) {
3711
		printf(printf(gettext("Error: cannot open dhclient_%s.conf in interface_dhcp_configure() for writing.%s"), $interface, "\n"));
3712
		return 1;
3713
	}
3714

    
3715
	if ($wancfg['dhcphostname']) {
3716
		$dhclientconf_hostname = "send dhcp-client-identifier \"{$wancfg['dhcphostname']}\";\n";
3717
		$dhclientconf_hostname .= "\tsend host-name \"{$wancfg['dhcphostname']}\";\n";
3718
	} else {
3719
		$dhclientconf_hostname = "";
3720
	}
3721

    
3722
	$wanif = get_real_interface($interface);
3723
	if (empty($wanif)) {
3724
		log_error(sprintf(gettext("Invalid interface \"%s\" in interface_dhcp_configure()"), $interface));
3725
		return 0;
3726
	}
3727
	$dhclientconf = "";
3728

    
3729
	$dhclientconf .= <<<EOD
3730
interface "{$wanif}" {
3731
timeout 60;
3732
retry 15;
3733
select-timeout 0;
3734
initial-interval 1;
3735
	{$dhclientconf_hostname}
3736
	script "/sbin/dhclient-script";
3737
EOD;
3738

    
3739
if (is_ipaddrv4($wancfg['dhcprejectfrom'])) {
3740
	$dhclientconf .= <<<EOD
3741

    
3742
	reject {$wancfg['dhcprejectfrom']};
3743
EOD;
3744
}
3745
	$dhclientconf .= <<<EOD
3746

    
3747
}
3748

    
3749
EOD;
3750

    
3751
	// DHCP Config File Advanced
3752
	if ($wancfg['adv_dhcp_config_advanced']) { $dhclientconf = DHCP_Config_File_Advanced($interface, $wancfg, $wanif); }
3753

    
3754
if(is_ipaddr($wancfg['alias-address'])) {
3755
	$subnetmask = gen_subnet_mask($wancfg['alias-subnet']);
3756
	$dhclientconf .= <<<EOD
3757
alias {
3758
	interface  "{$wanif}";
3759
	fixed-address {$wancfg['alias-address']};
3760
	option subnet-mask {$subnetmask};
3761
}
3762

    
3763
EOD;
3764
}
3765

    
3766
	// DHCP Config File Override
3767
	if ($wancfg['adv_dhcp_config_file_override']) { $dhclientconf = DHCP_Config_File_Override($wancfg, $wanif); }
3768

    
3769
	fwrite($fd, $dhclientconf);
3770
	fclose($fd);
3771

    
3772
	/* bring wan interface up before starting dhclient */
3773
	if($wanif)
3774
		interfaces_bring_up($wanif);
3775
	else
3776
		log_error(printf(gettext("Could not bring up %s interface in interface_dhcp_configure()"), $wanif));
3777

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

    
3781
	return 0;
3782
}
3783

    
3784
function DHCP_Config_File_Advanced($interface, $wancfg, $wanif) {
3785

    
3786
	$hostname = "";
3787
	if ($wancfg['dhcphostname'] != '') {
3788
		$hostname = "\tsend host-name \"{$wancfg['dhcphostname']}\";\n";
3789
	}
3790

    
3791
	/* DHCP Protocol Timings */
3792
	$protocol_timings = array ('adv_dhcp_pt_timeout' => "timeout", 'adv_dhcp_pt_retry' => "retry", 'adv_dhcp_pt_select_timeout' => "select-timeout", 'adv_dhcp_pt_reboot' => "reboot", 'adv_dhcp_pt_backoff_cutoff' => "backoff-cutoff", 'adv_dhcp_pt_initial_interval' => "initial-interval");
3793
	foreach ($protocol_timings as $Protocol_Timing => $PT_Name) {
3794
		$pt_variable = "{$Protocol_Timing}";
3795
		${$pt_variable} = "";
3796
		if ($wancfg[$Protocol_Timing] != "") {
3797
			${$pt_variable} = "{$PT_Name} {$wancfg[$Protocol_Timing]};\n";
3798
		}
3799
	}
3800

    
3801
	$send_options = "";
3802
	if ($wancfg['adv_dhcp_send_options'] != '') {
3803
		$options = split(",", $wancfg['adv_dhcp_send_options']);
3804
		foreach ($options as $option) {
3805
			$send_options .= "\tsend " . trim($option) . ";\n";
3806
		}
3807
	}
3808

    
3809
	$request_options = "";
3810
	if ($wancfg['adv_dhcp_request_options'] != '') {
3811
		$request_options = "\trequest {$wancfg['adv_dhcp_request_options']};\n";
3812
	}
3813

    
3814
	$required_options = "";
3815
	if ($wancfg['adv_dhcp_required_options'] != '') {
3816
		$required_options = "\trequired {$wancfg['adv_dhcp_required_options']};\n";
3817
	}
3818

    
3819
	$option_modifiers = "";
3820
	if ($wancfg['adv_dhcp_option_modifiers'] != '') {
3821
		$modifiers = split(",", $wancfg['adv_dhcp_option_modifiers']);
3822
		foreach ($modifiers as $modifier) {
3823
			$option_modifiers .= "\t" . trim($modifier) . ";\n";
3824
		}
3825
	}
3826

    
3827
 	$dhclientconf  = "interface \"{$wanif}\" {\n";
3828
 	$dhclientconf .= "\n";
3829
 	$dhclientconf .= "# DHCP Protocol Timing Values\n";
3830
 	$dhclientconf .= "{$adv_dhcp_pt_timeout}";
3831
 	$dhclientconf .= "{$adv_dhcp_pt_retry}";
3832
 	$dhclientconf .= "{$adv_dhcp_pt_select_timeout}";
3833
 	$dhclientconf .= "{$adv_dhcp_pt_reboot}";
3834
 	$dhclientconf .= "{$adv_dhcp_pt_backoff_cutoff}";
3835
 	$dhclientconf .= "{$adv_dhcp_pt_initial_interval}";
3836
 	$dhclientconf .= "\n";
3837
 	$dhclientconf .= "# DHCP Protocol Options\n";
3838
 	$dhclientconf .= "{$hostname}";
3839
 	$dhclientconf .= "{$send_options}";
3840
 	$dhclientconf .= "{$request_options}";
3841
 	$dhclientconf .= "{$required_options}";
3842
 	$dhclientconf .= "{$option_modifiers}";
3843
 	$dhclientconf .= "\n";
3844
 	$dhclientconf .= "\tscript \"/sbin/dhclient-script\";\n";
3845
 	$dhclientconf .= "}\n";
3846

    
3847
	$dhclientconf = DHCP_Config_File_Substitutions($wancfg, $wanif, $dhclientconf);
3848

    
3849
	return $dhclientconf;
3850
}
3851

    
3852

    
3853
function DHCP_Config_File_Override($wancfg, $wanif) {
3854

    
3855
	$dhclientconf = file_get_contents($wancfg['adv_dhcp_config_file_override_path']);
3856
	$dhclientconf = DHCP_Config_File_Substitutions($wancfg, $wanif, $dhclientconf);
3857

    
3858
	return $dhclientconf;
3859
}
3860

    
3861

    
3862
function DHCP_Config_File_Substitutions($wancfg, $wanif, $dhclientconf) {
3863

    
3864
	/* Apply Interface Substitutions */
3865
	$dhclientconf = str_replace("{interface}", "{$wanif}", $dhclientconf);
3866

    
3867
	/* Apply Hostname Substitutions */
3868
	$dhclientconf = str_replace("{hostname}", $wancfg['dhcphostname'], $dhclientconf);
3869

    
3870
	/* Arrays of MAC Address Types, Cases, Delimiters */
3871
	/* ASCII or HEX, Upper or Lower Case, Various Delimiters (none, space, colon, hyphen, period) */
3872
	$various_mac_types      = array("mac_addr_ascii", "mac_addr_hex");
3873
	$various_mac_cases      = array("U", "L");
3874
	$various_mac_delimiters = array("", " ", ":", "-", ".");
3875

    
3876
	/* Apply MAC Address Substitutions */
3877
	foreach ($various_mac_types as $various_mac_type) {
3878
		foreach ($various_mac_cases as $various_mac_case) {
3879
			foreach ($various_mac_delimiters as $various_mac_delimiter) {
3880

    
3881
				$res = stripos($dhclientconf, $various_mac_type . $various_mac_case . $various_mac_delimiter);
3882
				if ($res !== false) {
3883

    
3884
					/* Get MAC Address as ASCII String With Colon (:) Celimiters */
3885
					if ("$various_mac_case" == "U") $dhcpclientconf_mac = strtoupper(get_interface_mac($wanif));
3886
					if ("$various_mac_case" == "L") $dhcpclientconf_mac = strtolower(get_interface_mac($wanif));
3887

    
3888
					if ("$various_mac_type" == "mac_addr_hex") {
3889
						/* Convert MAC ascii string to HEX with colon (:) delimiters. */
3890
						$dhcpclientconf_mac = str_replace(":", "", $dhcpclientconf_mac);
3891
						$dhcpclientconf_mac_hex = "";
3892
						$delimiter = "";
3893
						for($i = 0; $i < strlen($dhcpclientconf_mac); $i++) {
3894
							$dhcpclientconf_mac_hex .= $delimiter. bin2hex($dhcpclientconf_mac[$i]);
3895
							$delimiter = ":";
3896
						}
3897
						$dhcpclientconf_mac = $dhcpclientconf_mac_hex;
3898
					}
3899

    
3900
					/* MAC Address Delimiter Substitutions */
3901
					$dhcpclientconf_mac = str_replace(":", $various_mac_delimiter, $dhcpclientconf_mac);
3902

    
3903
					/* Apply MAC Address Substitutions */
3904
					$dhclientconf = str_replace("{" . $various_mac_type . $various_mac_case . $various_mac_delimiter . "}", $dhcpclientconf_mac, $dhclientconf);
3905
				}
3906
			}
3907
		}
3908
	}
3909

    
3910
	return $dhclientconf;
3911
}
3912

    
3913
function interfaces_group_setup() {
3914
	global $config;
3915

    
3916
	if (!is_array($config['ifgroups']['ifgroupentry']))
3917
		return;
3918

    
3919
	foreach ($config['ifgroups']['ifgroupentry'] as $groupar)
3920
		interface_group_setup($groupar);
3921

    
3922
	return;
3923
}
3924

    
3925
function interface_group_setup(&$groupname /* The parameter is an array */) {
3926
	global $config;
3927

    
3928
	if (!is_array($groupname))
3929
		return;
3930
	$members = explode(" ", $groupname['members']);
3931
	foreach($members as $ifs) {
3932
		$realif = get_real_interface($ifs);
3933
		if ($realif)
3934
			mwexec("/sbin/ifconfig {$realif} group {$groupname['ifname']}");
3935
	}
3936

    
3937
	return;
3938
}
3939

    
3940
function is_interface_group($if) {
3941
	global $config;
3942

    
3943
	if (is_array($config['ifgroups']['ifgroupentry']))
3944
		foreach ($config['ifgroups']['ifgroupentry'] as $groupentry) {
3945
			if ($groupentry['ifname'] === $if)
3946
				return true;
3947
		}
3948

    
3949
	return false;
3950
}
3951

    
3952
function interface_group_add_member($interface, $groupname) {
3953
	$interface = get_real_interface($interface);
3954
	mwexec("/sbin/ifconfig {$interface} group {$groupname}", true);
3955
}
3956

    
3957
/* COMPAT Function */
3958
function convert_friendly_interface_to_real_interface_name($interface) {
3959
	return get_real_interface($interface);
3960
}
3961

    
3962
/* COMPAT Function */
3963
function get_real_wan_interface($interface = "wan") {
3964
	return get_real_interface($interface);
3965
}
3966

    
3967
/* COMPAT Function */
3968
function get_current_wan_address($interface = "wan") {
3969
	return get_interface_ip($interface);
3970
}
3971

    
3972
/*
3973
 * convert_real_interface_to_friendly_interface_name($interface): convert fxp0 -> wan, etc.
3974
 */
3975
function convert_real_interface_to_friendly_interface_name($interface = "wan") {
3976
	global $config;
3977

    
3978
	if (stristr($interface, "_vip")) {
3979
		foreach ($config['virtualip']['vip'] as $counter => $vip) {
3980
			if ($vip['mode'] == "carp")  {
3981
				if ($interface == "{$vip['interface']}_vip{$vip['vhid']}")
3982
					return $vip['interface'];
3983
			}
3984
		}
3985
	}
3986

    
3987
	/* XXX: For speed reasons reference directly the interface array */
3988
	$ifdescrs = &$config['interfaces'];
3989
	//$ifdescrs = get_configured_interface_list(false, true);
3990

    
3991
	foreach ($ifdescrs as $if => $ifname) {
3992
		if ($if == $interface || $config['interfaces'][$if]['if'] == $interface)
3993
			return $if;
3994

    
3995
		if (get_real_interface($if) == $interface)
3996
			return $if;
3997

    
3998
		// XXX: This case doesn't work anymore (segfaults - recursion?) - should be replaced with something else or just removed.
3999
		//      Not to be replaced with get_real_interface - causes slow interface listings here because of recursion!
4000
		/*
4001
		$int = get_parent_interface($if);
4002
		if ($int[0] == $interface)
4003
			return $ifname;
4004
		*/
4005
	}
4006

    
4007
	return NULL;
4008
}
4009

    
4010
/* attempt to resolve interface to friendly descr */
4011
function convert_friendly_interface_to_friendly_descr($interface) {
4012
	global $config;
4013

    
4014
	switch ($interface) {
4015
	case "l2tp":
4016
		$ifdesc = "L2TP";
4017
		break;
4018
	case "pptp":
4019
		$ifdesc = "PPTP";
4020
		break;
4021
	case "pppoe":
4022
		$ifdesc = "PPPoE";
4023
		break;
4024
	case "openvpn":
4025
		$ifdesc = "OpenVPN";
4026
		break;
4027
	case "enc0":
4028
	case "ipsec":
4029
		$ifdesc = "IPsec";
4030
		break;
4031
	default:
4032
		if (isset($config['interfaces'][$interface])) {
4033
			if (empty($config['interfaces'][$interface]['descr']))
4034
				$ifdesc = strtoupper($interface);
4035
			else
4036
				$ifdesc = strtoupper($config['interfaces'][$interface]['descr']);
4037
			break;
4038
		} else if (stristr($interface, "_vip")) {
4039
			if (is_array($config['virtualip']['vip'])) {
4040
				foreach ($config['virtualip']['vip'] as $counter => $vip) {
4041
					if ($vip['mode'] == "carp")  {
4042
						if ($interface == "{$vip['interface']}_vip{$vip['vhid']}")
4043
							return "{$vip['subnet']} - {$vip['descr']}";
4044
					}
4045
				}
4046
			}
4047
		} else {
4048
			/* if list */
4049
			$ifdescrs = get_configured_interface_with_descr(false, true);
4050
			foreach ($ifdescrs as $if => $ifname) {
4051
				if ($if == $interface || $ifname == $interface)
4052
					return $ifname;
4053
			}
4054
		}
4055
		break;
4056
	}
4057

    
4058
	return $ifdesc;
4059
}
4060

    
4061
function convert_real_interface_to_friendly_descr($interface) {
4062
	global $config;
4063

    
4064
	$ifdesc = convert_real_interface_to_friendly_interface_name("{$interface}");
4065

    
4066
	if ($ifdesc) {
4067
		$iflist = get_configured_interface_with_descr(false, true);
4068
		return $iflist[$ifdesc];
4069
	}
4070

    
4071
	return $interface;
4072
}
4073

    
4074
/*
4075
 *  get_parent_interface($interface):
4076
 *			--returns the (real or virtual) parent interface(s) array for a given interface friendly name (i.e. wan)
4077
 *				or virtual interface (i.e. vlan)
4078
 *				(We need array because MLPPP and bridge interfaces have more than one parent.)
4079
 *			-- returns $interface passed in if $interface parent is not found
4080
 *			-- returns empty array if an invalid interface is passed
4081
 *	(Only handles ppps and vlans now.)
4082
 */
4083
function get_parent_interface($interface) {
4084
	global $config;
4085

    
4086
	$parents = array();
4087
	//Check that we got a valid interface passed
4088
	$realif = get_real_interface($interface);
4089
	if ($realif == NULL)
4090
		return $parents;
4091

    
4092
	// If we got a real interface, find it's friendly assigned name
4093
	$interface = convert_real_interface_to_friendly_interface_name($interface);
4094

    
4095
	if (!empty($interface) && isset($config['interfaces'][$interface])) {
4096
		$ifcfg = $config['interfaces'][$interface];
4097
		switch ($ifcfg['ipaddr']) {
4098
			case "ppp":
4099
			case "pppoe":
4100
			case "pptp":
4101
			case "l2tp":
4102
				if (empty($parents))
4103
					if (is_array($config['ppps']['ppp']))
4104
						foreach ($config['ppps']['ppp'] as $pppidx => $ppp) {
4105
							if ($ifcfg['if'] == $ppp['if']) {
4106
								$ports = explode(',', $ppp['ports']);
4107
								foreach ($ports as $pid => $parent_if)
4108
									$parents[$pid] = get_real_interface($parent_if);
4109
								break;
4110
							}
4111
						}
4112
				break;
4113
			case "dhcp":
4114
			case "static":
4115
			default:
4116
				// Handle _vlans
4117
				if (stristr($realif,"_vlan"))
4118
					if (is_array($config['vlans']['vlan']))
4119
						foreach ($config['vlans']['vlan'] as $vlanidx => $vlan)
4120
							if ($ifcfg['if'] == $vlan['vlanif']){
4121
								$parents[0] = $vlan['if'];
4122
								break;
4123
							}
4124
				break;
4125
		}
4126
	}
4127

    
4128
	if (empty($parents))
4129
		$parents[0] = $realif;
4130

    
4131
	return $parents;
4132
}
4133

    
4134
function interface_is_wireless_clone($wlif) {
4135
	if(!stristr($wlif, "_wlan")) {
4136
		return false;
4137
	} else {
4138
		return true;
4139
	}
4140
}
4141

    
4142
function interface_get_wireless_base($wlif) {
4143
	if(!stristr($wlif, "_wlan")) {
4144
		return $wlif;
4145
	} else {
4146
		return substr($wlif, 0, stripos($wlif, "_wlan"));
4147
	}
4148
}
4149

    
4150
function interface_get_wireless_clone($wlif) {
4151
	if(!stristr($wlif, "_wlan")) {
4152
		return $wlif . "_wlan0";
4153
	} else {
4154
		return $wlif;
4155
	}
4156
}
4157

    
4158
function get_real_interface($interface = "wan", $family = "all") {
4159
	global $config, $g;
4160

    
4161
	$wanif = NULL;
4162

    
4163
	switch ($interface) {
4164
	case "l2tp":
4165
		$wanif = "l2tp";
4166
		break;
4167
	case "pptp":
4168
		$wanif = "pptp";
4169
		break;
4170
	case "pppoe":
4171
		$wanif = "pppoe";
4172
		break;
4173
	case "openvpn":
4174
		$wanif = "openvpn";
4175
		break;
4176
	case "ipsec":
4177
	case "enc0":
4178
		$wanif = "enc0";
4179
		break;
4180
	case "ppp":
4181
		$wanif = "ppp";
4182
		break;
4183
	default:
4184
		// If a real interface was alread passed simply
4185
		// pass the real interface back.  This encourages
4186
		// the usage of this function in more cases so that
4187
		// we can combine logic for more flexibility.
4188
		if(does_interface_exist($interface)) {
4189
			$wanif = $interface;
4190
			break;
4191
		}
4192

    
4193
		if (empty($config['interfaces'][$interface]))
4194
			break;
4195

    
4196
		$cfg = &$config['interfaces'][$interface];
4197

    
4198
		if ($family == "inet6") {
4199
			switch ($cfg['ipaddrv6']) {
4200
			case "6rd":
4201
			case "6to4":
4202
				$wanif = "{$interface}_stf";
4203
				break;
4204
			default:
4205
				switch ($cfg['ipaddr']) {
4206
				case 'pppoe':
4207
				case 'ppp':
4208
				case 'l2tp':
4209
				case 'pptp':
4210
					$parents = get_parent_interface($interface);
4211
					if (!empty($parents[0]))
4212
						$wanif = $parents[0];
4213
					else
4214
						$wanif = $cfg['if'];
4215
					break;
4216
				default:
4217
					if( is_array($cfg['wireless']) || preg_match($g['wireless_regex'], $cfg['if']))
4218
						$wanif = interface_get_wireless_clone($cfg['if']);
4219
					else
4220
						$wanif = $cfg['if'];
4221
					break;
4222
				}
4223
				break;
4224
			}
4225
		} else {
4226
			// Wireless cloned NIC support (FreeBSD 8+)
4227
			// interface name format: $parentnic_wlanparentnic#
4228
			// example: ath0_wlan0
4229
			if( is_array($cfg['wireless']) || preg_match($g['wireless_regex'], $cfg['if']))
4230
				$wanif = interface_get_wireless_clone($cfg['if']);
4231
			else
4232
				$wanif = $cfg['if'];
4233
		}
4234
		break;
4235
	}
4236

    
4237
	return $wanif;
4238
}
4239

    
4240
/* Guess the physical interface by providing a IP address */
4241
function guess_interface_from_ip($ipaddress) {
4242
	if(! is_ipaddr($ipaddress)) {
4243
		return false;
4244
	}
4245
	if(is_ipaddrv4($ipaddress)) {
4246
		/* create a route table we can search */
4247
		exec("netstat -rnWf inet", $output, $ret);
4248
		foreach($output as $line) {
4249
			if(preg_match("/^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\/[0-9]+[ ]+link[#]/", $line)) {
4250
				$fields = preg_split("/[ ]+/", $line);
4251
				if(ip_in_subnet($ipaddress, $fields[0])) {
4252
					return $fields[6];
4253
				}
4254
			}
4255
		}
4256
	}
4257
	/* FIXME: This works from cursory testing, regexp might need fine tuning */
4258
	if(is_ipaddrv6($ipaddress)) {
4259
		/* create a route table we can search */
4260
		exec("netstat -rnWf inet6", $output, $ret);
4261
		foreach($output as $line) {
4262
			if(preg_match("/[0-9a-f]+[:]+[0-9a-f]+[:]+[\/][0-9]+/", $line)) {
4263
				$fields = preg_split("/[ ]+/", $line);
4264
				if(ip_in_subnet($ipaddress, $fields[0])) {
4265
					return $fields[6];
4266
				}
4267
			}
4268
		}
4269
	}
4270
	$ret = exec_command("/sbin/route -n get {$ipaddress} | /usr/bin/awk '/interface/ { print \$2; };'");
4271
	if(empty($ret)) {
4272
		return false;
4273
	}
4274
	return $ret;
4275
}
4276

    
4277
/*
4278
 * find_ip_interface($ip): return the interface where an ip is defined
4279
 *   (or if $bits is specified, where an IP within the subnet is defined)
4280
 */
4281
function find_ip_interface($ip, $bits = null) {
4282
	if (!is_ipaddr($ip))
4283
		return false;
4284

    
4285
	$isv6ip = is_ipaddrv6($ip);
4286

    
4287
	/* if list */
4288
	$ifdescrs = get_configured_interface_list();
4289

    
4290
	foreach ($ifdescrs as $ifdescr => $ifname) {
4291
		$ifip = ($isv6ip) ? get_interface_ipv6($ifname) : get_interface_ip($ifname);
4292
		if (is_null($ifip))
4293
			continue;
4294
		if (is_null($bits)) {
4295
			if ($ip == $ifip) {
4296
				$int = get_real_interface($ifname);
4297
				return $int;
4298
			}
4299
		}
4300
		else {
4301
			if (ip_in_subnet($ifip, $ip . "/" . $bits)) {
4302
				$int = get_real_interface($ifname);
4303
				return $int;
4304
			}
4305
		}
4306
	}
4307

    
4308
	return false;
4309
}
4310

    
4311
/*
4312
 * find_virtual_ip_alias($ip): return the virtual IP alias where an IP is found
4313
 *   (or if $bits is specified, where an IP within the subnet is found)
4314
 */
4315
function find_virtual_ip_alias($ip, $bits = null) {
4316
	global $config;
4317

    
4318
	if (!is_array($config['virtualip']['vip'])) {
4319
		return false;
4320
	}
4321
	if (!is_ipaddr($ip))
4322
		return false;
4323

    
4324
	$isv6ip = is_ipaddrv6($ip);
4325

    
4326
	foreach ($config['virtualip']['vip'] as $vip) {
4327
		if ($vip['mode'] === "ipalias") {
4328
			if (is_ipaddrv6($vip['subnet']) != $isv6ip)
4329
				continue;
4330
			if (is_null($bits)) {
4331
				if (ip_in_subnet($ip, $vip['subnet'] . "/" . $vip['subnet_bits'])) {
4332
					return $vip;
4333
				}
4334
			}
4335
			else {
4336
				if (($isv6ip && check_subnetsv6_overlap($ip, $bits, $vip['subnet'], $vip['subnet_bits']))
4337
					|| (!$isv6ip && check_subnets_overlap($ip, $bits, $vip['subnet'], $vip['subnet_bits']))) {
4338
					return $vip;
4339
				}
4340
			}
4341
		}
4342
	}
4343
	return false;
4344
}
4345

    
4346
/*
4347
 *   find_number_of_created_carp_interfaces: return the number of carp interfaces
4348
 */
4349
function find_number_of_created_carp_interfaces() {
4350
	return `/sbin/ifconfig | grep "carp:" | wc -l`;
4351
}
4352

    
4353
function get_all_carp_interfaces() {
4354
	$ints = str_replace("\n", " ", `ifconfig | grep "carp:" -B2 | grep ": flag" | cut -d: -f1`);
4355
	$ints = explode(" ", $ints);
4356
	return $ints;
4357
}
4358

    
4359
/*
4360
 * find_carp_interface($ip): return the carp interface where an ip is defined
4361
 */
4362
function find_carp_interface($ip) {
4363
	global $config;
4364
	if (is_array($config['virtualip']['vip'])) {
4365
		foreach ($config['virtualip']['vip'] as $vip) {
4366
			if ($vip['mode'] == "carp") {
4367
				if(is_ipaddrv4($ip)) {
4368
					$carp_ip = get_interface_ip($vip['interface']);
4369
				}
4370
				if(is_ipaddrv6($ip)) {
4371
					$carp_ip = get_interface_ipv6($vip['interface']);
4372
				}
4373
				exec("/sbin/ifconfig", $output, $return);
4374
				foreach($output as $line) {
4375
					$elements = preg_split("/[ ]+/i", $line);
4376
					if(strstr($elements[0], "vip"))
4377
						$curif = str_replace(":", "", $elements[0]);
4378
					if(stristr($line, $ip)) {
4379
						$if = $curif;
4380
						continue;
4381
					}
4382
				}
4383

    
4384
				if ($if)
4385
					return $if;
4386
			}
4387
		}
4388
	}
4389
}
4390

    
4391
function link_carp_interface_to_parent($interface) {
4392
	global $config;
4393

    
4394
	if ($interface == "")
4395
		return;
4396

    
4397
	$carp_ip = get_interface_ip($interface);
4398
	$carp_ipv6 = get_interface_ipv6($interface);
4399

    
4400
	if((!is_ipaddrv4($carp_ip)) && (!is_ipaddrv6($carp_ipv6)))
4401
		return;
4402

    
4403
	/* if list */
4404
	$ifdescrs = get_configured_interface_list();
4405
	foreach ($ifdescrs as $ifdescr => $ifname) {
4406
		/* check IPv4 */
4407
		if(is_ipaddrv4($carp_ip)) {
4408
			$interfaceip = get_interface_ip($ifname);
4409
			$subnet_bits = get_interface_subnet($ifname);
4410
			$subnet_ip = gen_subnet("{$interfaceip}", "{$subnet_bits}");
4411
			if(ip_in_subnet($carp_ip, "{$subnet_ip}/{$subnet_bits}"))
4412
				return $ifname;
4413
		}
4414
		/* Check IPv6 */
4415
		if(is_ipaddrv6($carp_ipv6)) {
4416
			$interfaceipv6 = get_interface_ipv6($ifname);
4417
			$prefixlen = get_interface_subnetv6($ifname);
4418
			if(ip_in_subnet($carp_ipv6, "{$interfaceipv6}/{$prefixlen}"))
4419
				return $ifname;
4420
		}
4421
	}
4422
	return "";
4423
}
4424

    
4425

    
4426
/****f* interfaces/link_ip_to_carp_interface
4427
 * NAME
4428
 *   link_ip_to_carp_interface - Find where a CARP interface links to.
4429
 * INPUTS
4430
 *   $ip
4431
 * RESULT
4432
 *   $carp_ints
4433
 ******/
4434
function link_ip_to_carp_interface($ip) {
4435
	global $config;
4436

    
4437
	if (!is_ipaddr($ip))
4438
		return;
4439

    
4440
	$carp_ints = "";
4441
	if (is_array($config['virtualip']['vip'])) {
4442
		$first = 0;
4443
		$carp_int = array();
4444
		foreach ($config['virtualip']['vip'] as $vip) {
4445
			if ($vip['mode'] == "carp") {
4446
				$carp_ip = $vip['subnet'];
4447
				$carp_sn = $vip['subnet_bits'];
4448
				$carp_nw = gen_subnet($carp_ip, $carp_sn);
4449
				if (ip_in_subnet($ip, "{$carp_nw}/{$carp_sn}")) {
4450
					$carp_int[] = "{$vip['interface']}_vip{$vip['vhid']}";
4451
				}
4452
			}
4453
		}
4454
		if (!empty($carp_int))
4455
			$carp_ints = implode(" ", array_unique($carp_int));
4456
	}
4457

    
4458
	return $carp_ints;
4459
}
4460

    
4461
function link_interface_to_track6($int, $action = "") {
4462
	global $config;
4463

    
4464
	if (empty($int))
4465
		return;
4466

    
4467
	if (is_array($config['interfaces'])) {
4468
		$list = array();
4469
		foreach ($config['interfaces'] as $ifname => $ifcfg) {
4470
			if (!isset($ifcfg['enable']))
4471
				continue;
4472
			if (!empty($ifcfg['ipaddrv6']) && $ifcfg['track6-interface'] == $int) {
4473
				if ($action == "update")
4474
					interface_track6_configure($ifname, $ifcfg);
4475
				else if ($action == "")
4476
					$list[$ifname] = $ifcfg;
4477
			}
4478
		}
4479
		return $list;
4480
	}
4481
}
4482

    
4483
function link_interface_to_vlans($int, $action = "") {
4484
	global $config;
4485

    
4486
	if (empty($int))
4487
		return;
4488

    
4489
	if (is_array($config['vlans']['vlan'])) {
4490
		$ifaces = array();
4491
		foreach ($config['vlans']['vlan'] as $vlan) {
4492
			if ($int == $vlan['if']) {
4493
				if ($action == "update") {
4494
					interfaces_bring_up($int);
4495
				} else if ($action == "")
4496
					$ifaces[$vlan['tag']] = $vlan;
4497
			}
4498
		}
4499
		if (!empty($ifaces))
4500
			return $ifaces;
4501
	}
4502
}
4503

    
4504
function link_interface_to_vips($int, $action = "") {
4505
	global $config;
4506

    
4507
	if (is_array($config['virtualip']['vip'])) {
4508
		$result = array();
4509
		foreach ($config['virtualip']['vip'] as $vip) {
4510
			if ($int == $vip['interface']) {
4511
				if ($action == "update")
4512
					interfaces_vips_configure($int);
4513
				else
4514
					$result[] = $vip;
4515
			}
4516
		}
4517
		return $result;
4518
	}
4519
}
4520

    
4521
/****f* interfaces/link_interface_to_bridge
4522
 * NAME
4523
 *   link_interface_to_bridge - Finds out a bridge group for an interface
4524
 * INPUTS
4525
 *   $ip
4526
 * RESULT
4527
 *   bridge[0-99]
4528
 ******/
4529
function link_interface_to_bridge($int) {
4530
	global $config;
4531

    
4532
	if (is_array($config['bridges']['bridged'])) {
4533
		foreach ($config['bridges']['bridged'] as $bridge) {
4534
			if (in_array($int, explode(',', $bridge['members'])))
4535
				return "{$bridge['bridgeif']}";
4536
		}
4537
	}
4538
}
4539

    
4540
function link_interface_to_group($int) {
4541
	global $config;
4542

    
4543
	$result = array();
4544

    
4545
	if (is_array($config['ifgroups']['ifgroupentry'])) {
4546
		foreach ($config['ifgroups']['ifgroupentry'] as $group) {
4547
			if (in_array($int, explode(" ", $group['members'])))
4548
				$result[$group['ifname']] = $int;
4549
		}
4550
	}
4551

    
4552
	return $result;
4553
}
4554

    
4555
function link_interface_to_gre($interface) {
4556
	global $config;
4557

    
4558
	$result = array();
4559

    
4560
	if (is_array($config['gres']['gre'])) {
4561
		foreach ($config['gres']['gre'] as $gre)
4562
			if($gre['if'] == $interface)
4563
				$result[] = $gre;
4564
	}
4565

    
4566
	return $result;
4567
}
4568

    
4569
function link_interface_to_gif($interface) {
4570
	global $config;
4571

    
4572
	$result = array();
4573

    
4574
	if (is_array($config['gifs']['gif'])) {
4575
		foreach ($config['gifs']['gif'] as $gif)
4576
			if($gif['if'] == $interface)
4577
				$result[] = $gif;
4578
	}
4579

    
4580
	return $result;
4581
}
4582

    
4583
/*
4584
 * find_interface_ip($interface): return the interface ip (first found)
4585
 */
4586
function find_interface_ip($interface, $flush = false) {
4587
	global $interface_ip_arr_cache;
4588
	global $interface_sn_arr_cache;
4589

    
4590
	$interface = str_replace("\n", "", $interface);
4591

    
4592
	if (!does_interface_exist($interface))
4593
		return;
4594

    
4595
	/* Setup IP cache */
4596
	if (!isset($interface_ip_arr_cache[$interface]) or $flush) {
4597
		$ifinfo = pfSense_get_interface_addresses($interface);
4598
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
4599
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
4600
	}
4601

    
4602
	return $interface_ip_arr_cache[$interface];
4603
}
4604

    
4605
/*
4606
 * find_interface_ipv6($interface): return the interface ip (first found)
4607
 */
4608
function find_interface_ipv6($interface, $flush = false) {
4609
	global $interface_ipv6_arr_cache;
4610
	global $interface_snv6_arr_cache;
4611
	global $config;
4612

    
4613
	$interface = trim($interface);
4614
	$interface = get_real_interface($interface);
4615

    
4616
	if (!does_interface_exist($interface))
4617
		return;
4618

    
4619
	/* Setup IP cache */
4620
	if (!isset($interface_ipv6_arr_cache[$interface]) or $flush) {
4621
		// FIXME: Add IPv6 support to the pfSense module
4622
		$ifinfo = array();
4623
		exec("/sbin/ifconfig {$interface} inet6", $output);
4624
		foreach($output as $line) {
4625
			if(preg_match("/inet6/", $line)) {
4626
				$parts = explode(" ", $line);
4627
				if(!is_linklocal($parts[1])) {
4628
					$ifinfo['ipaddrv6'] = $parts[1];
4629
					if($parts[2] == "-->") {
4630
						$parts[5] = "126";
4631
						$ifinfo['subnetbitsv6'] = $parts[5];
4632
					} else {
4633
						$ifinfo['subnetbitsv6'] = $parts[3];
4634
					}
4635
					break;
4636
				}
4637
			}
4638
		}
4639
		$interface_ipv6_arr_cache[$interface] = $ifinfo['ipaddrv6'];
4640
		$interface_snv6_arr_cache[$interface] = $ifinfo['subnetbitsv6'];
4641
	}
4642

    
4643
	return $interface_ipv6_arr_cache[$interface];
4644
}
4645

    
4646
/*
4647
 * find_interface_ipv6_ll($interface): return the interface ipv6 link local (first found)
4648
 */
4649
function find_interface_ipv6_ll($interface, $flush = false) {
4650
	global $interface_llv6_arr_cache;
4651
	global $config;
4652

    
4653
	$interface = str_replace("\n", "", $interface);
4654

    
4655
	if (!does_interface_exist($interface))
4656
		return;
4657

    
4658
	/* Setup IP cache */
4659
	if (!isset($interface_llv6_arr_cache[$interface]) or $flush) {
4660
		$ifinfo = pfSense_get_interface_addresses($interface);
4661
		// FIXME: Add IPv6 support to the pfSense module
4662
		exec("/sbin/ifconfig {$interface} inet6", $output);
4663
		foreach($output as $line) {
4664
			if(preg_match("/inet6/", $line)) {
4665
				$parts = explode(" ", $line);
4666
				if(is_linklocal($parts[1])) {
4667
					$partsaddress = explode("%", $parts[1]);
4668
					$ifinfo['linklocal'] = $partsaddress[0];
4669
				}
4670
			}
4671
		}
4672
		$interface_llv6_arr_cache[$interface] = $ifinfo['linklocal'];
4673
	}
4674
	return $interface_llv6_arr_cache[$interface];
4675
}
4676

    
4677
function find_interface_subnet($interface, $flush = false) {
4678
	global $interface_sn_arr_cache;
4679
	global $interface_ip_arr_cache;
4680

    
4681
	$interface = str_replace("\n", "", $interface);
4682
	if (does_interface_exist($interface) == false)
4683
		return;
4684

    
4685
	if (!isset($interface_sn_arr_cache[$interface]) or $flush) {
4686
		$ifinfo = pfSense_get_interface_addresses($interface);
4687
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
4688
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
4689
	}
4690

    
4691
	return $interface_sn_arr_cache[$interface];
4692
}
4693

    
4694
function find_interface_subnetv6($interface, $flush = false) {
4695
	global $interface_snv6_arr_cache;
4696
	global $interface_ipv6_arr_cache;
4697

    
4698
	$interface = str_replace("\n", "", $interface);
4699
	if (does_interface_exist($interface) == false)
4700
		return;
4701

    
4702
	$foundv6 = false;
4703
	if (!isset($interface_snv6_arr_cache[$interface]) or $flush) {
4704
		$ifinfo = array();
4705
		// FIXME: Add IPv6 support to the pfSense module
4706
		unset($output);
4707
		exec("/sbin/ifconfig {$interface} inet6", $output);
4708
		foreach($output as $line) {
4709
			$line = trim($line);
4710
			if(preg_match("/inet6/", $line)) {
4711
				$parts = explode(" ", $line);
4712
				if(!is_linklocal($parts[1])) {
4713
					$ifinfo['ipaddrv6'] = $parts[1];
4714
					if($parts[2] == "-->") {
4715
						$parts[5] = "126";
4716
						$ifinfo['subnetbitsv6'] = $parts[5];
4717
					} else {
4718
						$ifinfo['subnetbitsv6'] = $parts[3];
4719
					}
4720
					$foundv6 = true;
4721
					break;
4722
				}
4723
			}
4724
		}
4725
		if ($foundv6 === true) {
4726
			$interface_ipv6_arr_cache[$interface] = $ifinfo['ipaddrv6'];
4727
			$interface_snv6_arr_cache[$interface] = $ifinfo['subnetbitsv6'];
4728
		} else
4729
			unset($interface_ipv6_arr_cache[$interface], $interface_snv6_arr_cache[$interface]);
4730
	}
4731

    
4732
	return $interface_snv6_arr_cache[$interface];
4733
}
4734

    
4735
function ip_in_interface_alias_subnet($interface, $ipalias) {
4736
	global $config;
4737

    
4738
	if (empty($interface) || !is_ipaddr($ipalias))
4739
		return false;
4740
	if (is_array($config['virtualip']['vip'])) {
4741
		foreach ($config['virtualip']['vip'] as $vip) {
4742
			switch ($vip['mode']) {
4743
			case "ipalias":
4744
				if ($vip['interface'] <> $interface)
4745
					break;
4746
				if (ip_in_subnet($ipalias, gen_subnet($vip['subnet'], $vip['subnet_bits']) . "/" . $vip['subnet_bits']))
4747
					return true;
4748
				break;
4749
			}
4750
		}
4751
	}
4752

    
4753
	return false;
4754
}
4755

    
4756
function get_interface_ip($interface = "wan") {
4757
	$realif = get_failover_interface($interface);
4758
	if (!$realif) {
4759
		if (preg_match("/^carp/i", $interface))
4760
			$realif = $interface;
4761
		else if (preg_match("/^[a-z0-9]+_vip/i", $interface))
4762
			$realif = $interface;
4763
		else
4764
			return null;
4765
	}
4766

    
4767
	$curip = find_interface_ip($realif);
4768
	if ($curip && is_ipaddr($curip) && ($curip != "0.0.0.0"))
4769
		return $curip;
4770
	else
4771
		return null;
4772
}
4773

    
4774
function get_interface_ipv6($interface = "wan", $flush = false) {
4775
	global $config;
4776

    
4777
	$realif = get_failover_interface($interface, "inet6");
4778
	if (!$realif) {
4779
		if (preg_match("/^[a-z0-9]+_vip/i", $interface))
4780
			$realif = $interface;
4781
		else
4782
			return null;
4783
	}
4784

    
4785
	$curip = find_interface_ipv6($realif, $flush);
4786
	if ($curip && is_ipaddrv6($curip) && ($curip != "::"))
4787
		return $curip;
4788
	else
4789
		return null;
4790
}
4791

    
4792
function get_interface_linklocal($interface = "wan") {
4793

    
4794
	$realif = get_failover_interface($interface, "inet6");
4795
	if (!$realif) {
4796
		if (preg_match("/^carp/i", $interface))
4797
			$realif = $interface;
4798
		else if (preg_match("/^[a-z0-9]+_vip/i", $interface))
4799
			$realif = $interface;
4800
		else
4801
			return null;
4802
	}
4803

    
4804
	$curip = find_interface_ipv6_ll($realif);
4805
	if ($curip && is_ipaddrv6($curip) && ($curip != "::"))
4806
		return $curip;
4807
	else
4808
		return null;
4809
}
4810

    
4811
function get_interface_subnet($interface = "wan") {
4812
	$realif = get_real_interface($interface);
4813
	if (!$realif) {
4814
		if (preg_match("/^carp/i", $interface))
4815
			$realif = $interface;
4816
		else if (preg_match("/^[a-z0-9]+_vip/i", $interface))
4817
			$realif = $interface;
4818
		else
4819
			return null;
4820
	}
4821

    
4822
	$cursn = find_interface_subnet($realif);
4823
	if (!empty($cursn))
4824
		return $cursn;
4825

    
4826
	return null;
4827
}
4828

    
4829
function get_interface_subnetv6($interface = "wan") {
4830
	global $config;
4831

    
4832
	$realif = get_real_interface($interface, "inet6");
4833
	if (!$realif) {
4834
		if (preg_match("/^[a-z0-9]+_vip/i", $interface))
4835
			$realif = $interface;
4836
		else
4837
			return null;
4838
	}
4839

    
4840
	$cursn = find_interface_subnetv6($realif);
4841
	if (!empty($cursn))
4842
		return $cursn;
4843

    
4844
	return null;
4845
}
4846

    
4847
/* return outside interfaces with a gateway */
4848
function get_interfaces_with_gateway() {
4849
	global $config;
4850

    
4851
	$ints = array();
4852

    
4853
	/* loop interfaces, check config for outbound */
4854
	foreach($config['interfaces'] as $ifdescr => $ifname) {
4855
		switch ($ifname['ipaddr']) {
4856
			case "dhcp":
4857
			case "ppp";
4858
			case "pppoe":
4859
			case "pptp":
4860
			case "l2tp":
4861
			case "ppp";
4862
				$ints[$ifdescr] = $ifdescr;
4863
			break;
4864
			default:
4865
				if (substr($ifname['if'], 0, 4) ==  "ovpn" ||
4866
				    !empty($ifname['gateway']))
4867
					$ints[$ifdescr] = $ifdescr;
4868
			break;
4869
		}
4870
	}
4871
	return $ints;
4872
}
4873

    
4874
/* return true if interface has a gateway */
4875
function interface_has_gateway($friendly) {
4876
	global $config;
4877

    
4878
	if (!empty($config['interfaces'][$friendly])) {
4879
		$ifname = &$config['interfaces'][$friendly];
4880
		switch ($ifname['ipaddr']) {
4881
			case "dhcp":
4882
			case "pppoe":
4883
			case "pptp":
4884
			case "l2tp":
4885
			case "ppp";
4886
				return true;
4887
			break;
4888
			default:
4889
				if (substr($ifname['if'], 0, 4) ==  "ovpn")
4890
					return true;
4891
				if (!empty($ifname['gateway']))
4892
					return true;
4893
			break;
4894
		}
4895
	}
4896

    
4897
	return false;
4898
}
4899

    
4900
/* return true if interface has a gateway */
4901
function interface_has_gatewayv6($friendly) {
4902
	global $config;
4903

    
4904
	if (!empty($config['interfaces'][$friendly])) {
4905
		$ifname = &$config['interfaces'][$friendly];
4906
		switch ($ifname['ipaddrv6']) {
4907
			case "slaac":
4908
			case "dhcp6":
4909
			case "6to4":
4910
			case "6rd":
4911
				return true;
4912
				break;
4913
			default:
4914
				if (substr($ifname['if'], 0, 4) ==  "ovpn")
4915
					return true;
4916
				if (!empty($ifname['gatewayv6']))
4917
					return true;
4918
				break;
4919
		}
4920
	}
4921

    
4922
	return false;
4923
}
4924

    
4925
/****f* interfaces/is_altq_capable
4926
 * NAME
4927
 *   is_altq_capable - Test if interface is capable of using ALTQ
4928
 * INPUTS
4929
 *   $int            - string containing interface name
4930
 * RESULT
4931
 *   boolean         - true or false
4932
 ******/
4933

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

    
4947
	$int_family = remove_ifindex($int);
4948

    
4949
	if (in_array($int_family, $capable))
4950
		return true;
4951
	else if (stristr($int, "l2tp")) /* VLANs are name $parent_$vlan now */
4952
		return true;
4953
	else if (stristr($int, "_vlan")) /* VLANs are name $parent_$vlan now */
4954
		return true;
4955
	else if (stristr($int, "_wlan")) /* WLANs are name $parent_$wlan now */
4956
		return true;
4957
	else
4958
		return false;
4959
}
4960

    
4961
/****f* interfaces/is_interface_wireless
4962
 * NAME
4963
 *   is_interface_wireless - Returns if an interface is wireless
4964
 * RESULT
4965
 *   $tmp       - Returns if an interface is wireless
4966
 ******/
4967
function is_interface_wireless($interface) {
4968
	global $config, $g;
4969

    
4970
	$friendly = convert_real_interface_to_friendly_interface_name($interface);
4971
	if(!isset($config['interfaces'][$friendly]['wireless'])) {
4972
		if (preg_match($g['wireless_regex'], $interface)) {
4973
			if (isset($config['interfaces'][$friendly]))
4974
				$config['interfaces'][$friendly]['wireless'] = array();
4975
			return true;
4976
		}
4977
		return false;
4978
	} else
4979
		return true;
4980
}
4981

    
4982
function get_wireless_modes($interface) {
4983
	/* return wireless modes and channels */
4984
	$wireless_modes = array();
4985

    
4986
	$cloned_interface = get_real_interface($interface);
4987

    
4988
	if($cloned_interface && is_interface_wireless($cloned_interface)) {
4989
		$chan_list = "/sbin/ifconfig {$cloned_interface} list chan";
4990
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
4991
		$format_list = "/usr/bin/awk '{print \$5 \" \" \$6 \",\" \$1}'";
4992

    
4993
		$interface_channels = "";
4994
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
4995
		$interface_channel_count = count($interface_channels);
4996

    
4997
		$c = 0;
4998
		while ($c < $interface_channel_count) {
4999
			$channel_line = explode(",", $interface_channels["$c"]);
5000
			$wireless_mode = trim($channel_line[0]);
5001
			$wireless_channel = trim($channel_line[1]);
5002
			if(trim($wireless_mode) != "") {
5003
				/* if we only have 11g also set 11b channels */
5004
				if($wireless_mode == "11g") {
5005
					if(!isset($wireless_modes["11b"]))
5006
						$wireless_modes["11b"] = array();
5007
				} else if($wireless_mode == "11g ht") {
5008
					if(!isset($wireless_modes["11b"]))
5009
						$wireless_modes["11b"] = array();
5010
					if(!isset($wireless_modes["11g"]))
5011
						$wireless_modes["11g"] = array();
5012
					$wireless_mode = "11ng";
5013
				} else if($wireless_mode == "11a ht") {
5014
					if(!isset($wireless_modes["11a"]))
5015
						$wireless_modes["11a"] = array();
5016
					$wireless_mode = "11na";
5017
				}
5018
				$wireless_modes["$wireless_mode"]["$c"] = $wireless_channel;
5019
			}
5020
			$c++;
5021
		}
5022
	}
5023
	return($wireless_modes);
5024
}
5025

    
5026
/* return channel numbers, frequency, max txpower, and max regulation txpower */
5027
function get_wireless_channel_info($interface) {
5028
	$wireless_channels = array();
5029

    
5030
	$cloned_interface = get_real_interface($interface);
5031

    
5032
	if($cloned_interface && is_interface_wireless($cloned_interface)) {
5033
		$chan_list = "/sbin/ifconfig {$cloned_interface} list txpower";
5034
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
5035
		$format_list = "/usr/bin/awk '{print \$1 \",\" \$3 \" \" \$4 \",\" \$5 \",\" \$7}'";
5036

    
5037
		$interface_channels = "";
5038
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
5039

    
5040
		foreach ($interface_channels as $channel_line) {
5041
			$channel_line = explode(",", $channel_line);
5042
			if(!isset($wireless_channels[$channel_line[0]]))
5043
				$wireless_channels[$channel_line[0]] = $channel_line;
5044
		}
5045
	}
5046
	return($wireless_channels);
5047
}
5048

    
5049
/****f* interfaces/get_interface_mtu
5050
 * NAME
5051
 *   get_interface_mtu - Return the mtu of an interface
5052
 * RESULT
5053
 *   $tmp       - Returns the mtu of an interface
5054
 ******/
5055
function get_interface_mtu($interface) {
5056
	$mtu = pfSense_get_interface_addresses($interface);
5057
	return $mtu['mtu'];
5058
}
5059

    
5060
function get_interface_mac($interface) {
5061

    
5062
	$macinfo = pfSense_get_interface_addresses($interface);
5063
	return $macinfo["macaddr"];
5064
}
5065

    
5066
/****f* pfsense-utils/generate_random_mac_address
5067
 * NAME
5068
 *   generate_random_mac - generates a random mac address
5069
 * INPUTS
5070
 *   none
5071
 * RESULT
5072
 *   $mac - a random mac address
5073
 ******/
5074
function generate_random_mac_address() {
5075
	$mac = "02";
5076
	for($x=0; $x<5; $x++)
5077
		$mac .= ":" . dechex(rand(16, 255));
5078
	return $mac;
5079
}
5080

    
5081
/****f* interfaces/is_jumbo_capable
5082
 * NAME
5083
 *   is_jumbo_capable - Test if interface is jumbo frame capable.  Useful for determining VLAN capability.
5084
 * INPUTS
5085
 *   $int             - string containing interface name
5086
 * RESULT
5087
 *   boolean          - true or false
5088
 ******/
5089
function is_jumbo_capable($iface) {
5090
	$iface = trim($iface);
5091
	$capable = pfSense_get_interface_addresses($iface);
5092

    
5093
	if (isset($capable['caps']['vlanmtu']))
5094
		return true;
5095

    
5096
	return false;
5097
}
5098

    
5099
function interface_setup_pppoe_reset_file($pppif, $iface="") {
5100
	global $g;
5101

    
5102
	$cron_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
5103

    
5104
	if(!empty($iface) && !empty($pppif)){
5105
		$cron_cmd = <<<EOD
5106
#!/bin/sh
5107
/usr/local/sbin/pfSctl -c 'interface reload {$iface}'
5108
/usr/bin/logger -t {$pppif} "PPPoE periodic reset executed on {$iface}"
5109

    
5110
EOD;
5111

    
5112
		@file_put_contents($cron_file, $cron_cmd);
5113
		chmod($cron_file, 0755);
5114
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
5115
	} else
5116
		unlink_if_exists($cron_file);
5117
}
5118

    
5119
function get_interface_default_mtu($type = "ethernet") {
5120
	switch ($type) {
5121
	case "gre":
5122
		return 1476;
5123
		break;
5124
	case "gif":
5125
		return 1280;
5126
		break;
5127
	case "tun":
5128
	case "vlan":
5129
	case "tap":
5130
	case "ethernet":
5131
	default:
5132
		return 1500;
5133
		break;
5134
	}
5135

    
5136
	/* Never reached */
5137
	return 1500;
5138
}
5139

    
5140
function get_vip_descr($ipaddress) {
5141
	global $config;
5142

    
5143
	foreach ($config['virtualip']['vip'] as $vip) {
5144
		if ($vip['subnet'] == $ipaddress) {
5145
			return ($vip['descr']);
5146
		}
5147
	}
5148
	return "";
5149
}
5150

    
5151
function interfaces_staticarp_configure($if) {
5152
	global $config, $g;
5153
	if(isset($config['system']['developerspew'])) {
5154
		$mt = microtime();
5155
		echo "interfaces_staticarp_configure($if) being called $mt\n";
5156
	}
5157

    
5158
	$ifcfg = $config['interfaces'][$if];
5159

    
5160
	if (empty($if) || empty($ifcfg['if']) || !isset($ifcfg['enable']))
5161
		return 0;
5162

    
5163
	/* Enable staticarp, if enabled */
5164
	if(isset($config['dhcpd'][$if]['staticarp'])) {
5165
		mwexec("/sbin/ifconfig " . escapeshellarg($ifcfg['if']) . " staticarp " );
5166
		mwexec("/usr/sbin/arp -d -i " . escapeshellarg($ifcfg['if']) . " -a > /dev/null 2>&1 ");
5167
		if (is_array($config['dhcpd'][$if]['staticmap'])) {
5168

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

    
5172
			}
5173

    
5174
		}
5175
	} else {
5176
		mwexec("/sbin/ifconfig " . escapeshellarg($ifcfg['if']) . " -staticarp " );
5177
		mwexec("/usr/sbin/arp -d -i " . escapeshellarg($ifcfg['if']) . " -a > /dev/null 2>&1 ");
5178
		if (is_array($config['dhcpd'][$if]) && is_array($config['dhcpd'][$if]['staticmap'])) {
5179
			foreach ($config['dhcpd'][$if]['staticmap'] as $arpent) {
5180
				if (isset($arpent['arp_table_static_entry'])) {
5181
					mwexec("/usr/sbin/arp -s " . escapeshellarg($arpent['ipaddr']) . " " . escapeshellarg($arpent['mac']));
5182
				}
5183
			}
5184
		}
5185
	}
5186

    
5187
	return 0;
5188
}
5189

    
5190
function get_failover_interface($interface, $family = "all") {
5191
	global $config;
5192

    
5193
	/* shortcut to get_real_interface if we find it in the config */
5194
	if (is_array($config['interfaces'][$interface])) {
5195
		return get_real_interface($interface, $family);
5196
	}
5197

    
5198
	/* compare against gateway groups */
5199
	$a_groups = return_gateway_groups_array();
5200
	if (is_array($a_groups[$interface])) {
5201
		/* we found a gateway group, fetch the interface or vip */
5202
		if ($a_groups[$interface][0]['vip'] <> "")
5203
			return $a_groups[$interface][0]['vip'];
5204
		else
5205
			return $a_groups[$interface][0]['int'];
5206
	}
5207
	/* fall through to get_real_interface */
5208
	/* XXX: Really needed? */
5209
	return get_real_interface($interface, $family);
5210
}
5211

    
5212
function remove_ifindex($ifname) {
5213
	return preg_replace("/[0-9]+$/", "", $ifname);
5214
}
5215

    
5216
?>
(25-25/66)