Project

General

Profile

Download (157 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['caps']['txcsum']))
491
			$commontx = false;
492
		if (!isset($opts['caps']['rxcsum']))
493
			$commonrx = false;
494
		if (!isset($opts['caps']['tso4']))
495
			$commontso4 = false;
496
		if (!isset($opts['caps']['tso6']))
497
			$commontso6 = false;
498
		if (!isset($opts['caps']['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_on = 0;
513
	$flags_off = 0;
514
	if (isset($config['system']['disablechecksumoffloading']) || ($commonrx === false))
515
		$flags_off |= IFCAP_RXCSUM;
516
	else
517
		$flags_on |= IFCAP_RXCSUM;
518
	if (isset($config['system']['disablechecksumoffloading']) || ($commontx === false))
519
		$flags_off |= IFCAP_TXCSUM;
520
	else
521
		$flags_on |= IFCAP_TXCSUM;
522
	if (isset($config['system']['disablesegmentationoffloading']) || ($commontso4 === false))
523
		$flags_off |= IFCAP_TSO4;
524
	else
525
		$flags_on |= IFCAP_TSO4;
526
	if (isset($config['system']['disablesegmentationoffloading']) || ($commontso6 === false))
527
		$flags_off |= IFCAP_TSO6;
528
	else
529
		$flags_on |= IFCAP_TSO6;
530
	if (isset($config['system']['disablelargereceiveoffloading']) || ($commonlro === false))
531
		$flags_off |= IFCAP_LRO;
532
	else
533
		$flags_on |= IFCAP_LRO;
534

    
535
	if ($g['booting'] || !empty($bridge['bridgeif'])) {
536
		pfSense_interface_destroy($bridge['bridgeif']);
537
		pfSense_interface_create($bridge['bridgeif']);
538
		$bridgeif = escapeshellarg($bridge['bridgeif']);
539
	} else {
540
		$bridgeif = pfSense_interface_create("bridge");
541
		$bridge['bridgeif'] = $bridgeif;
542
	}
543

    
544
	$checklist = get_configured_interface_list();
545

    
546
	/* Add interfaces to bridge */
547
	foreach ($members as $member) {
548
		if (empty($checklist[$member]))
549
			continue;
550
		$realif = get_real_interface($member);
551
		if (!$realif) {
552
			log_error(gettext("realif not defined in interfaces bridge - up"));
553
			continue;
554
		}
555
		/* make sure the parent interface is up */
556
		pfSense_interface_mtu($realif, $smallermtu);
557
		pfSense_interface_capabilities($realif, -$flags_off);
558
		pfSense_interface_capabilities($realif, $flags_on);
559
		interfaces_bring_up($realif);
560
		pfSense_bridge_add_member($bridge['bridgeif'], $realif);
561
	}
562

    
563
	if (isset($bridge['enablestp'])) {
564
		/* Choose spanning tree proto */
565
		mwexec("/sbin/ifconfig {$bridgeif} proto " . escapeshellarg($bridge['proto']));
566

    
567
		if (!empty($bridge['stp'])) {
568
			$stpifs = explode(',', $bridge['stp']);
569
			foreach ($stpifs as $stpif) {
570
				$realif = get_real_interface($stpif);
571
				mwexec("/sbin/ifconfig {$bridgeif} stp {$realif}");
572
			}
573
		}
574
		if (!empty($bridge['maxage']))
575
			mwexec("/sbin/ifconfig {$bridgeif} maxage " . escapeshellarg($bridge['maxage']));
576
		if (!empty($bridge['fwdelay']))
577
			mwexec("/sbin/ifconfig {$bridgeif} fwddelay " . escapeshellarg($bridge['fwdelay']));
578
		if (!empty($bridge['hellotime']))
579
			mwexec("/sbin/ifconfig {$bridgeif} hellotime " . escapeshellarg($bridge['hellotime']));
580
		if (!empty($bridge['priority']))
581
			mwexec("/sbin/ifconfig {$bridgeif} priority " . escapeshellarg($bridge['priority']));
582
		if (!empty($bridge['holdcnt']))
583
			mwexec("/sbin/ifconfig {$bridgeif} holdcnt " . escapeshellarg($bridge['holdcnt']));
584
		if (!empty($bridge['ifpriority'])) {
585
			$pconfig = explode(",", $bridge['ifpriority']);
586
			$ifpriority = array();
587
			foreach ($pconfig as $cfg) {
588
				$embcfg = explode_assoc(":", $cfg);
589
				foreach ($embcfg as $key => $value)
590
					$ifpriority[$key] = $value;
591
			}
592
			foreach ($ifpriority as $key => $value) {
593
				$realif = get_real_interface($key);
594
				mwexec("/sbin/ifconfig ${bridgeif} ifpriority {$realif} " . escapeshellarg($value));
595
			}
596
		}
597
		if (!empty($bridge['ifpathcost'])) {
598
			$pconfig = explode(",", $bridge['ifpathcost']);
599
			$ifpathcost = array();
600
			foreach ($pconfig as $cfg) {
601
				$embcfg = explode_assoc(":", $cfg);
602
				foreach ($embcfg as $key => $value)
603
					$ifpathcost[$key] = $value;
604
			}
605
			foreach ($ifpathcost as $key => $value) {
606
				$realif = get_real_interface($key);
607
				mwexec("/sbin/ifconfig ${bridgeif} ifpathcost {$realif} " . escapeshellarg($value));
608
			}
609
		}
610
	}
611

    
612
	if ($bridge['maxaddr'] <> "")
613
		mwexec("/sbin/ifconfig {$bridgeif} maxaddr {$bridge['maxaddr']}");
614
	if ($bridge['timeout'] <> "")
615
		mwexec("/sbin/ifconfig {$bridgeif} timeout {$bridge['timeout']}");
616
	if ($bridge['span'] <> "") {
617
		$realif = get_real_interface($bridge['span']);
618
		mwexec("/sbin/ifconfig {$bridgeif} span {$realif}");
619
	}
620
	if (!empty($bridge['edge'])) {
621
		$edgeifs = explode(',', $bridge['edge']);
622
		foreach ($edgeifs as $edgeif) {
623
			$realif = get_real_interface($edgeif);
624
			mwexec("/sbin/ifconfig {$bridgeif} edge {$realif}");
625
		}
626
	}
627
	if (!empty($bridge['autoedge'])) {
628
		$edgeifs = explode(',', $bridge['autoedge']);
629
		foreach ($edgeifs as $edgeif) {
630
			$realif = get_real_interface($edgeif);
631
			mwexec("/sbin/ifconfig {$bridgeif} -autoedge {$realif}");
632
		}
633
	}
634
	if (!empty($bridge['ptp'])) {
635
		$ptpifs = explode(',', $bridge['ptp']);
636
		foreach ($ptpifs as $ptpif) {
637
			$realif = get_real_interface($ptpif);
638
			mwexec("/sbin/ifconfig {$bridgeif} ptp {$realif}");
639
		}
640
	}
641
	if (!empty($bridge['autoptp'])) {
642
		$ptpifs = explode(',', $bridge['autoptp']);
643
		foreach ($ptpifs as $ptpif) {
644
			$realif = get_real_interface($ptpif);
645
			mwexec("/sbin/ifconfig {$bridgeif} -autoptp {$realif}");
646
		}
647
	}
648
	if (!empty($bridge['static'])) {
649
		$stickyifs = explode(',', $bridge['static']);
650
		foreach ($stickyifs as $stickyif) {
651
			$realif = get_real_interface($stickyif);
652
			mwexec("/sbin/ifconfig {$bridgeif} sticky {$realif}");
653
		}
654
	}
655
	if (!empty($bridge['private'])) {
656
		$privateifs = explode(',', $bridge['private']);
657
		foreach ($privateifs as $privateif) {
658
			$realif = get_real_interface($privateif);
659
			mwexec("/sbin/ifconfig {$bridgeif} private {$realif}");
660
		}
661
	}
662

    
663
	if ($bridge['bridgeif'])
664
		interfaces_bring_up($bridge['bridgeif']);
665
	else
666
		log_error(gettext("bridgeif not defined -- could not bring interface up"));
667
}
668

    
669
function interface_bridge_add_member($bridgeif, $interface) {
670

    
671
	if (!does_interface_exist($bridgeif) || !does_interface_exist($interface))
672
		return;
673

    
674
	$mtu = get_interface_mtu($bridgeif);
675
	$mtum = get_interface_mtu($interface);
676

    
677
	if ($mtu != $mtum && !(substr($interface, 0, 3) == "gif" && $mtu <= 1500))
678
		pfSense_interface_mtu($interface, $mtu);
679

    
680
	$options = pfSense_get_interface_addresses($bridgeif);
681
	$flags_on = 0;
682
	$flags_off = 0;
683
	if (isset($options['encaps']['txcsum']))
684
		$flags_on |= IFCAP_TXCSUM;
685
	else
686
		$flags_off |= IFCAP_TXCSUM;
687
	if (isset($options['encaps']['rxcsum']))
688
		$flags_on |= IFCAP_RXCSUM;
689
	else
690
		$flags_off |= IFCAP_RXCSUM;
691
	if (isset($options['encaps']['tso4']))
692
		$flags_on |= IFCAP_TSO4;
693
	else
694
		$flags_off |= IFCAP_TSO4;
695
	if (isset($options['encaps']['tso6']))
696
		$flags_on |= IFCAP_TSO6;
697
	else
698
		$flags_off |= IFCAP_TSO6;
699
	if (isset($options['encaps']['lro']))
700
		$flags_on |= IFCAP_LRO;
701
	else
702
		$flags_off |= IFCAP_LRO;
703

    
704
	pfSense_interface_capabilities($interface, -$flags_off);
705
	pfSense_interface_capabilities($interface, $flags_on);
706

    
707
	interfaces_bring_up($interface);
708
	pfSense_bridge_add_member($bridgeif, $interface);
709
}
710

    
711
function interfaces_lagg_configure() {
712
	global $config, $g;
713
	if($g['booting'])
714
		echo gettext("Configuring LAGG interfaces...");
715
	$i = 0;
716
	if (is_array($config['laggs']['lagg']) && count($config['laggs']['lagg'])) {
717
		foreach ($config['laggs']['lagg'] as $lagg) {
718
			if(empty($lagg['laggif']))
719
				$lagg['laggif'] = "lagg{$i}";
720
			/* XXX: Maybe we should report any errors?! */
721
			interface_lagg_configure($lagg);
722
			$i++;
723
		}
724
	}
725
	if($g['booting'])
726
		echo gettext("done.") . "\n";
727
}
728

    
729
function interface_lagg_configure(&$lagg) {
730
	global $config, $g;
731

    
732
	if (!is_array($lagg))
733
		return -1;
734

    
735
	$members = explode(',', $lagg['members']);
736
	if (!count($members))
737
		return -1;
738

    
739
	if ($g['booting'] || !(empty($lagg['laggif']))) {
740
		pfSense_interface_destroy($lagg['laggif']);
741
		pfSense_interface_create($lagg['laggif']);
742
		$laggif = $lagg['laggif'];
743
	} else
744
		$laggif = pfSense_interface_create("lagg");
745

    
746
	/* Calculate smaller mtu and enforce it */
747
	$smallermtu = 0;
748
	foreach ($members as $member) {
749
		$opts = pfSense_get_interface_addresses($member);
750
		$mtu = $opts['mtu'];
751
		if (!isset($opts['caps']['txcsum']))
752
			$commontx = false;
753
		if (!isset($opts['caps']['rxcsum']))
754
			$commonrx = false;
755
		if (!isset($opts['caps']['tso4']))
756
			$commontso4 = false;
757
		if (!isset($opts['caps']['tso6']))
758
			$commontso6 = false;
759
		if (!isset($opts['caps']['lro']))
760
			$commonlro = false;
761
		if ($smallermtu == 0 && !empty($mtu))
762
			$smallermtu = $mtu;
763
		else if (!empty($mtu) && $mtu < $smallermtu)
764
			$smallermtu = $mtu;
765
	}
766

    
767
	/* Just in case anything is not working well */
768
	if ($smallermtu == 0)
769
		$smallermtu = 1500;
770

    
771
	$flags_on = 0;
772
	$flags_off = 0;
773
	if (isset($config['system']['disablechecksumoffloading']) || ($commonrx === false))
774
		$flags_off |= IFCAP_RXCSUM;
775
	else
776
		$flags_on |= IFCAP_RXCSUM;
777
	if (isset($config['system']['disablechecksumoffloading']) || ($commontx === false))
778
		$flags_off |= IFCAP_TXCSUM;
779
	else
780
		$flags_on |= IFCAP_TXCSUM;
781
	if (isset($config['system']['disablesegmentationoffloading']) || ($commontso4 === false))
782
		$flags_off |= IFCAP_TSO4;
783
	else
784
		$flags_on |= IFCAP_TSO4;
785
	if (isset($config['system']['disablesegmentationoffloading']) || ($commontso6 === false))
786
		$flags_off |= IFCAP_TSO6;
787
	else
788
		$flags_on |= IFCAP_TSO6;
789
	if (isset($config['system']['disablelargereceiveoffloading']) || ($commonlro === false))
790
		$flags_off |= IFCAP_LRO;
791
	else
792
		$flags_on |= IFCAP_LRO;
793

    
794
	$checklist = get_interface_list();
795

    
796
	foreach ($members as $member) {
797
		if (!array_key_exists($member, $checklist))
798
			continue;
799
		/* make sure the parent interface is up */
800
		pfSense_interface_mtu($member, $smallermtu);
801
		pfSense_interface_capabilities($member, -$flags_off);
802
		pfSense_interface_capabilities($member, $flags_on);
803
		interfaces_bring_up($member);
804
		mwexec("/sbin/ifconfig {$laggif} laggport {$member}");
805
	}
806

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

    
809
	interfaces_bring_up($laggif);
810

    
811
	return $laggif;
812
}
813

    
814
function interfaces_gre_configure($checkparent = 0) {
815
	global $config;
816

    
817
	if (is_array($config['gres']['gre']) && count($config['gres']['gre'])) {
818
		foreach ($config['gres']['gre'] as $i => $gre) {
819
			if(empty($gre['greif']))
820
				$gre['greif'] = "gre{$i}";
821
			if ($checkparent == 1) {
822
				if (strstr($gre['if'], "_vip"))
823
					continue;
824
				if (!empty($config['interfaces'][$gre['if']]) && $config['interfaces'][$gre['if']]['ipaddrv6'] == "track6")
825
					continue;
826
			}
827
			else if ($checkparent == 2) {
828
				if (!strstr($gre['if'], "_vip"))
829
					continue;
830
				if (empty($config['interfaces'][$gre['if']]) || $config['interfaces'][$gre['if']]['ipaddrv6'] != "track6")
831
					continue;
832
			}
833
			/* XXX: Maybe we should report any errors?! */
834
			interface_gre_configure($gre);
835
		}
836
	}
837
}
838

    
839
/* NOTE: $grekey is not used but useful for passing this function to array_walk. */
840
function interface_gre_configure(&$gre, $grekey = "") {
841
	global $config, $g;
842

    
843
	if (!is_array($gre))
844
		return -1;
845

    
846
	$realif = get_real_interface($gre['if']);
847
	$realifip = get_interface_ip($gre['if']);
848

    
849
	/* make sure the parent interface is up */
850
	interfaces_bring_up($realif);
851

    
852
	if ($g['booting'] || !(empty($gre['greif']))) {
853
		pfSense_interface_destroy($gre['greif']);
854
		pfSense_interface_create($gre['greif']);
855
		$greif = $gre['greif'];
856
	} else
857
		$greif = pfSense_interface_create("gre");
858

    
859
	/* Do not change the order here for more see gre(4) NOTES section. */
860
	mwexec("/sbin/ifconfig {$greif} tunnel {$realifip} {$gre['remote-addr']}");
861
	if((is_ipaddrv6($gre['tunnel-local-addr'])) || (is_ipaddrv6($gre['tunnel-remote-addr']))) {
862
		mwexec("/sbin/ifconfig {$greif} inet6 {$gre['tunnel-local-addr']} {$gre['tunnel-remote-addr']} prefixlen /{$gre['tunnel-remote-net']} ");
863
	} else {
864
		mwexec("/sbin/ifconfig {$greif} {$gre['tunnel-local-addr']} {$gre['tunnel-remote-addr']} netmask " . gen_subnet_mask($gre['tunnel-remote-net']));
865
	}
866
	if (isset($gre['link0']))
867
		pfSense_interface_flags($greif, IFF_LINK0);
868
	if (isset($gre['link1']))
869
		pfSense_interface_flags($greif, IFF_LINK1);
870
	if (isset($gre['link2']))
871
		pfSense_interface_flags($greif, IFF_LINK2);
872

    
873
	if($greif)
874
		interfaces_bring_up($greif);
875
	else
876
		log_error(gettext("Could not bring greif up -- variable not defined."));
877

    
878
	if (isset($gre['link1']) && $gre['link1'])
879
		mwexec("/sbin/route add {$gre['tunnel-remote-addr']}/{$gre['tunnel-remote-net']} {$gre['tunnel-local-addr']}");
880
	if(is_ipaddrv4($gre['tunnel-remote-addr']))
881
		file_put_contents("{$g['tmp_path']}/{$greif}_router", $gre['tunnel-remote-addr']);
882
	if(is_ipaddrv6($gre['tunnel-remote-addr']))
883
		file_put_contents("{$g['tmp_path']}/{$greif}_routerv6", $gre['tunnel-remote-addr']);
884

    
885
	return $greif;
886
}
887

    
888
function interfaces_gif_configure($checkparent = 0) {
889
	global $config;
890

    
891
	if (is_array($config['gifs']['gif']) && count($config['gifs']['gif'])) {
892
		foreach ($config['gifs']['gif'] as $i => $gif) {
893
			if(empty($gif['gifif']))
894
				$gre['gifif'] = "gif{$i}";
895
			if ($checkparent == 1) {
896
				if (strstr($gif['if'], "_vip"))
897
					continue;
898
				if (!empty($config['interfaces'][$gif['if']]) && $config['interfaces'][$gif['if']]['ipaddrv6'] == "track6")
899
					continue;
900
			}
901
			else if ($checkparent == 2) {
902
				if (!strstr($gre['if'], "_vip"))
903
					continue;
904
				if (empty($config['interfaces'][$gif['if']]) || $config['interfaces'][$gif['if']]['ipaddrv6'] != "track6")
905
					continue;
906
			}
907
			/* XXX: Maybe we should report any errors?! */
908
			interface_gif_configure($gif);
909
		}
910
	}
911
}
912

    
913
/* NOTE: $gifkey is not used but useful for passing this function to array_walk. */
914
function interface_gif_configure(&$gif, $gifkey = "") {
915
	global $config, $g;
916

    
917
	if (!is_array($gif))
918
		return -1;
919

    
920
	$realif = get_real_interface($gif['if']);
921
	$ipaddr = $gif['ipaddr'];
922

    
923
	if (is_ipaddrv4($gif['remote-addr'])) {
924
		if (is_ipaddrv4($ipaddr))
925
			$realifip = $ipaddr;
926
		else
927
			$realifip = get_interface_ip($gif['if']);
928
		$realifgw = get_interface_gateway($gif['if']);
929
	} else if (is_ipaddrv6($gif['remote-addr'])) {
930
		if (is_ipaddrv6($ipaddr))
931
			$realifip = $ipaddr;
932
		else
933
			$realifip = get_interface_ipv6($gif['if']);
934
		$realifgw = get_interface_gatewayv6($gif['if']);
935
	}
936
	/* make sure the parent interface is up */
937
	if($realif)
938
		interfaces_bring_up($realif);
939
	else
940
		log_error(gettext("could not bring realif up -- variable not defined -- interface_gif_configure()"));
941

    
942
	if ($g['booting'] || !(empty($gif['gifif']))) {
943
		pfSense_interface_destroy($gif['gifif']);
944
		pfSense_interface_create($gif['gifif']);
945
		$gifif = $gif['gifif'];
946
	} else
947
		$gifif = pfSense_interface_create("gif");
948

    
949
	/* Do not change the order here for more see gif(4) NOTES section. */
950
	mwexec("/sbin/ifconfig {$gifif} tunnel {$realifip} {$gif['remote-addr']}");
951
	if((is_ipaddrv6($gif['tunnel-local-addr'])) || (is_ipaddrv6($gif['tunnel-remote-addr']))) {
952
		mwexec("/sbin/ifconfig {$gifif} inet6 {$gif['tunnel-local-addr']} {$gif['tunnel-remote-addr']} prefixlen /{$gif['tunnel-remote-net']} ");
953
	} else {
954
		mwexec("/sbin/ifconfig {$gifif} {$gif['tunnel-local-addr']} {$gif['tunnel-remote-addr']} netmask " . gen_subnet_mask($gif['tunnel-remote-net']));
955
	}
956
	if (isset($gif['link0']))
957
		pfSense_interface_flags($gifif, IFF_LINK0);
958
	if (isset($gif['link1']))
959
		pfSense_interface_flags($gifif, IFF_LINK1);
960
	if($gifif)
961
		interfaces_bring_up($gifif);
962
	else
963
		log_error(gettext("could not bring gifif up -- variable not defined"));
964

    
965
	$iflist = get_configured_interface_list();
966
	foreach($iflist as $ifname) {
967
		if($config['interfaces'][$ifname]['if'] == $gifif) {
968
			if(get_interface_gateway($ifname)) {
969
				system_routing_configure($ifname);
970
				break;
971
			}
972
			if(get_interface_gateway_v6($ifname)) {
973
				system_routing_configure($ifname);
974
				break;
975
			}
976
		}
977
	}
978

    
979

    
980
	if(is_ipaddrv4($gif['tunnel-remote-addr']))
981
		file_put_contents("{$g['tmp_path']}/{$gifif}_router", $gif['tunnel-remote-addr']);
982
	if(is_ipaddrv6($gif['tunnel-remote-addr']))
983
		file_put_contents("{$g['tmp_path']}/{$gifif}_routerv6", $gif['tunnel-remote-addr']);
984

    
985
	if (is_ipaddrv4($realifgw)) {
986
		mwexec("/sbin/route change -host {$gif['remote-addr']} {$realifgw}");
987
	}
988
	if (is_ipaddrv6($realifgw)) {
989
		mwexec("/sbin/route change -host -inet6 {$gif['remote-addr']} {$realifgw}");
990
	}
991

    
992
	return $gifif;
993
}
994

    
995
function interfaces_configure() {
996
	global $config, $g;
997

    
998
	if ($g['platform'] == 'jail')
999
		return;
1000

    
1001
	/* Set up our loopback interface */
1002
	interfaces_loopback_configure();
1003

    
1004
	/* create the unconfigured wireless clones */
1005
	interfaces_create_wireless_clones();
1006

    
1007
	/* set up LAGG virtual interfaces */
1008
	interfaces_lagg_configure();
1009

    
1010
	/* set up VLAN virtual interfaces */
1011
	interfaces_vlan_configure();
1012

    
1013
	interfaces_qinq_configure();
1014

    
1015
	$iflist = get_configured_interface_with_descr();
1016
	$delayed_list = array();
1017
	$bridge_list = array();
1018
	$track6_list = array();
1019

    
1020
	/* This is needed to speedup interfaces on bootup. */
1021
	$reload = false;
1022
	if (!$g['booting'])
1023
		$reload = true;
1024

    
1025
	foreach($iflist as $if => $ifname) {
1026
		$realif = $config['interfaces'][$if]['if'];
1027
		if (strstr($realif, "bridge"))
1028
			$bridge_list[$if] = $ifname;
1029
		else if (strstr($realif, "gre"))
1030
			$delayed_list[$if] = $ifname;
1031
		else if (strstr($realif, "gif"))
1032
			$delayed_list[$if] = $ifname;
1033
		else if (strstr($realif, "ovpn")) {
1034
			//echo "Delaying OpenVPN interface configuration...done.\n";
1035
			continue;
1036
		} else if (!empty($config['interfaces'][$if]['ipaddrv6']) && $config['interfaces'][$if]['ipaddrv6'] == "track6") {
1037
			$track6_list[$if] = $ifname;
1038
		} else {
1039
			if ($g['booting'])
1040
				printf(gettext("Configuring %s interface..."), $ifname);
1041

    
1042
			if($g['debug'])
1043
				log_error(sprintf(gettext("Configuring %s"), $ifname));
1044
			interface_configure($if, $reload);
1045
			if ($g['booting'])
1046
				echo gettext( "done.") . "\n";
1047
		}
1048
	}
1049

    
1050
	/*
1051
	 * NOTE: The following function parameter consists of
1052
	 *	1 - Do not load gre/gif/bridge with parent/member as vip
1053
	 *	2 - Do load gre/gif/bridge with parent/member as vip
1054
	 */
1055

    
1056
	/* set up GRE virtual interfaces */
1057
	interfaces_gre_configure(1);
1058

    
1059
	/* set up GIF virtual interfaces */
1060
	interfaces_gif_configure(1);
1061

    
1062
	/* set up BRIDGe virtual interfaces */
1063
	interfaces_bridge_configure(1);
1064

    
1065
	foreach ($track6_list as $if => $ifname) {
1066
		if ($g['booting'])
1067
			printf(gettext("Configuring %s interface..."), $ifname);
1068
		if ($g['debug'])
1069
			log_error(sprintf(gettext("Configuring %s"), $ifname));
1070

    
1071
		interface_configure($if, $reload);
1072

    
1073
		if ($g['booting'])
1074
			echo gettext("done.") . "\n";
1075
	}
1076

    
1077
	/* bring up vip interfaces */
1078
	interfaces_vips_configure();
1079

    
1080
	/* set up GRE virtual interfaces */
1081
	interfaces_gre_configure(2);
1082

    
1083
	/* set up GIF virtual interfaces */
1084
	interfaces_gif_configure(2);
1085

    
1086
	foreach ($delayed_list as $if => $ifname) {
1087
		if ($g['booting'])
1088
			printf(gettext("Configuring %s interface..."), $ifname);
1089
		if ($g['debug'])
1090
			log_error(sprintf(gettext("Configuring %s"), $ifname));
1091

    
1092
		interface_configure($if, $reload);
1093

    
1094
		if ($g['booting'])
1095
			echo gettext("done.") . "\n";
1096
	}
1097

    
1098
	/* set up BRIDGe virtual interfaces */
1099
	interfaces_bridge_configure(2);
1100

    
1101
	foreach ($bridge_list as $if => $ifname) {
1102
		if ($g['booting'])
1103
			printf(gettext("Configuring %s interface..."), $ifname);
1104
		if($g['debug'])
1105
			log_error(sprintf(gettext("Configuring %s"), $ifname));
1106

    
1107
		interface_configure($if, $reload);
1108

    
1109
		if ($g['booting'])
1110
			echo gettext("done.") . "\n";
1111
	}
1112

    
1113
	/* configure interface groups */
1114
	interfaces_group_setup();
1115

    
1116
	if (!$g['booting']) {
1117
		/* reconfigure static routes (kernel may have deleted them) */
1118
		system_routing_configure();
1119

    
1120
		/* reload IPsec tunnels */
1121
		vpn_ipsec_configure();
1122

    
1123
		/* reload dhcpd (interface enabled/disabled status may have changed) */
1124
		services_dhcpd_configure();
1125

    
1126
		/* restart dnsmasq */
1127
		services_dnsmasq_configure();
1128

    
1129
		/* reload captive portal */
1130
		if (function_exists('captiveportal_init_rules'))
1131
			captiveportal_init_rules();
1132
	}
1133

    
1134
	return 0;
1135
}
1136

    
1137
function interface_reconfigure($interface = "wan", $reloadall = false) {
1138
	interface_bring_down($interface);
1139
	interface_configure($interface, $reloadall);
1140
}
1141

    
1142
function interface_vip_bring_down($vip) {
1143
	global $g;
1144

    
1145
	switch ($vip['mode']) {
1146
	case "proxyarp":
1147
		$vipif = get_real_interface($vip['interface']);
1148
		if (file_exists("{$g['varrun_path']}/choparp_{$vipif}.pid"))
1149
			killbypid("{$g['varrun_path']}/choparp_{$vipif}.pid");
1150
		break;
1151
	case "ipalias":
1152
		$vipif = get_real_interface($vip['interface']);
1153
		if (does_interface_exist($vipif)) {
1154
			if (is_ipaddrv6($vip['subnet']))
1155
				mwexec("/sbin/ifconfig {$vipif} inet6 {$vip['subnet']} -alias");
1156
			else
1157
				pfSense_interface_deladdress($vipif, $vip['subnet']);
1158
		}
1159
		break;
1160
	case "carp":
1161
		$vipif = "{$vip['interface']}_vip{$vip['vhid']}";
1162
		if (does_interface_exist($vipif))
1163
			pfSense_interface_destroy($vipif);
1164
		break;
1165
	}
1166
}
1167

    
1168
function interface_bring_down($interface = "wan", $destroy = false, $ifacecfg = false) {
1169
	global $config, $g;
1170

    
1171
	if (!isset($config['interfaces'][$interface]))
1172
		return;
1173

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

    
1177
	/*
1178
	 * NOTE: The $realifv6 is needed when WANv4 is type PPP and v6 is DHCP and the option v6 from v4 is used.
1179
	 * In this case the real $realif of v4 is different from that of v6 for operation.
1180
	 * Keep this in mind while doing changes here!
1181
	 */
1182
	if ($ifacecfg === false) {
1183
		$ifcfg = $config['interfaces'][$interface];
1184
		$ppps = $config['ppps']['ppp'];
1185
		$realif = get_real_interface($interface);
1186
		$realifv6 = get_real_interface($interface, "inet6", true);
1187
	} elseif (!is_array($ifacecfg)) {
1188
		log_error(gettext("Wrong parameters used during interface_bring_down"));
1189
		$ifcfg = $config['interfaces'][$interface];
1190
		$ppps = $config['ppps']['ppp'];
1191
		$realif = get_real_interface($interface);
1192
		$realifv6 = get_real_interface($interface, "inet6", true);
1193
	} else {
1194
		$ifcfg = $ifacecfg['ifcfg'];
1195
		$ppps = $ifacecfg['ppps'];
1196
		if (isset($ifacecfg['ifcfg']['realif'])) {
1197
			$realif = $ifacecfg['ifcfg']['realif'];
1198
			/* XXX: Any better way? */
1199
			$realifv6 = $realif;
1200
		} else {
1201
			$realif = get_real_interface($interface);
1202
			$realifv6 = get_real_interface($interface, "inet6", true);
1203
		}
1204
	}
1205

    
1206
	switch ($ifcfg['ipaddr']) {
1207
	case "ppp":
1208
	case "pppoe":
1209
	case "pptp":
1210
	case "l2tp":
1211
		if (is_array($ppps) && count($ppps)) {
1212
			foreach ($ppps as $pppid => $ppp) {
1213
				if ($realif == $ppp['if']) {
1214
					if (isset($ppp['ondemand']) && !$destroy){
1215
						send_event("interface reconfigure {$interface}");
1216
						break;
1217
					}
1218
					if (file_exists("{$g['varrun_path']}/{$ppp['type']}_{$interface}.pid")) {
1219
						killbypid("{$g['varrun_path']}/{$ppp['type']}_{$interface}.pid");
1220
						sleep(2);
1221
					}
1222
					unlink_if_exists("{$g['varetc_path']}/mpd_{$interface}.conf");
1223
					break;
1224
				}
1225
			}
1226
		}
1227
		break;
1228
	case "dhcp":
1229
		$pid = find_dhclient_process($realif);
1230
		if($pid)
1231
			posix_kill($pid, SIGTERM);
1232
		sleep(1);
1233
		unlink_if_exists("{$g['varetc_path']}/dhclient_{$interface}.conf");
1234
		if(does_interface_exist("$realif")) {
1235
			mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete", true);
1236
			if ($destroy == true)
1237
				pfSense_interface_flags($realif, -IFF_UP);
1238
			mwexec("/usr/sbin/arp -d -i {$realif} -a");
1239
		}
1240
		break;
1241
	default:
1242
		if(does_interface_exist("$realif")) {
1243
			mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete", true);
1244
			if ($destroy == true)
1245
				pfSense_interface_flags($realif, -IFF_UP);
1246
			mwexec("/usr/sbin/arp -d -i {$realif} -a");
1247
		}
1248
		break;
1249
	}
1250

    
1251
	switch ($ifcfg['ipaddrv6']) {
1252
	case "slaac":
1253
	case "dhcp6":
1254
		$pidv6 = find_dhcp6c_process($realif);
1255
		if($pidv6)
1256
			posix_kill($pidv6, SIGTERM);
1257
		sleep(3);
1258
		unlink_if_exists("{$g['varetc_path']}/dhcp6c_{$interface}.conf");
1259
		if (does_interface_exist($realifv6)) {
1260
			$ip6 = find_interface_ipv6($realifv6);
1261
			if (is_ipaddrv6($ip6) && $ip6 != "::")
1262
				mwexec("/sbin/ifconfig " . escapeshellarg($realifv6) . " inet6 {$ip6} delete", true);
1263
			if ($destroy == true)
1264
				pfSense_interface_flags($realif, -IFF_UP);
1265
			mwexec("/usr/sbin/arp -d -i {$realif} -a");
1266
		}
1267
		break;
1268
	case "6rd":
1269
	case "6to4":
1270
		$realif = "{$interface}_stf";
1271
		if(does_interface_exist("$realif")) {
1272
			$ip6 = get_interface_ipv6($interface);
1273
			if (is_ipaddrv6($ip6))
1274
				mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 {$ip6} delete", true);
1275
			if ($destroy == true)
1276
				pfSense_interface_flags($realif, -IFF_UP);
1277
		}
1278
		break;
1279
	default:
1280
		if(does_interface_exist("$realif")) {
1281
			$ip6 = get_interface_ipv6($interface);
1282
			if (is_ipaddrv6($ip6))
1283
				mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 {$ip6} delete", true);
1284
			if (!empty($ifcfg['ipaddrv6']) && is_ipaddrv6($ifcfg['ipaddrv6']))
1285
				mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 {$ifcfg['ipaddrv6']} delete", true);
1286
			if ($destroy == true)
1287
				pfSense_interface_flags($realif, -IFF_UP);
1288
			mwexec("/usr/sbin/arp -d -i {$realif} -a");
1289
		}
1290
		break;
1291
	}
1292

    
1293
	if (file_exists("{$g['tmp_path']}/{$realif}_router"))
1294
		$old_router = trim(file_get_contents("{$g['tmp_path']}/{$realif}_router"));
1295
//	log_error("Checking for old router states: {$g['tmp_path']}/{$realif}_router = {$old_router}");
1296
	if (!empty($old_router)) {
1297
		log_error("Clearing states to old gateway {$old_router}.");
1298
		mwexec("/sbin/pfctl -i {$realif} -Fs -G {$old_router}");
1299
	}
1300

    
1301
	/* remove interface up file if it exists */
1302
	unlink_if_exists("{$g['tmp_path']}/{$realif}up");
1303
	unlink_if_exists("{$g['vardb_path']}/{$interface}ip");
1304
	unlink_if_exists("{$g['vardb_path']}/{$interface}ipv6");
1305
	unlink_if_exists("{$g['tmp_path']}/{$realif}_router");
1306
	unlink_if_exists("{$g['tmp_path']}/{$realif}_routerv6");
1307
	unlink_if_exists("{$g['varetc_path']}/nameserver_{$realif}");
1308
	unlink_if_exists("{$g['varetc_path']}/searchdomain_{$realif}");
1309

    
1310
	/* hostapd and wpa_supplicant do not need to be running when the interface is down.
1311
	 * They will also use 100% CPU if running after the wireless clone gets deleted. */
1312
	if (is_array($ifcfg['wireless'])) {
1313
		kill_hostapd($realif);
1314
		mwexec(kill_wpasupplicant($realif));
1315
	}
1316

    
1317
	if ($destroy == true) {
1318
		if (preg_match("/^[a-z0-9]+_vip|^tun|^ovpn|^gif|^gre|^lagg|^bridge|vlan|_stf$/i", $realif))
1319
			pfSense_interface_destroy($realif);
1320
	}
1321

    
1322
	return;
1323
}
1324

    
1325
function interfaces_ptpid_used($ptpid) {
1326
	global $config;
1327

    
1328
	if (is_array($config['ppps']['ppp']))
1329
		foreach ($config['ppps']['ppp'] as & $settings)
1330
			if ($ptpid == $settings['ptpid'])
1331
				return true;
1332

    
1333
	return false;
1334
}
1335

    
1336
function interfaces_ptpid_next() {
1337

    
1338
	$ptpid = 0;
1339
	while(interfaces_ptpid_used($ptpid))
1340
		$ptpid++;
1341

    
1342
	return $ptpid;
1343
}
1344

    
1345
function getMPDCRONSettings($pppif) {
1346
	global $config;
1347

    
1348
	$cron_cmd_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
1349
	if (is_array($config['cron']['item'])) {
1350
		foreach ($config['cron']['item'] as $i => $item) {
1351
			if (stripos($item['command'], $cron_cmd_file) !== false)
1352
				return array("ID" => $i, "ITEM" => $item);
1353
		}
1354
	}
1355

    
1356
	return NULL;
1357
}
1358

    
1359
function handle_pppoe_reset($post_array) {
1360
	global $config, $g;
1361

    
1362
	$pppif = "{$post_array['type']}{$post_array['ptpid']}";
1363
	$cron_cmd_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
1364

    
1365
	if (!is_array($config['cron']['item']))
1366
		$config['cron']['item'] = array();
1367

    
1368
	$itemhash = getMPDCRONSettings($pppif);
1369

    
1370
	// reset cron items if necessary and return
1371
	if (empty($post_array['pppoe-reset-type'])) {
1372
		if (isset($itemhash))
1373
			unset($config['cron']['item'][$itemhash['ID']]);
1374
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
1375
		return;
1376
	}
1377

    
1378
	if (empty($itemhash))
1379
		$itemhash = array();
1380
	$item = array();
1381
	if (isset($post_array['pppoe-reset-type']) && $post_array['pppoe-reset-type'] == "custom") {
1382
		$item['minute'] = $post_array['pppoe_resetminute'];
1383
		$item['hour'] = $post_array['pppoe_resethour'];
1384
		if (isset($post_array['pppoe_resetdate']) && $post_array['pppoe_resetdate'] <> "") {
1385
			$date = explode("/", $post_array['pppoe_resetdate']);
1386
			$item['mday'] = $date[1];
1387
			$item['month'] = $date[0];
1388
		} else {
1389
			$item['mday'] = "*";
1390
			$item['month'] = "*";
1391
		}
1392
		$item['wday'] = "*";
1393
		$item['who'] = "root";
1394
		$item['command'] = $cron_cmd_file;
1395
	} else if (isset($post_array['pppoe-reset-type']) && $post_array['pppoe-reset-type'] == "preset") {
1396
		switch ($post_array['pppoe_pr_preset_val']) {
1397
		case "monthly":
1398
			$item['minute'] = "0";
1399
			$item['hour'] = "0";
1400
			$item['mday'] = "1";
1401
			$item['month'] = "*";
1402
			$item['wday'] = "*";
1403
			break;
1404
		case "weekly":
1405
			$item['minute'] = "0";
1406
			$item['hour'] = "0";
1407
			$item['mday'] = "*";
1408
			$item['month'] = "*";
1409
			$item['wday'] = "0";
1410
			break;
1411
		case "daily":
1412
			$item['minute'] = "0";
1413
			$item['hour'] = "0";
1414
			$item['mday'] = "*";
1415
			$item['month'] = "*";
1416
			$item['wday'] = "*";
1417
			break;
1418
		case "hourly":
1419
			$item['minute'] = "0";
1420
			$item['hour'] = "*";
1421
			$item['mday'] = "*";
1422
			$item['month'] = "*";
1423
			$item['wday'] = "*";
1424
			break;
1425
		} // end switch
1426
		$item['who'] = "root";
1427
		$item['command'] = $cron_cmd_file;
1428
	}
1429
	if (empty($item))
1430
		return;
1431
	if (isset($itemhash['ID']))
1432
		$config['cron']['item'][$itemhash['ID']] = $item;
1433
	else
1434
		$config['cron']['item'][] = $item;
1435
}
1436

    
1437
/*
1438
 * This function can configure PPPoE, MLPPP (PPPoE), PPTP.
1439
 * It writes the mpd config file to /var/etc every time the link is opened.
1440
 */
1441
function interface_ppps_configure($interface) {
1442
	global $config, $g;
1443

    
1444
	/* Return for unassigned interfaces. This is a minimum requirement. */
1445
	if (empty($config['interfaces'][$interface]))
1446
		return 0;
1447
	$ifcfg = $config['interfaces'][$interface];
1448
	if (!isset($ifcfg['enable']))
1449
		return 0;
1450

    
1451
	// mpd5 requires a /var/spool/lock directory for PPP modem links.
1452
	if(!is_dir("/var/spool/lock")) {
1453
		exec("/bin/mkdir -p /var/spool/lock");
1454
		exec("/bin/chmod a+rw /var/spool/lock/.");
1455
	}
1456
	// mpd5 modem chat script expected in the same directory as the mpd_xxx.conf files
1457
	if (!file_exists("{$g['varetc_path']}/mpd.script"))
1458
		mwexec("/bin/ln -s /usr/local/sbin/mpd.script {$g['varetc_path']}/.");
1459

    
1460
	if (is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) {
1461
		foreach ($config['ppps']['ppp'] as $pppid => $ppp) {
1462
			if ($ifcfg['if'] == $ppp['if'])
1463
				break;
1464
		}
1465
	}
1466
	if (!$ppp || $ifcfg['if'] != $ppp['if']){
1467
		log_error(sprintf(gettext("Can't find PPP config for %s in interface_ppps_configure()."), $ifcfg['if']));
1468
		return 0;
1469
	}
1470
	$pppif = $ifcfg['if'];
1471
	if ($ppp['type'] == "ppp")
1472
		$type = "modem";
1473
	else
1474
		$type = $ppp['type'];
1475
	$upper_type = strtoupper($ppp['type']);
1476

    
1477
	if($g['booting']) {
1478
		$descr = isset($ifcfg['descr']) ? $ifcfg['descr'] : strtoupper($interface);
1479
		echo "starting {$pppif} link...";
1480
		// Do not re-configure the interface if we are booting and it's already been started
1481
		if(file_exists("{$g['varrun_path']}/{$ppp['type']}_{$interface}.pid"))
1482
			return 0;
1483
	}
1484

    
1485
	$ports = explode(',',$ppp['ports']);
1486
	if ($type != "modem") {
1487
		foreach ($ports as $pid => $port) {
1488
			$ports[$pid] = get_real_interface($port);
1489
			if (empty($ports[$pid]))
1490
				return 0;
1491
		}
1492
	}
1493
	$localips = explode(',',$ppp['localip']);
1494
	$gateways = explode(',',$ppp['gateway']);
1495
	$subnets = explode(',',$ppp['subnet']);
1496

    
1497
	/* We bring up the parent interface first because if DHCP is configured on the parent we need
1498
	 * to obtain an address first so we can write it in the mpd .conf file for PPTP and L2TP configs
1499
	 */
1500
	foreach($ports as $pid => $port){
1501
		switch ($ppp['type']) {
1502
			case "pppoe":
1503
				/* Bring the parent interface up */
1504
				interfaces_bring_up($port);
1505
				pfSense_ngctl_attach(".", $port);
1506
				/* Enable setautosrc to automatically change mac address if parent interface's changes */
1507
				mwexec("ngctl msg {$port}: setautosrc 1");
1508
				break;
1509
			case "pptp":
1510
			case "l2tp":
1511
				/* configure interface */
1512
				if(is_ipaddr($localips[$pid])){
1513
					// Manually configure interface IP/subnet
1514
					pfSense_interface_setaddress($port, "{$localips[$pid]}/{$subnets[$pid]}");
1515
					interfaces_bring_up($port);
1516
				} else if (empty($localips[$pid]))
1517
					$localips[$pid] = get_interface_ip($port); // try to get the interface IP from the port
1518

    
1519
				if(!is_ipaddr($localips[$pid])){
1520
					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!");
1521
					$localips[$pid] = "0.0.0.0";
1522
				}
1523
				if(!is_ipaddr($gateways[$pid])){
1524
					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));
1525
					return 0;
1526
				}
1527
				pfSense_ngctl_attach(".", $port);
1528
				break;
1529
			case "ppp":
1530
				if (!file_exists("{$port}")) {
1531
					log_error(sprintf(gettext("Device %s does not exist. PPP link cannot start without the modem device."), $port));
1532
					return 0;
1533
				}
1534
				break;
1535
			default:
1536
				log_error(sprintf(gettext("Unkown %s configured as ppp interface."), $type));
1537
				break;
1538
		}
1539
	}
1540

    
1541
	if (is_array($ports) && count($ports) > 1)
1542
		$multilink = "enable";
1543
	else
1544
		$multilink = "disable";
1545

    
1546
	if ($type == "modem"){
1547
		if (is_ipaddr($ppp['localip']))
1548
			$localip = $ppp['localip'];
1549
		else
1550
			$localip = '0.0.0.0';
1551

    
1552
		if (is_ipaddr($ppp['gateway']))
1553
			$gateway = $ppp['gateway'];
1554
		else
1555
			$gateway = "10.64.64.{$pppid}";
1556
		$ranges = "{$localip}/0 {$gateway}/0";
1557

    
1558
		if (empty($ppp['apnum']))
1559
			$ppp['apnum'] = 1;
1560
	} else
1561
		$ranges = "0.0.0.0/0 0.0.0.0/0";
1562

    
1563
	if (isset($ppp['ondemand']))
1564
		$ondemand = "enable";
1565
	else
1566
		$ondemand = "disable";
1567
	if (!isset($ppp['idletimeout']))
1568
		$ppp['idletimeout'] = 0;
1569

    
1570
	if (empty($ppp['username']) && $type == "modem"){
1571
		$ppp['username'] = "user";
1572
		$ppp['password'] = "none";
1573
	}
1574
	if (empty($ppp['password']) && $type == "modem")
1575
		$passwd = "none";
1576
	else
1577
		$passwd = base64_decode($ppp['password']);
1578

    
1579
	$bandwidths = explode(',',$ppp['bandwidth']);
1580
	$defaultmtu = "1492";
1581
	if (!empty($ifcfg['mtu']))
1582
		$defaultmtu = intval($ifcfg['mtu']);
1583
	$mtus = explode(',',$ppp['mtu']);
1584
	$mrus = explode(',',$ppp['mru']);
1585

    
1586
	if (isset($ppp['mrru']))
1587
		$mrrus = explode(',',$ppp['mrru']);
1588

    
1589
	// Construct the mpd.conf file
1590
	$mpdconf = <<<EOD
1591
startup:
1592
	# configure the console
1593
	set console close
1594
	# configure the web server
1595
	set web close
1596

    
1597
default:
1598
{$ppp['type']}client:
1599
	create bundle static {$interface}
1600
	set bundle enable ipv6cp
1601
	set iface name {$pppif}
1602

    
1603
EOD;
1604
	$setdefaultgw = false;
1605
	$founddefaultgw = false;
1606
	if (is_array($config['gateways']['gateway_item'])) {
1607
		foreach($config['gateways']['gateway_item'] as $gateway) {
1608
			if($interface == $gateway['interface'] && isset($gateway['defaultgw'])) {
1609
				$setdefaultgw = true;
1610
				break;
1611
			} else if (isset($gateway['defaultgw']) && !empty($gateway['interface'])) {
1612
				$founddefaultgw = true;
1613
				break;
1614
			}
1615
		}
1616
	}
1617

    
1618
	if (($interface == "wan" && $founddefaultgw == false) || $setdefaultgw == true){
1619
		$setdefaultgw = true;
1620
		$mpdconf .= <<<EOD
1621
	set iface route default
1622

    
1623
EOD;
1624
	}
1625
	$mpdconf .= <<<EOD
1626
	set iface {$ondemand} on-demand
1627
	set iface idle {$ppp['idletimeout']}
1628

    
1629
EOD;
1630

    
1631
	if (isset($ppp['ondemand']))
1632
		$mpdconf .= <<<EOD
1633
	set iface addrs 10.10.1.1 10.10.1.2
1634

    
1635
EOD;
1636

    
1637
	if (isset($ppp['tcpmssfix']))
1638
		$tcpmss = "disable";
1639
	else
1640
		$tcpmss = "enable";
1641
		$mpdconf .= <<<EOD
1642
	set iface {$tcpmss} tcpmssfix
1643

    
1644
EOD;
1645

    
1646
	$mpdconf .= <<<EOD
1647
	set iface up-script /usr/local/sbin/ppp-linkup
1648
	set iface down-script /usr/local/sbin/ppp-linkdown
1649
	set ipcp ranges {$ranges}
1650

    
1651
EOD;
1652
	if (isset($ppp['vjcomp']))
1653
		$mpdconf .= <<<EOD
1654
	set ipcp no vjcomp
1655

    
1656
EOD;
1657

    
1658
	if (isset($config['system']['dnsallowoverride']))
1659
		$mpdconf .= <<<EOD
1660
	set ipcp enable req-pri-dns
1661
	set ipcp enable req-sec-dns
1662

    
1663
EOD;
1664
	if (!isset($ppp['verbose_log']))
1665
		$mpdconf .= <<<EOD
1666
	#log -bund -ccp -chat -iface -ipcp -lcp -link
1667

    
1668
EOD;
1669
	foreach($ports as $pid => $port){
1670
		$port = get_real_interface($port);
1671
		$mpdconf .= <<<EOD
1672

    
1673
	create link static {$interface}_link{$pid} {$type}
1674
	set link action bundle {$interface}
1675
	set link {$multilink} multilink
1676
	set link keep-alive 10 60
1677
	set link max-redial 0
1678

    
1679
EOD;
1680
		if (isset($ppp['shortseq']))
1681
			$mpdconf .= <<<EOD
1682
	set link no shortseq
1683

    
1684
EOD;
1685

    
1686
		if (isset($ppp['acfcomp']))
1687
			$mpdconf .= <<<EOD
1688
	set link no acfcomp
1689

    
1690
EOD;
1691

    
1692
		if (isset($ppp['protocomp']))
1693
			$mpdconf .= <<<EOD
1694
	set link no protocomp
1695

    
1696
EOD;
1697

    
1698
		$mpdconf .= <<<EOD
1699
	set link disable chap pap
1700
	set link accept chap pap eap
1701
	set link disable incoming
1702

    
1703
EOD;
1704

    
1705

    
1706
		if (!empty($bandwidths[$pid]))
1707
			$mpdconf .= <<<EOD
1708
	set link bandwidth {$bandwidths[$pid]}
1709

    
1710
EOD;
1711

    
1712
		if (empty($mtus[$pid]))
1713
			$mtus[$pid] = $defaultmtu;
1714
			$mpdconf .= <<<EOD
1715
	set link mtu {$mtus[$pid]}
1716

    
1717
EOD;
1718

    
1719
		if (!empty($mrus[$pid]))
1720
			$mpdconf .= <<<EOD
1721
	set link mru {$mrus[$pid]}
1722

    
1723
EOD;
1724

    
1725
		if (!empty($mrrus[$pid]))
1726
			$mpdconf .= <<<EOD
1727
	set link mrru {$mrrus[$pid]}
1728

    
1729
EOD;
1730

    
1731
		$mpdconf .= <<<EOD
1732
	set auth authname "{$ppp['username']}"
1733
	set auth password {$passwd}
1734

    
1735
EOD;
1736
		if ($type == "modem") {
1737
			$mpdconf .= <<<EOD
1738
	set modem device {$ppp['ports']}
1739
	set modem script DialPeer
1740
	set modem idle-script Ringback
1741
	set modem watch -cd
1742
	set modem var \$DialPrefix "DT"
1743
	set modem var \$Telephone "{$ppp['phone']}"
1744

    
1745
EOD;
1746
		}
1747
		if (isset($ppp['connect-timeout']) && $type == "modem") {
1748
			$mpdconf .= <<<EOD
1749
	set modem var \$ConnectTimeout "{$ppp['connect-timeout']}"
1750

    
1751
EOD;
1752
		}
1753
		if (isset($ppp['initstr']) && $type == "modem") {
1754
			$initstr = base64_decode($ppp['initstr']);
1755
			$mpdconf .= <<<EOD
1756
	set modem var \$InitString "{$initstr}"
1757

    
1758
EOD;
1759
		}
1760
		if (isset($ppp['simpin']) && $type == "modem") {
1761
			if($ppp['pin-wait'] == "")
1762
				$ppp['pin-wait'] = 0;
1763
			$mpdconf .= <<<EOD
1764
	set modem var \$SimPin "{$ppp['simpin']}"
1765
	set modem var \$PinWait "{$ppp['pin-wait']}"
1766

    
1767
EOD;
1768
		}
1769
		if (isset($ppp['apn']) && $type == "modem") {
1770
			$mpdconf .= <<<EOD
1771
	set modem var \$APN "{$ppp['apn']}"
1772
	set modem var \$APNum "{$ppp['apnum']}"
1773

    
1774
EOD;
1775
		}
1776
		if ($type == "pppoe") {
1777
			// Send a null service name if none is set.
1778
			$provider = isset($ppp['provider']) ? $ppp['provider'] : "";
1779
			$mpdconf .= <<<EOD
1780
	set pppoe service "{$provider}"
1781

    
1782
EOD;
1783
		}
1784
		if ($type == "pppoe")
1785
			$mpdconf .= <<<EOD
1786
	set pppoe iface {$port}
1787

    
1788
EOD;
1789

    
1790
		if ($type == "pptp" || $type == "l2tp") {
1791
			$mpdconf .= <<<EOD
1792
	set {$type} self {$localips[$pid]}
1793
	set {$type} peer {$gateways[$pid]}
1794

    
1795
EOD;
1796
		}
1797

    
1798
		$mpdconf .= "\topen\n";
1799
	} //end foreach($port)
1800

    
1801

    
1802
	/* Generate mpd.conf. If mpd_[interface].conf exists in the conf path, then link to it instead of generating a fresh conf file. */
1803
	if (file_exists("{$g['conf_path']}/mpd_{$interface}.conf"))
1804
		mwexec("/bin/ln -s {$g['conf_path']}/mpd_{$interface}.conf {$g['varetc_path']}/.");
1805
	else {
1806
		$fd = fopen("{$g['varetc_path']}/mpd_{$interface}.conf", "w");
1807
		if (!$fd) {
1808
			log_error(sprintf(gettext("Error: cannot open mpd_%s.conf in interface_ppps_configure().%s"), $interface, "\n"));
1809
			return 0;
1810
		}
1811
		// Write out mpd_ppp.conf
1812
		fwrite($fd, $mpdconf);
1813
		fclose($fd);
1814
		unset($mpdconf);
1815
	}
1816

    
1817
	// Create the uptime log if requested and if it doesn't exist already, or delete it if it is no longer requested.
1818
	if (isset($ppp['uptime'])) {
1819
		if (!file_exists("/conf/{$pppif}.log")) {
1820
			conf_mount_rw();
1821
			mwexec("echo /dev/null > /conf/{$pppif}.log");
1822
			conf_mount_ro();
1823
		}
1824
	} else {
1825
		if (file_exists("/conf/{$pppif}.log")) {
1826
			conf_mount_rw();
1827
			mwexec("rm -f /conf/{$pppif}.log");
1828
			conf_mount_ro();
1829
		}
1830
	}
1831

    
1832
	/* clean up old lock files */
1833
	foreach($ports as $port) {
1834
		if(file_exists("{$g['var_path']}/spool/lock/LCK..{$port}"))
1835
			unlink("{$g['var_path']}/spool/lock/LCK..{$port}");
1836
	}
1837

    
1838
	/* fire up mpd */
1839
	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");
1840

    
1841
	// Check for PPPoE periodic reset request
1842
	if ($type == "pppoe") {
1843
		if (!empty($ppp['pppoe-reset-type']))
1844
			interface_setup_pppoe_reset_file($ppp['if'], $interface);
1845
		else
1846
			interface_setup_pppoe_reset_file($ppp['if']);
1847
	}
1848
	/* wait for upto 10 seconds for the interface to appear (ppp(oe)) */
1849
	$i = 0;
1850
	while($i < 10) {
1851
		exec("/sbin/ifconfig {$ppp['if']} 2>&1", $out, $ret);
1852
		if($ret == 0)
1853
			break;
1854
		sleep(1);
1855
		$i++;
1856
	}
1857

    
1858
	/* we only support the 3gstats.php for huawei modems for now. Will add more later. */
1859
	/* We should be able to launch the right version for each modem */
1860
	/* We can also guess the mondev from the manufacturer */
1861
	exec("usbconfig | egrep -ie '(huawei)'", $usbmodemoutput);
1862
	mwexec("/bin/ps auxww|grep \"{$interface}\" |grep \"[3]gstats\" | awk '{print $2}' |xargs kill");
1863
	foreach($ports as $port) {
1864
		if(preg_match("/huawei/i", implode("\n", $usbmodemoutput))) {
1865
			$mondev  = substr(basename($port), 0, -1);
1866
			$devlist = glob("/dev/{$mondev}?");
1867
			$mondev = basename(end($devlist));
1868
		}
1869
		if(preg_match("/zte/i", implode("\n", $usbmodemoutput))) {
1870
			$mondev  = substr(basename($port), 0, -1) . "1";
1871
		}
1872
		log_error("Starting 3gstats.php on device '{$mondev}' for interface '{$interface}'");
1873
		mwexec_bg("/usr/local/bin/3gstats.php {$mondev} {$interface}");
1874
	}
1875

    
1876
	return 1;
1877
}
1878

    
1879
function interfaces_carp_setup() {
1880
	global $g, $config;
1881

    
1882
	if (isset($config['system']['developerspew'])) {
1883
		$mt = microtime();
1884
		echo "interfaces_carp_setup() being called $mt\n";
1885
	}
1886

    
1887
	if ($g['booting']) {
1888
		echo gettext("Configuring CARP settings...");
1889
		mute_kernel_msgs();
1890
	}
1891

    
1892
	/* suck in configuration items */
1893
	if ($config['hasync']) {
1894
		$pfsyncenabled = $config['hasync']['pfsyncenabled'];
1895
		$balanacing = $config['hasync']['balancing'];
1896
		$pfsyncinterface = $config['hasync']['pfsyncinterface'];
1897
		$pfsyncpeerip = $config['hasync']['pfsyncpeerip'];
1898
	} else {
1899
		unset($pfsyncinterface);
1900
		unset($balanacing);
1901
		unset($pfsyncenabled);
1902
	}
1903

    
1904
	if ($balanacing) {
1905
		mwexec("/sbin/sysctl net.inet.carp.arpbalance=1", true);
1906
		mwexec("/sbin/sysctl net.inet.carp.preempt=0", true);
1907
	} else
1908
		mwexec("/sbin/sysctl net.inet.carp.preempt=1", true);
1909

    
1910
	mwexec("sbin/sysctl net.inet.carp.log=1", true);
1911
	if (!empty($pfsyncinterface))
1912
		$carp_sync_int = get_real_interface($pfsyncinterface);
1913
	else
1914
		unset($carp_sync_int);
1915

    
1916
	/* setup pfsync interface */
1917
	if ($carp_sync_int and $pfsyncenabled) {
1918
		if (is_ipaddr($pfsyncpeerip))
1919
			$syncpeer = "syncpeer {$pfsyncpeerip}";
1920
		else
1921
			$syncpeer = "-syncpeer";
1922

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

    
1925
		sleep(1);
1926

    
1927
		/* 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
1928
		 * for existing sessions.
1929
		 */
1930
		log_error("waiting for pfsync...");
1931
		$i = 0;
1932
		while (intval(trim(`/sbin/ifconfig pfsync0 | /usr/bin/grep 'syncok: 0' | /usr/bin/grep -v grep | /usr/bin/wc -l`)) == 0 && $i < 30) {
1933
			$i++;
1934
			sleep(1);
1935
		}
1936
		log_error("pfsync done in $i seconds.");
1937
		log_error("Configuring CARP settings finalize...");
1938
	} else {
1939
		mwexec("/sbin/ifconfig pfsync0 -syncdev -syncpeer down", false);
1940
	}
1941

    
1942
	if($config['virtualip']['vip'])
1943
		mwexec("/sbin/sysctl net.inet.carp.allow=1", true);
1944
	else
1945
		mwexec("/sbin/sysctl net.inet.carp.allow=0", true);
1946

    
1947
	if ($g['booting']) {
1948
		unmute_kernel_msgs();
1949
		echo gettext("done.") . "\n";
1950
	}
1951
}
1952

    
1953
function interface_proxyarp_configure($interface = "") {
1954
	global $config, $g;
1955
	if(isset($config['system']['developerspew'])) {
1956
		$mt = microtime();
1957
		echo "interface_proxyarp_configure() being called $mt\n";
1958
	}
1959

    
1960
	/* kill any running choparp */
1961
	if (empty($interface))
1962
		killbyname("choparp");
1963
	else {
1964
		$vipif = get_real_interface($interface);
1965
		if (file_exists("{$g['varrun_path']}/choparp_{$vipif}.pid"))
1966
			killbypid("{$g['varrun_path']}/choparp_{$vipif}.pid");
1967
	}
1968

    
1969
	$paa = array();
1970
	if (!empty($config['virtualip']) && is_array($config['virtualip']['vip'])) {
1971

    
1972
		/* group by interface */
1973
		foreach ($config['virtualip']['vip'] as $vipent) {
1974
			if ($vipent['mode'] === "proxyarp") {
1975
				if ($vipent['interface'])
1976
					$proxyif = $vipent['interface'];
1977
				else
1978
					$proxyif = "wan";
1979

    
1980
				if (!empty($interface) && $interface != $proxyif)
1981
					continue;
1982

    
1983
				if (!is_array($paa[$proxyif]))
1984
					$paa[$proxyif] = array();
1985

    
1986
				$paa[$proxyif][] = $vipent;
1987
			}
1988
		}
1989
	}
1990

    
1991
	if (!empty($interface)) {
1992
		if (is_array($paa[$interface])) {
1993
			$paaifip = get_interface_ip($interface);
1994
			if (!is_ipaddr($paaifip))
1995
				return;
1996
			$args = get_real_interface($interface) . " auto";
1997
			foreach ($paa[$interface] as $paent) {
1998
				if (isset($paent['subnet']))
1999
					$args .= " " . escapeshellarg("{$paent['subnet']}/{$paent['subnet_bits']}");
2000
				else if (isset($paent['range']))
2001
					$args .= " " . escapeshellarg($paent['range']['from'] . "-" . $paent['range']['to']);
2002
			}
2003
			mwexec_bg("/usr/local/sbin/choparp " . $args);
2004
		}
2005
	} else if (count($paa) > 0) {
2006
		foreach ($paa as $paif => $paents)  {
2007
			$paaifip = get_interface_ip($paif);
2008
			if (!is_ipaddr($paaifip))
2009
				continue;
2010
			$args = get_real_interface($paif) . " auto";
2011
			foreach ($paents as $paent) {
2012
				if (isset($paent['subnet']))
2013
					$args .= " " . escapeshellarg("{$paent['subnet']}/{$paent['subnet_bits']}");
2014
				else if (isset($paent['range']))
2015
					$args .= " " . escapeshellarg($paent['range']['from'] . "-" . $paent['range']['to']);
2016
			}
2017
			mwexec_bg("/usr/local/sbin/choparp " . $args);
2018
		}
2019
	}
2020
}
2021

    
2022
function interface_ipalias_cleanup($interface, $inet = "inet4") {
2023
	global $g, $config;
2024

    
2025
	if (is_array($config['virtualip']['vip'])) {
2026
		foreach ($config['virtualip']['vip'] as $vip) {
2027
			if ($vip['mode'] == "ipalias" && $vip['interface'] == $interface) {
2028
				if ($inet == "inet6" && is_ipaddrv6($vip['subnet']))
2029
					interface_vip_bring_down($vip);
2030
				else if ($inet == "inet4" && is_ipaddrv4($vip['subnet']))
2031
					interface_vip_bring_down($vip);
2032
			}
2033
		}
2034
	}
2035
}
2036

    
2037
function interfaces_vips_configure($interface = "") {
2038
	global $g, $config;
2039
	if(isset($config['system']['developerspew'])) {
2040
		$mt = microtime();
2041
		echo "interfaces_vips_configure() being called $mt\n";
2042
	}
2043
	$paa = array();
2044
	if(is_array($config['virtualip']['vip'])) {
2045
		$carp_setuped = false;
2046
		$anyproxyarp = false;
2047
		foreach ($config['virtualip']['vip'] as $vip) {
2048
			switch ($vip['mode']) {
2049
			case "proxyarp":
2050
				/* nothing it is handled on interface_proxyarp_configure() */
2051
				if ($interface <> "" && $vip['interface'] <> $interface)
2052
					continue;
2053
				$anyproxyarp = true;
2054
				break;
2055
			case "ipalias":
2056
				if ($interface <> "" && $vip['interface'] <> $interface)
2057
					continue;
2058
				interface_ipalias_configure($vip);
2059
				break;
2060
			case "carp":
2061
				if ($interface <> "" && $vip['interface'] <> $interface)
2062
					continue;
2063
				if ($carp_setuped == false)
2064
					$carp_setuped = true;
2065
				interface_carp_configure($vip);
2066
				break;
2067
			}
2068
		}
2069
		if ($carp_setuped == true)
2070
			interfaces_carp_setup();
2071
		if ($anyproxyarp == true)
2072
			interface_proxyarp_configure();
2073
	}
2074
}
2075

    
2076
function interface_ipalias_configure(&$vip) {
2077
	if ($vip['mode'] == "ipalias") {
2078
		$if = get_real_interface($vip['interface']);
2079
		$af = "inet";
2080
		if(is_ipaddrv6($vip['subnet']))
2081
			$af = "inet6";
2082
		mwexec("/sbin/ifconfig " . escapeshellarg($if) ." {$af} ". escapeshellarg($vip['subnet']) ."/" . escapeshellarg($vip['subnet_bits']) . " alias");
2083
	}
2084
}
2085

    
2086
function interface_reload_carps($cif) {
2087
	global $config;
2088

    
2089
	$carpifs = link_ip_to_carp_interface(find_interface_ip($cif));
2090
	if (empty($carpifs))
2091
		return;
2092

    
2093
	$carps = explode(" ", $carpifs);
2094
	if(is_array($config['virtualip']['vip'])) {
2095
		$viparr = &$config['virtualip']['vip'];
2096
		foreach ($viparr as $vip) {
2097
			if (in_array($vip['carpif'], $carps)) {
2098
				switch ($vip['mode']) {
2099
				case "carp":
2100
					interface_vip_bring_down($vip);
2101
					sleep(1);
2102
					interface_carp_configure($vip);
2103
					break;
2104
				case "ipalias":
2105
					interface_vip_bring_down($vip);
2106
					sleep(1);
2107
					interface_ipalias_configure($vip);
2108
					break;
2109
				}
2110
			}
2111
		}
2112
	}
2113
}
2114

    
2115
function interface_carp_configure(&$vip) {
2116
	global $config, $g;
2117
	if(isset($config['system']['developerspew'])) {
2118
		$mt = microtime();
2119
		echo "interface_carp_configure() being called $mt\n";
2120
	}
2121

    
2122
	if ($vip['mode'] != "carp")
2123
		return;
2124

    
2125
	/*
2126
	 * ensure the interface containing the VIP really exists
2127
	 * prevents a panic if the interface is missing or invalid
2128
	 */
2129
	$realif = get_real_interface($vip['interface']);
2130
	if (!does_interface_exist($realif)) {
2131
		file_notice("CARP", sprintf(gettext("Interface specified for the virtual IP address %s does not exist. Skipping this VIP."), $vip['subnet']), "Firewall: Virtual IP", "");
2132
		return;
2133
	}
2134

    
2135
	if(is_ipaddrv4($vip['subnet'])) {
2136
		/* Ensure CARP IP really exists prior to loading up. */
2137
		$ww_subnet_ip = find_interface_ip($realif);
2138
		$ww_subnet_bits = find_interface_subnet($realif);
2139
		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'])) {
2140
			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", "");
2141
			return;
2142
		}
2143
	}
2144
	if(is_ipaddrv6($vip['subnet'])) {
2145
		/* Ensure CARP IP really exists prior to loading up. */
2146
		$ww_subnet_ip = find_interface_ipv6($realif);
2147
		$ww_subnet_bits = find_interface_subnetv6($realif);
2148
		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'])) {
2149
			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", "");
2150
			return;
2151
		}
2152
	}
2153

    
2154
	// set the vip interface to the vhid
2155
	$vipif = "{$vip['interface']}_vip{$vip['vhid']}";
2156

    
2157
	/* create the carp interface and setup */
2158
	if (does_interface_exist($vipif)) {
2159
		pfSense_interface_flags($vipif, -IFF_UP);
2160
	} else {
2161
		$carpif = pfSense_interface_create("carp");
2162
		pfSense_interface_rename($carpif, $vipif);
2163
		pfSense_ngctl_name("{$carpif}:", $vipif);
2164
	}
2165

    
2166
	/* invalidate interface cache */
2167
	get_interface_arr(true);
2168

    
2169
	$vip_password = $vip['password'];
2170
	$vip_password = escapeshellarg(addslashes(str_replace(" ", "", $vip_password)));
2171
	if ($vip['password'] != "")
2172
		$password = " pass {$vip_password}";
2173

    
2174
	$broadcast_address = gen_subnet_max($vip['subnet'], $vip['subnet_bits']);
2175
	$advbase = "";
2176
	if (!empty($vip['advbase']))
2177
		$advbase = "advbase {$vip['advbase']}";
2178

    
2179
	if(is_ipaddrv4($vip['subnet'])) {
2180
		$broadcast_address = gen_subnet_max($vip['subnet'], $vip['subnet_bits']);
2181
		mwexec("/sbin/ifconfig {$vipif} {$vip['subnet']}/{$vip['subnet_bits']} vhid {$vip['vhid']} advskew {$vip['advskew']} {$advbase} {$password}");
2182
	}
2183
	if(is_ipaddrv6($vip['subnet'])) {
2184
		$broadcast_address = gen_subnet_max($vip['subnet'], $vip['subnet_bits']);
2185
		mwexec("/sbin/ifconfig {$vipif} inet6 {$vip['subnet']} prefixlen {$vip['subnet_bits']} vhid {$vip['vhid']} advskew {$vip['advskew']} {$advbase} {$password}");
2186
	}
2187

    
2188
	interfaces_bring_up($vipif);
2189

    
2190
	return $vipif;
2191
}
2192

    
2193
function interface_wireless_clone($realif, $wlcfg) {
2194
	global $config, $g;
2195
	/*   Check to see if interface has been cloned as of yet.
2196
	 *   If it has not been cloned then go ahead and clone it.
2197
	 */
2198
	$needs_clone = false;
2199
	if(is_array($wlcfg['wireless']))
2200
		$wlcfg_mode = $wlcfg['wireless']['mode'];
2201
	else
2202
		$wlcfg_mode = $wlcfg['mode'];
2203
	switch($wlcfg_mode) {
2204
	case "hostap":
2205
		$mode = "wlanmode hostap";
2206
		break;
2207
	case "adhoc":
2208
		$mode = "wlanmode adhoc";
2209
		break;
2210
	default:
2211
		$mode = "";
2212
		break;
2213
	}
2214
	$baseif = interface_get_wireless_base($wlcfg['if']);
2215
	if(does_interface_exist($realif)) {
2216
		exec("/sbin/ifconfig {$realif}", $output, $ret);
2217
		$ifconfig_str = implode($output);
2218
		if(($wlcfg_mode == "hostap") && (! preg_match("/hostap/si", $ifconfig_str))) {
2219
			log_error(sprintf(gettext("Interface %s changed to hostap mode"), $realif));
2220
			$needs_clone = true;
2221
		}
2222
		if(($wlcfg_mode == "adhoc") && (! preg_match("/adhoc/si", $ifconfig_str))) {
2223
			log_error(sprintf(gettext("Interface %s changed to adhoc mode"), $realif));
2224
			$needs_clone = true;
2225
		}
2226
		if(($wlcfg_mode == "bss") && (preg_match("/hostap|adhoc/si", $ifconfig_str))) {
2227
			log_error(sprintf(gettext("Interface %s changed to infrastructure mode"), $realif));
2228
			$needs_clone = true;
2229
		}
2230
	} else {
2231
		$needs_clone = true;
2232
	}
2233

    
2234
	if($needs_clone == true) {
2235
		/* remove previous instance if it exists */
2236
		if(does_interface_exist($realif))
2237
			pfSense_interface_destroy($realif);
2238

    
2239
		log_error(sprintf(gettext("Cloning new wireless interface %s"), $realif));
2240
		// Create the new wlan interface. FreeBSD returns the new interface name.
2241
		// example:  wlan2
2242
		exec("/sbin/ifconfig wlan create wlandev {$baseif} {$mode} bssid 2>&1", $out, $ret);
2243
		if($ret <> 0) {
2244
			log_error(sprintf(gettext('Failed to clone interface %1$s with error code %2$s, output %3$s'), $baseif, $ret, $out[0]));
2245
			return false;
2246
		}
2247
		$newif = trim($out[0]);
2248
		// Rename the interface to {$parentnic}_wlan{$number}#: EX: ath0_wlan0
2249
		pfSense_interface_rename($newif, $realif);
2250
		// FIXME: not sure what ngctl is for. Doesn't work.
2251
		// mwexec("/usr/sbin/ngctl name {$newif}: {$realif}", false);
2252
		file_put_contents("{$g['tmp_path']}/{$realif}_oldmac", get_interface_mac($realif));
2253
	}
2254
	return true;
2255
}
2256

    
2257
function interface_sync_wireless_clones(&$ifcfg, $sync_changes = false) {
2258
	global $config, $g;
2259

    
2260
	$shared_settings = array('standard', 'turbo', 'protmode', 'txpower', 'channel',
2261
				 'diversity', 'txantenna', 'rxantenna', 'distance',
2262
				 'regdomain', 'regcountry', 'reglocation');
2263

    
2264
	if(!is_interface_wireless($ifcfg['if']))
2265
		return;
2266

    
2267
	$baseif = interface_get_wireless_base($ifcfg['if']);
2268

    
2269
	// Sync shared settings for assigned clones
2270
	$iflist = get_configured_interface_list(false, true);
2271
	foreach ($iflist as $if) {
2272
		if ($baseif == interface_get_wireless_base($config['interfaces'][$if]['if']) && $ifcfg['if'] != $config['interfaces'][$if]['if']) {
2273
			if (isset($config['interfaces'][$if]['wireless']['standard']) || $sync_changes) {
2274
				foreach ($shared_settings as $setting) {
2275
					if ($sync_changes) {
2276
						if (isset($ifcfg['wireless'][$setting]))
2277
							$config['interfaces'][$if]['wireless'][$setting] = $ifcfg['wireless'][$setting];
2278
						else if (isset($config['interfaces'][$if]['wireless'][$setting]))
2279
							unset($config['interfaces'][$if]['wireless'][$setting]);
2280
					} else {
2281
						if (isset($config['interfaces'][$if]['wireless'][$setting]))
2282
							$ifcfg['wireless'][$setting] = $config['interfaces'][$if]['wireless'][$setting];
2283
						else if (isset($ifcfg['wireless'][$setting]))
2284
							unset($ifcfg['wireless'][$setting]);
2285
					}
2286
				}
2287
				if (!$sync_changes)
2288
					break;
2289
			}
2290
		}
2291
	}
2292

    
2293
	// Read or write settings at shared area
2294
	if (isset($config['wireless']['interfaces'][$baseif]) && is_array($config['wireless']['interfaces'][$baseif])) {
2295
		foreach ($shared_settings as $setting) {
2296
			if ($sync_changes) {
2297
				if (isset($ifcfg['wireless'][$setting]))
2298
					$config['wireless']['interfaces'][$baseif][$setting] = $ifcfg['wireless'][$setting];
2299
				else if (isset($config['wireless']['interfaces'][$baseif][$setting]))
2300
					unset($config['wireless']['interfaces'][$baseif][$setting]);
2301
			} else if (isset($config['wireless']['interfaces'][$baseif][$setting])) {
2302
				if (isset($config['wireless']['interfaces'][$baseif][$setting]))
2303
					$ifcfg['wireless'][$setting] = $config['wireless']['interfaces'][$baseif][$setting];
2304
				else if (isset($ifcfg['wireless'][$setting]))
2305
					unset($ifcfg['wireless'][$setting]);
2306
			}
2307
		}
2308
	}
2309

    
2310
	// Sync the mode on the clone creation page with the configured mode on the interface
2311
	if (interface_is_wireless_clone($ifcfg['if']) && isset($config['wireless']['clone']) && is_array($config['wireless']['clone'])) {
2312
		foreach ($config['wireless']['clone'] as &$clone) {
2313
			if ($clone['cloneif'] == $ifcfg['if']) {
2314
				if ($sync_changes) {
2315
					$clone['mode'] = $ifcfg['wireless']['mode'];
2316
				} else {
2317
					$ifcfg['wireless']['mode'] = $clone['mode'];
2318
				}
2319
				break;
2320
			}
2321
		}
2322
		unset($clone);
2323
	}
2324
}
2325

    
2326
function interface_wireless_configure($if, &$wl, &$wlcfg) {
2327
	global $config, $g;
2328

    
2329
	/*    open up a shell script that will be used to output the commands.
2330
	 *    since wireless is changing a lot, these series of commands are fragile
2331
	 *    and will sometimes need to be verified by a operator by executing the command
2332
	 *    and returning the output of the command to the developers for inspection.  please
2333
	 *    do not change this routine from a shell script to individual exec commands.  -sullrich
2334
	 */
2335

    
2336
	// Remove script file
2337
	unlink_if_exists("{$g['tmp_path']}/{$if}_setup.sh");
2338

    
2339
	// Clone wireless nic if needed.
2340
	interface_wireless_clone($if, $wl);
2341

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

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

    
2349
	/* set values for /path/program */
2350
	$hostapd = "/usr/sbin/hostapd";
2351
	$wpa_supplicant = "/usr/sbin/wpa_supplicant";
2352
	$ifconfig = "/sbin/ifconfig";
2353
	$sysctl = "/sbin/sysctl";
2354
	$killall = "/usr/bin/killall";
2355

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

    
2358
	$wlcmd = array();
2359
	$wl_sysctl = array();
2360
	/* Make sure it's up */
2361
	$wlcmd[] = "up";
2362
	/* Set a/b/g standard */
2363
	$standard = str_replace(" Turbo", "", $wlcfg['standard']);
2364
	$wlcmd[] = "mode " . escapeshellarg($standard);
2365

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

    
2371
	/* Set ssid */
2372
	if($wlcfg['ssid'])
2373
		$wlcmd[] = "ssid " .escapeshellarg($wlcfg['ssid']);
2374

    
2375
	/* Set 802.11g protection mode */
2376
	$wlcmd[] = "protmode " . escapeshellarg($wlcfg['protmode']);
2377

    
2378
	/* set wireless channel value */
2379
	if(isset($wlcfg['channel'])) {
2380
		if($wlcfg['channel'] == "0") {
2381
			$wlcmd[] = "channel any";
2382
		} else {
2383
			$wlcmd[] = "channel " . escapeshellarg($wlcfg['channel']);
2384
		}
2385
	}
2386

    
2387
	/* Set antenna diversity value */
2388
	if(isset($wlcfg['diversity']))
2389
		$wl_sysctl[] = "diversity=" . escapeshellarg($wlcfg['diversity']);
2390

    
2391
	/* Set txantenna value */
2392
	if(isset($wlcfg['txantenna']))
2393
		$wl_sysctl[] = "txantenna=" . escapeshellarg($wlcfg['txantenna']);
2394

    
2395
	/* Set rxantenna value */
2396
	if(isset($wlcfg['rxantenna']))
2397
		$wl_sysctl[] = "rxantenna=" . escapeshellarg($wlcfg['rxantenna']);
2398

    
2399
	/* set Distance value */
2400
	if($wlcfg['distance'])
2401
		$distance = escapeshellarg($wlcfg['distance']);
2402

    
2403
	/* Set wireless hostap mode */
2404
	if ($wlcfg['mode'] == "hostap") {
2405
		$wlcmd[] = "mediaopt hostap";
2406
	} else {
2407
		$wlcmd[] = "-mediaopt hostap";
2408
	}
2409

    
2410
	/* Set wireless adhoc mode */
2411
	if ($wlcfg['mode'] == "adhoc") {
2412
		$wlcmd[] = "mediaopt adhoc";
2413
	} else {
2414
		$wlcmd[] = "-mediaopt adhoc";
2415
	}
2416

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

    
2419
	/* handle hide ssid option */
2420
	if(isset($wlcfg['hidessid']['enable'])) {
2421
		$wlcmd[] = "hidessid";
2422
	} else {
2423
		$wlcmd[] = "-hidessid";
2424
	}
2425

    
2426
	/* handle pureg (802.11g) only option */
2427
	if(isset($wlcfg['pureg']['enable'])) {
2428
		$wlcmd[] = "mode 11g pureg";
2429
	} else {
2430
		$wlcmd[] = "-pureg";
2431
	}
2432

    
2433
	/* handle puren (802.11n) only option */
2434
	if(isset($wlcfg['puren']['enable'])) {
2435
		$wlcmd[] = "puren";
2436
	} else {
2437
		$wlcmd[] = "-puren";
2438
	}
2439

    
2440
	/* enable apbridge option */
2441
	if(isset($wlcfg['apbridge']['enable'])) {
2442
		$wlcmd[] = "apbridge";
2443
	} else {
2444
		$wlcmd[] = "-apbridge";
2445
	}
2446

    
2447
	/* handle turbo option */
2448
	if(isset($wlcfg['turbo']['enable'])) {
2449
		$wlcmd[] = "mediaopt turbo";
2450
	} else {
2451
		$wlcmd[] = "-mediaopt turbo";
2452
	}
2453

    
2454
	/* handle txpower setting */
2455
	/* if($wlcfg['txpower'] <> "")
2456
		$wlcmd[] = "txpower " . escapeshellarg($wlcfg['txpower']);
2457
	*/
2458
	/* handle wme option */
2459
	if(isset($wlcfg['wme']['enable'])) {
2460
		$wlcmd[] = "wme";
2461
	} else {
2462
		$wlcmd[] = "-wme";
2463
	}
2464

    
2465
	/* set up wep if enabled */
2466
	$wepset = "";
2467
	if (isset($wlcfg['wep']['enable']) && is_array($wlcfg['wep']['key'])) {
2468
		switch($wlcfg['wpa']['auth_algs']) {
2469
			case "1":
2470
				$wepset .= "authmode open wepmode on ";
2471
				break;
2472
			case "2":
2473
				$wepset .= "authmode shared wepmode on ";
2474
				break;
2475
			case "3":
2476
				$wepset .= "authmode mixed wepmode on ";
2477
		}
2478
		$i = 1;
2479
		foreach ($wlcfg['wep']['key'] as $wepkey) {
2480
			$wepset .= "wepkey " . escapeshellarg("{$i}:{$wepkey['value']}") . " ";
2481
			if (isset($wepkey['txkey'])) {
2482
				$wlcmd[] = "weptxkey {$i} ";
2483
			}
2484
			$i++;
2485
		}
2486
		$wlcmd[] = $wepset;
2487
	} else {
2488
		$wlcmd[] = "authmode open wepmode off ";
2489
	}
2490

    
2491
	kill_hostapd($if);
2492
	mwexec(kill_wpasupplicant("{$if}"));
2493

    
2494
	/* generate wpa_supplicant/hostap config if wpa is enabled */
2495
	conf_mount_rw();
2496

    
2497
	switch ($wlcfg['mode']) {
2498
		case 'bss':
2499
			if (isset($wlcfg['wpa']['enable'])) {
2500
				$wpa .= <<<EOD
2501
ctrl_interface={$g['varrun_path']}/wpa_supplicant
2502
ctrl_interface_group=0
2503
ap_scan=1
2504
#fast_reauth=1
2505
network={
2506
ssid="{$wlcfg['ssid']}"
2507
scan_ssid=1
2508
priority=5
2509
key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
2510
psk="{$wlcfg['wpa']['passphrase']}"
2511
pairwise={$wlcfg['wpa']['wpa_pairwise']}
2512
group={$wlcfg['wpa']['wpa_pairwise']}
2513
}
2514
EOD;
2515

    
2516
				$fd = fopen("{$g['varetc_path']}/wpa_supplicant_{$if}.conf", "w");
2517
				fwrite($fd, "{$wpa}");
2518
				fclose($fd);
2519
			}
2520
			break;
2521
		case 'hostap':
2522
			if($wlcfg['wpa']['passphrase'])
2523
				$wpa_passphrase = "wpa_passphrase={$wlcfg['wpa']['passphrase']}\n";
2524
			else
2525
				$wpa_passphrase = "";
2526
			if (isset($wlcfg['wpa']['enable'])) {
2527
				$wpa .= <<<EOD
2528
interface={$if}
2529
driver=bsd
2530
logger_syslog=-1
2531
logger_syslog_level=0
2532
logger_stdout=-1
2533
logger_stdout_level=0
2534
dump_file={$g['tmp_path']}/hostapd_{$if}.dump
2535
ctrl_interface={$g['varrun_path']}/hostapd
2536
ctrl_interface_group=wheel
2537
#accept_mac_file={$g['tmp_path']}/hostapd_{$if}.accept
2538
#deny_mac_file={$g['tmp_path']}/hostapd_{$if}.deny
2539
#macaddr_acl={$wlcfg['wpa']['macaddr_acl']}
2540
ssid={$wlcfg['ssid']}
2541
debug={$wlcfg['wpa']['debug_mode']}
2542
auth_algs={$wlcfg['wpa']['auth_algs']}
2543
wpa={$wlcfg['wpa']['wpa_mode']}
2544
wpa_key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
2545
wpa_pairwise={$wlcfg['wpa']['wpa_pairwise']}
2546
wpa_group_rekey={$wlcfg['wpa']['wpa_group_rekey']}
2547
wpa_gmk_rekey={$wlcfg['wpa']['wpa_gmk_rekey']}
2548
wpa_strict_rekey={$wlcfg['wpa']['wpa_strict_rekey']}
2549
{$wpa_passphrase}
2550

    
2551
EOD;
2552

    
2553
if (isset($wlcfg['wpa']['rsn_preauth'])) {
2554
	$wpa .= <<<EOD
2555
# Enable the next lines for preauth when roaming. Interface = wired or wireless interface talking to the AP you want to roam from/to
2556
rsn_preauth=1
2557
rsn_preauth_interfaces={$if}
2558

    
2559
EOD;
2560

    
2561
}
2562
				if($wlcfg['auth_server_addr'] && $wlcfg['auth_server_shared_secret']) {
2563
					$auth_server_port = "1812";
2564
					if($wlcfg['auth_server_port'])
2565
						$auth_server_port = $wlcfg['auth_server_port'];
2566
					$auth_server_port2 = "1812";
2567
					if($wlcfg['auth_server_port2'])
2568
						$auth_server_port2 = $wlcfg['auth_server_port2'];
2569
					$wpa .= <<<EOD
2570

    
2571
ieee8021x=1
2572
auth_server_addr={$wlcfg['auth_server_addr']}
2573
auth_server_port={$auth_server_port}
2574
auth_server_shared_secret={$wlcfg['auth_server_shared_secret']}
2575
auth_server_addr={$wlcfg['auth_server_addr2']}
2576
auth_server_port={$auth_server_port2}
2577
auth_server_shared_secret={$wlcfg['auth_server_shared_secret2']}
2578

    
2579
EOD;
2580
				} else {
2581
					$wpa .= "ieee8021x={$wlcfg['wpa']['ieee8021x']}\n";
2582
				}
2583

    
2584
				$fd = fopen("{$g['varetc_path']}/hostapd_{$if}.conf", "w");
2585
				fwrite($fd, "{$wpa}");
2586
				fclose($fd);
2587

    
2588
			}
2589
			break;
2590
	}
2591

    
2592
	/*
2593
	 *    all variables are set, lets start up everything
2594
	 */
2595

    
2596
	$baseif = interface_get_wireless_base($if);
2597
	preg_match("/^(.*?)([0-9]*)$/", $baseif, $baseif_split);
2598
	$wl_sysctl_prefix = 'dev.' . $baseif_split[1] . '.' . $baseif_split[2];
2599

    
2600
	/* set sysctls for the wireless interface */
2601
	if (!empty($wl_sysctl)) {
2602
		fwrite($fd_set, "# sysctls for {$baseif}\n");
2603
		foreach ($wl_sysctl as $wl_sysctl_line) {
2604
			fwrite($fd_set, "{$sysctl} {$wl_sysctl_prefix}.{$wl_sysctl_line}\n");
2605
		}
2606
	}
2607

    
2608
	/* set ack timers according to users preference (if he/she has any) */
2609
	if($distance) {
2610
		fwrite($fd_set, "# Enable ATH distance settings\n");
2611
		fwrite($fd_set, "/sbin/athctrl.sh -i {$baseif} -d {$distance}\n");
2612
	}
2613

    
2614
	if (isset($wlcfg['wpa']['enable'])) {
2615
		if ($wlcfg['mode'] == "bss") {
2616
			fwrite($fd_set, "{$wpa_supplicant} -B -i {$if} -c {$g['varetc_path']}/wpa_supplicant_{$if}.conf\n");
2617
		}
2618
		if ($wlcfg['mode'] == "hostap") {
2619
			/* add line to script to restore old mac to make hostapd happy */
2620
			if (file_exists("{$g['tmp_path']}/{$if}_oldmac")) {
2621
				$if_oldmac = file_get_contents("{$g['tmp_path']}/{$if}_oldmac");
2622
				if (is_macaddr($if_oldmac))
2623
					fwrite($fd_set, "{$ifconfig} " . escapeshellarg($if) .
2624
						" link " . escapeshellarg($if_oldmac) . "\n");
2625
			}
2626

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

    
2629
			/* add line to script to restore spoofed mac after running hostapd */
2630
			if (file_exists("{$g['tmp_path']}/{$if}_oldmac")) {
2631
				if ($wl['spoofmac'])
2632
					$if_curmac = $wl['spoofmac'];
2633
				else
2634
					$if_curmac = get_interface_mac($if);
2635
				if (is_macaddr($if_curmac))
2636
					fwrite($fd_set, "{$ifconfig} " . escapeshellarg($if) .
2637
						" link " . escapeshellarg($if_curmac) . "\n");
2638
			}
2639
		}
2640
	}
2641

    
2642
	fclose($fd_set);
2643
	conf_mount_ro();
2644

    
2645
	/* Making sure regulatory settings have actually changed
2646
	 * before applying, because changing them requires bringing
2647
	 * down all wireless networks on the interface. */
2648
	exec("{$ifconfig} " . escapeshellarg($if), $output);
2649
	$ifconfig_str = implode($output);
2650
	unset($output);
2651
	$reg_changing = false;
2652

    
2653
	/* special case for the debug country code */
2654
	if ($wlcfg['regcountry'] == 'DEBUG' && !preg_match("/\sregdomain\s+DEBUG\s/si", $ifconfig_str))
2655
		$reg_changing = true;
2656
	else if ($wlcfg['regdomain'] && !preg_match("/\sregdomain\s+{$wlcfg['regdomain']}\s/si", $ifconfig_str))
2657
		$reg_changing = true;
2658
	else if ($wlcfg['regcountry'] && !preg_match("/\scountry\s+{$wlcfg['regcountry']}\s/si", $ifconfig_str))
2659
		$reg_changing = true;
2660
	else if ($wlcfg['reglocation'] == 'anywhere' && preg_match("/\s(indoor|outdoor)\s/si", $ifconfig_str))
2661
		$reg_changing = true;
2662
	else if ($wlcfg['reglocation'] && $wlcfg['reglocation'] != 'anywhere' && !preg_match("/\s{$wlcfg['reglocation']}\s/si", $ifconfig_str))
2663
		$reg_changing = true;
2664

    
2665
	if ($reg_changing) {
2666
		/* set regulatory domain */
2667
		if($wlcfg['regdomain'])
2668
			$wlregcmd[] = "regdomain " . escapeshellarg($wlcfg['regdomain']);
2669

    
2670
		/* set country */
2671
		if($wlcfg['regcountry'])
2672
			$wlregcmd[] = "country " . escapeshellarg($wlcfg['regcountry']);
2673

    
2674
		/* set location */
2675
		if($wlcfg['reglocation'])
2676
			$wlregcmd[] = escapeshellarg($wlcfg['reglocation']);
2677

    
2678
		$wlregcmd_args = implode(" ", $wlregcmd);
2679

    
2680
		/* build a complete list of the wireless clones for this interface */
2681
		$clone_list = array();
2682
		if (does_interface_exist(interface_get_wireless_clone($baseif)))
2683
			$clone_list[] = interface_get_wireless_clone($baseif);
2684
		if (isset($config['wireless']['clone']) && is_array($config['wireless']['clone'])) {
2685
			foreach ($config['wireless']['clone'] as $clone) {
2686
				if ($clone['if'] == $baseif)
2687
					$clone_list[] = $clone['cloneif'];
2688
			}
2689
		}
2690

    
2691
		/* find which clones are up and bring them down */
2692
		$clones_up = array();
2693
		foreach ($clone_list as $clone_if) {
2694
			$clone_status = pfSense_get_interface_addresses($clone_if);
2695
			if ($clone_status['status'] == 'up') {
2696
				$clones_up[] = $clone_if;
2697
				mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " down");
2698
			}
2699
		}
2700

    
2701
		/* apply the regulatory settings */
2702
		mwexec("{$ifconfig} " . escapeshellarg($if) . " {$wlregcmd_args}");
2703

    
2704
		/* bring the clones back up that were previously up */
2705
		foreach ($clones_up as $clone_if) {
2706
			mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " up");
2707

    
2708
			/*
2709
			 * Rerun the setup script for the interface if it isn't this interface, the interface
2710
			 * is in infrastructure mode, and WPA is enabled.
2711
			 * This can be removed if wpa_supplicant stops dying when you bring the interface down.
2712
			 */
2713
			if ($clone_if != $if) {
2714
				$friendly_if = convert_real_interface_to_friendly_interface_name($clone_if);
2715
				if ( !empty($friendly_if)
2716
				    && $config['interfaces'][$friendly_if]['wireless']['mode'] == "bss"
2717
				    && isset($config['interfaces'][$friendly_if]['wireless']['wpa']['enable']) ) {
2718
					mwexec("/bin/sh {$g['tmp_path']}/{$clone_if}_setup.sh");
2719
				}
2720
			}
2721
		}
2722
	}
2723

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

    
2728
	/* configure wireless */
2729
	$wlcmd_args = implode(" ", $wlcmd);
2730
	mwexec("/sbin/ifconfig {$if} $wlcmd_args", false);
2731

    
2732

    
2733
	sleep(1);
2734
	/* execute hostapd and wpa_supplicant if required in shell */
2735
	mwexec("/bin/sh {$g['tmp_path']}/{$if}_setup.sh");
2736

    
2737
	return 0;
2738

    
2739
}
2740

    
2741
function kill_hostapd($interface) {
2742
	global $g;
2743

    
2744
	if (isvalidpid("{$g['varrun_path']}/hostapd_{$interface}.pid"))
2745
		return killbypid("{$g['varrun_path']}/hostapd_{$interface}.pid");
2746
}
2747

    
2748
function kill_wpasupplicant($interface) {
2749
	return "/bin/pkill -f \"wpa_supplicant .*{$interface}\\.conf\"\n";
2750
}
2751

    
2752
function find_dhclient_process($interface) {
2753
	if ($interface)
2754
		$pid = `/bin/pgrep -axf "dhclient: {$interface}"`;
2755
	else
2756
		$pid = 0;
2757

    
2758
	return intval($pid);
2759
}
2760

    
2761
function find_dhcp6c_process($interface) {
2762
	global $g;
2763

    
2764
	if ($interface && isvalidpid("{$g['varrun_path']}/dhcp6c_{$interface}.pid"))
2765
		$pid = trim(file_get_contents("{$g['varrun_path']}/dhcp6c_{$interface}.pid"), " \n");
2766
	else
2767
		return(false);
2768

    
2769
	return intval($pid);
2770
}
2771

    
2772
function interface_vlan_mtu_configured($realhwif, $mtu) {
2773
	global $config;
2774

    
2775
	if (is_array($config['vlans']['vlan'])) {
2776
		foreach ($config['vlans']['vlan'] as $vlan) {
2777
			if ($vlan['if'] != $realhwif)
2778
				continue;
2779
			$assignedport = convert_real_interface_to_friendly_interface_name($vlan['vlanif']);
2780
			if (!empty($assignedport)) {
2781
				$portmtu = $config['interfaces'][$assignedport]['mtu'];
2782
				if (!empty($portmtu) && $portmtu > $mtu)
2783
					$mtu = $portmtu;
2784
			}
2785
		}
2786
	}
2787

    
2788
	return $mtu;
2789
}
2790

    
2791
function interface_configure($interface = "wan", $reloadall = false, $linkupevent = false) {
2792
	global $config, $g;
2793
	global $interface_sn_arr_cache, $interface_ip_arr_cache;
2794
	global $interface_snv6_arr_cache, $interface_ipv6_arr_cache;
2795

    
2796
	$wancfg = $config['interfaces'][$interface];
2797

    
2798
	if (!isset($wancfg['enable']))
2799
		return;
2800

    
2801
	$realif = get_real_interface($interface);
2802
	$realhwif_array = get_parent_interface($interface);
2803
	// Need code to handle MLPPP if we ever use $realhwif for MLPPP handling
2804
	$realhwif = $realhwif_array[0];
2805

    
2806
	if (!does_interface_exist($realif)) {
2807
		$matches = array();
2808
		if (preg_match('/^(.*)_vlan([0-9]+)$/', $realif, $matches))
2809
			if (is_array($config['vlans']['vlan']))
2810
				foreach ($config['vlans']['vlan'] as $vlan)
2811
					if ($vlan['if'] == $matches[1] && $vlan['tag'] == $matches[2]) {
2812
						interface_vlan_configure($vlan);
2813
						break;
2814
					}
2815
		unset($matches);
2816
	}
2817

    
2818
	/* Disable Accepting router advertisements unless specifically requested */
2819
	if ($g['debug'])
2820
		log_error("Deny router advertisements for interface {$interface}");
2821
	mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 -accept_rtadv");
2822

    
2823
	if (!$g['booting'] && !(substr($realif, 0, 4) == "ovpn")) {
2824
		/* remove all IPv4 and IPv6 addresses */
2825
		$tmpifaces = pfSense_getall_interface_addresses($realif);
2826
		if (is_array($tmpifaces)) {
2827
			foreach ($tmpifaces as $tmpiface) {
2828
				if (strstr($iface, ":"))
2829
					mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 {$iface} delete");
2830
				else
2831
					mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet {$iface} delete");
2832
			}
2833
		}
2834

    
2835
		/* only bring down the interface when both v4 and v6 are set to NONE */
2836
		if(empty($wancfg['ipaddr']) && empty($wancfg['ipaddrv6'])) {
2837
			interface_bring_down($interface);
2838
		}
2839
	}
2840

    
2841
	/* wireless configuration? */
2842
	if (is_array($wancfg['wireless']))
2843
		interface_wireless_configure($realif, $wancfg, $wancfg['wireless']);
2844

    
2845
	$mac = get_interface_mac($realhwif);
2846
	/*
2847
	 * Don't try to reapply the spoofed MAC if it's already applied.
2848
	 * When ifconfig link is used, it cycles the interface down/up, which triggers
2849
	 * the interface config again, which attempts to spoof the MAC again,
2850
	 * which cycles the link again...
2851
	 */
2852
	if ($wancfg['spoofmac'] && ($wancfg['spoofmac'] != $mac)) {
2853
		mwexec("/sbin/ifconfig " . escapeshellarg($realhwif) .
2854
			" link " . escapeshellarg($wancfg['spoofmac']));
2855

    
2856
		/*
2857
		 * All vlans need to spoof their parent mac address, too.  see
2858
		 * ticket #1514: http://cvstrac.pfsense.com/tktview?tn=1514,33
2859
		 */
2860
		if (is_array($config['vlans']['vlan'])) {
2861
			foreach ($config['vlans']['vlan'] as $vlan) {
2862
				if ($vlan['if'] == $realhwif)
2863
					mwexec("/sbin/ifconfig " . escapeshellarg($vlan['vlanif']) .
2864
					" link " . escapeshellarg($wancfg['spoofmac']));
2865
			}
2866
		}
2867
	}  else {
2868

    
2869
		if ($mac == "ff:ff:ff:ff:ff:ff") {
2870
			/*   this is not a valid mac address.  generate a
2871
			 *   temporary mac address so the machine can get online.
2872
			 */
2873
			echo gettext("Generating new MAC address.");
2874
			$random_mac = generate_random_mac_address();
2875
			mwexec("/sbin/ifconfig " . escapeshellarg($realhwif) .
2876
				" link " . escapeshellarg($random_mac));
2877
			$wancfg['spoofmac'] = $random_mac;
2878
			write_config();
2879
			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");
2880
		}
2881
	}
2882

    
2883
	/* media */
2884
	if ($wancfg['media'] || $wancfg['mediaopt']) {
2885
		$cmd = "/sbin/ifconfig " . escapeshellarg($realhwif);
2886
		if ($wancfg['media'])
2887
			$cmd .= " media " . escapeshellarg($wancfg['media']);
2888
		if ($wancfg['mediaopt'])
2889
			$cmd .= " mediaopt " . escapeshellarg($wancfg['mediaopt']);
2890
		mwexec($cmd);
2891
	}
2892
	$options = pfSense_get_interface_addresses($realhwif);
2893

    
2894
	/* skip vlans for checksumming and polling */
2895
	if (!stristr($realif, "_vlan") && is_array($options)) {
2896
		$flags_on = 0;
2897
		$flags_off = 0;
2898
		if(isset($config['system']['disablechecksumoffloading'])) {
2899
			if (isset($options['encaps']['txcsum']))
2900
				$flags_off |= IFCAP_TXCSUM;
2901
			if (isset($options['encaps']['rxcsum']))
2902
				$flags_off |= IFCAP_RXCSUM;
2903
		} else {
2904
			if (isset($options['caps']['txcsum']))
2905
				$flags_on |= IFCAP_TXCSUM;
2906
			if (isset($options['caps']['rxcsum']))
2907
				$flags_on |= IFCAP_RXCSUM;
2908
		}
2909

    
2910
		if(isset($config['system']['disablesegmentationoffloading']))
2911
			$flags_off |= IFCAP_TSO;
2912
		else if (isset($options['caps']['tso']) || isset($options['caps']['tso4']) || isset($options['caps']['tso6']))
2913
			$flags_on |= IFCAP_TSO;
2914

    
2915
		if(isset($config['system']['disablelargereceiveoffloading']))
2916
			$flags_off |= IFCAP_LRO;
2917
		else if (isset($options['caps']['lro']))
2918
			$flags_on |= IFCAP_LRO;
2919

    
2920
		/* if the NIC supports polling *AND* it is enabled in the GUI */
2921
		if (!isset($config['system']['polling']))
2922
			$flags_off |= IFCAP_POLLING;
2923
		else if (isset($options['caps']['polling']))
2924
			$flags_on |= IFCAP_POLLING;
2925

    
2926
		pfSense_interface_capabilities($realhwif, -$flags_off);
2927
		pfSense_interface_capabilities($realhwif, $flags_on);
2928
	}
2929

    
2930
	/* invalidate interface/ip/sn cache */
2931
	get_interface_arr(true);
2932
	unset($interface_ip_arr_cache[$realif]);
2933
	unset($interface_sn_arr_cache[$realif]);
2934
	unset($interface_ipv6_arr_cache[$realif]);
2935
	unset($interface_snv6_arr_cache[$realif]);
2936

    
2937
	switch ($wancfg['ipaddr']) {
2938
		case 'dhcp':
2939
			interface_dhcp_configure($interface);
2940
			break;
2941
		case 'pppoe':
2942
		case 'l2tp':
2943
		case 'pptp':
2944
		case 'ppp':
2945
			interface_ppps_configure($interface);
2946
			break;
2947
		default:
2948
			if (is_ipaddr($wancfg['ipaddr']) && $wancfg['subnet'] <> "") {
2949
				pfSense_interface_setaddress($realif, "{$wancfg['ipaddr']}/{$wancfg['subnet']}");
2950
			} else if (substr($realif, 0, 3) == "gre") {
2951
				if (is_array($config['gres']['gre'])) {
2952
					foreach ($config['gres']['gre'] as $gre)
2953
						if ($gre['greif'] == $realif)
2954
							interface_gre_configure($gre);
2955
				}
2956
			} else if (substr($realif, 0, 3) == "gif") {
2957
				if (is_array($config['gifs']['gif'])) {
2958
					foreach ($config['gifs']['gif'] as $gif)
2959
						if($gif['gifif'] == $realif)
2960
							interface_gif_configure($gif);
2961
				}
2962
			} else if (substr($realif, 0, 4) == "ovpn") {
2963
				/* XXX: Should be done anything?! */
2964
			}
2965
			break;
2966
	}
2967

    
2968
	switch ($wancfg['ipaddrv6']) {
2969
		case 'slaac':
2970
		case 'dhcp6':
2971
			interface_dhcpv6_configure($interface, $wancfg);
2972
			break;
2973
		case '6rd':
2974
			interface_6rd_configure($interface, $wancfg);
2975
			break;
2976
		case '6to4':
2977
			interface_6to4_configure($interface, $wancfg);
2978
			break;
2979
		case 'track6':
2980
			interface_track6_configure($interface, $wancfg);
2981
			break;
2982
		default:
2983
			if (is_ipaddr($wancfg['ipaddrv6']) && $wancfg['subnetv6'] <> "") {
2984
				pfSense_interface_setaddress($realif, "{$wancfg['ipaddrv6']}/{$wancfg['subnetv6']}");
2985
				// FIXME: Add IPv6 Support to the pfSense module
2986
				mwexec("/sbin/ifconfig {$realif} inet6 {$wancfg['ipaddrv6']} prefixlen {$wancfg['subnetv6']} ");
2987
			}
2988
			break;
2989
	}
2990

    
2991
	$mtu = get_interface_default_mtu(remove_ifindex($realhwif));
2992
	$assignedparent = convert_real_interface_to_friendly_interface_name($realhwif);
2993
	if (!empty($assignedparent) && !empty($config['interfaces'][$assignedparent]['mtu']))
2994
		$mtu = $config['interfaces'][$assignedparent]['mtu'];
2995

    
2996
	$vlanifs = link_interface_to_vlans($realhwif);
2997
	if (empty($vlanifs))
2998
		$vlanifs = array();
2999

    
3000
	if (!empty($wancfg['mtu'])) {
3001
		if (stristr($realif, "_vlan")) {
3002
			if (!empty($assignedparent)) {
3003
				$parentmtu = $config['interfaces'][$assignedparent]['mtu'];
3004
				if (empty($parentmtu))
3005
					$parentmtu = interface_vlan_mtu_configured($realhwif, $wancfg['mtu']);
3006
				if ($wancfg['mtu'] > $parentmtu) {
3007
					if (get_interface_mtu($realhwif) != $wancfg['mtu'])
3008
						pfSense_interface_mtu($realhwif, $wancfg['mtu']);
3009

    
3010
					/* All vlans need to use the same mtu value as their parent. */
3011
					foreach ($vlanifs as $vlan) {
3012
						if ($vlan['vlanif'] == $realif)
3013
							continue;
3014
						$assignedport = convert_real_interface_to_friendly_interface_name($vlan['vlanif']);
3015
						if (!empty($assignedport)) {
3016
							$portmtu = $config['interfaces'][$assignedport]['mtu'];
3017
							if (empty($portmtu) && (get_interface_mtu($vlan['vlanif']) != $wancfg['mtu']))
3018
								pfSense_interface_mtu($vlan['vlanif'], $wancfg['mtu']);
3019
						} else if (get_interface_mtu($vlan['vlanif']) != $wancfg['mtu'])
3020
							pfSense_interface_mtu($vlan['vlanif'], $wancfg['mtu']);
3021
					}
3022
				}
3023
			} else {
3024
				/* Parent is not assigned, back to default */
3025
				if (get_interface_mtu($realhwif) != $mtu)
3026
					pfSense_interface_mtu($realhwif, $mtu);
3027

    
3028
				/* All vlans need to use the same mtu value as their parent. */
3029
				foreach ($vlanifs as $vlan) {
3030
					if ($vlan['vlanif'] == $realif)
3031
						continue;
3032
					$assignedport = convert_real_interface_to_friendly_interface_name($vlan['vlanif']);
3033
					if (!empty($assignedport)) {
3034
						$portmtu = $config['interfaces'][$assignedport]['mtu'];
3035
						if (empty($portmtu) && (get_interface_mtu($vlan['vlanif']) != $mtu))
3036
							pfSense_interface_mtu($vlan['vlanif'], $mtu);
3037
					} else if (get_interface_mtu($vlan['vlanif']) != $mtu)
3038
						pfSense_interface_mtu($vlan['vlanif'], $mtu);
3039
				}
3040

    
3041
				if (get_interface_mtu($realif) != $wancfg['mtu'])
3042
					pfSense_interface_mtu($realif, $wancfg['mtu']);
3043
			}
3044
		} else {
3045
			foreach ($vlanifs as $vlan) {
3046
				$assignedport = convert_real_interface_to_friendly_interface_name($vlan['vlanif']);
3047
				if (empty($assignedport)) {
3048
					if (get_interface_mtu($vlan['vlanif']) != $wancfg['mtu'])
3049
						pfSense_interface_mtu($vlan['vlanif'], $wancfg['mtu']);
3050
				} else {
3051
					$vlanmtu = $config['interfaces'][$assignedport]['mtu'];
3052
					if ((empty($vlanmtu) || ($vlanmtu >= $wancfg['mtu'])) && (get_interface_mtu($vlan['vlanif']) != $wancfg['mtu']))
3053
						pfSense_interface_mtu($vlan['vlanif'], $wancfg['mtu']);
3054
				}
3055
			}
3056
		}
3057
		if ($wancfg['mtu'] != get_interface_mtu($realif))
3058
			pfSense_interface_mtu($realif, $wancfg['mtu']);
3059
	} else if (stristr($realif, "_vlan")) {
3060
		/* XXX: This is really dangerous for example with vlans changing their parent mtu! */
3061
		$bigmtu = interface_vlan_mtu_configured($realhwif, $mtu);
3062
		if ($mtu < $bigmtu)
3063
			$mtu = $bigmtu;
3064

    
3065
		if (get_interface_mtu($realhwif) != $mtu)
3066
			pfSense_interface_mtu($realhwif, $mtu);
3067

    
3068
		/* All vlans need to use the same mtu value as their parent. */
3069
		foreach ($vlanifs as $vlan) {
3070
			if ($vlan['vlanif'] == $realif)
3071
				continue;
3072
			$assignedport = convert_real_interface_to_friendly_interface_name($vlan['vlanif']);
3073
			if (!empty($assignedport)) {
3074
				$portmtu = $config['interfaces'][$assignedport]['mtu'];
3075
				if (empty($portmtu) && (get_interface_mtu($vlan['vlanif']) != $mtu))
3076
					pfSense_interface_mtu($vlan['vlanif'], $mtu);
3077
			} else if (get_interface_mtu($vlan['vlanif']) != $mtu)
3078
				pfSense_interface_mtu($vlan['vlanif'], $mtu);
3079
		}
3080
		if (get_interface_mtu($realif) != $mtu)
3081
			pfSense_interface_mtu($realif, $mtu);
3082
	} else {
3083
		/* All vlans need to use the same mtu value as their parent. */
3084
		foreach ($vlanifs as $vlan) {
3085
			$assignedport = convert_real_interface_to_friendly_interface_name($vlan['vlanif']);
3086
			if (!empty($assignedport)) {
3087
				$portmtu = $config['interfaces'][$assignedport]['mtu'];
3088
				if (empty($portmtu) && (get_interface_mtu($vlan['vlanif']) != $mtu))
3089
					pfSense_interface_mtu($vlan['vlanif'], $mtu);
3090
			} else if (get_interface_mtu($vlan['vlanif']) != $mtu)
3091
				pfSense_interface_mtu($vlan['vlanif'], $mtu);
3092
		}
3093
		if ($mtu != get_interface_mtu($realhwif))
3094
			pfSense_interface_mtu($realhwif, $mtu);
3095
	}
3096

    
3097
	unset($vlanifs);
3098

    
3099
	if(does_interface_exist($wancfg['if']))
3100
		interfaces_bring_up($wancfg['if']);
3101

    
3102
	interface_netgraph_needed($interface);
3103

    
3104
	if (!$g['booting']) {
3105
		link_interface_to_vips($interface, "update");
3106

    
3107
		unset($gre);
3108
		$gre = link_interface_to_gre($interface);
3109
		if (!empty($gre))
3110
			array_walk($gre, 'interface_gre_configure');
3111

    
3112
		unset($gif);
3113
		$gif = link_interface_to_gif($interface);
3114
		if (!empty($gif))
3115
			array_walk($gif, 'interface_gif_configure');
3116

    
3117
		if ($linkupevent == false || substr($realif, 0, 4) == "ovpn") {
3118
			unset($bridgetmp);
3119
			$bridgetmp = link_interface_to_bridge($interface);
3120
			if (!empty($bridgetmp))
3121
				interface_bridge_add_member($bridgetmp, $realif);
3122
		}
3123

    
3124
		$grouptmp = link_interface_to_group($interface);
3125
		if (!empty($grouptmp))
3126
			array_walk($grouptmp, 'interface_group_add_member');
3127

    
3128
		if ($interface == "lan")
3129
			/* make new hosts file */
3130
			system_hosts_generate();
3131

    
3132
		if ($reloadall == true) {
3133

    
3134
			/* reconfigure static routes (kernel may have deleted them) */
3135
			system_routing_configure($interface);
3136

    
3137
			/* reload ipsec tunnels */
3138
			vpn_ipsec_configure();
3139

    
3140
			/* restart dnsmasq */
3141
			services_dnsmasq_configure();
3142

    
3143
			/* update dyndns */
3144
			send_event("service reload dyndns {$interface}");
3145

    
3146
			/* reload captive portal */
3147
			captiveportal_init_rules();
3148
		}
3149
	}
3150

    
3151
	interfaces_staticarp_configure($interface);
3152
	return 0;
3153
}
3154

    
3155
function interface_track6_configure($interface = "lan", $wancfg) {
3156
	global $config, $g;
3157

    
3158
	if (!is_array($wancfg))
3159
		return;
3160

    
3161
	if (!isset($wancfg['enable']))
3162
		return;
3163

    
3164
	/* If the interface is not configured via another, exit */
3165
	if (empty($wancfg['track6-interface']))
3166
		return;
3167

    
3168
	/* always configure a link-local of fe80::1:1 on the track6 interfaces */
3169
	$realif = get_real_interface($interface);
3170
	$linklocal = find_interface_ipv6_ll($realif);
3171
	if (!empty($linklocal))
3172
		mwexec("/sbin/ifconfig {$realif} inet6 {$linklocal} delete");
3173
	/* XXX: This might break for good on a carp installation using link-local as network ips */
3174
	/* XXX: Probably should remove? */
3175
	mwexec("/sbin/ifconfig {$realif} inet6 fe80::1:1%{$realif}");
3176

    
3177
	$trackcfg = $config['interfaces'][$wancfg['track6-interface']];
3178
	if (!isset($trackcfg['enable'])) {
3179
		log_error("Interface {$interface} tracking non-existant interface {$wancfg['track6-interface']}");
3180
		return;
3181
	}
3182

    
3183
	switch($trackcfg['ipaddrv6']) {
3184
	case "6to4":
3185
		if ($g['debug'])
3186
			log_error("Interface {$interface} configured via {$wancfg['track6-interface']}  type {$type}");
3187
		interface_track6_6to4_configure($interface, $wancfg);
3188
		break;
3189
	case "6rd":
3190
		if ($g['debug'])
3191
			log_error("Interface {$interface} configured via {$wancfg['track6-interface']}  type {$type}");
3192
		interface_track6_6rd_configure($interface, $wancfg);
3193
		break;
3194
	}
3195

    
3196
	if (!$g['booting']) {
3197
		if (!function_exists('services_dhcpd_configure'))
3198
			require_once("services.inc");
3199

    
3200
		services_dhcpd_configure("inet6");
3201
	}
3202

    
3203
	return 0;
3204
}
3205

    
3206
function interface_track6_6rd_configure($interface = "lan", $lancfg) {
3207
	global $config, $g;
3208
	global $interface_ipv6_arr_cache;
3209
	global $interface_snv6_arr_cache;
3210

    
3211
	if (!is_array($lancfg))
3212
		return;
3213

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

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

    
3224
	$ip4address = get_interface_ip($lancfg['track6-interface']);
3225
	if (!is_ipaddrv4($ip4address)) { /* XXX: This should not be needed by 6rd || (is_private_ip($ip4address))) { */
3226
		log_error("The interface IPv4 '{$ip4address}' address on interface '{$lancfg['track6-interface']}' is not public, not configuring 6RD tunnel");
3227
		return;
3228
	}
3229
	$hexwanv4 = return_hex_ipv4($ip4address);
3230

    
3231
	/* create the long prefix notation for math, save the prefix length */
3232
	$rd6prefix = explode("/", $wancfg['prefix-6rd']);
3233
	$rd6prefixlen = $rd6prefix[1];
3234
	$rd6prefix = Net_IPv6::uncompress($rd6prefix[0]);
3235

    
3236
	/* binary presentation of the prefix for all 128 bits. */
3237
	$rd6lanbin = convert_ipv6_to_128bit($rd6prefix);
3238

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

    
3244
	/* add the custom prefix id, max 32bits long? (64 bits - (prefixlen + (32 - v4plen)) */
3245
	/* 64 - (37 + (32 - 17)) = 8 == /52 */
3246
	$restbits = 64 - ($rd6prefixlen + (32 - $wancfg['prefix-6rd-v4plen']));
3247
	// echo "64 - (prefixlen {$rd6prefixlen} + v4len (32 - {$wancfg['prefix-6rd-v4plen']})) = {$restbits} \n";
3248
	$rd6lanbin .= substr(sprintf("%032b", str_pad($lancfg['track6-prefix-id'], 32, "0", STR_PAD_LEFT)), (32 - $restbits), 32);
3249
	/* fill the rest out with zeros */
3250
	$rd6lanbin = str_pad($rd6lanbin, 128, "0", STR_PAD_RIGHT);;
3251

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

    
3255
	$lanif = get_real_interface($interface);
3256
	$oip = find_interface_ipv6($lanif);
3257
	if (is_ipaddrv6($oip))
3258
		mwexec("/sbin/ifconfig {$lanif} inet6 {$oip} delete");
3259
	unset($interface_ipv6_arr_cache[$lanif]);
3260
	unset($interface_snv6_arr_cache[$lanif]);
3261
	log_error("rd6 {$interface} with ipv6 address {$rd6lan} based on {$lancfg['track6-interface']} ipv4 {$ip4address}");
3262
	mwexec("/sbin/ifconfig {$lanif} inet6 {$rd6lan} prefixlen 64");
3263

    
3264
	return 0;
3265
}
3266

    
3267
function interface_track6_6to4_configure($interface = "lan", $lancfg) {
3268
	global $config, $g;
3269
	global $interface_ipv6_arr_cache;
3270
	global $interface_snv6_arr_cache;
3271

    
3272
	if (!is_array($lancfg))
3273
		return;
3274

    
3275
	/* If the interface is not configured via another, exit */
3276
	if (empty($lancfg['track6-interface']))
3277
		return;
3278

    
3279
	$wancfg = $config['interfaces'][$lancfg['track6-interface']];
3280
	if (empty($wancfg)) {
3281
		log_error("Interface {$interface} tracking non-existant interface {$lancfg['track6-interface']}");
3282
		return;
3283
	}
3284

    
3285
	$ip4address = get_interface_ip($lancfg['track6-interface']);
3286
	if (!is_ipaddrv4($ip4address) || is_private_ip($ip4address)) {
3287
		log_error("The interface IPv4 '{$ip4address}' address on interface '{$lancfg['track6-interface']}' is not public, not configuring 6RD tunnel");
3288
		return;
3289
	}
3290
	$hexwanv4 = return_hex_ipv4($ip4address);
3291

    
3292
	/* create the long prefix notation for math, save the prefix length */
3293
	$sixto4prefix = "2002::";
3294
	$sixto4prefixlen = 16;
3295
	$sixto4prefix = Net_IPv6::uncompress($sixto4prefix);
3296

    
3297
	/* binary presentation of the prefix for all 128 bits. */
3298
	$sixto4lanbin = convert_ipv6_to_128bit($sixto4prefix);
3299

    
3300
	/* just save the left prefix length bits */
3301
	$sixto4lanbin = substr($sixto4lanbin, 0, $sixto4prefixlen);
3302
	/* add the v4 address */
3303
	$sixto4lanbin .= sprintf("%032b", hexdec($hexwanv4));
3304
	/* add the custom prefix id */
3305
	$sixto4lanbin .= sprintf("%016b", $lancfg['track6-prefix-id']);
3306
	/* fill the rest out with zeros */
3307
	$sixto4lanbin = str_pad($sixto4lanbin, 128, "0", STR_PAD_RIGHT);;
3308

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

    
3312
	$lanif = get_real_interface($interface);
3313
	$oip = find_interface_ipv6($lanif);
3314
	if (is_ipaddrv6($oip))
3315
		mwexec("/sbin/ifconfig {$lanif} inet6 {$oip} delete");
3316
	unset($interface_ipv6_arr_cache[$lanif]);
3317
	unset($interface_snv6_arr_cache[$lanif]);
3318
	log_error("sixto4 {$interface} with ipv6 address {$sixto4lan} based on {$lancfg['track6-interface']} ipv4 {$ip4address}");
3319
	mwexec("/sbin/ifconfig {$lanif} inet6 {$sixto4lan} prefixlen 64");
3320

    
3321
	return 0;
3322
}
3323

    
3324
function interface_6rd_configure($interface = "wan", $wancfg) {
3325
	global $config, $g;
3326

    
3327
	/* because this is a tunnel interface we can only function
3328
	 *	with a public IPv4 address on the interface */
3329

    
3330
	if (!is_array($wancfg))
3331
		return;
3332

    
3333
	$wanif = get_real_interface($interface);
3334
	$ip4address = find_interface_ip($wanif);
3335
	if ((!is_ipaddrv4($ip4address)) || (is_private_ip($ip4address))) {
3336
		log_error("The interface IPv4 '{$ip4address}' address on interface '{$wanif}' is not public, not configuring 6RD tunnel");
3337
		return false;
3338
	}
3339
	$hexwanv4 = return_hex_ipv4($ip4address);
3340

    
3341
	if (!is_numeric($wancfg['prefix-6rd-v4plen']))
3342
		$wancfg['prefix-6rd-v4plen'] = 0;
3343

    
3344
	/* create the long prefix notation for math, save the prefix length */
3345
	$rd6prefix = explode("/", $wancfg['prefix-6rd']);
3346
	$rd6prefixlen = $rd6prefix[1];
3347
	$rd6prefix = Net_IPv6::uncompress($rd6prefix[0]);
3348

    
3349
	/* binary presentation of the prefix for all 128 bits. */
3350
	$rd6prefixbin = convert_ipv6_to_128bit($rd6prefix);
3351

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

    
3359
	/* convert the 128 bits for the broker address back into a valid IPv6 address */
3360
	$rd6prefix = convert_128bit_to_ipv6($rd6prefixbin);
3361

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

    
3364
	/* XXX: need to extend to support variable prefix size for v4 */
3365
	if (!is_module_loaded("if_stf"))
3366
		mwexec("/sbin/kldload if_stf.ko");
3367
	$stfiface = "{$interface}_stf";
3368
	if (does_interface_exist($stfiface))
3369
		pfSense_interface_destroy($stfiface);
3370
	$tmpstfiface = pfSense_interface_create("stf");
3371
	pfSense_interface_rename($tmpstfiface, $stfiface);
3372
	pfSense_interface_flags($stfiface, IFF_LINK2);
3373
	mwexec("/sbin/ifconfig {$stfiface} inet6 {$rd6prefix}/{$rd6prefixlen}");
3374
	mwexec("/sbin/ifconfig {$stfiface} stfv4br " . escapeshellarg($wancfg['gateway-6rd']));
3375
	if ($wancfg['prefix-6rd-v4plen'] > 0 && $wancfg['prefix-6rd-v4plen'] < 32)
3376
		mwexec("/sbin/ifconfig {$stfiface} stfv4net {$ip4address}/{$wancfg['prefix-6rd-v4plen']}");
3377
	if ($g['debug'])
3378
		log_error("Created 6rd interface {$stfiface} {$rd6prefix}/{$rd6prefixlen}");
3379

    
3380
	/* write out a default router file */
3381
	file_put_contents("{$g['tmp_path']}/{$wanif}_routerv6", "{$rd6brgw}\n");
3382
	file_put_contents("{$g['tmp_path']}/{$wanif}_defaultgwv6", "{$rd6brgw}\n");
3383

    
3384
	$ip4gateway = get_interface_gateway($interface);
3385
	if (is_ipaddrv4($ip4gateway))
3386
		mwexec("/sbin/route change -host " . escapeshellarg($wancfg['gateway-6rd']) . " {$ip4gateway}");
3387

    
3388
	/* configure dependent interfaces */
3389
	if (!$g['booting'])
3390
		link_interface_to_track6($interface, "update");
3391

    
3392
	return 0;
3393
}
3394

    
3395
function interface_6to4_configure($interface = "wan", $wancfg){
3396
	global $config, $g;
3397

    
3398
	/* because this is a tunnel interface we can only function
3399
	 *	with a public IPv4 address on the interface */
3400

    
3401
	if (!is_array($wancfg))
3402
		return;
3403

    
3404
	$wanif = get_real_interface($interface);
3405
	$ip4address = find_interface_ip($wanif);
3406
	if((!is_ipaddrv4($ip4address)) || (is_private_ip($ip4address))) {
3407
		log_error("The interface IPv4 '{$ip4address}' address on interface '{$wanif}' is not public, not configuring 6RD tunnel");
3408
		return false;
3409
	}
3410

    
3411
	/* create the long prefix notation for math, save the prefix length */
3412
	$stfprefixlen = 16;
3413
	$stfprefix = Net_IPv6::uncompress("2002::");
3414
	$stfarr = explode(":", $stfprefix);
3415
	$v4prefixlen = "0";
3416

    
3417
	/* we need the hex form of the interface IPv4 address */
3418
	$ip4arr = explode(".", $ip4address);
3419
	$hexwanv4 = "";
3420
	foreach($ip4arr as $octet)
3421
		$hexwanv4 .= sprintf("%02x", $octet);
3422

    
3423
	/* we need the hex form of the broker IPv4 address */
3424
	$ip4arr = explode(".", "192.88.99.1");
3425
	$hexbrv4 = "";
3426
	foreach($ip4arr as $octet)
3427
		$hexbrv4 .= sprintf("%02x", $octet);
3428

    
3429
	/* binary presentation of the prefix for all 128 bits. */
3430
	$stfprefixbin = "";
3431
	foreach($stfarr as $element) {
3432
		$stfprefixbin .= sprintf("%016b", hexdec($element));
3433
	}
3434
	/* just save the left prefix length bits */
3435
	$stfprefixstartbin = substr($stfprefixbin, 0, $stfprefixlen);
3436

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

    
3441
	/* for the local subnet too. */
3442
	$stflanbin = substr(sprintf("%032b", hexdec($hexwanv4)), $v4prefixlen, 32);
3443
	$stflanbin = str_pad($stfprefixstartbin . $stflanbin, 128, "0", STR_PAD_RIGHT);;
3444

    
3445
	/* convert the 128 bits for the broker address back into a valid IPv6 address */
3446
	$stfbrarr = array();
3447
	$stfbrbinarr = array();
3448
	$stfbrbinarr = str_split($stfbrokerbin, 16);
3449
	foreach($stfbrbinarr as $bin)
3450
		$stfbrarr[] = dechex(bindec($bin));
3451
	$stfbrgw = Net_IPv6::compress(implode(":", $stfbrarr));
3452

    
3453
	/* convert the 128 bits for the broker address back into a valid IPv6 address */
3454
	$stflanarr = array();
3455
	$stflanbinarr = array();
3456
	$stflanbinarr = str_split($stflanbin, 16);
3457
	foreach($stflanbinarr as $bin)
3458
		$stflanarr[] = dechex(bindec($bin));
3459
	$stflanpr = Net_IPv6::compress(implode(":", $stflanarr));
3460
	$stflanarr[7] = 1;
3461
	$stflan = Net_IPv6::compress(implode(":", $stflanarr));
3462

    
3463
	/* setup the stf interface */
3464
	if (!is_module_loaded("if_stf"))
3465
		mwexec("/sbin/kldload if_stf.ko");
3466
	$stfiface = "{$interface}_stf";
3467
	if (does_interface_exist($stfiface))
3468
		pfSense_interface_destroy($stfiface);
3469
	$tmpstfiface = pfSense_interface_create("stf");
3470
	pfSense_interface_rename($tmpstfiface, $stfiface);
3471
	pfSense_interface_flags($stfiface, IFF_LINK2);
3472
	mwexec("/sbin/ifconfig {$stfiface} inet6 {$stflanpr} prefixlen 16");
3473

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

    
3477
	/* write out a default router file */
3478
	file_put_contents("{$g['tmp_path']}/{$wanif}_routerv6", "{$stfbrgw}");
3479
	file_put_contents("{$g['tmp_path']}/{$wanif}_defaultgwv6", "{$stfbrgw}");
3480

    
3481
	$ip4gateway = get_interface_gateway($interface);
3482
	if (is_ipaddrv4($ip4gateway))
3483
		mwexec("/sbin/route change -host 192.88.99.1 {$ip4gateway}");
3484

    
3485
	if (!$g['booting'])
3486
		link_interface_to_track6($interface, "update");
3487

    
3488
	return 0;
3489
}
3490

    
3491
function interface_dhcpv6_configure($interface = "wan", $wancfg) {
3492
	global $config, $g;
3493

    
3494
	if (!is_array($wancfg))
3495
		return;
3496

    
3497
	$wanif = get_real_interface($interface, "inet6");
3498
	$dhcp6cconf = "";
3499
	$dhcp6cconf .= "interface {$wanif} {\n";
3500

    
3501
	/* for SLAAC interfaces we do fire off a dhcp6 client for just our name servers */
3502
	if($wancfg['ipaddrv6'] == "slaac") {
3503
		$dhcp6cconf .= "	information-only;\n";
3504
		$dhcp6cconf .= "	request domain-name-servers;\n";
3505
		$dhcp6cconf .= "	request domain-name;\n";
3506
		$dhcp6cconf .= "	script \"{$g['varetc_path']}/dhcp6c_{$interface}_script.sh\"; # we'd like some nameservers please\n";
3507
		$dhcp6cconf .= "};\n";
3508
	} else {
3509
		/* skip address request if this is set */
3510
		if(!isset($wancfg['dhcp6prefixonly']))
3511
			$dhcp6cconf .= "        send ia-na 0;   # request stateful address\n";
3512
		if(is_numeric($wancfg['dhcp6-ia-pd-len']))
3513
			$dhcp6cconf .= "	send ia-pd 0;	# request prefix delegation\n";
3514

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

    
3519
		$dhcp6cconf .= "};\n";
3520

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

    
3524
		if(is_numeric($wancfg['dhcp6-ia-pd-len'])) {
3525
			/* Setup the prefix delegation */
3526
			$dhcp6cconf .= "id-assoc pd 0 {\n";
3527
			$preflen = 64 - $wancfg['dhcp6-ia-pd-len'];
3528
			if (isset($wancfg['dhcp6-ia-pd-send-hint']))
3529
				$dhcp6cconf .= "	prefix ::/{$preflen} infinity;\n";
3530
			$iflist = link_interface_to_track6($interface);
3531
			foreach ($iflist as $friendly => $ifcfg) {
3532
				if (is_numeric($ifcfg['track6-prefix-id'])) {
3533
					if ($g['debug'])
3534
						log_error("setting up $ifdescr - {$ifcfg['track6-prefix-id']}");
3535
					$realif = get_real_interface($friendly);
3536
					$dhcp6cconf .= "	prefix-interface {$realif} {\n";
3537
					$dhcp6cconf .= "		sla-id {$ifcfg['track6-prefix-id']};\n";
3538
					$dhcp6cconf .= "		sla-len {$wancfg['dhcp6-ia-pd-len']};\n";
3539
					$dhcp6cconf .= "	};\n";
3540
				}
3541
			}
3542
			unset($preflen, $iflist, $ifcfg);
3543
			$dhcp6cconf .= "};\n";
3544
		}
3545
	}
3546

    
3547
	// DHCP6 Config File Advanced
3548
	if ($wancfg['adv_dhcp6_config_advanced']) { $dhcp6cconf = DHCP6_Config_File_Advanced($interface, $wancfg, $wanif); }
3549

    
3550
	// DHCP6 Config File Override
3551
	if ($wancfg['adv_dhcp6_config_file_override']) { $dhcp6cconf = DHCP6_Config_File_Override($wancfg, $wanif); }
3552

    
3553
	/* wide-dhcp6c works for now. */
3554
	if (!@file_put_contents("{$g['varetc_path']}/dhcp6c_{$interface}.conf", $dhcp6cconf)) {
3555
		printf("Error: cannot open dhcp6c_{$interface}.conf in interface_dhcpv6_configure() for writing.\n");
3556
		unset($dhcp6cconf);
3557
		return 1;
3558
	}
3559
	unset($dhcp6cconf);
3560

    
3561
	$dhcp6cscript = "#!/bin/sh\n";
3562
	$dhcp6cscript .= "# This shell script launches /etc/rc.newwanipv6 with a interface argument.\n";
3563
	$dhcp6cscript .= "/etc/rc.newwanipv6 {$wanif} \n";
3564
	/* Add wide-dhcp6c shell script here. Because we can not pass a argument to it. */
3565
	if (!@file_put_contents("{$g['varetc_path']}/dhcp6c_{$interface}_script.sh", $dhcp6cscript)) {
3566
		printf("Error: cannot open dhcp6c_{$interface}_script.sh in interface_dhcpv6_configure() for writing.\n");
3567
		unset($dhcp6cscript);
3568
		return 1;
3569
	}
3570
	unset($dhcp6cscript);
3571
	@chmod("{$g['varetc_path']}/dhcp6c_{$interface}_script.sh", 0755);
3572

    
3573
	$rtsoldscript = "#!/bin/sh\n";
3574
	$rtsoldscript .= "# This shell script launches dhcp6c and configured gateways for this interface.\n";
3575
	$rtsoldscript .= "echo $2 > {$g['tmp_path']}/{$wanif}_routerv6\n";
3576
	$rtsoldscript .= "echo $2 > {$g['tmp_path']}/{$wanif}_defaultgwv6\n";
3577
	$rtsoldscript .= "if [ -f {$g['varrun_path']}/dhcp6c_{$wanif}.pid ]; then\n";
3578
	$rtsoldscript .= "\t/bin/pkill -F {$g['varrun_path']}/dhcp6c_{$wanif}.pid\n";
3579
	$rtsoldscript .= "\t/bin/sleep 1\n";
3580
	$rtsoldscript .= "fi\n";
3581
	$rtsoldscript .= "/usr/local/sbin/dhcp6c -d -c {$g['varetc_path']}/dhcp6c_{$interface}.conf -p {$g['varrun_path']}/dhcp6c_{$wanif}.pid {$wanif}\n";
3582
	$rtsoldscript .= "/usr/bin/logger -t rtsold \"Starting dhcp6 client for interface {$interface}({$wanif})\"\n";
3583
	/* Add wide-dhcp6c shell script here. Because we can not pass a argument to it. */
3584
	if (!@file_put_contents("{$g['varetc_path']}/rtsold_{$wanif}_script.sh", $rtsoldscript)) {
3585
		printf("Error: cannot open rtsold_{$interface}_script.sh in interface_dhcpv6_configure() for writing.\n");
3586
		unset($rtsoldscript);
3587
		return 1;
3588
	}
3589
	unset($rtsoldscript);
3590
	@chmod("{$g['varetc_path']}/rtsold_{$wanif}_script.sh", 0755);
3591

    
3592
	/* accept router advertisements for this interface */
3593
	mwexec("/sbin/sysctl -w net.inet6.ip6.accept_rtadv=1");
3594
	log_error("Accept router advertisements on interface {$wanif} ");
3595
	mwexec("/sbin/ifconfig {$wanif} inet6 accept_rtadv");
3596

    
3597
	/* fire up rtsold for IPv6 RAs first, this backgrounds immediately. It will call dhcp6c */
3598
	if (isvalidpid("{$g['varrun_path']}/rtsold_{$wanif}.pid")) {
3599
		killbypid("{$g['varrun_path']}/rtsold_{$wanif}.pid");
3600
		sleep(2);
3601
	}
3602
	mwexec("/usr/sbin/rtsold -1 -p {$g['varrun_path']}/rtsold_{$wanif}.pid -O {$g['varetc_path']}/rtsold_{$wanif}_script.sh {$wanif}");
3603

    
3604
	/* NOTE: will be called from rtsold invoked script
3605
	 * link_interface_to_track6($interface, "update");
3606
	 */
3607

    
3608
	return 0;
3609
}
3610

    
3611
function DHCP6_Config_File_Advanced($interface, $wancfg, $wanif) {
3612
	global $g;
3613

    
3614
	$send_options = "";
3615
	if ($wancfg['adv_dhcp6_interface_statement_send_options'] != '') {
3616
		$options = split(",", $wancfg['adv_dhcp6_interface_statement_send_options']);
3617
		foreach ($options as $option) {
3618
			$send_options .= "\tsend " . trim($option) . ";\n";
3619
		}
3620
	}
3621

    
3622
	$request_options = "";
3623
	if ($wancfg['adv_dhcp6_interface_statement_request_options'] != '') {
3624
		$options = split(",", $wancfg['adv_dhcp6_interface_statement_request_options']);
3625
		foreach ($options as $option) {
3626
			$request_options .= "\trequest " . trim($option) . ";\n";
3627
		}
3628
	}
3629

    
3630
	$information_only = "";
3631
	if ($wancfg['adv_dhcp6_interface_statement_information_only_enable'] != '') 
3632
		$information_only = "\tinformation-only;\n";
3633

    
3634
	$script = "\tscript \"{$g['varetc_path']}/dhcp6c_{$interface}_script.sh\";\n";
3635
	if ($wancfg['adv_dhcp6_interface_statement_script'] != '')
3636
		$script = "\tscript \"{$wancfg['adv_dhcp6_interface_statement_script']}\";\n";
3637

    
3638
	$interface_statement  = "interface";
3639
	$interface_statement .= " {$wanif}";
3640
	$interface_statement .= " {\n";
3641
	$interface_statement .= "$send_options";
3642
	$interface_statement .= "$request_options";
3643
	$interface_statement .= "$information_only";
3644
	$interface_statement .= "$script";
3645
	$interface_statement .= "};\n";
3646

    
3647
	$id_assoc_statement_address = "";
3648
	if ($wancfg['adv_dhcp6_id_assoc_statement_address_enable'] != '') {
3649
		$id_assoc_statement_address .= "id-assoc";
3650
		$id_assoc_statement_address .= " na";
3651
		if (is_numeric($wancfg['adv_dhcp6_id_assoc_statement_address_id'])) 
3652
			$id_assoc_statement_address .= " {$wancfg['adv_dhcp6_id_assoc_statement_address_id']}";
3653
		$id_assoc_statement_address .= " { ";
3654

    
3655
		if ( ($wancfg['adv_dhcp6_id_assoc_statement_address'] != '') && 
3656
			 (is_numeric($wancfg['adv_dhcp6_id_assoc_statement_address_pltime']) || 
3657
			 ($wancfg['adv_dhcp6_id_assoc_statement_address_pltime'] == 'infinity')) ) {
3658
			$id_assoc_statement_address .= "\n\taddress";
3659
			$id_assoc_statement_address .= " {$wancfg['adv_dhcp6_id_assoc_statement_address']}";
3660
			$id_assoc_statement_address .= " {$wancfg['adv_dhcp6_id_assoc_statement_address_pltime']}";
3661
			if ( (is_numeric($wancfg['adv_dhcp6_id_assoc_statement_address_vltime'])) || 
3662
							($wancfg['adv_dhcp6_id_assoc_statement_address_vltime'] == 'infinity') ) 
3663
				$id_assoc_statement_address .= " {$wancfg['adv_dhcp6_id_assoc_statement_address_vltime']}";
3664
			$id_assoc_statement_address .= ";\n";
3665
		}
3666

    
3667
		$id_assoc_statement_address  .= "};\n";
3668
	}
3669

    
3670
	$id_assoc_statement_prefix = "";
3671
	if ($wancfg['adv_dhcp6_id_assoc_statement_prefix_enable'] != '') {
3672
		$id_assoc_statement_prefix .= "id-assoc";
3673
		$id_assoc_statement_prefix .= " pd";
3674
		if (is_numeric($wancfg['adv_dhcp6_id_assoc_statement_prefix_id'])) 
3675
			$id_assoc_statement_prefix .= " {$wancfg['adv_dhcp6_id_assoc_statement_prefix_id']}";
3676
		$id_assoc_statement_prefix .= " { ";
3677

    
3678
		if ( ($wancfg['adv_dhcp6_id_assoc_statement_prefix'] != '') && 
3679
			 (is_numeric($wancfg['adv_dhcp6_id_assoc_statement_prefix_pltime']) || 
3680
			 ($wancfg['adv_dhcp6_id_assoc_statement_prefix_pltime'] == 'infinity')) ) {
3681
			$id_assoc_statement_prefix .= "\n\tprefix";
3682
			$id_assoc_statement_prefix .= " {$wancfg['adv_dhcp6_id_assoc_statement_prefix']}";
3683
			$id_assoc_statement_prefix .= " {$wancfg['adv_dhcp6_id_assoc_statement_prefix_pltime']}";
3684
			if ( (is_numeric($wancfg['adv_dhcp6_id_assoc_statement_prefix_vltime'])) || 
3685
						  ($wancfg['adv_dhcp6_id_assoc_statement_prefix_vltime'] == 'infinity') ) 
3686
				$id_assoc_statement_prefix .= " {$wancfg['adv_dhcp6_id_assoc_statement_prefix_vltime']}";
3687
			$id_assoc_statement_prefix .= ";";
3688
		}
3689

    
3690
		if (is_numeric($wancfg['adv_dhcp6_prefix_interface_statement_sla_id'])) {
3691
			$id_assoc_statement_prefix .= "\n\tprefix-interface";
3692
			$id_assoc_statement_prefix .= " {$wanif}";
3693
			$id_assoc_statement_prefix .= " {\n";
3694
			$id_assoc_statement_prefix .= "\t\tsla-id {$wancfg['adv_dhcp6_prefix_interface_statement_sla_id']};\n";
3695
			if ( ($wancfg['adv_dhcp6_prefix_interface_statement_sla_len'] >= 0) && 
3696
				 ($wancfg['adv_dhcp6_prefix_interface_statement_sla_len'] <= 128) ) 
3697
				 $id_assoc_statement_prefix .= "\t\tsla-len {$wancfg['adv_dhcp6_prefix_interface_statement_sla_len']};\n";
3698
			$id_assoc_statement_prefix .= "\t};";
3699
		}
3700

    
3701
		if ( ($wancfg['adv_dhcp6_id_assoc_statement_prefix'] != '') || 
3702
			 (is_numeric($wancfg['adv_dhcp6_prefix_interface_statement_sla_id'])) ) { 
3703
			$id_assoc_statement_prefix .= "\n";
3704
		}
3705

    
3706
		$id_assoc_statement_prefix  .= "};\n";
3707
	}
3708

    
3709
	$authentication_statement = "";
3710
	if ( ($wancfg['adv_dhcp6_authentication_statement_authname'] != '') && 
3711
		 ($wancfg['adv_dhcp6_authentication_statement_protocol'] == 'delayed') ) {
3712
		$authentication_statement .= "authentication";
3713
		$authentication_statement .= " {$wancfg['adv_dhcp6_authentication_statement_authname']}";
3714
		$authentication_statement .= " {\n";
3715
		$authentication_statement .= "\tprotocol {$wancfg['adv_dhcp6_authentication_statement_protocol']};\n";
3716
		if (preg_match("/(hmac(-)?md5)||(HMAC(-)?MD5)/", $wancfg['adv_dhcp6_authentication_statement_algorithm'])) 
3717
			$authentication_statement .= "\talgorithm {$wancfg['adv_dhcp6_authentication_statement_algorithm']};\n";
3718
		if ($wancfg['adv_dhcp6_authentication_statement_rdm'] == 'monocounter') 
3719
			$authentication_statement .= "\trdm {$wancfg['adv_dhcp6_authentication_statement_rdm']};\n";
3720
		$authentication_statement .= "};\n";
3721
	}
3722

    
3723
	$key_info_statement = "";
3724
	if ( ($wancfg['adv_dhcp6_key_info_statement_keyname'] != '') && 
3725
		 ($wancfg['adv_dhcp6_key_info_statement_realm'] != '') && 
3726
		 (is_numeric($wancfg['adv_dhcp6_key_info_statement_keyid'])) && 
3727
		 ($wancfg['adv_dhcp6_key_info_statement_secret'] != '') ) {
3728
		$key_info_statement .= "keyinfo";
3729
		$key_info_statement .= " {$wancfg['adv_dhcp6_key_info_statement_keyname']}";
3730
		$key_info_statement .= " {\n";
3731
		$key_info_statement .= "\trealm \"{$wancfg['adv_dhcp6_key_info_statement_realm']}\";\n";
3732
		$key_info_statement .= "\tkeyid {$wancfg['adv_dhcp6_key_info_statement_keyid']};\n";
3733
		$key_info_statement .= "\tsecret \"{$wancfg['adv_dhcp6_key_info_statement_secret']}\";\n";
3734
		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'])) 
3735
			$key_info_statement .= "\texpire \"{$wancfg['adv_dhcp6_key_info_statement_expire']}\";\n";
3736
		$key_info_statement .= "};\n";
3737
	}
3738

    
3739
	$dhcp6cconf  = $interface_statement;
3740
	$dhcp6cconf .= $id_assoc_statement_address;
3741
	$dhcp6cconf .= $id_assoc_statement_prefix;
3742
	$dhcp6cconf .= $authentication_statement;
3743
	$dhcp6cconf .= $key_info_statement;
3744

    
3745
	$dhcp6cconf = DHCP6_Config_File_Substitutions($wancfg, $wanif, $dhcp6cconf);
3746

    
3747
	return $dhcp6cconf;
3748
}
3749

    
3750

    
3751
function DHCP6_Config_File_Override($wancfg, $wanif) {
3752

    
3753
	$dhcp6cconf = file_get_contents($wancfg['adv_dhcp6_config_file_override_path']);
3754
	$dhcp6cconf = DHCP6_Config_File_Substitutions($wancfg, $wanif, $dhcp6cconf);
3755

    
3756
	return $dhcp6cconf;
3757
}
3758

    
3759

    
3760
function DHCP6_Config_File_Substitutions($wancfg, $wanif, $dhcp6cconf) {
3761

    
3762
	$dhcp6cconf = DHCP_Config_File_Substitutions($wancfg, $wanif, $dhcp6cconf);
3763

    
3764
	return $dhcp6cconf;
3765
}
3766

    
3767

    
3768
function interface_dhcp_configure($interface = "wan") {
3769
	global $config, $g;
3770

    
3771
	$wancfg = $config['interfaces'][$interface];
3772
	$wanif = $wancfg['if'];
3773
	if (empty($wancfg))
3774
		$wancfg = array();
3775

    
3776
	/* generate dhclient_wan.conf */
3777
	$fd = fopen("{$g['varetc_path']}/dhclient_{$interface}.conf", "w");
3778
	if (!$fd) {
3779
		printf(printf(gettext("Error: cannot open dhclient_%s.conf in interface_dhcp_configure() for writing.%s"), $interface, "\n"));
3780
		return 1;
3781
	}
3782

    
3783
	if ($wancfg['dhcphostname']) {
3784
		$dhclientconf_hostname = "send dhcp-client-identifier \"{$wancfg['dhcphostname']}\";\n";
3785
		$dhclientconf_hostname .= "\tsend host-name \"{$wancfg['dhcphostname']}\";\n";
3786
	} else {
3787
		$dhclientconf_hostname = "";
3788
	}
3789

    
3790
	$wanif = get_real_interface($interface);
3791
	if (empty($wanif)) {
3792
		log_error(sprintf(gettext("Invalid interface \"%s\" in interface_dhcp_configure()"), $interface));
3793
		return 0;
3794
	}
3795
	$dhclientconf = "";
3796

    
3797
	$dhclientconf .= <<<EOD
3798
interface "{$wanif}" {
3799
timeout 60;
3800
retry 15;
3801
select-timeout 0;
3802
initial-interval 1;
3803
	{$dhclientconf_hostname}
3804
	script "/sbin/dhclient-script";
3805
EOD;
3806

    
3807
if (is_ipaddrv4($wancfg['dhcprejectfrom'])) {
3808
	$dhclientconf .= <<<EOD
3809

    
3810
	reject {$wancfg['dhcprejectfrom']};
3811
EOD;
3812
}
3813
	$dhclientconf .= <<<EOD
3814

    
3815
}
3816

    
3817
EOD;
3818

    
3819
	// DHCP Config File Advanced
3820
	if ($wancfg['adv_dhcp_config_advanced']) { $dhclientconf = DHCP_Config_File_Advanced($interface, $wancfg, $wanif); }
3821

    
3822
if(is_ipaddr($wancfg['alias-address'])) {
3823
	$subnetmask = gen_subnet_mask($wancfg['alias-subnet']);
3824
	$dhclientconf .= <<<EOD
3825
alias {
3826
	interface  "{$wanif}";
3827
	fixed-address {$wancfg['alias-address']};
3828
	option subnet-mask {$subnetmask};
3829
}
3830

    
3831
EOD;
3832
}
3833

    
3834
	// DHCP Config File Override
3835
	if ($wancfg['adv_dhcp_config_file_override']) { $dhclientconf = DHCP_Config_File_Override($wancfg, $wanif); }
3836

    
3837
	fwrite($fd, $dhclientconf);
3838
	fclose($fd);
3839

    
3840
	/* bring wan interface up before starting dhclient */
3841
	if($wanif)
3842
		interfaces_bring_up($wanif);
3843
	else
3844
		log_error(printf(gettext("Could not bring up %s interface in interface_dhcp_configure()"), $wanif));
3845

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

    
3849
	return 0;
3850
}
3851

    
3852
function DHCP_Config_File_Advanced($interface, $wancfg, $wanif) {
3853

    
3854
	$hostname = "";
3855
	if ($wancfg['dhcphostname'] != '') {
3856
		$hostname = "\tsend host-name \"{$wancfg['dhcphostname']}\";\n";
3857
	}
3858

    
3859
	/* DHCP Protocol Timings */
3860
	$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");
3861
	foreach ($protocol_timings as $Protocol_Timing => $PT_Name) {
3862
		$pt_variable = "{$Protocol_Timing}";
3863
		${$pt_variable} = "";
3864
		if ($wancfg[$Protocol_Timing] != "") {
3865
			${$pt_variable} = "{$PT_Name} {$wancfg[$Protocol_Timing]};\n";
3866
		}
3867
	}
3868

    
3869
	$send_options = "";
3870
	if ($wancfg['adv_dhcp_send_options'] != '') {
3871
		$options = split(",", $wancfg['adv_dhcp_send_options']);
3872
		foreach ($options as $option) {
3873
			$send_options .= "\tsend " . trim($option) . ";\n";
3874
		}
3875
	}
3876

    
3877
	$request_options = "";
3878
	if ($wancfg['adv_dhcp_request_options'] != '') {
3879
		$request_options = "\trequest {$wancfg['adv_dhcp_request_options']};\n";
3880
	}
3881

    
3882
	$required_options = "";
3883
	if ($wancfg['adv_dhcp_required_options'] != '') {
3884
		$required_options = "\trequire {$wancfg['adv_dhcp_required_options']};\n";
3885
	}
3886

    
3887
	$option_modifiers = "";
3888
	if ($wancfg['adv_dhcp_option_modifiers'] != '') {
3889
		$modifiers = split(",", $wancfg['adv_dhcp_option_modifiers']);
3890
		foreach ($modifiers as $modifier) {
3891
			$option_modifiers .= "\t" . trim($modifier) . ";\n";
3892
		}
3893
	}
3894

    
3895
 	$dhclientconf  = "interface \"{$wanif}\" {\n";
3896
 	$dhclientconf .= "\n";
3897
 	$dhclientconf .= "# DHCP Protocol Timing Values\n";
3898
 	$dhclientconf .= "{$adv_dhcp_pt_timeout}";
3899
 	$dhclientconf .= "{$adv_dhcp_pt_retry}";
3900
 	$dhclientconf .= "{$adv_dhcp_pt_select_timeout}";
3901
 	$dhclientconf .= "{$adv_dhcp_pt_reboot}";
3902
 	$dhclientconf .= "{$adv_dhcp_pt_backoff_cutoff}";
3903
 	$dhclientconf .= "{$adv_dhcp_pt_initial_interval}";
3904
 	$dhclientconf .= "\n";
3905
 	$dhclientconf .= "# DHCP Protocol Options\n";
3906
 	$dhclientconf .= "{$hostname}";
3907
 	$dhclientconf .= "{$send_options}";
3908
 	$dhclientconf .= "{$request_options}";
3909
 	$dhclientconf .= "{$required_options}";
3910
 	$dhclientconf .= "{$option_modifiers}";
3911
 	$dhclientconf .= "\n";
3912
 	$dhclientconf .= "\tscript \"/sbin/dhclient-script\";\n";
3913
 	$dhclientconf .= "}\n";
3914

    
3915
	$dhclientconf = DHCP_Config_File_Substitutions($wancfg, $wanif, $dhclientconf);
3916

    
3917
	return $dhclientconf;
3918
}
3919

    
3920

    
3921
function DHCP_Config_File_Override($wancfg, $wanif) {
3922

    
3923
	$dhclientconf = file_get_contents($wancfg['adv_dhcp_config_file_override_path']);
3924
	$dhclientconf = DHCP_Config_File_Substitutions($wancfg, $wanif, $dhclientconf);
3925

    
3926
	return $dhclientconf;
3927
}
3928

    
3929

    
3930
function DHCP_Config_File_Substitutions($wancfg, $wanif, $dhclientconf) {
3931

    
3932
	/* Apply Interface Substitutions */
3933
	$dhclientconf = str_replace("{interface}", "{$wanif}", $dhclientconf);
3934

    
3935
	/* Apply Hostname Substitutions */
3936
	$dhclientconf = str_replace("{hostname}", $wancfg['dhcphostname'], $dhclientconf);
3937

    
3938
	/* Arrays of MAC Address Types, Cases, Delimiters */
3939
	/* ASCII or HEX, Upper or Lower Case, Various Delimiters (none, space, colon, hyphen, period) */
3940
	$various_mac_types      = array("mac_addr_ascii", "mac_addr_hex");
3941
	$various_mac_cases      = array("U", "L");
3942
	$various_mac_delimiters = array("", " ", ":", "-", ".");
3943

    
3944
	/* Apply MAC Address Substitutions */
3945
	foreach ($various_mac_types as $various_mac_type) {
3946
		foreach ($various_mac_cases as $various_mac_case) {
3947
			foreach ($various_mac_delimiters as $various_mac_delimiter) {
3948

    
3949
				$res = stripos($dhclientconf, $various_mac_type . $various_mac_case . $various_mac_delimiter);
3950
				if ($res !== false) {
3951

    
3952
					/* Get MAC Address as ASCII String With Colon (:) Celimiters */
3953
					if ("$various_mac_case" == "U") $dhcpclientconf_mac = strtoupper(get_interface_mac($wanif));
3954
					if ("$various_mac_case" == "L") $dhcpclientconf_mac = strtolower(get_interface_mac($wanif));
3955

    
3956
					if ("$various_mac_type" == "mac_addr_hex") {
3957
						/* Convert MAC ascii string to HEX with colon (:) delimiters. */
3958
						$dhcpclientconf_mac = str_replace(":", "", $dhcpclientconf_mac);
3959
						$dhcpclientconf_mac_hex = "";
3960
						$delimiter = "";
3961
						for($i = 0; $i < strlen($dhcpclientconf_mac); $i++) {
3962
							$dhcpclientconf_mac_hex .= $delimiter. bin2hex($dhcpclientconf_mac[$i]);
3963
							$delimiter = ":";
3964
						}
3965
						$dhcpclientconf_mac = $dhcpclientconf_mac_hex;
3966
					}
3967

    
3968
					/* MAC Address Delimiter Substitutions */
3969
					$dhcpclientconf_mac = str_replace(":", $various_mac_delimiter, $dhcpclientconf_mac);
3970

    
3971
					/* Apply MAC Address Substitutions */
3972
					$dhclientconf = str_replace("{" . $various_mac_type . $various_mac_case . $various_mac_delimiter . "}", $dhcpclientconf_mac, $dhclientconf);
3973
				}
3974
			}
3975
		}
3976
	}
3977

    
3978
	return $dhclientconf;
3979
}
3980

    
3981
function interfaces_group_setup() {
3982
	global $config;
3983

    
3984
	if (!is_array($config['ifgroups']['ifgroupentry']))
3985
		return;
3986

    
3987
	foreach ($config['ifgroups']['ifgroupentry'] as $groupar)
3988
		interface_group_setup($groupar);
3989

    
3990
	return;
3991
}
3992

    
3993
function interface_group_setup(&$groupname /* The parameter is an array */) {
3994
	global $config;
3995

    
3996
	if (!is_array($groupname))
3997
		return;
3998
	$members = explode(" ", $groupname['members']);
3999
	foreach($members as $ifs) {
4000
		$realif = get_real_interface($ifs);
4001
		if ($realif)
4002
			mwexec("/sbin/ifconfig {$realif} group {$groupname['ifname']}");
4003
	}
4004

    
4005
	return;
4006
}
4007

    
4008
function is_interface_group($if) {
4009
	global $config;
4010

    
4011
	if (is_array($config['ifgroups']['ifgroupentry']))
4012
		foreach ($config['ifgroups']['ifgroupentry'] as $groupentry) {
4013
			if ($groupentry['ifname'] === $if)
4014
				return true;
4015
		}
4016

    
4017
	return false;
4018
}
4019

    
4020
function interface_group_add_member($interface, $groupname) {
4021
	$interface = get_real_interface($interface);
4022
	mwexec("/sbin/ifconfig {$interface} group {$groupname}", true);
4023
}
4024

    
4025
/* COMPAT Function */
4026
function convert_friendly_interface_to_real_interface_name($interface) {
4027
	return get_real_interface($interface);
4028
}
4029

    
4030
/* COMPAT Function */
4031
function get_real_wan_interface($interface = "wan") {
4032
	return get_real_interface($interface);
4033
}
4034

    
4035
/* COMPAT Function */
4036
function get_current_wan_address($interface = "wan") {
4037
	return get_interface_ip($interface);
4038
}
4039

    
4040
/*
4041
 * convert_real_interface_to_friendly_interface_name($interface): convert fxp0 -> wan, etc.
4042
 */
4043
function convert_real_interface_to_friendly_interface_name($interface = "wan") {
4044
	global $config;
4045

    
4046
	if (stristr($interface, "_vip")) {
4047
		foreach ($config['virtualip']['vip'] as $counter => $vip) {
4048
			if ($vip['mode'] == "carp")  {
4049
				if ($interface == "{$vip['interface']}_vip{$vip['vhid']}")
4050
					return $vip['interface'];
4051
			}
4052
		}
4053
	}
4054

    
4055
	/* XXX: For speed reasons reference directly the interface array */
4056
	$ifdescrs = &$config['interfaces'];
4057
	//$ifdescrs = get_configured_interface_list(false, true);
4058

    
4059
	foreach ($ifdescrs as $if => $ifname) {
4060
		if ($if == $interface || $config['interfaces'][$if]['if'] == $interface)
4061
			return $if;
4062

    
4063
		if (get_real_interface($if) == $interface)
4064
			return $if;
4065

    
4066
		// XXX: This case doesn't work anymore (segfaults - recursion?) - should be replaced with something else or just removed.
4067
		//      Not to be replaced with get_real_interface - causes slow interface listings here because of recursion!
4068
		/*
4069
		$int = get_parent_interface($if);
4070
		if ($int[0] == $interface)
4071
			return $ifname;
4072
		*/
4073
	}
4074

    
4075
	return NULL;
4076
}
4077

    
4078
/* attempt to resolve interface to friendly descr */
4079
function convert_friendly_interface_to_friendly_descr($interface) {
4080
	global $config;
4081

    
4082
	switch ($interface) {
4083
	case "l2tp":
4084
		$ifdesc = "L2TP";
4085
		break;
4086
	case "pptp":
4087
		$ifdesc = "PPTP";
4088
		break;
4089
	case "pppoe":
4090
		$ifdesc = "PPPoE";
4091
		break;
4092
	case "openvpn":
4093
		$ifdesc = "OpenVPN";
4094
		break;
4095
	case "enc0":
4096
	case "ipsec":
4097
		$ifdesc = "IPsec";
4098
		break;
4099
	default:
4100
		if (isset($config['interfaces'][$interface])) {
4101
			if (empty($config['interfaces'][$interface]['descr']))
4102
				$ifdesc = strtoupper($interface);
4103
			else
4104
				$ifdesc = strtoupper($config['interfaces'][$interface]['descr']);
4105
			break;
4106
		} else if (stristr($interface, "_vip")) {
4107
			if (is_array($config['virtualip']['vip'])) {
4108
				foreach ($config['virtualip']['vip'] as $counter => $vip) {
4109
					if ($vip['mode'] == "carp")  {
4110
						if ($interface == "{$vip['interface']}_vip{$vip['vhid']}")
4111
							return "{$vip['subnet']} - {$vip['descr']}";
4112
					}
4113
				}
4114
			}
4115
		} else {
4116
			/* if list */
4117
			$ifdescrs = get_configured_interface_with_descr(false, true);
4118
			foreach ($ifdescrs as $if => $ifname) {
4119
				if ($if == $interface || $ifname == $interface)
4120
					return $ifname;
4121
			}
4122
		}
4123
		break;
4124
	}
4125

    
4126
	return $ifdesc;
4127
}
4128

    
4129
function convert_real_interface_to_friendly_descr($interface) {
4130
	global $config;
4131

    
4132
	$ifdesc = convert_real_interface_to_friendly_interface_name("{$interface}");
4133

    
4134
	if ($ifdesc) {
4135
		$iflist = get_configured_interface_with_descr(false, true);
4136
		return $iflist[$ifdesc];
4137
	}
4138

    
4139
	return $interface;
4140
}
4141

    
4142
/*
4143
 *  get_parent_interface($interface):
4144
 *			--returns the (real or virtual) parent interface(s) array for a given interface friendly name (i.e. wan)
4145
 *				or virtual interface (i.e. vlan)
4146
 *				(We need array because MLPPP and bridge interfaces have more than one parent.)
4147
 *			-- returns $interface passed in if $interface parent is not found
4148
 *			-- returns empty array if an invalid interface is passed
4149
 *	(Only handles ppps and vlans now.)
4150
 */
4151
function get_parent_interface($interface) {
4152
	global $config;
4153

    
4154
	$parents = array();
4155
	//Check that we got a valid interface passed
4156
	$realif = get_real_interface($interface);
4157
	if ($realif == NULL)
4158
		return $parents;
4159

    
4160
	// If we got a real interface, find it's friendly assigned name
4161
	if ($interface == $realif)
4162
		$interface = convert_real_interface_to_friendly_interface_name($interface);
4163

    
4164
	if (!empty($interface) && isset($config['interfaces'][$interface])) {
4165
		$ifcfg = $config['interfaces'][$interface];
4166
		switch ($ifcfg['ipaddr']) {
4167
			case "ppp":
4168
			case "pppoe":
4169
			case "pptp":
4170
			case "l2tp":
4171
				if (empty($parents))
4172
					if (is_array($config['ppps']['ppp']))
4173
						foreach ($config['ppps']['ppp'] as $pppidx => $ppp) {
4174
							if ($ifcfg['if'] == $ppp['if']) {
4175
								$ports = explode(',', $ppp['ports']);
4176
								foreach ($ports as $pid => $parent_if)
4177
									$parents[$pid] = get_real_interface($parent_if);
4178
								break;
4179
							}
4180
						}
4181
				break;
4182
			case "dhcp":
4183
			case "static":
4184
			default:
4185
				// Handle _vlans
4186
				if (stristr($realif,"_vlan"))
4187
					if (is_array($config['vlans']['vlan']))
4188
						foreach ($config['vlans']['vlan'] as $vlanidx => $vlan)
4189
							if ($ifcfg['if'] == $vlan['vlanif']){
4190
								$parents[0] = $vlan['if'];
4191
								break;
4192
							}
4193
				break;
4194
		}
4195
	}
4196

    
4197
	if (empty($parents))
4198
		$parents[0] = $realif;
4199

    
4200
	return $parents;
4201
}
4202

    
4203
function interface_is_wireless_clone($wlif) {
4204
	if(!stristr($wlif, "_wlan")) {
4205
		return false;
4206
	} else {
4207
		return true;
4208
	}
4209
}
4210

    
4211
function interface_get_wireless_base($wlif) {
4212
	if(!stristr($wlif, "_wlan")) {
4213
		return $wlif;
4214
	} else {
4215
		return substr($wlif, 0, stripos($wlif, "_wlan"));
4216
	}
4217
}
4218

    
4219
function interface_get_wireless_clone($wlif) {
4220
	if(!stristr($wlif, "_wlan")) {
4221
		return $wlif . "_wlan0";
4222
	} else {
4223
		return $wlif;
4224
	}
4225
}
4226

    
4227
function get_real_interface($interface = "wan", $family = "all", $realv6iface = false) {
4228
	global $config, $g;
4229

    
4230
	$wanif = NULL;
4231

    
4232
	switch ($interface) {
4233
	case "l2tp":
4234
		$wanif = "l2tp";
4235
		break;
4236
	case "pptp":
4237
		$wanif = "pptp";
4238
		break;
4239
	case "pppoe":
4240
		$wanif = "pppoe";
4241
		break;
4242
	case "openvpn":
4243
		$wanif = "openvpn";
4244
		break;
4245
	case "ipsec":
4246
	case "enc0":
4247
		$wanif = "enc0";
4248
		break;
4249
	case "ppp":
4250
		$wanif = "ppp";
4251
		break;
4252
	default:
4253
		// If a real interface was alread passed simply
4254
		// pass the real interface back.  This encourages
4255
		// the usage of this function in more cases so that
4256
		// we can combine logic for more flexibility.
4257
		if(does_interface_exist($interface)) {
4258
			$wanif = $interface;
4259
			break;
4260
		}
4261

    
4262
		if (empty($config['interfaces'][$interface]))
4263
			break;
4264

    
4265
		$cfg = &$config['interfaces'][$interface];
4266

    
4267
		if ($family == "inet6") {
4268
			switch ($cfg['ipaddrv6']) {
4269
			case "6rd":
4270
			case "6to4":
4271
				$wanif = "{$interface}_stf";
4272
				break;
4273
			case 'pppoe':
4274
			case 'ppp':
4275
			case 'l2tp':
4276
			case 'pptp':
4277
				if( is_array($cfg['wireless']) || preg_match($g['wireless_regex'], $cfg['if']))
4278
					$wanif = interface_get_wireless_clone($cfg['if']);
4279
				else
4280
					$wanif = $cfg['if'];
4281
				break;
4282
			default:
4283
				switch ($cfg['ipaddr']) {
4284
				case 'pppoe':
4285
				case 'ppp':
4286
				case 'l2tp':
4287
				case 'pptp':
4288
					if (isset($cfg['dhcp6usev4iface']) && $realv6iface === false)
4289
						$wanif = $cfg['if'];
4290
					else {
4291
						$parents = get_parent_interface($interface);
4292
						if (!empty($parents[0]))
4293
							$wanif = $parents[0];
4294
						else
4295
							$wanif = $cfg['if'];
4296
					}
4297
					break;
4298
				default:
4299
					if( is_array($cfg['wireless']) || preg_match($g['wireless_regex'], $cfg['if']))
4300
						$wanif = interface_get_wireless_clone($cfg['if']);
4301
					else
4302
						$wanif = $cfg['if'];
4303
					break;
4304
				}
4305
				break;
4306
			}
4307
		} else {
4308
			// Wireless cloned NIC support (FreeBSD 8+)
4309
			// interface name format: $parentnic_wlanparentnic#
4310
			// example: ath0_wlan0
4311
			if( is_array($cfg['wireless']) || preg_match($g['wireless_regex'], $cfg['if']))
4312
				$wanif = interface_get_wireless_clone($cfg['if']);
4313
			else
4314
				$wanif = $cfg['if'];
4315
		}
4316
		break;
4317
	}
4318

    
4319
	return $wanif;
4320
}
4321

    
4322
/* Guess the physical interface by providing a IP address */
4323
function guess_interface_from_ip($ipaddress) {
4324
	if(! is_ipaddr($ipaddress)) {
4325
		return false;
4326
	}
4327
	if(is_ipaddrv4($ipaddress)) {
4328
		/* create a route table we can search */
4329
		exec("netstat -rnWf inet", $output, $ret);
4330
		foreach($output as $line) {
4331
			if(preg_match("/^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\/[0-9]+[ ]+link[#]/", $line)) {
4332
				$fields = preg_split("/[ ]+/", $line);
4333
				if(ip_in_subnet($ipaddress, $fields[0])) {
4334
					return $fields[6];
4335
				}
4336
			}
4337
		}
4338
	}
4339
	/* FIXME: This works from cursory testing, regexp might need fine tuning */
4340
	if(is_ipaddrv6($ipaddress)) {
4341
		/* create a route table we can search */
4342
		exec("netstat -rnWf inet6", $output, $ret);
4343
		foreach($output as $line) {
4344
			if(preg_match("/[0-9a-f]+[:]+[0-9a-f]+[:]+[\/][0-9]+/", $line)) {
4345
				$fields = preg_split("/[ ]+/", $line);
4346
				if(ip_in_subnet($ipaddress, $fields[0])) {
4347
					return $fields[6];
4348
				}
4349
			}
4350
		}
4351
	}
4352
	$ret = exec_command("/sbin/route -n get {$ipaddress} | /usr/bin/awk '/interface/ { print \$2; };'");
4353
	if(empty($ret)) {
4354
		return false;
4355
	}
4356
	return $ret;
4357
}
4358

    
4359
/*
4360
 * find_ip_interface($ip): return the interface where an ip is defined
4361
 *   (or if $bits is specified, where an IP within the subnet is defined)
4362
 */
4363
function find_ip_interface($ip, $bits = null) {
4364
	if (!is_ipaddr($ip))
4365
		return false;
4366

    
4367
	$isv6ip = is_ipaddrv6($ip);
4368

    
4369
	/* if list */
4370
	$ifdescrs = get_configured_interface_list();
4371

    
4372
	foreach ($ifdescrs as $ifdescr => $ifname) {
4373
		$ifip = ($isv6ip) ? get_interface_ipv6($ifname) : get_interface_ip($ifname);
4374
		if (is_null($ifip))
4375
			continue;
4376
		if (is_null($bits)) {
4377
			if ($ip == $ifip) {
4378
				$int = get_real_interface($ifname);
4379
				return $int;
4380
			}
4381
		}
4382
		else {
4383
			if (ip_in_subnet($ifip, $ip . "/" . $bits)) {
4384
				$int = get_real_interface($ifname);
4385
				return $int;
4386
			}
4387
		}
4388
	}
4389

    
4390
	return false;
4391
}
4392

    
4393
/*
4394
 * find_virtual_ip_alias($ip): return the virtual IP alias where an IP is found
4395
 *   (or if $bits is specified, where an IP within the subnet is found)
4396
 */
4397
function find_virtual_ip_alias($ip, $bits = null) {
4398
	global $config;
4399

    
4400
	if (!is_array($config['virtualip']['vip'])) {
4401
		return false;
4402
	}
4403
	if (!is_ipaddr($ip))
4404
		return false;
4405

    
4406
	$isv6ip = is_ipaddrv6($ip);
4407

    
4408
	foreach ($config['virtualip']['vip'] as $vip) {
4409
		if ($vip['mode'] === "ipalias") {
4410
			if (is_ipaddrv6($vip['subnet']) != $isv6ip)
4411
				continue;
4412
			if (is_null($bits)) {
4413
				if (ip_in_subnet($ip, $vip['subnet'] . "/" . $vip['subnet_bits'])) {
4414
					return $vip;
4415
				}
4416
			}
4417
			else {
4418
				if (($isv6ip && check_subnetsv6_overlap($ip, $bits, $vip['subnet'], $vip['subnet_bits']))
4419
					|| (!$isv6ip && check_subnets_overlap($ip, $bits, $vip['subnet'], $vip['subnet_bits']))) {
4420
					return $vip;
4421
				}
4422
			}
4423
		}
4424
	}
4425
	return false;
4426
}
4427

    
4428
/*
4429
 *   find_number_of_created_carp_interfaces: return the number of carp interfaces
4430
 */
4431
function find_number_of_created_carp_interfaces() {
4432
	return `/sbin/ifconfig | grep "carp:" | wc -l`;
4433
}
4434

    
4435
function get_all_carp_interfaces() {
4436
	$ints = str_replace("\n", " ", `ifconfig | grep "carp:" -B2 | grep ": flag" | cut -d: -f1`);
4437
	$ints = explode(" ", $ints);
4438
	return $ints;
4439
}
4440

    
4441
/*
4442
 * find_carp_interface($ip): return the carp interface where an ip is defined
4443
 */
4444
function find_carp_interface($ip) {
4445
	global $config;
4446
	if (is_array($config['virtualip']['vip'])) {
4447
		foreach ($config['virtualip']['vip'] as $vip) {
4448
			if ($vip['mode'] == "carp") {
4449
				if(is_ipaddrv4($ip)) {
4450
					$carp_ip = get_interface_ip($vip['interface']);
4451
				}
4452
				if(is_ipaddrv6($ip)) {
4453
					$carp_ip = get_interface_ipv6($vip['interface']);
4454
				}
4455
				exec("/sbin/ifconfig", $output, $return);
4456
				foreach($output as $line) {
4457
					$elements = preg_split("/[ ]+/i", $line);
4458
					if(strstr($elements[0], "vip"))
4459
						$curif = str_replace(":", "", $elements[0]);
4460
					if(stristr($line, $ip)) {
4461
						$if = $curif;
4462
						continue;
4463
					}
4464
				}
4465

    
4466
				if ($if)
4467
					return $if;
4468
			}
4469
		}
4470
	}
4471
}
4472

    
4473
function link_carp_interface_to_parent($interface) {
4474
	global $config;
4475

    
4476
	if ($interface == "")
4477
		return;
4478

    
4479
	$carp_ip = get_interface_ip($interface);
4480
	$carp_ipv6 = get_interface_ipv6($interface);
4481

    
4482
	if((!is_ipaddrv4($carp_ip)) && (!is_ipaddrv6($carp_ipv6)))
4483
		return;
4484

    
4485
	/* if list */
4486
	$ifdescrs = get_configured_interface_list();
4487
	foreach ($ifdescrs as $ifdescr => $ifname) {
4488
		/* check IPv4 */
4489
		if(is_ipaddrv4($carp_ip)) {
4490
			$interfaceip = get_interface_ip($ifname);
4491
			$subnet_bits = get_interface_subnet($ifname);
4492
			$subnet_ip = gen_subnet("{$interfaceip}", "{$subnet_bits}");
4493
			if(ip_in_subnet($carp_ip, "{$subnet_ip}/{$subnet_bits}"))
4494
				return $ifname;
4495
		}
4496
		/* Check IPv6 */
4497
		if(is_ipaddrv6($carp_ipv6)) {
4498
			$interfaceipv6 = get_interface_ipv6($ifname);
4499
			$prefixlen = get_interface_subnetv6($ifname);
4500
			if(ip_in_subnet($carp_ipv6, "{$interfaceipv6}/{$prefixlen}"))
4501
				return $ifname;
4502
		}
4503
	}
4504
	return "";
4505
}
4506

    
4507

    
4508
/****f* interfaces/link_ip_to_carp_interface
4509
 * NAME
4510
 *   link_ip_to_carp_interface - Find where a CARP interface links to.
4511
 * INPUTS
4512
 *   $ip
4513
 * RESULT
4514
 *   $carp_ints
4515
 ******/
4516
function link_ip_to_carp_interface($ip) {
4517
	global $config;
4518

    
4519
	if (!is_ipaddr($ip))
4520
		return;
4521

    
4522
	$carp_ints = "";
4523
	if (is_array($config['virtualip']['vip'])) {
4524
		$first = 0;
4525
		$carp_int = array();
4526
		foreach ($config['virtualip']['vip'] as $vip) {
4527
			if ($vip['mode'] == "carp") {
4528
				$carp_ip = $vip['subnet'];
4529
				$carp_sn = $vip['subnet_bits'];
4530
				$carp_nw = gen_subnet($carp_ip, $carp_sn);
4531
				if (ip_in_subnet($ip, "{$carp_nw}/{$carp_sn}")) {
4532
					$carp_int[] = "{$vip['interface']}_vip{$vip['vhid']}";
4533
				}
4534
			}
4535
		}
4536
		if (!empty($carp_int))
4537
			$carp_ints = implode(" ", array_unique($carp_int));
4538
	}
4539

    
4540
	return $carp_ints;
4541
}
4542

    
4543
function link_interface_to_track6($int, $action = "") {
4544
	global $config;
4545

    
4546
	if (empty($int))
4547
		return;
4548

    
4549
	if (is_array($config['interfaces'])) {
4550
		$list = array();
4551
		foreach ($config['interfaces'] as $ifname => $ifcfg) {
4552
			if (!isset($ifcfg['enable']))
4553
				continue;
4554
			if (!empty($ifcfg['ipaddrv6']) && $ifcfg['track6-interface'] == $int) {
4555
				if ($action == "update")
4556
					interface_track6_configure($ifname, $ifcfg);
4557
				else if ($action == "")
4558
					$list[$ifname] = $ifcfg;
4559
			}
4560
		}
4561
		return $list;
4562
	}
4563
}
4564

    
4565
function link_interface_to_vlans($int, $action = "") {
4566
	global $config;
4567

    
4568
	if (empty($int))
4569
		return;
4570

    
4571
	if (is_array($config['vlans']['vlan'])) {
4572
		$ifaces = array();
4573
		foreach ($config['vlans']['vlan'] as $vlan) {
4574
			if ($int == $vlan['if']) {
4575
				if ($action == "update") {
4576
					interfaces_bring_up($int);
4577
				} else if ($action == "")
4578
					$ifaces[$vlan['tag']] = $vlan;
4579
			}
4580
		}
4581
		if (!empty($ifaces))
4582
			return $ifaces;
4583
	}
4584
}
4585

    
4586
function link_interface_to_vips($int, $action = "") {
4587
	global $config;
4588

    
4589
	if (is_array($config['virtualip']['vip'])) {
4590
		$result = array();
4591
		foreach ($config['virtualip']['vip'] as $vip) {
4592
			if ($int == $vip['interface']) {
4593
				if ($action == "update")
4594
					interfaces_vips_configure($int);
4595
				else
4596
					$result[] = $vip;
4597
			}
4598
		}
4599
		return $result;
4600
	}
4601
}
4602

    
4603
/****f* interfaces/link_interface_to_bridge
4604
 * NAME
4605
 *   link_interface_to_bridge - Finds out a bridge group for an interface
4606
 * INPUTS
4607
 *   $ip
4608
 * RESULT
4609
 *   bridge[0-99]
4610
 ******/
4611
function link_interface_to_bridge($int) {
4612
	global $config;
4613

    
4614
	if (is_array($config['bridges']['bridged'])) {
4615
		foreach ($config['bridges']['bridged'] as $bridge) {
4616
			if (in_array($int, explode(',', $bridge['members'])))
4617
				return "{$bridge['bridgeif']}";
4618
		}
4619
	}
4620
}
4621

    
4622
function link_interface_to_group($int) {
4623
	global $config;
4624

    
4625
	$result = array();
4626

    
4627
	if (is_array($config['ifgroups']['ifgroupentry'])) {
4628
		foreach ($config['ifgroups']['ifgroupentry'] as $group) {
4629
			if (in_array($int, explode(" ", $group['members'])))
4630
				$result[$group['ifname']] = $int;
4631
		}
4632
	}
4633

    
4634
	return $result;
4635
}
4636

    
4637
function link_interface_to_gre($interface) {
4638
	global $config;
4639

    
4640
	$result = array();
4641

    
4642
	if (is_array($config['gres']['gre'])) {
4643
		foreach ($config['gres']['gre'] as $gre)
4644
			if($gre['if'] == $interface)
4645
				$result[] = $gre;
4646
	}
4647

    
4648
	return $result;
4649
}
4650

    
4651
function link_interface_to_gif($interface) {
4652
	global $config;
4653

    
4654
	$result = array();
4655

    
4656
	if (is_array($config['gifs']['gif'])) {
4657
		foreach ($config['gifs']['gif'] as $gif)
4658
			if($gif['if'] == $interface)
4659
				$result[] = $gif;
4660
	}
4661

    
4662
	return $result;
4663
}
4664

    
4665
/*
4666
 * find_interface_ip($interface): return the interface ip (first found)
4667
 */
4668
function find_interface_ip($interface, $flush = false) {
4669
	global $interface_ip_arr_cache;
4670
	global $interface_sn_arr_cache;
4671

    
4672
	$interface = str_replace("\n", "", $interface);
4673

    
4674
	if (!does_interface_exist($interface))
4675
		return;
4676

    
4677
	/* Setup IP cache */
4678
	if (!isset($interface_ip_arr_cache[$interface]) or $flush) {
4679
		$ifinfo = pfSense_get_interface_addresses($interface);
4680
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
4681
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
4682
	}
4683

    
4684
	return $interface_ip_arr_cache[$interface];
4685
}
4686

    
4687
/*
4688
 * find_interface_ipv6($interface): return the interface ip (first found)
4689
 */
4690
function find_interface_ipv6($interface, $flush = false) {
4691
	global $interface_ipv6_arr_cache;
4692
	global $interface_snv6_arr_cache;
4693
	global $config;
4694

    
4695
	$interface = trim($interface);
4696
	$interface = get_real_interface($interface);
4697

    
4698
	if (!does_interface_exist($interface))
4699
		return;
4700

    
4701
	/* Setup IP cache */
4702
	if (!isset($interface_ipv6_arr_cache[$interface]) or $flush) {
4703
		$ifinfo = pfSense_get_interface_addresses($interface);
4704
		$interface_ipv6_arr_cache[$interface] = $ifinfo['ipaddr6'];
4705
		$interface_snv6_arr_cache[$interface] = $ifinfo['subnetbits6'];
4706
	}
4707

    
4708
	return $interface_ipv6_arr_cache[$interface];
4709
}
4710

    
4711
/*
4712
 * find_interface_ipv6_ll($interface): return the interface ipv6 link local (first found)
4713
 */
4714
function find_interface_ipv6_ll($interface, $flush = false) {
4715
	global $interface_llv6_arr_cache;
4716
	global $config;
4717

    
4718
	$interface = str_replace("\n", "", $interface);
4719

    
4720
	if (!does_interface_exist($interface))
4721
		return;
4722

    
4723
	/* Setup IP cache */
4724
	if (!isset($interface_llv6_arr_cache[$interface]) or $flush) {
4725
		$ifinfo = pfSense_getall_interface_addresses($interface);
4726
		foreach($ifinfo as $line) {
4727
			if (strstr($line, ":")) {
4728
				$parts = explode("/", $line);
4729
				if(is_linklocal($parts[0])) {
4730
					$ifinfo['linklocal'] = $parts[0];
4731
				}
4732
			}
4733
		}
4734
		$interface_llv6_arr_cache[$interface] = $ifinfo['linklocal'];
4735
	}
4736
	return $interface_llv6_arr_cache[$interface];
4737
}
4738

    
4739
function find_interface_subnet($interface, $flush = false) {
4740
	global $interface_sn_arr_cache;
4741
	global $interface_ip_arr_cache;
4742

    
4743
	$interface = str_replace("\n", "", $interface);
4744
	if (does_interface_exist($interface) == false)
4745
		return;
4746

    
4747
	if (!isset($interface_sn_arr_cache[$interface]) or $flush) {
4748
		$ifinfo = pfSense_get_interface_addresses($interface);
4749
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
4750
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
4751
	}
4752

    
4753
	return $interface_sn_arr_cache[$interface];
4754
}
4755

    
4756
function find_interface_subnetv6($interface, $flush = false) {
4757
	global $interface_snv6_arr_cache;
4758
	global $interface_ipv6_arr_cache;
4759

    
4760
	$interface = str_replace("\n", "", $interface);
4761
	if (does_interface_exist($interface) == false)
4762
		return;
4763

    
4764
	if (!isset($interface_snv6_arr_cache[$interface]) or $flush) {
4765
		$ifinfo = pfSense_get_interface_addresses($interface);
4766
		$interface_ipv6_arr_cache[$interface] = $ifinfo['ipaddr6'];
4767
		$interface_snv6_arr_cache[$interface] = $ifinfo['subnetbits6'];
4768
	}
4769

    
4770
	return $interface_snv6_arr_cache[$interface];
4771
}
4772

    
4773
function ip_in_interface_alias_subnet($interface, $ipalias) {
4774
	global $config;
4775

    
4776
	if (empty($interface) || !is_ipaddr($ipalias))
4777
		return false;
4778
	if (is_array($config['virtualip']['vip'])) {
4779
		foreach ($config['virtualip']['vip'] as $vip) {
4780
			switch ($vip['mode']) {
4781
			case "ipalias":
4782
				if ($vip['interface'] <> $interface)
4783
					break;
4784
				$subnet = is_ipaddrv6($ipalias) ? gen_subnetv6($vip['subnet'], $vip['subnet_bits']) : gen_subnet($vip['subnet'], $vip['subnet_bits']);
4785
				if (ip_in_subnet($ipalias, $subnet . "/" . $vip['subnet_bits']))
4786
					return true;
4787
				break;
4788
			}
4789
		}
4790
	}
4791

    
4792
	return false;
4793
}
4794

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

    
4806
	$curip = find_interface_ip($realif);
4807
	if ($curip && is_ipaddr($curip) && ($curip != "0.0.0.0"))
4808
		return $curip;
4809
	else
4810
		return null;
4811
}
4812

    
4813
function get_interface_ipv6($interface = "wan", $flush = false) {
4814
	global $config;
4815

    
4816
	$realif = get_failover_interface($interface, "inet6");
4817
	if (!$realif) {
4818
		if (preg_match("/^[a-z0-9]+_vip/i", $interface))
4819
			$realif = $interface;
4820
		else
4821
			return null;
4822
	}
4823

    
4824
	/*
4825
	 * NOTE: On the case when only the prefix is requested,
4826
	 * the communication on WAN will be done over link-local.
4827
	 */
4828
	if (is_array($config['interfaces'][$interface])) {
4829
		switch ($config['interfaces'][$interface]['ipaddr']) {
4830
		case 'pppoe':
4831
		case 'l2tp':
4832
		case 'pptp':
4833
		case 'ppp':
4834
			if ($config['interfaces'][$interface]['ipaddrv6'] == 'dhcp6')
4835
				$realif = get_real_interface($interface, "inet6", true);
4836
			break;
4837
		}
4838
		if (isset($config['interfaces'][$interface]['dhcp6prefixonly'])) {
4839
			$curip = find_interface_ipv6_ll($realif, $flush);
4840
			if ($curip && is_ipaddrv6($curip) && ($curip != "::"))
4841
				return $curip;
4842
		}
4843
	}
4844

    
4845
	$curip = find_interface_ipv6($realif, $flush);
4846
	if ($curip && is_ipaddrv6($curip) && ($curip != "::"))
4847
		return $curip;
4848
	else
4849
		return null;
4850
}
4851

    
4852
function get_interface_linklocal($interface = "wan") {
4853

    
4854
	$realif = get_failover_interface($interface, "inet6");
4855
	if (!$realif) {
4856
		if (preg_match("/^carp/i", $interface))
4857
			$realif = $interface;
4858
		else if (preg_match("/^[a-z0-9]+_vip/i", $interface))
4859
			$realif = $interface;
4860
		else
4861
			return null;
4862
	}
4863

    
4864
	$curip = find_interface_ipv6_ll($realif);
4865
	if ($curip && is_ipaddrv6($curip) && ($curip != "::"))
4866
		return $curip;
4867
	else
4868
		return null;
4869
}
4870

    
4871
function get_interface_subnet($interface = "wan") {
4872
	$realif = get_real_interface($interface);
4873
	if (!$realif) {
4874
		if (preg_match("/^carp/i", $interface))
4875
			$realif = $interface;
4876
		else if (preg_match("/^[a-z0-9]+_vip/i", $interface))
4877
			$realif = $interface;
4878
		else
4879
			return null;
4880
	}
4881

    
4882
	$cursn = find_interface_subnet($realif);
4883
	if (!empty($cursn))
4884
		return $cursn;
4885

    
4886
	return null;
4887
}
4888

    
4889
function get_interface_subnetv6($interface = "wan") {
4890
	global $config;
4891

    
4892
	$realif = get_real_interface($interface, "inet6");
4893
	if (!$realif) {
4894
		if (preg_match("/^[a-z0-9]+_vip/i", $interface))
4895
			$realif = $interface;
4896
		else
4897
			return null;
4898
	}
4899

    
4900
	$cursn = find_interface_subnetv6($realif);
4901
	if (!empty($cursn))
4902
		return $cursn;
4903

    
4904
	return null;
4905
}
4906

    
4907
/* return outside interfaces with a gateway */
4908
function get_interfaces_with_gateway() {
4909
	global $config;
4910

    
4911
	$ints = array();
4912

    
4913
	/* loop interfaces, check config for outbound */
4914
	foreach($config['interfaces'] as $ifdescr => $ifname) {
4915
		switch ($ifname['ipaddr']) {
4916
			case "dhcp":
4917
			case "ppp";
4918
			case "pppoe":
4919
			case "pptp":
4920
			case "l2tp":
4921
			case "ppp";
4922
				$ints[$ifdescr] = $ifdescr;
4923
			break;
4924
			default:
4925
				if (substr($ifname['if'], 0, 4) ==  "ovpn" ||
4926
				    !empty($ifname['gateway']))
4927
					$ints[$ifdescr] = $ifdescr;
4928
			break;
4929
		}
4930
	}
4931
	return $ints;
4932
}
4933

    
4934
/* return true if interface has a gateway */
4935
function interface_has_gateway($friendly) {
4936
	global $config;
4937

    
4938
	if (!empty($config['interfaces'][$friendly])) {
4939
		$ifname = &$config['interfaces'][$friendly];
4940
		switch ($ifname['ipaddr']) {
4941
			case "dhcp":
4942
			case "pppoe":
4943
			case "pptp":
4944
			case "l2tp":
4945
			case "ppp";
4946
				return true;
4947
			break;
4948
			default:
4949
				if (substr($ifname['if'], 0, 4) ==  "ovpn")
4950
					return true;
4951
				if (!empty($ifname['gateway']))
4952
					return true;
4953
			break;
4954
		}
4955
	}
4956

    
4957
	return false;
4958
}
4959

    
4960
/* return true if interface has a gateway */
4961
function interface_has_gatewayv6($friendly) {
4962
	global $config;
4963

    
4964
	if (!empty($config['interfaces'][$friendly])) {
4965
		$ifname = &$config['interfaces'][$friendly];
4966
		switch ($ifname['ipaddrv6']) {
4967
			case "slaac":
4968
			case "dhcp6":
4969
			case "6to4":
4970
			case "6rd":
4971
				return true;
4972
				break;
4973
			default:
4974
				if (substr($ifname['if'], 0, 4) ==  "ovpn")
4975
					return true;
4976
				if (!empty($ifname['gatewayv6']))
4977
					return true;
4978
				break;
4979
		}
4980
	}
4981

    
4982
	return false;
4983
}
4984

    
4985
/****f* interfaces/is_altq_capable
4986
 * NAME
4987
 *   is_altq_capable - Test if interface is capable of using ALTQ
4988
 * INPUTS
4989
 *   $int            - string containing interface name
4990
 * RESULT
4991
 *   boolean         - true or false
4992
 ******/
4993

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

    
5007
	$int_family = remove_ifindex($int);
5008

    
5009
	if (in_array($int_family, $capable))
5010
		return true;
5011
	else if (stristr($int, "l2tp")) /* VLANs are name $parent_$vlan now */
5012
		return true;
5013
	else if (stristr($int, "_vlan")) /* VLANs are name $parent_$vlan now */
5014
		return true;
5015
	else if (stristr($int, "_wlan")) /* WLANs are name $parent_$wlan now */
5016
		return true;
5017
	else
5018
		return false;
5019
}
5020

    
5021
/****f* interfaces/is_interface_wireless
5022
 * NAME
5023
 *   is_interface_wireless - Returns if an interface is wireless
5024
 * RESULT
5025
 *   $tmp       - Returns if an interface is wireless
5026
 ******/
5027
function is_interface_wireless($interface) {
5028
	global $config, $g;
5029

    
5030
	$friendly = convert_real_interface_to_friendly_interface_name($interface);
5031
	if(!isset($config['interfaces'][$friendly]['wireless'])) {
5032
		if (preg_match($g['wireless_regex'], $interface)) {
5033
			if (isset($config['interfaces'][$friendly]))
5034
				$config['interfaces'][$friendly]['wireless'] = array();
5035
			return true;
5036
		}
5037
		return false;
5038
	} else
5039
		return true;
5040
}
5041

    
5042
function get_wireless_modes($interface) {
5043
	/* return wireless modes and channels */
5044
	$wireless_modes = array();
5045

    
5046
	$cloned_interface = get_real_interface($interface);
5047

    
5048
	if($cloned_interface && is_interface_wireless($cloned_interface)) {
5049
		$chan_list = "/sbin/ifconfig {$cloned_interface} list chan";
5050
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
5051
		$format_list = "/usr/bin/awk '{print \$5 \" \" \$6 \",\" \$1}'";
5052

    
5053
		$interface_channels = "";
5054
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
5055
		$interface_channel_count = count($interface_channels);
5056

    
5057
		$c = 0;
5058
		while ($c < $interface_channel_count) {
5059
			$channel_line = explode(",", $interface_channels["$c"]);
5060
			$wireless_mode = trim($channel_line[0]);
5061
			$wireless_channel = trim($channel_line[1]);
5062
			if(trim($wireless_mode) != "") {
5063
				/* if we only have 11g also set 11b channels */
5064
				if($wireless_mode == "11g") {
5065
					if(!isset($wireless_modes["11b"]))
5066
						$wireless_modes["11b"] = array();
5067
				} else if($wireless_mode == "11g ht") {
5068
					if(!isset($wireless_modes["11b"]))
5069
						$wireless_modes["11b"] = array();
5070
					if(!isset($wireless_modes["11g"]))
5071
						$wireless_modes["11g"] = array();
5072
					$wireless_mode = "11ng";
5073
				} else if($wireless_mode == "11a ht") {
5074
					if(!isset($wireless_modes["11a"]))
5075
						$wireless_modes["11a"] = array();
5076
					$wireless_mode = "11na";
5077
				}
5078
				$wireless_modes["$wireless_mode"]["$c"] = $wireless_channel;
5079
			}
5080
			$c++;
5081
		}
5082
	}
5083
	return($wireless_modes);
5084
}
5085

    
5086
/* return channel numbers, frequency, max txpower, and max regulation txpower */
5087
function get_wireless_channel_info($interface) {
5088
	$wireless_channels = array();
5089

    
5090
	$cloned_interface = get_real_interface($interface);
5091

    
5092
	if($cloned_interface && is_interface_wireless($cloned_interface)) {
5093
		$chan_list = "/sbin/ifconfig {$cloned_interface} list txpower";
5094
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
5095
		$format_list = "/usr/bin/awk '{print \$1 \",\" \$3 \" \" \$4 \",\" \$5 \",\" \$7}'";
5096

    
5097
		$interface_channels = "";
5098
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
5099

    
5100
		foreach ($interface_channels as $channel_line) {
5101
			$channel_line = explode(",", $channel_line);
5102
			if(!isset($wireless_channels[$channel_line[0]]))
5103
				$wireless_channels[$channel_line[0]] = $channel_line;
5104
		}
5105
	}
5106
	return($wireless_channels);
5107
}
5108

    
5109
/****f* interfaces/get_interface_mtu
5110
 * NAME
5111
 *   get_interface_mtu - Return the mtu of an interface
5112
 * RESULT
5113
 *   $tmp       - Returns the mtu of an interface
5114
 ******/
5115
function get_interface_mtu($interface) {
5116
	$mtu = pfSense_get_interface_addresses($interface);
5117
	return $mtu['mtu'];
5118
}
5119

    
5120
function get_interface_mac($interface) {
5121

    
5122
	$macinfo = pfSense_get_interface_addresses($interface);
5123
	return $macinfo["macaddr"];
5124
}
5125

    
5126
/****f* pfsense-utils/generate_random_mac_address
5127
 * NAME
5128
 *   generate_random_mac - generates a random mac address
5129
 * INPUTS
5130
 *   none
5131
 * RESULT
5132
 *   $mac - a random mac address
5133
 ******/
5134
function generate_random_mac_address() {
5135
	$mac = "02";
5136
	for($x=0; $x<5; $x++)
5137
		$mac .= ":" . dechex(rand(16, 255));
5138
	return $mac;
5139
}
5140

    
5141
/****f* interfaces/is_jumbo_capable
5142
 * NAME
5143
 *   is_jumbo_capable - Test if interface is jumbo frame capable.  Useful for determining VLAN capability.
5144
 * INPUTS
5145
 *   $int             - string containing interface name
5146
 * RESULT
5147
 *   boolean          - true or false
5148
 ******/
5149
function is_jumbo_capable($iface) {
5150
	$iface = trim($iface);
5151
	$capable = pfSense_get_interface_addresses($iface);
5152

    
5153
	if (isset($capable['caps']['vlanmtu']))
5154
		return true;
5155

    
5156
	return false;
5157
}
5158

    
5159
function interface_setup_pppoe_reset_file($pppif, $iface="") {
5160
	global $g;
5161

    
5162
	$cron_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
5163

    
5164
	if(!empty($iface) && !empty($pppif)){
5165
		$cron_cmd = <<<EOD
5166
#!/bin/sh
5167
/usr/local/sbin/pfSctl -c 'interface reload {$iface}'
5168
/usr/bin/logger -t {$pppif} "PPPoE periodic reset executed on {$iface}"
5169

    
5170
EOD;
5171

    
5172
		@file_put_contents($cron_file, $cron_cmd);
5173
		chmod($cron_file, 0755);
5174
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
5175
	} else
5176
		unlink_if_exists($cron_file);
5177
}
5178

    
5179
function get_interface_default_mtu($type = "ethernet") {
5180
	switch ($type) {
5181
	case "gre":
5182
		return 1476;
5183
		break;
5184
	case "gif":
5185
		return 1280;
5186
		break;
5187
	case "tun":
5188
	case "vlan":
5189
	case "tap":
5190
	case "ethernet":
5191
	default:
5192
		return 1500;
5193
		break;
5194
	}
5195

    
5196
	/* Never reached */
5197
	return 1500;
5198
}
5199

    
5200
function get_vip_descr($ipaddress) {
5201
	global $config;
5202

    
5203
	foreach ($config['virtualip']['vip'] as $vip) {
5204
		if ($vip['subnet'] == $ipaddress) {
5205
			return ($vip['descr']);
5206
		}
5207
	}
5208
	return "";
5209
}
5210

    
5211
function interfaces_staticarp_configure($if) {
5212
	global $config, $g;
5213
	if(isset($config['system']['developerspew'])) {
5214
		$mt = microtime();
5215
		echo "interfaces_staticarp_configure($if) being called $mt\n";
5216
	}
5217

    
5218
	$ifcfg = $config['interfaces'][$if];
5219

    
5220
	if (empty($if) || empty($ifcfg['if']) || !isset($ifcfg['enable']))
5221
		return 0;
5222

    
5223
	/* Enable staticarp, if enabled */
5224
	if(isset($config['dhcpd'][$if]['staticarp'])) {
5225
		mwexec("/sbin/ifconfig " . escapeshellarg($ifcfg['if']) . " staticarp " );
5226
		mwexec("/usr/sbin/arp -d -i " . escapeshellarg($ifcfg['if']) . " -a > /dev/null 2>&1 ");
5227
		if (is_array($config['dhcpd'][$if]['staticmap'])) {
5228

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

    
5232
			}
5233

    
5234
		}
5235
	} else {
5236
		mwexec("/sbin/ifconfig " . escapeshellarg($ifcfg['if']) . " -staticarp " );
5237
		mwexec("/usr/sbin/arp -d -i " . escapeshellarg($ifcfg['if']) . " -a > /dev/null 2>&1 ");
5238
		if (is_array($config['dhcpd'][$if]) && is_array($config['dhcpd'][$if]['staticmap'])) {
5239
			foreach ($config['dhcpd'][$if]['staticmap'] as $arpent) {
5240
				if (isset($arpent['arp_table_static_entry'])) {
5241
					mwexec("/usr/sbin/arp -s " . escapeshellarg($arpent['ipaddr']) . " " . escapeshellarg($arpent['mac']));
5242
				}
5243
			}
5244
		}
5245
	}
5246

    
5247
	return 0;
5248
}
5249

    
5250
function get_failover_interface($interface, $family = "all") {
5251
	global $config;
5252

    
5253
	/* shortcut to get_real_interface if we find it in the config */
5254
	if (is_array($config['interfaces'][$interface])) {
5255
		return get_real_interface($interface, $family);
5256
	}
5257

    
5258
	/* compare against gateway groups */
5259
	$a_groups = return_gateway_groups_array();
5260
	if (is_array($a_groups[$interface])) {
5261
		/* we found a gateway group, fetch the interface or vip */
5262
		if ($a_groups[$interface][0]['vip'] <> "")
5263
			return $a_groups[$interface][0]['vip'];
5264
		else
5265
			return $a_groups[$interface][0]['int'];
5266
	}
5267
	/* fall through to get_real_interface */
5268
	/* XXX: Really needed? */
5269
	return get_real_interface($interface, $family);
5270
}
5271

    
5272
function remove_ifindex($ifname) {
5273
	return preg_replace("/[0-9]+$/", "", $ifname);
5274
}
5275

    
5276
?>
(25-25/66)