Project

General

Profile

Download (158 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, $flush = true) {
76
	global $config;
77

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

    
81
	$ints = get_interface_arr($flush);
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
	case "ipalias":
102
		/* XXX: Make proper checks? */
103
		$realif = get_real_interface($vip['interface']);
104
		if (!does_interface_exist($realif)) {
105
			return false;
106
		}
107
		break;
108
	case "proxyarp":
109
		/* XXX: Implement this */
110
	default:
111
		return false;
112
	}
113

    
114
	$ifacedata = pfSense_getall_interface_addresses($realif);
115
	foreach ($ifacedata as $vipips) {
116
		if ($vipips == "{$vip['subnet']}/{$vip['subnet_bits']}")
117
			return true;
118
	}
119

    
120
	return false;
121
}
122

    
123
function interface_netgraph_needed($interface = "wan") {
124
	global $config;
125

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

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

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

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

    
202
function interfaces_loopback_configure() {
203
	global $g;
204

    
205
	if ($g['platform'] == 'jail')
206
		return;
207
	if (platform_booting())
208
		echo gettext("Configuring loopback interface...");
209
	pfSense_interface_setaddress("lo0", "127.0.0.1");
210
	interfaces_bring_up("lo0");
211
	if (platform_booting())
212
		echo gettext("done.") . "\n";
213
	return 0;
214
}
215

    
216
function interfaces_vlan_configure($realif = "") {
217
	global $config, $g;
218
	if (platform_booting())
219
		echo gettext("Configuring VLAN interfaces...");
220
	if (is_array($config['vlans']['vlan']) && count($config['vlans']['vlan'])) {
221
		foreach ($config['vlans']['vlan'] as $vlan) {
222
			if (empty($vlan['vlanif']))
223
				$vlan['vlanif'] = "{$vlan['if']}_vlan{$vlan['tag']}";
224
			if (!empty($realif) && $realif != $vlan['vlanif'])
225
				continue;
226

    
227
			/* XXX: Maybe we should report any errors?! */
228
			interface_vlan_configure($vlan);
229
		}
230
	}
231
	if (platform_booting())
232
		echo gettext("done.") . "\n";
233
}
234

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

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

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

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

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

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

    
266
	interfaces_bring_up($vlanif);
267

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

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

    
274
	return $vlanif;
275
}
276

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

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

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

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

    
297
	$vlanif = interface_vlan_configure($vlan);
298

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

    
307
	pfSense_ngctl_attach(".", $qinqif);
308
	if (!empty($vlanif) && does_interface_exist($vlanif)) {
309
		fwrite($fd, "shutdown {$qinqif}qinq:\n");
310
		exec("/usr/sbin/ngctl msg {$qinqif}qinq: gettable", $result);
311
		if (empty($result)) {
312
			fwrite($fd, "mkpeer {$qinqif}: vlan lower downstream\n");
313
			fwrite($fd, "name {$qinqif}:lower {$vlanif}qinq\n");
314
			fwrite($fd, "connect {$qinqif}: {$vlanif}qinq: upper nomatch\n");
315
		}
316
	} else {
317
		fwrite($fd, "mkpeer {$qinqif}: vlan lower downstream\n");
318
		fwrite($fd, "name {$qinqif}:lower {$vlanif}qinq\n");
319
		fwrite($fd, "connect {$qinqif}: {$vlanif}qinq: upper nomatch\n");
320
	}
321

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

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

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

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

    
350
	return $vlanif;
351
}
352

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

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

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

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

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

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

    
393
	return $vlanif;
394
}
395

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

    
399
	if (platform_booting())
400
		echo gettext("Creating wireless clone interfaces...");
401

    
402
	$iflist = get_configured_interface_list();
403

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

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

    
423
}
424

    
425
function interfaces_bridge_configure($checkmember = 0, $realif = "") {
426
	global $config;
427

    
428
	$i = 0;
429
	if (is_array($config['bridges']['bridged']) && count($config['bridges']['bridged'])) {
430
		foreach ($config['bridges']['bridged'] as $bridge) {
431
			if (empty($bridge['bridgeif']))
432
				$bridge['bridgeif'] = "bridge{$i}";
433
			if (!empty($realif) && $realif != $bridge['bridgeif'])
434
				continue;
435

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

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

    
464
	if (!is_array($bridge))
465
		return;
466

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

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

    
476
	/* Calculate smaller mtu and enforce it */
477
	$smallermtu = 0;
478
	$commonrx = true;
479
	$commontx = true;
480
	$foundgif = false;
481
	foreach ($members as $member) {
482
		$realif = get_real_interface($member);
483
		$mtu = get_interface_mtu($realif);
484
		if (substr($realif, 0, 3) == "gif") {
485
			$foundgif = true;
486
			if ($checkmember == 1)
487
				return;
488
			if ($mtu <= 1500)
489
				continue;
490
		}
491
		if ($smallermtu == 0 && !empty($mtu))
492
			$smallermtu = $mtu;
493
		else if (!empty($mtu) && $mtu < $smallermtu)
494
			$smallermtu = $mtu;
495
	}
496
	if ($foundgif == false && $checkmember == 2)
497
		return;
498

    
499
	/* Just in case anything is not working well */
500
	if ($smallermtu == 0)
501
		$smallermtu = 1500;
502

    
503
	if (platform_booting() || !empty($bridge['bridgeif'])) {
504
		pfSense_interface_destroy($bridge['bridgeif']);
505
		pfSense_interface_create($bridge['bridgeif']);
506
		$bridgeif = escapeshellarg($bridge['bridgeif']);
507
	} else {
508
		$bridgeif = pfSense_interface_create("bridge");
509
		$bridge['bridgeif'] = $bridgeif;
510
	}
511

    
512
	$bridgemtu = interface_find_child_cfgmtu($bridge['bridgeif']);
513
	if ($bridgemtu > $smallermtu)
514
		$smallermtu = $bridgemtu;
515

    
516
	$checklist = get_configured_interface_list();
517

    
518
	/* Add interfaces to bridge */
519
	foreach ($members as $member) {
520
		if (empty($checklist[$member]))
521
			continue;
522
		$realif = get_real_interface($member);
523
		if (!$realif) {
524
			log_error(gettext("realif not defined in interfaces bridge - up"));
525
			continue;
526
		}
527
		/* make sure the parent interface is up */
528
		pfSense_interface_mtu($realif, $smallermtu);
529
		interfaces_bring_up($realif);
530
		enable_hardware_offloading($member);
531
		pfSense_bridge_add_member($bridge['bridgeif'], $realif);
532
	}
533

    
534
	if (isset($bridge['enablestp'])) {
535
		/* Choose spanning tree proto */
536
		mwexec("/sbin/ifconfig {$bridgeif} proto " . escapeshellarg($bridge['proto']));
537

    
538
		if (!empty($bridge['stp'])) {
539
			$stpifs = explode(',', $bridge['stp']);
540
			foreach ($stpifs as $stpif) {
541
				$realif = get_real_interface($stpif);
542
				mwexec("/sbin/ifconfig {$bridgeif} stp {$realif}");
543
			}
544
		}
545
		if (!empty($bridge['maxage']))
546
			mwexec("/sbin/ifconfig {$bridgeif} maxage " . escapeshellarg($bridge['maxage']));
547
		if (!empty($bridge['fwdelay']))
548
			mwexec("/sbin/ifconfig {$bridgeif} fwddelay " . escapeshellarg($bridge['fwdelay']));
549
		if (!empty($bridge['hellotime']))
550
			mwexec("/sbin/ifconfig {$bridgeif} hellotime " . escapeshellarg($bridge['hellotime']));
551
		if (!empty($bridge['priority']))
552
			mwexec("/sbin/ifconfig {$bridgeif} priority " . escapeshellarg($bridge['priority']));
553
		if (!empty($bridge['holdcnt']))
554
			mwexec("/sbin/ifconfig {$bridgeif} holdcnt " . escapeshellarg($bridge['holdcnt']));
555
		if (!empty($bridge['ifpriority'])) {
556
			$pconfig = explode(",", $bridge['ifpriority']);
557
			$ifpriority = array();
558
			foreach ($pconfig as $cfg) {
559
				$embcfg = explode_assoc(":", $cfg);
560
				foreach ($embcfg as $key => $value)
561
					$ifpriority[$key] = $value;
562
			}
563
			foreach ($ifpriority as $key => $value) {
564
				$realif = get_real_interface($key);
565
				mwexec("/sbin/ifconfig ${bridgeif} ifpriority {$realif} " . escapeshellarg($value));
566
			}
567
		}
568
		if (!empty($bridge['ifpathcost'])) {
569
			$pconfig = explode(",", $bridge['ifpathcost']);
570
			$ifpathcost = array();
571
			foreach ($pconfig as $cfg) {
572
				$embcfg = explode_assoc(":", $cfg);
573
				foreach ($embcfg as $key => $value)
574
					$ifpathcost[$key] = $value;
575
			}
576
			foreach ($ifpathcost as $key => $value) {
577
				$realif = get_real_interface($key);
578
				mwexec("/sbin/ifconfig ${bridgeif} ifpathcost {$realif} " . escapeshellarg($value));
579
			}
580
		}
581
	}
582

    
583
	if ($bridge['maxaddr'] <> "")
584
		mwexec("/sbin/ifconfig {$bridgeif} maxaddr " . escapeshellarg($bridge['maxaddr']));
585
	if ($bridge['timeout'] <> "")
586
		mwexec("/sbin/ifconfig {$bridgeif} timeout " . escapeshellarg($bridge['timeout']));
587
	if ($bridge['span'] <> "") {
588
		$realif = get_real_interface($bridge['span']);
589
		mwexec("/sbin/ifconfig {$bridgeif} span {$realif}");
590
	}
591
	if (!empty($bridge['edge'])) {
592
		$edgeifs = explode(',', $bridge['edge']);
593
		foreach ($edgeifs as $edgeif) {
594
			$realif = get_real_interface($edgeif);
595
			mwexec("/sbin/ifconfig {$bridgeif} edge {$realif}");
596
		}
597
	}
598
	if (!empty($bridge['autoedge'])) {
599
		$edgeifs = explode(',', $bridge['autoedge']);
600
		foreach ($edgeifs as $edgeif) {
601
			$realif = get_real_interface($edgeif);
602
			mwexec("/sbin/ifconfig {$bridgeif} -autoedge {$realif}");
603
		}
604
	}
605
	if (!empty($bridge['ptp'])) {
606
		$ptpifs = explode(',', $bridge['ptp']);
607
		foreach ($ptpifs as $ptpif) {
608
			$realif = get_real_interface($ptpif);
609
			mwexec("/sbin/ifconfig {$bridgeif} ptp {$realif}");
610
		}
611
	}
612
	if (!empty($bridge['autoptp'])) {
613
		$ptpifs = explode(',', $bridge['autoptp']);
614
		foreach ($ptpifs as $ptpif) {
615
			$realif = get_real_interface($ptpif);
616
			mwexec("/sbin/ifconfig {$bridgeif} -autoptp {$realif}");
617
		}
618
	}
619
	if (!empty($bridge['static'])) {
620
		$stickyifs = explode(',', $bridge['static']);
621
		foreach ($stickyifs as $stickyif) {
622
			$realif = get_real_interface($stickyif);
623
			mwexec("/sbin/ifconfig {$bridgeif} sticky {$realif}");
624
		}
625
	}
626
	if (!empty($bridge['private'])) {
627
		$privateifs = explode(',', $bridge['private']);
628
		foreach ($privateifs as $privateif) {
629
			$realif = get_real_interface($privateif);
630
			mwexec("/sbin/ifconfig {$bridgeif} private {$realif}");
631
		}
632
	}
633

    
634
	if ($bridge['bridgeif'])
635
		interfaces_bring_up($bridge['bridgeif']);
636
	else
637
		log_error(gettext("bridgeif not defined -- could not bring interface up"));
638
}
639

    
640
function interface_bridge_add_member($bridgeif, $interface, $flagsapplied = false) {
641

    
642
	if (!does_interface_exist($bridgeif) || !does_interface_exist($interface))
643
		return;
644

    
645
	if ($flagsapplied == false) {
646
		$mtu = get_interface_mtu($bridgeif);
647
		$mtum = get_interface_mtu($interface);
648
		if ($mtu != $mtum && !(substr($interface, 0, 3) == "gif" && $mtu <= 1500))
649
			pfSense_interface_mtu($interface, $mtu);
650

    
651
		hardware_offloading_applyflags($interface);
652
		interfaces_bring_up($interface);
653
	}
654

    
655
	pfSense_bridge_add_member($bridgeif, $interface);
656
}
657

    
658
function interfaces_lagg_configure($realif = "") {
659
	global $config, $g;
660
	if (platform_booting())
661
		echo gettext("Configuring LAGG interfaces...");
662
	$i = 0;
663
	if (is_array($config['laggs']['lagg']) && count($config['laggs']['lagg'])) {
664
		foreach ($config['laggs']['lagg'] as $lagg) {
665
			if(empty($lagg['laggif']))
666
				$lagg['laggif'] = "lagg{$i}";
667
			if (!empty($realif) && $realif != $lagg['laggif'])
668
				continue;
669
			/* XXX: Maybe we should report any errors?! */
670
			interface_lagg_configure($lagg);
671
			$i++;
672
		}
673
	}
674
	if (platform_booting())
675
		echo gettext("done.") . "\n";
676
}
677

    
678
function interface_lagg_configure($lagg) {
679
	global $config, $g;
680

    
681
	if (!is_array($lagg))
682
		return -1;
683

    
684
	$members = explode(',', $lagg['members']);
685
	if (!count($members))
686
		return -1;
687

    
688
	if (platform_booting() || !(empty($lagg['laggif']))) {
689
		pfSense_interface_destroy($lagg['laggif']);
690
		pfSense_interface_create($lagg['laggif']);
691
		$laggif = $lagg['laggif'];
692
	} else
693
		$laggif = pfSense_interface_create("lagg");
694

    
695
	/* Check if MTU was defined for this lagg interface */
696
	$lagg_mtu = interface_find_child_cfgmtu($laggif);
697
	if ($lagg_mtu == 0) {
698
		/* Calculate smaller mtu and enforce it */
699
		$smallermtu = 0;
700
		foreach ($members as $member) {
701
			$mtu = get_interface_mtu($member);
702
			if ($smallermtu == 0 && !empty($mtu))
703
				$smallermtu = $mtu;
704
			else if (!empty($mtu) && $mtu < $smallermtu)
705
				$smallermtu = $mtu;
706
		}
707
		$lagg_mtu = $smallermtu;
708
	}
709

    
710
	/* Just in case anything is not working well */
711
	if ($lagg_mtu == 0)
712
		$lagg_mtu = 1500;
713

    
714
	foreach ($members as $member) {
715
		if (!does_interface_exist($member))
716
			continue;
717
		/* make sure the parent interface is up */
718
		pfSense_interface_mtu($member, $lagg_mtu);
719
		interfaces_bring_up($member);
720
		hardware_offloading_applyflags($member);
721
		mwexec("/sbin/ifconfig " . escapeshellarg($laggif) . " laggport " . escapeshellarg($member));
722
	}
723
	pfSense_interface_capabilities($laggif, -$flags_off);
724
	pfSense_interface_capabilities($laggif, $flags_on);
725

    
726
	mwexec("/sbin/ifconfig {$laggif} laggproto " . escapeshellarg($lagg['proto']));
727

    
728
	interfaces_bring_up($laggif);
729

    
730
	return $laggif;
731
}
732

    
733
function interfaces_gre_configure($checkparent = 0, $realif = "") {
734
	global $config;
735

    
736
	if (is_array($config['gres']['gre']) && count($config['gres']['gre'])) {
737
		foreach ($config['gres']['gre'] as $i => $gre) {
738
			if (empty($gre['greif']))
739
				$gre['greif'] = "gre{$i}";
740
			if (!empty($realif) && $realif != $gre['greif'])
741
				continue;
742

    
743
			if ($checkparent == 1) {
744
				if (strstr($gre['if'], "_vip"))
745
					continue;
746
				if (!empty($config['interfaces'][$gre['if']]) && $config['interfaces'][$gre['if']]['ipaddrv6'] == "track6")
747
					continue;
748
			}
749
			else if ($checkparent == 2) {
750
				if (strstr($gre['if'], "_vip"))
751
					continue;
752
				if (empty($config['interfaces'][$gre['if']]) || $config['interfaces'][$gre['if']]['ipaddrv6'] != "track6")
753
					continue;
754
			}
755
			/* XXX: Maybe we should report any errors?! */
756
			interface_gre_configure($gre);
757
		}
758
	}
759
}
760

    
761
/* NOTE: $grekey is not used but useful for passing this function to array_walk. */
762
function interface_gre_configure(&$gre, $grekey = "") {
763
	global $config, $g;
764

    
765
	if (!is_array($gre))
766
		return -1;
767

    
768
	$realif = get_real_interface($gre['if']);
769
	$realifip = get_interface_ip($gre['if']);
770

    
771
	/* make sure the parent interface is up */
772
	interfaces_bring_up($realif);
773

    
774
	if (platform_booting() || !(empty($gre['greif']))) {
775
		pfSense_interface_destroy($gre['greif']);
776
		pfSense_interface_create($gre['greif']);
777
		$greif = $gre['greif'];
778
	} else
779
		$greif = pfSense_interface_create("gre");
780

    
781
	/* Do not change the order here for more see gre(4) NOTES section. */
782
	mwexec("/sbin/ifconfig {$greif} tunnel {$realifip} " . escapeshellarg($gre['remote-addr']));
783
	if((is_ipaddrv6($gre['tunnel-local-addr'])) || (is_ipaddrv6($gre['tunnel-remote-addr']))) {
784
		/* XXX: The prefixlen argument for tunnels of ipv6 is useless since it needs to be 128 as enforced by kernel */
785
		//mwexec("/sbin/ifconfig {$greif} inet6 " . escapeshellarg($gre['tunnel-local-addr']) . " " . escapeshellarg($gre['tunnel-remote-addr']) . " prefixlen /" . escapeshellarg($gre['tunnel-remote-net']));
786
		mwexec("/sbin/ifconfig {$greif} inet6 " . escapeshellarg($gre['tunnel-local-addr']) . " " . escapeshellarg($gre['tunnel-remote-addr']) . " prefixlen 128");
787
	} else {
788
		mwexec("/sbin/ifconfig {$greif} " . escapeshellarg($gre['tunnel-local-addr']) . " " . escapeshellarg($gre['tunnel-remote-addr']) . " netmask " . gen_subnet_mask($gre['tunnel-remote-net']));
789
	}
790
	if (isset($gre['link0']))
791
		pfSense_interface_flags($greif, IFF_LINK0);
792
	if (isset($gre['link1']))
793
		pfSense_interface_flags($greif, IFF_LINK1);
794
	if (isset($gre['link2']))
795
		pfSense_interface_flags($greif, IFF_LINK2);
796

    
797
	if($greif)
798
		interfaces_bring_up($greif);
799
	else
800
		log_error(gettext("Could not bring greif up -- variable not defined."));
801

    
802
	if (isset($gre['link1']) && $gre['link1'])
803
		mwexec("/sbin/route add " . escapeshellarg($gre['tunnel-remote-addr']) . "/" . escapeshellarg($gre['tunnel-remote-net']) . " " . escapeshellarg($gre['tunnel-local-addr']));
804
	if(is_ipaddrv4($gre['tunnel-remote-addr']))
805
		file_put_contents("{$g['tmp_path']}/{$greif}_router", $gre['tunnel-remote-addr']);
806
	if(is_ipaddrv6($gre['tunnel-remote-addr']))
807
		file_put_contents("{$g['tmp_path']}/{$greif}_routerv6", $gre['tunnel-remote-addr']);
808

    
809
	interfaces_bring_up($greif);
810

    
811
	return $greif;
812
}
813

    
814
function interfaces_gif_configure($checkparent = 0, $realif = "") {
815
	global $config;
816

    
817
	if (is_array($config['gifs']['gif']) && count($config['gifs']['gif'])) {
818
		foreach ($config['gifs']['gif'] as $i => $gif) {
819
			if (empty($gif['gifif']))
820
				$gre['gifif'] = "gif{$i}";
821
			if (!empty($realif) && $realif != $gif['gifif'])
822
				continue;
823

    
824
			if ($checkparent == 1) {
825
				if (strstr($gif['if'], "_vip"))
826
					continue;
827
				if (!empty($config['interfaces'][$gif['if']]) && $config['interfaces'][$gif['if']]['ipaddrv6'] == "track6")
828
					continue;
829
			}
830
			else if ($checkparent == 2) {
831
				if (strstr($gif['if'], "_vip"))
832
					continue;
833
				if (empty($config['interfaces'][$gif['if']]) || $config['interfaces'][$gif['if']]['ipaddrv6'] != "track6")
834
					continue;
835
			}
836
			/* XXX: Maybe we should report any errors?! */
837
			interface_gif_configure($gif);
838
		}
839
	}
840
}
841

    
842
/* NOTE: $gifkey is not used but useful for passing this function to array_walk. */
843
function interface_gif_configure(&$gif, $gifkey = "") {
844
	global $config, $g;
845

    
846
	if (!is_array($gif))
847
		return -1;
848

    
849
	$realif = get_real_interface($gif['if']);
850
	$ipaddr = $gif['ipaddr'];
851

    
852
	if (is_ipaddrv4($gif['remote-addr'])) {
853
		if (is_ipaddrv4($ipaddr))
854
			$realifip = $ipaddr;
855
		else
856
			$realifip = get_interface_ip($gif['if']);
857
		$realifgw = get_interface_gateway($gif['if']);
858
	} else if (is_ipaddrv6($gif['remote-addr'])) {
859
		if (is_ipaddrv6($ipaddr))
860
			$realifip = $ipaddr;
861
		else
862
			$realifip = get_interface_ipv6($gif['if']);
863
		$realifgw = get_interface_gateway_v6($gif['if']);
864
	}
865
	/* make sure the parent interface is up */
866
	if($realif)
867
		interfaces_bring_up($realif);
868
	else
869
		log_error(gettext("could not bring realif up -- variable not defined -- interface_gif_configure()"));
870

    
871
	if (platform_booting() || !(empty($gif['gifif']))) {
872
		pfSense_interface_destroy($gif['gifif']);
873
		pfSense_interface_create($gif['gifif']);
874
		$gifif = $gif['gifif'];
875
	} else
876
		$gifif = pfSense_interface_create("gif");
877

    
878
	/* Do not change the order here for more see gif(4) NOTES section. */
879
	mwexec("/sbin/ifconfig {$gifif} tunnel {$realifip} " . escapeshellarg($gif['remote-addr']));
880
	if((is_ipaddrv6($gif['tunnel-local-addr'])) || (is_ipaddrv6($gif['tunnel-remote-addr']))) {
881
		/* XXX: The prefixlen argument for tunnels of ipv6 is useless since it needs to be 128 as enforced by kernel */
882
		//mwexec("/sbin/ifconfig {$gifif} inet6 " . escapeshellarg($gif['tunnel-local-addr']) . " " . escapeshellarg($gif['tunnel-remote-addr']) . " prefixlen /" . escapeshellarg($gif['tunnel-remote-net']));
883
		mwexec("/sbin/ifconfig {$gifif} inet6 " . escapeshellarg($gif['tunnel-local-addr']) . " " . escapeshellarg($gif['tunnel-remote-addr']) . " prefixlen 128");
884
	} else {
885
		mwexec("/sbin/ifconfig {$gifif} " . escapeshellarg($gif['tunnel-local-addr']) . " " . escapeshellarg($gif['tunnel-remote-addr']) . " netmask " . gen_subnet_mask($gif['tunnel-remote-net']));
886
	}
887
	if (isset($gif['link0']))
888
		pfSense_interface_flags($gifif, IFF_LINK0);
889
	if (isset($gif['link1']))
890
		pfSense_interface_flags($gifif, IFF_LINK1);
891
	if($gifif)
892
		interfaces_bring_up($gifif);
893
	else
894
		log_error(gettext("could not bring gifif up -- variable not defined"));
895

    
896
	if (!platform_booting()) {
897
		$iflist = get_configured_interface_list();
898
		foreach($iflist as $ifname) {
899
			if($config['interfaces'][$ifname]['if'] == $gifif) {
900
				if(get_interface_gateway($ifname)) {
901
					system_routing_configure($ifname);
902
					break;
903
				}
904
				if(get_interface_gateway_v6($ifname)) {
905
					system_routing_configure($ifname);
906
					break;
907
				}
908
			}
909
		}
910
	}
911

    
912

    
913
	if(is_ipaddrv4($gif['tunnel-remote-addr']))
914
		file_put_contents("{$g['tmp_path']}/{$gifif}_router", $gif['tunnel-remote-addr']);
915
	if(is_ipaddrv6($gif['tunnel-remote-addr']))
916
		file_put_contents("{$g['tmp_path']}/{$gifif}_routerv6", $gif['tunnel-remote-addr']);
917

    
918
	if (is_ipaddrv4($realifgw)) {
919
		mwexec("/sbin/route change -host " . escapeshellarg($gif['remote-addr']) . " {$realifgw}");
920
	}
921
	if (is_ipaddrv6($realifgw)) {
922
		mwexec("/sbin/route change -host -inet6 " . escapeshellarg($gif['remote-addr']) . " {$realifgw}");
923
	}
924

    
925
	interfaces_bring_up($gifif);
926

    
927
	return $gifif;
928
}
929

    
930
function interfaces_configure() {
931
	global $config, $g;
932

    
933
	if ($g['platform'] == 'jail')
934
		return;
935

    
936
	/* Set up our loopback interface */
937
	interfaces_loopback_configure();
938

    
939
	/* create the unconfigured wireless clones */
940
	interfaces_create_wireless_clones();
941

    
942
	/* set up LAGG virtual interfaces */
943
	interfaces_lagg_configure();
944

    
945
	/* set up VLAN virtual interfaces */
946
	interfaces_vlan_configure();
947

    
948
	interfaces_qinq_configure();
949

    
950
	$iflist = get_configured_interface_with_descr();
951
	$delayed_list = array();
952
	$bridge_list = array();
953
	$track6_list = array();
954

    
955
	/* This is needed to speedup interfaces on bootup. */
956
	$reload = false;
957
	if (!platform_booting())
958
		$reload = true;
959

    
960
	foreach($iflist as $if => $ifname) {
961
		$realif = $config['interfaces'][$if]['if'];
962
		if (strstr($realif, "bridge"))
963
			$bridge_list[$if] = $ifname;
964
		else if (strstr($realif, "gre"))
965
			$delayed_list[$if] = $ifname;
966
		else if (strstr($realif, "gif"))
967
			$delayed_list[$if] = $ifname;
968
		else if (strstr($realif, "ovpn")) {
969
			//echo "Delaying OpenVPN interface configuration...done.\n";
970
			continue;
971
		} else if (!empty($config['interfaces'][$if]['ipaddrv6']) && $config['interfaces'][$if]['ipaddrv6'] == "track6") {
972
			$track6_list[$if] = $ifname;
973
		} else {
974
			if (platform_booting())
975
				printf(gettext("Configuring %s interface..."), $ifname);
976

    
977
			if($g['debug'])
978
				log_error(sprintf(gettext("Configuring %s"), $ifname));
979
			interface_configure($if, $reload);
980
			if (platform_booting())
981
				echo gettext( "done.") . "\n";
982
		}
983
	}
984

    
985
	/*
986
	 * NOTE: The following function parameter consists of
987
	 *	1 - Do not load gre/gif/bridge with parent/member as vip
988
	 *	2 - Do load gre/gif/bridge with parent/member as vip
989
	 */
990

    
991
	/* set up GRE virtual interfaces */
992
	interfaces_gre_configure(1);
993

    
994
	/* set up GIF virtual interfaces */
995
	interfaces_gif_configure(1);
996

    
997
	/* set up BRIDGe virtual interfaces */
998
	interfaces_bridge_configure(1);
999

    
1000
	foreach ($track6_list as $if => $ifname) {
1001
		if (platform_booting())
1002
			printf(gettext("Configuring %s interface..."), $ifname);
1003
		if ($g['debug'])
1004
			log_error(sprintf(gettext("Configuring %s"), $ifname));
1005

    
1006
		interface_configure($if, $reload);
1007

    
1008
		if (platform_booting())
1009
			echo gettext("done.") . "\n";
1010
	}
1011

    
1012
	/* bring up vip interfaces */
1013
	interfaces_vips_configure();
1014

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

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

    
1021
	foreach ($delayed_list as $if => $ifname) {
1022
		if (platform_booting())
1023
			printf(gettext("Configuring %s interface..."), $ifname);
1024
		if ($g['debug'])
1025
			log_error(sprintf(gettext("Configuring %s"), $ifname));
1026

    
1027
		interface_configure($if, $reload);
1028

    
1029
		if (platform_booting())
1030
			echo gettext("done.") . "\n";
1031
	}
1032

    
1033
	/* set up BRIDGe virtual interfaces */
1034
	interfaces_bridge_configure(2);
1035

    
1036
	foreach ($bridge_list as $if => $ifname) {
1037
		if (platform_booting())
1038
			printf(gettext("Configuring %s interface..."), $ifname);
1039
		if($g['debug'])
1040
			log_error(sprintf(gettext("Configuring %s"), $ifname));
1041

    
1042
		interface_configure($if, $reload);
1043

    
1044
		if (platform_booting())
1045
			echo gettext("done.") . "\n";
1046
	}
1047

    
1048
	/* configure interface groups */
1049
	interfaces_group_setup();
1050

    
1051
	if (!platform_booting()) {
1052
		/* reconfigure static routes (kernel may have deleted them) */
1053
		system_routing_configure();
1054

    
1055
		/* reload IPsec tunnels */
1056
		vpn_ipsec_configure();
1057

    
1058
		/* reload dhcpd (interface enabled/disabled status may have changed) */
1059
		services_dhcpd_configure();
1060

    
1061
		/* restart dnsmasq or unbound */
1062
		if (isset($config['dnsmasq']['enable']))
1063
			services_dnsmasq_configure();
1064
		elseif (isset($config['unbound']['enable']))
1065
			services_unbound_configure();
1066
	}
1067

    
1068
	return 0;
1069
}
1070

    
1071
function interface_reconfigure($interface = "wan", $reloadall = false) {
1072
	interface_bring_down($interface);
1073
	interface_configure($interface, $reloadall);
1074
}
1075

    
1076
function interface_vip_bring_down($vip) {
1077
	global $g;
1078

    
1079
	$vipif = get_real_interface($vip['interface']);
1080
	switch ($vip['mode']) {
1081
	case "proxyarp":
1082
		if (file_exists("{$g['varrun_path']}/choparp_{$vipif}.pid"))
1083
			killbypid("{$g['varrun_path']}/choparp_{$vipif}.pid");
1084
		break;
1085
	case "ipalias":
1086
		if (does_interface_exist($vipif)) {
1087
			if (is_ipaddrv6($vip['subnet']))
1088
				mwexec("/sbin/ifconfig {$vipif} inet6 " . escapeshellarg($vip['subnet']) . " -alias");
1089
			else
1090
				pfSense_interface_deladdress($vipif, $vip['subnet']);
1091
		}
1092
		break;
1093
	case "carp":
1094
		/* XXX: Is enough to delete ip address? */
1095
		if (does_interface_exist($vipif)) {
1096
			if (is_ipaddrv6($vip['subnet']))
1097
				mwexec("/sbin/ifconfig {$vipif} inet6 " . escapeshellarg($vip['subnet']) . " delete");
1098
			else
1099
				pfSense_interface_deladdress($vipif, $vip['subnet']);
1100
		}
1101
		break;
1102
	}
1103
}
1104

    
1105
function interface_bring_down($interface = "wan", $destroy = false, $ifacecfg = false) {
1106
	global $config, $g;
1107

    
1108
	if (!isset($config['interfaces'][$interface]))
1109
		return;
1110

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

    
1114
	/*
1115
	 * NOTE: The $realifv6 is needed when WANv4 is type PPP and v6 is DHCP and the option v6 from v4 is used.
1116
	 * In this case the real $realif of v4 is different from that of v6 for operation.
1117
	 * Keep this in mind while doing changes here!
1118
	 */
1119
	if ($ifacecfg === false) {
1120
		$ifcfg = $config['interfaces'][$interface];
1121
		$ppps = $config['ppps']['ppp'];
1122
		$realif = get_real_interface($interface);
1123
		$realifv6 = get_real_interface($interface, "inet6", true);
1124
	} elseif (!is_array($ifacecfg)) {
1125
		log_error(gettext("Wrong parameters used during interface_bring_down"));
1126
		$ifcfg = $config['interfaces'][$interface];
1127
		$ppps = $config['ppps']['ppp'];
1128
		$realif = get_real_interface($interface);
1129
		$realifv6 = get_real_interface($interface, "inet6", true);
1130
	} else {
1131
		$ifcfg = $ifacecfg['ifcfg'];
1132
		$ppps = $ifacecfg['ppps'];
1133
		if (isset($ifacecfg['ifcfg']['realif'])) {
1134
			$realif = $ifacecfg['ifcfg']['realif'];
1135
			/* XXX: Any better way? */
1136
			$realifv6 = $realif;
1137
		} else {
1138
			$realif = get_real_interface($interface);
1139
			$realifv6 = get_real_interface($interface, "inet6", true);
1140
		}
1141
	}
1142

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

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

    
1236
	if (!empty($track6) && is_array($track6)) {
1237
		if (!function_exists('services_dhcp_configure'))
1238
			require_once('services.inc');
1239
		/* Bring down radvd and dhcp6 on these interfaces */
1240
		services_dhcpd_configure('inet6', $track6);
1241
	}
1242

    
1243
	$old_router = '';
1244
	if (file_exists("{$g['tmp_path']}/{$realif}_router"))
1245
		$old_router = trim(file_get_contents("{$g['tmp_path']}/{$realif}_router"));
1246

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

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

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

    
1268
	return;
1269
}
1270

    
1271
function interfaces_carp_set_maintenancemode($carp_maintenancemode){
1272
	global $config;
1273
	if (isset($config["virtualip_carp_maintenancemode"]) && $carp_maintenancemode == false) {
1274
		unset($config["virtualip_carp_maintenancemode"]);
1275
		write_config("Leave CARP maintenance mode");
1276
		if(is_array($config['virtualip']['vip'])) {
1277
			$viparr = &$config['virtualip']['vip'];
1278
			foreach ($viparr as $vip) {
1279
				switch ($vip['mode']) {
1280
				case "carp":
1281
					interface_vip_bring_down($vip);
1282
					//sleep(1);
1283
					break;
1284
				}
1285
			}
1286
		}
1287
	} else {
1288
		if (!isset($config["virtualip_carp_maintenancemode"]) && $carp_maintenancemode == true) {
1289
			$config["virtualip_carp_maintenancemode"] = true;
1290
			write_config("Enter CARP maintenance mode");
1291
		}
1292
	}
1293

    
1294
	$viparr = &$config['virtualip']['vip'];
1295
	foreach ($viparr as $vip) {
1296
		if ($vip['mode'] == "carp") {
1297
			interface_carp_configure($vip);
1298
		}
1299
	}
1300
}
1301

    
1302
function interfaces_ptpid_used($ptpid) {
1303
	global $config;
1304

    
1305
	if (is_array($config['ppps']['ppp']))
1306
		foreach ($config['ppps']['ppp'] as & $settings)
1307
			if ($ptpid == $settings['ptpid'])
1308
				return true;
1309

    
1310
	return false;
1311
}
1312

    
1313
function interfaces_ptpid_next() {
1314

    
1315
	$ptpid = 0;
1316
	while(interfaces_ptpid_used($ptpid))
1317
		$ptpid++;
1318

    
1319
	return $ptpid;
1320
}
1321

    
1322
function getMPDCRONSettings($pppif) {
1323
	global $config;
1324

    
1325
	$cron_cmd_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
1326
	if (is_array($config['cron']['item'])) {
1327
		foreach ($config['cron']['item'] as $i => $item) {
1328
			if (stripos($item['command'], $cron_cmd_file) !== false)
1329
				return array("ID" => $i, "ITEM" => $item);
1330
		}
1331
	}
1332

    
1333
	return NULL;
1334
}
1335

    
1336
function handle_pppoe_reset($post_array) {
1337
	global $config, $g;
1338

    
1339
	$pppif = "{$post_array['type']}{$post_array['ptpid']}";
1340
	$cron_cmd_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
1341

    
1342
	if (!is_array($config['cron']['item']))
1343
		$config['cron']['item'] = array();
1344

    
1345
	$itemhash = getMPDCRONSettings($pppif);
1346

    
1347
	// reset cron items if necessary and return
1348
	if (empty($post_array['pppoe-reset-type'])) {
1349
		if (isset($itemhash))
1350
			unset($config['cron']['item'][$itemhash['ID']]);
1351
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
1352
		return;
1353
	}
1354

    
1355
	if (empty($itemhash))
1356
		$itemhash = array();
1357
	$item = array();
1358
	if (isset($post_array['pppoe-reset-type']) && $post_array['pppoe-reset-type'] == "custom") {
1359
		$item['minute'] = $post_array['pppoe_resetminute'];
1360
		$item['hour'] = $post_array['pppoe_resethour'];
1361
		if (isset($post_array['pppoe_resetdate']) && $post_array['pppoe_resetdate'] <> "") {
1362
			$date = explode("/", $post_array['pppoe_resetdate']);
1363
			$item['mday'] = $date[1];
1364
			$item['month'] = $date[0];
1365
		} else {
1366
			$item['mday'] = "*";
1367
			$item['month'] = "*";
1368
		}
1369
		$item['wday'] = "*";
1370
		$item['who'] = "root";
1371
		$item['command'] = $cron_cmd_file;
1372
	} else if (isset($post_array['pppoe-reset-type']) && $post_array['pppoe-reset-type'] == "preset") {
1373
		switch ($post_array['pppoe_pr_preset_val']) {
1374
		case "monthly":
1375
			$item['minute'] = "0";
1376
			$item['hour'] = "0";
1377
			$item['mday'] = "1";
1378
			$item['month'] = "*";
1379
			$item['wday'] = "*";
1380
			break;
1381
		case "weekly":
1382
			$item['minute'] = "0";
1383
			$item['hour'] = "0";
1384
			$item['mday'] = "*";
1385
			$item['month'] = "*";
1386
			$item['wday'] = "0";
1387
			break;
1388
		case "daily":
1389
			$item['minute'] = "0";
1390
			$item['hour'] = "0";
1391
			$item['mday'] = "*";
1392
			$item['month'] = "*";
1393
			$item['wday'] = "*";
1394
			break;
1395
		case "hourly":
1396
			$item['minute'] = "0";
1397
			$item['hour'] = "*";
1398
			$item['mday'] = "*";
1399
			$item['month'] = "*";
1400
			$item['wday'] = "*";
1401
			break;
1402
		} // end switch
1403
		$item['who'] = "root";
1404
		$item['command'] = $cron_cmd_file;
1405
	}
1406
	if (empty($item))
1407
		return;
1408
	if (isset($itemhash['ID']))
1409
		$config['cron']['item'][$itemhash['ID']] = $item;
1410
	else
1411
		$config['cron']['item'][] = $item;
1412
}
1413

    
1414
/*
1415
 * This function can configure PPPoE, MLPPP (PPPoE), PPTP.
1416
 * It writes the mpd config file to /var/etc every time the link is opened.
1417
 */
1418
function interface_ppps_configure($interface) {
1419
	global $config, $g;
1420

    
1421
	/* Return for unassigned interfaces. This is a minimum requirement. */
1422
	if (empty($config['interfaces'][$interface]))
1423
		return 0;
1424
	$ifcfg = $config['interfaces'][$interface];
1425
	if (!isset($ifcfg['enable']))
1426
		return 0;
1427

    
1428
	// mpd5 requires a /var/spool/lock directory for PPP modem links.
1429
	if(!is_dir("/var/spool/lock")) {
1430
		mkdir("/var/spool/lock", 0777, true);
1431
	}
1432
	// mpd5 modem chat script expected in the same directory as the mpd_xxx.conf files
1433
	if (!file_exists("{$g['varetc_path']}/mpd.script"))
1434
		@symlink("/usr/local/sbin/mpd.script", "{$g['varetc_path']}/mpd.script");
1435

    
1436
	if (is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) {
1437
		foreach ($config['ppps']['ppp'] as $pppid => $ppp) {
1438
			if ($ifcfg['if'] == $ppp['if'])
1439
				break;
1440
		}
1441
	}
1442
	if (!$ppp || $ifcfg['if'] != $ppp['if']){
1443
		log_error(sprintf(gettext("Can't find PPP config for %s in interface_ppps_configure()."), $ifcfg['if']));
1444
		return 0;
1445
	}
1446
	$pppif = $ifcfg['if'];
1447
	if ($ppp['type'] == "ppp")
1448
		$type = "modem";
1449
	else
1450
		$type = $ppp['type'];
1451
	$upper_type = strtoupper($ppp['type']);
1452

    
1453
	if (platform_booting()) {
1454
		$descr = isset($ifcfg['descr']) ? $ifcfg['descr'] : strtoupper($interface);
1455
		echo "starting {$pppif} link...";
1456
		// Do not re-configure the interface if we are booting and it's already been started
1457
		if(file_exists("{$g['varrun_path']}/{$ppp['type']}_{$interface}.pid"))
1458
			return 0;
1459
	}
1460

    
1461
	$ports = explode(',',$ppp['ports']);
1462
	if ($type != "modem") {
1463
		foreach ($ports as $pid => $port) {
1464
			$ports[$pid] = get_real_interface($port);
1465
			if (empty($ports[$pid]))
1466
				return 0;
1467
		}
1468
	}
1469
	$localips = explode(',',$ppp['localip']);
1470
	$gateways = explode(',',$ppp['gateway']);
1471
	$subnets = explode(',',$ppp['subnet']);
1472

    
1473
	/* We bring up the parent interface first because if DHCP is configured on the parent we need
1474
	 * to obtain an address first so we can write it in the mpd .conf file for PPTP and L2TP configs
1475
	 */
1476
	foreach($ports as $pid => $port){
1477
		switch ($ppp['type']) {
1478
			case "pppoe":
1479
				/* Bring the parent interface up */
1480
				interfaces_bring_up($port);
1481
				pfSense_ngctl_attach(".", $port);
1482
				/* Enable setautosrc to automatically change mac address if parent interface's changes */
1483
				mwexec("ngctl msg {$port}: setautosrc 1");
1484
				break;
1485
			case "pptp":
1486
			case "l2tp":
1487
				/* configure interface */
1488
				if(is_ipaddr($localips[$pid])){
1489
					// Manually configure interface IP/subnet
1490
					pfSense_interface_setaddress($port, "{$localips[$pid]}/{$subnets[$pid]}");
1491
					interfaces_bring_up($port);
1492
				} else if (empty($localips[$pid]))
1493
					$localips[$pid] = get_interface_ip($port); // try to get the interface IP from the port
1494

    
1495
				if(!is_ipaddr($localips[$pid])){
1496
					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!");
1497
					$localips[$pid] = "0.0.0.0";
1498
				}
1499
				if(!is_ipaddr($gateways[$pid])){
1500
					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));
1501
					return 0;
1502
				}
1503
				pfSense_ngctl_attach(".", $port);
1504
				break;
1505
			case "ppp":
1506
				if (!file_exists("{$port}")) {
1507
					log_error(sprintf(gettext("Device %s does not exist. PPP link cannot start without the modem device."), $port));
1508
					return 0;
1509
				}
1510
				break;
1511
			default:
1512
				log_error(sprintf(gettext("Unkown %s configured as ppp interface."), $type));
1513
				break;
1514
		}
1515
	}
1516

    
1517
	if (is_array($ports) && count($ports) > 1)
1518
		$multilink = "enable";
1519
	else
1520
		$multilink = "disable";
1521

    
1522
	if ($type == "modem"){
1523
		if (is_ipaddr($ppp['localip']))
1524
			$localip = $ppp['localip'];
1525
		else
1526
			$localip = '0.0.0.0';
1527

    
1528
		if (is_ipaddr($ppp['gateway']))
1529
			$gateway = $ppp['gateway'];
1530
		else
1531
			$gateway = "10.64.64.{$pppid}";
1532
		$ranges = "{$localip}/0 {$gateway}/0";
1533

    
1534
		if (empty($ppp['apnum']))
1535
			$ppp['apnum'] = 1;
1536
	} else
1537
		$ranges = "0.0.0.0/0 0.0.0.0/0";
1538

    
1539
	if (isset($ppp['ondemand']))
1540
		$ondemand = "enable";
1541
	else
1542
		$ondemand = "disable";
1543
	if (!isset($ppp['idletimeout']))
1544
		$ppp['idletimeout'] = 0;
1545

    
1546
	if (empty($ppp['username']) && $type == "modem"){
1547
		$ppp['username'] = "user";
1548
		$ppp['password'] = "none";
1549
	}
1550
	if (empty($ppp['password']) && $type == "modem")
1551
		$passwd = "none";
1552
	else
1553
		$passwd = base64_decode($ppp['password']);
1554

    
1555
	$bandwidths = explode(',',$ppp['bandwidth']);
1556
	$defaultmtu = "1492";
1557
	if (!empty($ifcfg['mtu']))
1558
		$defaultmtu = intval($ifcfg['mtu']);
1559
	$mtus = explode(',',$ppp['mtu']);
1560
	$mrus = explode(',',$ppp['mru']);
1561

    
1562
	if (isset($ppp['mrru']))
1563
		$mrrus = explode(',',$ppp['mrru']);
1564

    
1565
	// Construct the mpd.conf file
1566
	$mpdconf = <<<EOD
1567
startup:
1568
	# configure the console
1569
	set console close
1570
	# configure the web server
1571
	set web close
1572

    
1573
default:
1574
{$ppp['type']}client:
1575
	create bundle static {$interface}
1576
	set bundle enable ipv6cp
1577
	set iface name {$pppif}
1578

    
1579
EOD;
1580
	$setdefaultgw = false;
1581
	$founddefaultgw = false;
1582
	if (is_array($config['gateways']['gateway_item'])) {
1583
		foreach($config['gateways']['gateway_item'] as $gateway) {
1584
			if($interface == $gateway['interface'] && isset($gateway['defaultgw'])) {
1585
				$setdefaultgw = true;
1586
				break;
1587
			} else if (isset($gateway['defaultgw']) && !empty($gateway['interface'])) {
1588
				$founddefaultgw = true;
1589
				break;
1590
			}
1591
		}
1592
	}
1593

    
1594
	if (($interface == "wan" && $founddefaultgw == false) || $setdefaultgw == true){
1595
		$setdefaultgw = true;
1596
		$mpdconf .= <<<EOD
1597
	set iface route default
1598

    
1599
EOD;
1600
	}
1601
	$mpdconf .= <<<EOD
1602
	set iface {$ondemand} on-demand
1603
	set iface idle {$ppp['idletimeout']}
1604

    
1605
EOD;
1606

    
1607
	if (isset($ppp['ondemand']))
1608
		$mpdconf .= <<<EOD
1609
	set iface addrs 10.10.1.1 10.10.1.2
1610

    
1611
EOD;
1612

    
1613
	if (isset($ppp['tcpmssfix']))
1614
		$tcpmss = "disable";
1615
	else
1616
		$tcpmss = "enable";
1617
		$mpdconf .= <<<EOD
1618
	set iface {$tcpmss} tcpmssfix
1619

    
1620
EOD;
1621

    
1622
	$mpdconf .= <<<EOD
1623
	set iface up-script /usr/local/sbin/ppp-linkup
1624
	set iface down-script /usr/local/sbin/ppp-linkdown
1625
	set ipcp ranges {$ranges}
1626

    
1627
EOD;
1628
	if (isset($ppp['vjcomp']))
1629
		$mpdconf .= <<<EOD
1630
	set ipcp no vjcomp
1631

    
1632
EOD;
1633

    
1634
	if (isset($config['system']['dnsallowoverride']))
1635
		$mpdconf .= <<<EOD
1636
	set ipcp enable req-pri-dns
1637
	set ipcp enable req-sec-dns
1638

    
1639
EOD;
1640
	if (!isset($ppp['verbose_log']))
1641
		$mpdconf .= <<<EOD
1642
	#log -bund -ccp -chat -iface -ipcp -lcp -link
1643

    
1644
EOD;
1645
	foreach($ports as $pid => $port){
1646
		$port = get_real_interface($port);
1647
		$mpdconf .= <<<EOD
1648

    
1649
	create link static {$interface}_link{$pid} {$type}
1650
	set link action bundle {$interface}
1651
	set link {$multilink} multilink
1652
	set link keep-alive 10 60
1653
	set link max-redial 0
1654

    
1655
EOD;
1656
		if (isset($ppp['shortseq']))
1657
			$mpdconf .= <<<EOD
1658
	set link no shortseq
1659

    
1660
EOD;
1661

    
1662
		if (isset($ppp['acfcomp']))
1663
			$mpdconf .= <<<EOD
1664
	set link no acfcomp
1665

    
1666
EOD;
1667

    
1668
		if (isset($ppp['protocomp']))
1669
			$mpdconf .= <<<EOD
1670
	set link no protocomp
1671

    
1672
EOD;
1673

    
1674
		$mpdconf .= <<<EOD
1675
	set link disable chap pap
1676
	set link accept chap pap eap
1677
	set link disable incoming
1678

    
1679
EOD;
1680

    
1681

    
1682
		if (!empty($bandwidths[$pid]))
1683
			$mpdconf .= <<<EOD
1684
	set link bandwidth {$bandwidths[$pid]}
1685

    
1686
EOD;
1687

    
1688
		if (empty($mtus[$pid]))
1689
			$mtus[$pid] = $defaultmtu;
1690
			$mpdconf .= <<<EOD
1691
	set link mtu {$mtus[$pid]}
1692

    
1693
EOD;
1694

    
1695
		if (!empty($mrus[$pid]))
1696
			$mpdconf .= <<<EOD
1697
	set link mru {$mrus[$pid]}
1698

    
1699
EOD;
1700

    
1701
		if (!empty($mrrus[$pid]))
1702
			$mpdconf .= <<<EOD
1703
	set link mrru {$mrrus[$pid]}
1704

    
1705
EOD;
1706

    
1707
		$mpdconf .= <<<EOD
1708
	set auth authname "{$ppp['username']}"
1709
	set auth password {$passwd}
1710

    
1711
EOD;
1712
		if ($type == "modem") {
1713
			$mpdconf .= <<<EOD
1714
	set modem device {$ppp['ports']}
1715
	set modem script DialPeer
1716
	set modem idle-script Ringback
1717
	set modem watch -cd
1718
	set modem var \$DialPrefix "DT"
1719
	set modem var \$Telephone "{$ppp['phone']}"
1720

    
1721
EOD;
1722
		}
1723
		if (isset($ppp['connect-timeout']) && $type == "modem") {
1724
			$mpdconf .= <<<EOD
1725
	set modem var \$ConnectTimeout "{$ppp['connect-timeout']}"
1726

    
1727
EOD;
1728
		}
1729
		if (isset($ppp['initstr']) && $type == "modem") {
1730
			$initstr = base64_decode($ppp['initstr']);
1731
			$mpdconf .= <<<EOD
1732
	set modem var \$InitString "{$initstr}"
1733

    
1734
EOD;
1735
		}
1736
		if (isset($ppp['simpin']) && $type == "modem") {
1737
			if($ppp['pin-wait'] == "")
1738
				$ppp['pin-wait'] = 0;
1739
			$mpdconf .= <<<EOD
1740
	set modem var \$SimPin "{$ppp['simpin']}"
1741
	set modem var \$PinWait "{$ppp['pin-wait']}"
1742

    
1743
EOD;
1744
		}
1745
		if (isset($ppp['apn']) && $type == "modem") {
1746
			$mpdconf .= <<<EOD
1747
	set modem var \$APN "{$ppp['apn']}"
1748
	set modem var \$APNum "{$ppp['apnum']}"
1749

    
1750
EOD;
1751
		}
1752
		if ($type == "pppoe") {
1753
			// Send a null service name if none is set.
1754
			$provider = isset($ppp['provider']) ? $ppp['provider'] : "";
1755
			$mpdconf .= <<<EOD
1756
	set pppoe service "{$provider}"
1757

    
1758
EOD;
1759
		}
1760
		if ($type == "pppoe")
1761
			$mpdconf .= <<<EOD
1762
	set pppoe iface {$port}
1763

    
1764
EOD;
1765

    
1766
		if ($type == "pptp" || $type == "l2tp") {
1767
			$mpdconf .= <<<EOD
1768
	set {$type} self {$localips[$pid]}
1769
	set {$type} peer {$gateways[$pid]}
1770

    
1771
EOD;
1772
		}
1773

    
1774
		$mpdconf .= "\topen\n";
1775
	} //end foreach($port)
1776

    
1777

    
1778
	/* Generate mpd.conf. If mpd_[interface].conf exists in the conf path, then link to it instead of generating a fresh conf file. */
1779
	if (file_exists("{$g['conf_path']}/mpd_{$interface}.conf"))
1780
		@symlink("{$g['conf_path']}/mpd_{$interface}.conf", "{$g['varetc_path']}/mpd_{$interface}.conf");
1781
	else {
1782
		$fd = fopen("{$g['varetc_path']}/mpd_{$interface}.conf", "w");
1783
		if (!$fd) {
1784
			log_error(sprintf(gettext("Error: cannot open mpd_%s.conf in interface_ppps_configure().%s"), $interface, "\n"));
1785
			return 0;
1786
		}
1787
		// Write out mpd_ppp.conf
1788
		fwrite($fd, $mpdconf);
1789
		fclose($fd);
1790
		unset($mpdconf);
1791
	}
1792

    
1793
	// Create the uptime log if requested and if it doesn't exist already, or delete it if it is no longer requested.
1794
	if (isset($ppp['uptime'])) {
1795
		if (!file_exists("/conf/{$pppif}.log")) {
1796
			conf_mount_rw();
1797
			file_put_contents("/conf/{$pppif}.log", '');
1798
			conf_mount_ro();
1799
		}
1800
	} else {
1801
		if (file_exists("/conf/{$pppif}.log")) {
1802
			conf_mount_rw();
1803
			@unlink("/conf/{$pppif}.log");
1804
			conf_mount_ro();
1805
		}
1806
	}
1807

    
1808
	/* clean up old lock files */
1809
	foreach($ports as $port) {
1810
		if(file_exists("{$g['var_path']}/spool/lock/LCK..{$port}"))
1811
			unlink("{$g['var_path']}/spool/lock/LCK..{$port}");
1812
	}
1813

    
1814
	/* fire up mpd */
1815
	mwexec("/usr/local/sbin/mpd5 -b -k -d {$g['varetc_path']} -f mpd_{$interface}.conf -p {$g['varrun_path']}/" .
1816
		escapeshellarg($ppp['type']) . "_{$interface}.pid -s ppp " . escapeshellarg($ppp['type']) . "client");
1817

    
1818
	// Check for PPPoE periodic reset request
1819
	if ($type == "pppoe") {
1820
		if (!empty($ppp['pppoe-reset-type']))
1821
			interface_setup_pppoe_reset_file($ppp['if'], $interface);
1822
		else
1823
			interface_setup_pppoe_reset_file($ppp['if']);
1824
	}
1825
	/* wait for upto 10 seconds for the interface to appear (ppp(oe)) */
1826
	$i = 0;
1827
	while($i < 10) {
1828
		exec("/sbin/ifconfig " . escapeshellarg($ppp['if']) . " 2>&1", $out, $ret);
1829
		if($ret == 0)
1830
			break;
1831
		sleep(1);
1832
		$i++;
1833
	}
1834

    
1835
	/* we only support the 3gstats.php for huawei modems for now. Will add more later. */
1836
	/* We should be able to launch the right version for each modem */
1837
	/* We can also guess the mondev from the manufacturer */
1838
	exec("usbconfig | egrep -ie '(huawei)'", $usbmodemoutput);
1839
	mwexec("/bin/ps auxww|grep \"{$interface}\" |grep \"[3]gstats\" | awk '{print $2}' |xargs kill");
1840
	foreach($ports as $port) {
1841
		if(preg_match("/huawei/i", implode("\n", $usbmodemoutput))) {
1842
			$mondev  = substr(basename($port), 0, -1);
1843
			$devlist = glob("/dev/{$mondev}?");
1844
			$mondev = basename(end($devlist));
1845
		}
1846
		if(preg_match("/zte/i", implode("\n", $usbmodemoutput))) {
1847
			$mondev  = substr(basename($port), 0, -1) . "1";
1848
		}
1849
		log_error("Starting 3gstats.php on device '{$mondev}' for interface '{$interface}'");
1850
		mwexec_bg("/usr/local/bin/3gstats.php {$mondev} {$interface}");
1851
	}
1852

    
1853
	return 1;
1854
}
1855

    
1856
function interfaces_sync_setup() {
1857
	global $g, $config;
1858

    
1859
	if (isset($config['system']['developerspew'])) {
1860
		$mt = microtime();
1861
		echo "interfaces_sync_setup() being called $mt\n";
1862
	}
1863

    
1864
	if (platform_booting()) {
1865
		echo gettext("Configuring CARP settings...");
1866
		mute_kernel_msgs();
1867
	}
1868

    
1869
	/* suck in configuration items */
1870
	if ($config['hasync']) {
1871
		$pfsyncenabled = $config['hasync']['pfsyncenabled'];
1872
		$pfsyncinterface = $config['hasync']['pfsyncinterface'];
1873
		$pfsyncpeerip = $config['hasync']['pfsyncpeerip'];
1874
	} else {
1875
		unset($pfsyncinterface);
1876
		unset($pfsyncenabled);
1877
	}
1878

    
1879
	set_sysctl(array(
1880
		"net.inet.carp.preempt" => "1",
1881
		"net.inet.carp.log" => "1")
1882
	);
1883

    
1884
	if (!empty($pfsyncinterface))
1885
		$carp_sync_int = get_real_interface($pfsyncinterface);
1886
	else
1887
		unset($carp_sync_int);
1888

    
1889
	/* setup pfsync interface */
1890
	if (isset($carp_sync_int) and isset($pfsyncenabled)) {
1891
		if (is_ipaddr($pfsyncpeerip))
1892
			$syncpeer = "syncpeer {$pfsyncpeerip}";
1893
		else
1894
			$syncpeer = "-syncpeer";
1895

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

    
1898
		sleep(1);
1899

    
1900
		/* 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
1901
		 * for existing sessions.
1902
		 */
1903
		log_error("waiting for pfsync...");
1904
		$i = 0;
1905
		while (intval(trim(`/sbin/ifconfig pfsync0 | /usr/bin/grep 'syncok: 0' | /usr/bin/grep -v grep | /usr/bin/wc -l`)) == 0 && $i < 30) {
1906
			$i++;
1907
			sleep(1);
1908
		}
1909
		log_error("pfsync done in $i seconds.");
1910
		log_error("Configuring CARP settings finalize...");
1911
	} else {
1912
		mwexec("/sbin/ifconfig pfsync0 -syncdev -syncpeer down", false);
1913
	}
1914

    
1915
	if($config['virtualip']['vip'])
1916
		set_single_sysctl("net.inet.carp.allow", "1");
1917
	else
1918
		set_single_sysctl("net.inet.carp.allow", "0");
1919

    
1920
	if (platform_booting()) {
1921
		unmute_kernel_msgs();
1922
		echo gettext("done.") . "\n";
1923
	}
1924
}
1925

    
1926
function interface_proxyarp_configure($interface = "") {
1927
	global $config, $g;
1928
	if(isset($config['system']['developerspew'])) {
1929
		$mt = microtime();
1930
		echo "interface_proxyarp_configure() being called $mt\n";
1931
	}
1932

    
1933
	/* kill any running choparp */
1934
	if (empty($interface))
1935
		killbyname("choparp");
1936
	else {
1937
		$vipif = get_real_interface($interface);
1938
		if (file_exists("{$g['varrun_path']}/choparp_{$vipif}.pid"))
1939
			killbypid("{$g['varrun_path']}/choparp_{$vipif}.pid");
1940
	}
1941

    
1942
	$paa = array();
1943
	if (!empty($config['virtualip']) && is_array($config['virtualip']['vip'])) {
1944

    
1945
		/* group by interface */
1946
		foreach ($config['virtualip']['vip'] as $vipent) {
1947
			if ($vipent['mode'] === "proxyarp") {
1948
				if ($vipent['interface'])
1949
					$proxyif = $vipent['interface'];
1950
				else
1951
					$proxyif = "wan";
1952

    
1953
				if (!empty($interface) && $interface != $proxyif)
1954
					continue;
1955

    
1956
				if (!is_array($paa[$proxyif]))
1957
					$paa[$proxyif] = array();
1958

    
1959
				$paa[$proxyif][] = $vipent;
1960
			}
1961
		}
1962
	}
1963

    
1964
	if (!empty($interface)) {
1965
		if (is_array($paa[$interface])) {
1966
			$paaifip = get_interface_ip($interface);
1967
			if (!is_ipaddr($paaifip))
1968
				return;
1969
			$args = get_real_interface($interface) . " auto";
1970
			foreach ($paa[$interface] as $paent) {
1971
				if (isset($paent['subnet']))
1972
					$args .= " " . escapeshellarg("{$paent['subnet']}/{$paent['subnet_bits']}");
1973
				else if (isset($paent['range']))
1974
					$args .= " " . escapeshellarg($paent['range']['from'] . "-" . $paent['range']['to']);
1975
			}
1976
			mwexec_bg("/usr/local/sbin/choparp " . $args);
1977
		}
1978
	} else if (count($paa) > 0) {
1979
		foreach ($paa as $paif => $paents)  {
1980
			$paaifip = get_interface_ip($paif);
1981
			if (!is_ipaddr($paaifip))
1982
				continue;
1983
			$args = get_real_interface($paif) . " auto";
1984
			foreach ($paents as $paent) {
1985
				if (isset($paent['subnet']))
1986
					$args .= " " . escapeshellarg("{$paent['subnet']}/{$paent['subnet_bits']}");
1987
				else if (isset($paent['range']))
1988
					$args .= " " . escapeshellarg($paent['range']['from'] . "-" . $paent['range']['to']);
1989
			}
1990
			mwexec_bg("/usr/local/sbin/choparp " . $args);
1991
		}
1992
	}
1993
}
1994

    
1995
function interface_ipalias_cleanup($interface, $inet = "inet4") {
1996
	global $g, $config;
1997

    
1998
	if (is_array($config['virtualip']['vip'])) {
1999
		foreach ($config['virtualip']['vip'] as $vip) {
2000
			if ($vip['mode'] == "ipalias" && $vip['interface'] == $interface) {
2001
				if ($inet == "inet6" && is_ipaddrv6($vip['subnet']))
2002
					interface_vip_bring_down($vip);
2003
				else if ($inet == "inet4" && is_ipaddrv4($vip['subnet']))
2004
					interface_vip_bring_down($vip);
2005
			}
2006
		}
2007
	}
2008
}
2009

    
2010
function interfaces_vips_configure($interface = "") {
2011
	global $g, $config;
2012
	if(isset($config['system']['developerspew'])) {
2013
		$mt = microtime();
2014
		echo "interfaces_vips_configure() being called $mt\n";
2015
	}
2016
	$paa = array();
2017
	if(is_array($config['virtualip']['vip'])) {
2018
		$carp_setuped = false;
2019
		$anyproxyarp = false;
2020
		foreach ($config['virtualip']['vip'] as $vip) {
2021
			switch ($vip['mode']) {
2022
			case "proxyarp":
2023
				/* nothing it is handled on interface_proxyarp_configure() */
2024
				if ($interface <> "" && $vip['interface'] <> $interface)
2025
					continue;
2026
				$anyproxyarp = true;
2027
				break;
2028
			case "ipalias":
2029
				if ($interface <> "" && $vip['interface'] <> $interface)
2030
					continue;
2031
				interface_ipalias_configure($vip);
2032
				break;
2033
			case "carp":
2034
				if ($interface <> "" && $vip['interface'] <> $interface)
2035
					continue;
2036
				if ($carp_setuped == false)
2037
					$carp_setuped = true;
2038
				interface_carp_configure($vip);
2039
				break;
2040
			}
2041
		}
2042
		if ($carp_setuped == true)
2043
			interfaces_sync_setup();
2044
		if ($anyproxyarp == true)
2045
			interface_proxyarp_configure();
2046
	}
2047
}
2048

    
2049
function interface_ipalias_configure(&$vip) {
2050
	global $config;
2051

    
2052
	if ($vip['mode'] != 'ipalias')
2053
		return;
2054

    
2055
	if ($vip['interface'] != 'lo0' && stripos($vip['interface'], '_vip') === false) {
2056
		if (!isset($config['interfaces'][$vip['interface']]))
2057
			return;
2058

    
2059
		if (!isset($config['interfaces'][$vip['interface']]['enable']))
2060
			return;
2061
	}
2062

    
2063
	$af = 'inet';
2064
	if(is_ipaddrv6($vip['subnet']))
2065
		$af = 'inet6';
2066
	$iface = $vip['interface'];
2067
	$vipadd = '';
2068
	if (strpos($vip['interface'], '_vip')) {
2069
		$carpvip = get_configured_carp_interface_list($vip['interface'], $af, 'vip');
2070
		$iface = $carpvip['interface'];
2071
		$vipadd = "vhid {$carpvip['vhid']}";
2072
	}
2073
	$if = get_real_interface($iface);
2074
	mwexec("/sbin/ifconfig " . escapeshellarg($if) ." {$af} ". escapeshellarg($vip['subnet']) ."/" . escapeshellarg($vip['subnet_bits']) . " alias {$vipadd}");
2075
	unset($iface, $af, $if, $carpvip, $vipadd);
2076
}
2077

    
2078
function interface_reload_carps($cif) {
2079
	global $config;
2080

    
2081
	$carpifs = link_ip_to_carp_interface(find_interface_ip($cif));
2082
	if (empty($carpifs))
2083
		return;
2084

    
2085
	$carps = explode(" ", $carpifs);
2086
	if(is_array($config['virtualip']['vip'])) {
2087
		$viparr = &$config['virtualip']['vip'];
2088
		foreach ($viparr as $vip) {
2089
			if (in_array($vip['carpif'], $carps)) {
2090
				switch ($vip['mode']) {
2091
				case "carp":
2092
					interface_vip_bring_down($vip);
2093
					sleep(1);
2094
					interface_carp_configure($vip);
2095
					break;
2096
				case "ipalias":
2097
					interface_vip_bring_down($vip);
2098
					sleep(1);
2099
					interface_ipalias_configure($vip);
2100
					break;
2101
				}
2102
			}
2103
		}
2104
	}
2105
}
2106

    
2107
function interface_carp_configure(&$vip) {
2108
	global $config, $g;
2109
	if(isset($config['system']['developerspew'])) {
2110
		$mt = microtime();
2111
		echo "interface_carp_configure() being called $mt\n";
2112
	}
2113

    
2114
	if ($vip['mode'] != "carp")
2115
		return;
2116

    
2117
	/* NOTE: Maybe its useless nowdays */
2118
	$realif = get_real_interface($vip['interface']);
2119
	if (!does_interface_exist($realif)) {
2120
		file_notice("CARP", sprintf(gettext("Interface specified for the virtual IP address %s does not exist. Skipping this VIP."), $vip['subnet']), "Firewall: Virtual IP", "");
2121
		return;
2122
	}
2123

    
2124
	if (is_ipaddrv4($vip['subnet'])) {
2125
		/* Ensure a IP on this interface exists prior to configuring CARP. */
2126
		$ww_subnet_ip = find_interface_ip($realif);
2127
		if (!is_ipaddrv4($ww_subnet_ip)) {
2128
			file_notice("CARP", sprintf(gettext("Interface does not have required IP address in the subnet of virtual IP address %s. Skipping this VIP."), $vip['subnet']), "Firewall: Virtual IP", "");
2129
			return;
2130
		}
2131
	} else if (is_ipaddrv6($vip['subnet'])) {
2132
		/* Ensure a IP on this interface exists prior to configuring CARP. */
2133
		$ww_subnet_ip = find_interface_ipv6($realif);
2134
		if (!is_ipaddrv6($ww_subnet_ip)) {
2135
			file_notice("CARP", sprintf(gettext("Interface does not have required IPv6 address in the subnet of virtual IPv6 address %s. Skipping this VIP."), $vip['subnet']), "Firewall: Virtual IP", "");
2136
			return;
2137
		}
2138
	}
2139

    
2140
	$vip_password = $vip['password'];
2141
	$vip_password = escapeshellarg(addslashes(str_replace(" ", "", $vip_password)));
2142
	if ($vip['password'] != "")
2143
		$password = " pass {$vip_password}";
2144

    
2145
	$advbase = "";
2146
	if (!empty($vip['advbase']))
2147
		$advbase = "advbase " . escapeshellarg($vip['advbase']);
2148

    
2149
	$carp_maintenancemode = isset($config["virtualip_carp_maintenancemode"]);
2150
	if ($carp_maintenancemode)
2151
		$advskew = "advskew 254";
2152
	else
2153
		$advskew = "advskew " . escapeshellarg($vip['advskew']);
2154
	
2155
	mwexec("/sbin/ifconfig {$realif} vhid " . escapeshellarg($vip['vhid']) . " {$advskew} {$advbase} {$password}");
2156

    
2157
	if (is_ipaddrv4($vip['subnet']))
2158
		mwexec("/sbin/ifconfig {$realif} " . escapeshellarg($vip['subnet']) . "/" . escapeshellarg($vip['subnet_bits']) . " alias vhid " . escapeshellarg($vip['vhid']));
2159
	else if (is_ipaddrv6($vip['subnet']))
2160
		mwexec("/sbin/ifconfig {$realif} inet6 " . escapeshellarg($vip['subnet']) . " prefixlen " . escapeshellarg($vip['subnet_bits']) . " alias vhid " . escapeshellarg($vip['vhid']));
2161

    
2162
	return $realif;
2163
}
2164

    
2165
function interface_wireless_clone($realif, $wlcfg) {
2166
	global $config, $g;
2167
	/*   Check to see if interface has been cloned as of yet.
2168
	 *   If it has not been cloned then go ahead and clone it.
2169
	 */
2170
	$needs_clone = false;
2171
	if(is_array($wlcfg['wireless']))
2172
		$wlcfg_mode = $wlcfg['wireless']['mode'];
2173
	else
2174
		$wlcfg_mode = $wlcfg['mode'];
2175
	switch($wlcfg_mode) {
2176
	case "hostap":
2177
		$mode = "wlanmode hostap";
2178
		break;
2179
	case "adhoc":
2180
		$mode = "wlanmode adhoc";
2181
		break;
2182
	default:
2183
		$mode = "";
2184
		break;
2185
	}
2186
	$baseif = interface_get_wireless_base($wlcfg['if']);
2187
	if(does_interface_exist($realif)) {
2188
		exec("/sbin/ifconfig " . escapeshellarg($realif), $output, $ret);
2189
		$ifconfig_str = implode($output);
2190
		if(($wlcfg_mode == "hostap") && (! preg_match("/hostap/si", $ifconfig_str))) {
2191
			log_error(sprintf(gettext("Interface %s changed to hostap mode"), $realif));
2192
			$needs_clone = true;
2193
		}
2194
		if(($wlcfg_mode == "adhoc") && (! preg_match("/adhoc/si", $ifconfig_str))) {
2195
			log_error(sprintf(gettext("Interface %s changed to adhoc mode"), $realif));
2196
			$needs_clone = true;
2197
		}
2198
		if(($wlcfg_mode == "bss") && (preg_match("/hostap|adhoc/si", $ifconfig_str))) {
2199
			log_error(sprintf(gettext("Interface %s changed to infrastructure mode"), $realif));
2200
			$needs_clone = true;
2201
		}
2202
	} else {
2203
		$needs_clone = true;
2204
	}
2205

    
2206
	if($needs_clone == true) {
2207
		/* remove previous instance if it exists */
2208
		if(does_interface_exist($realif))
2209
			pfSense_interface_destroy($realif);
2210

    
2211
		log_error(sprintf(gettext("Cloning new wireless interface %s"), $realif));
2212
		// Create the new wlan interface. FreeBSD returns the new interface name.
2213
		// example:  wlan2
2214
		exec("/sbin/ifconfig wlan create wlandev {$baseif} {$mode} bssid 2>&1", $out, $ret);
2215
		if($ret <> 0) {
2216
			log_error(sprintf(gettext('Failed to clone interface %1$s with error code %2$s, output %3$s'), $baseif, $ret, $out[0]));
2217
			return false;
2218
		}
2219
		$newif = trim($out[0]);
2220
		// Rename the interface to {$parentnic}_wlan{$number}#: EX: ath0_wlan0
2221
		pfSense_interface_rename($newif, $realif);
2222
		// FIXME: not sure what ngctl is for. Doesn't work.
2223
		// mwexec("/usr/sbin/ngctl name {$newif}: {$realif}", false);
2224
		file_put_contents("{$g['tmp_path']}/{$realif}_oldmac", get_interface_mac($realif));
2225
	}
2226
	return true;
2227
}
2228

    
2229
function interface_sync_wireless_clones(&$ifcfg, $sync_changes = false) {
2230
	global $config, $g;
2231

    
2232
	$shared_settings = array('standard', 'turbo', 'protmode', 'txpower', 'channel',
2233
				 'diversity', 'txantenna', 'rxantenna', 'distance',
2234
				 'regdomain', 'regcountry', 'reglocation');
2235

    
2236
	if(!is_interface_wireless($ifcfg['if']))
2237
		return;
2238

    
2239
	$baseif = interface_get_wireless_base($ifcfg['if']);
2240

    
2241
	// Sync shared settings for assigned clones
2242
	$iflist = get_configured_interface_list(false, true);
2243
	foreach ($iflist as $if) {
2244
		if ($baseif == interface_get_wireless_base($config['interfaces'][$if]['if']) && $ifcfg['if'] != $config['interfaces'][$if]['if']) {
2245
			if (isset($config['interfaces'][$if]['wireless']['standard']) || $sync_changes) {
2246
				foreach ($shared_settings as $setting) {
2247
					if ($sync_changes) {
2248
						if (isset($ifcfg['wireless'][$setting]))
2249
							$config['interfaces'][$if]['wireless'][$setting] = $ifcfg['wireless'][$setting];
2250
						else if (isset($config['interfaces'][$if]['wireless'][$setting]))
2251
							unset($config['interfaces'][$if]['wireless'][$setting]);
2252
					} else {
2253
						if (isset($config['interfaces'][$if]['wireless'][$setting]))
2254
							$ifcfg['wireless'][$setting] = $config['interfaces'][$if]['wireless'][$setting];
2255
						else if (isset($ifcfg['wireless'][$setting]))
2256
							unset($ifcfg['wireless'][$setting]);
2257
					}
2258
				}
2259
				if (!$sync_changes)
2260
					break;
2261
			}
2262
		}
2263
	}
2264

    
2265
	// Read or write settings at shared area
2266
	if (isset($config['wireless']['interfaces'][$baseif]) && is_array($config['wireless']['interfaces'][$baseif])) {
2267
		foreach ($shared_settings as $setting) {
2268
			if ($sync_changes) {
2269
				if (isset($ifcfg['wireless'][$setting]))
2270
					$config['wireless']['interfaces'][$baseif][$setting] = $ifcfg['wireless'][$setting];
2271
				else if (isset($config['wireless']['interfaces'][$baseif][$setting]))
2272
					unset($config['wireless']['interfaces'][$baseif][$setting]);
2273
			} else if (isset($config['wireless']['interfaces'][$baseif][$setting])) {
2274
				if (isset($config['wireless']['interfaces'][$baseif][$setting]))
2275
					$ifcfg['wireless'][$setting] = $config['wireless']['interfaces'][$baseif][$setting];
2276
				else if (isset($ifcfg['wireless'][$setting]))
2277
					unset($ifcfg['wireless'][$setting]);
2278
			}
2279
		}
2280
	}
2281

    
2282
	// Sync the mode on the clone creation page with the configured mode on the interface
2283
	if (interface_is_wireless_clone($ifcfg['if']) && isset($config['wireless']['clone']) && is_array($config['wireless']['clone'])) {
2284
		foreach ($config['wireless']['clone'] as &$clone) {
2285
			if ($clone['cloneif'] == $ifcfg['if']) {
2286
				if ($sync_changes) {
2287
					$clone['mode'] = $ifcfg['wireless']['mode'];
2288
				} else {
2289
					$ifcfg['wireless']['mode'] = $clone['mode'];
2290
				}
2291
				break;
2292
			}
2293
		}
2294
		unset($clone);
2295
	}
2296
}
2297

    
2298
function interface_wireless_configure($if, &$wl, &$wlcfg) {
2299
	global $config, $g;
2300

    
2301
	/*    open up a shell script that will be used to output the commands.
2302
	 *    since wireless is changing a lot, these series of commands are fragile
2303
	 *    and will sometimes need to be verified by a operator by executing the command
2304
	 *    and returning the output of the command to the developers for inspection.  please
2305
	 *    do not change this routine from a shell script to individual exec commands.  -sullrich
2306
	 */
2307

    
2308
	// Remove script file
2309
	unlink_if_exists("{$g['tmp_path']}/{$if}_setup.sh");
2310

    
2311
	// Clone wireless nic if needed.
2312
	interface_wireless_clone($if, $wl);
2313

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

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

    
2321
	/* set values for /path/program */
2322
	$hostapd = "/usr/sbin/hostapd";
2323
	$wpa_supplicant = "/usr/sbin/wpa_supplicant";
2324
	$ifconfig = "/sbin/ifconfig";
2325
	$sysctl = "/sbin/sysctl";
2326
	$killall = "/usr/bin/killall";
2327

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

    
2330
	$wlcmd = array();
2331
	$wl_sysctl = array();
2332
	/* Make sure it's up */
2333
	$wlcmd[] = "up";
2334
	/* Set a/b/g standard */
2335
	$standard = str_replace(" Turbo", "", $wlcfg['standard']);
2336
	$wlcmd[] = "mode " . escapeshellarg($standard);
2337

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

    
2343
	/* Set ssid */
2344
	if($wlcfg['ssid'])
2345
		$wlcmd[] = "ssid " .escapeshellarg($wlcfg['ssid']);
2346

    
2347
	/* Set 802.11g protection mode */
2348
	$wlcmd[] = "protmode " . escapeshellarg($wlcfg['protmode']);
2349

    
2350
	/* set wireless channel value */
2351
	if(isset($wlcfg['channel'])) {
2352
		if($wlcfg['channel'] == "0") {
2353
			$wlcmd[] = "channel any";
2354
		} else {
2355
			$wlcmd[] = "channel " . escapeshellarg($wlcfg['channel']);
2356
		}
2357
	}
2358

    
2359
	/* Set antenna diversity value */
2360
	if(isset($wlcfg['diversity']))
2361
		$wl_sysctl[] = "diversity=" . escapeshellarg($wlcfg['diversity']);
2362

    
2363
	/* Set txantenna value */
2364
	if(isset($wlcfg['txantenna']))
2365
		$wl_sysctl[] = "txantenna=" . escapeshellarg($wlcfg['txantenna']);
2366

    
2367
	/* Set rxantenna value */
2368
	if(isset($wlcfg['rxantenna']))
2369
		$wl_sysctl[] = "rxantenna=" . escapeshellarg($wlcfg['rxantenna']);
2370

    
2371
	/* set Distance value */
2372
	if($wlcfg['distance'])
2373
		$distance = escapeshellarg($wlcfg['distance']);
2374

    
2375
	/* Set wireless hostap mode */
2376
	if ($wlcfg['mode'] == "hostap") {
2377
		$wlcmd[] = "mediaopt hostap";
2378
	} else {
2379
		$wlcmd[] = "-mediaopt hostap";
2380
	}
2381

    
2382
	/* Set wireless adhoc mode */
2383
	if ($wlcfg['mode'] == "adhoc") {
2384
		$wlcmd[] = "mediaopt adhoc";
2385
	} else {
2386
		$wlcmd[] = "-mediaopt adhoc";
2387
	}
2388

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

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

    
2398
	/* handle pureg (802.11g) only option */
2399
	if(isset($wlcfg['pureg']['enable'])) {
2400
		$wlcmd[] = "mode 11g pureg";
2401
	} else {
2402
		$wlcmd[] = "-pureg";
2403
	}
2404

    
2405
	/* handle puren (802.11n) only option */
2406
	if(isset($wlcfg['puren']['enable'])) {
2407
		$wlcmd[] = "puren";
2408
	} else {
2409
		$wlcmd[] = "-puren";
2410
	}
2411

    
2412
	/* enable apbridge option */
2413
	if(isset($wlcfg['apbridge']['enable'])) {
2414
		$wlcmd[] = "apbridge";
2415
	} else {
2416
		$wlcmd[] = "-apbridge";
2417
	}
2418

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

    
2426
	/* handle txpower setting */
2427
	/* if($wlcfg['txpower'] <> "")
2428
		$wlcmd[] = "txpower " . escapeshellarg($wlcfg['txpower']);
2429
	*/
2430
	/* handle wme option */
2431
	if(isset($wlcfg['wme']['enable'])) {
2432
		$wlcmd[] = "wme";
2433
	} else {
2434
		$wlcmd[] = "-wme";
2435
	}
2436

    
2437
	/* set up wep if enabled */
2438
	$wepset = "";
2439
	if (isset($wlcfg['wep']['enable']) && is_array($wlcfg['wep']['key'])) {
2440
		switch($wlcfg['wpa']['auth_algs']) {
2441
			case "1":
2442
				$wepset .= "authmode open wepmode on ";
2443
				break;
2444
			case "2":
2445
				$wepset .= "authmode shared wepmode on ";
2446
				break;
2447
			case "3":
2448
				$wepset .= "authmode mixed wepmode on ";
2449
		}
2450
		$i = 1;
2451
		foreach ($wlcfg['wep']['key'] as $wepkey) {
2452
			$wepset .= "wepkey " . escapeshellarg("{$i}:{$wepkey['value']}") . " ";
2453
			if (isset($wepkey['txkey'])) {
2454
				$wlcmd[] = "weptxkey {$i} ";
2455
			}
2456
			$i++;
2457
		}
2458
		$wlcmd[] = $wepset;
2459
	} else {
2460
		$wlcmd[] = "authmode open wepmode off ";
2461
	}
2462

    
2463
	kill_hostapd($if);
2464
	mwexec(kill_wpasupplicant("{$if}"));
2465

    
2466
	/* generate wpa_supplicant/hostap config if wpa is enabled */
2467
	conf_mount_rw();
2468

    
2469
	switch ($wlcfg['mode']) {
2470
	case 'bss':
2471
		if (isset($wlcfg['wpa']['enable'])) {
2472
			$wpa .= <<<EOD
2473
ctrl_interface={$g['varrun_path']}/wpa_supplicant
2474
ctrl_interface_group=0
2475
ap_scan=1
2476
#fast_reauth=1
2477
network={
2478
ssid="{$wlcfg['ssid']}"
2479
scan_ssid=1
2480
priority=5
2481
key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
2482
psk="{$wlcfg['wpa']['passphrase']}"
2483
pairwise={$wlcfg['wpa']['wpa_pairwise']}
2484
group={$wlcfg['wpa']['wpa_pairwise']}
2485
}
2486
EOD;
2487

    
2488
			@file_put_contents("{$g['varetc_path']}/wpa_supplicant_{$if}.conf", $wpa);
2489
			unset($wpa);
2490
		}
2491
		break;
2492
	case 'hostap':
2493
		if (!empty($wlcfg['wpa']['passphrase']))
2494
			$wpa_passphrase = "wpa_passphrase={$wlcfg['wpa']['passphrase']}\n";
2495
		else
2496
			$wpa_passphrase = "";
2497
		if (isset($wlcfg['wpa']['enable'])) {
2498
			$wpa .= <<<EOD
2499
interface={$if}
2500
driver=bsd
2501
logger_syslog=-1
2502
logger_syslog_level=0
2503
logger_stdout=-1
2504
logger_stdout_level=0
2505
dump_file={$g['tmp_path']}/hostapd_{$if}.dump
2506
ctrl_interface={$g['varrun_path']}/hostapd
2507
ctrl_interface_group=wheel
2508
#accept_mac_file={$g['tmp_path']}/hostapd_{$if}.accept
2509
#deny_mac_file={$g['tmp_path']}/hostapd_{$if}.deny
2510
#macaddr_acl={$wlcfg['wpa']['macaddr_acl']}
2511
ssid={$wlcfg['ssid']}
2512
debug={$wlcfg['wpa']['debug_mode']}
2513
auth_algs={$wlcfg['wpa']['auth_algs']}
2514
wpa={$wlcfg['wpa']['wpa_mode']}
2515
wpa_key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
2516
wpa_pairwise={$wlcfg['wpa']['wpa_pairwise']}
2517
wpa_group_rekey={$wlcfg['wpa']['wpa_group_rekey']}
2518
wpa_gmk_rekey={$wlcfg['wpa']['wpa_gmk_rekey']}
2519
wpa_strict_rekey={$wlcfg['wpa']['wpa_strict_rekey']}
2520
{$wpa_passphrase}
2521

    
2522
EOD;
2523

    
2524
			if (isset($wlcfg['wpa']['rsn_preauth'])) {
2525
				$wpa .= <<<EOD
2526
# Enable the next lines for preauth when roaming. Interface = wired or wireless interface talking to the AP you want to roam from/to
2527
rsn_preauth=1
2528
rsn_preauth_interfaces={$if}
2529

    
2530
EOD;
2531
			}
2532
			if (is_array($wlcfg['wpa']['ieee8021x']) && isset($wlcfg['wpa']['ieee8021x']['enable'])) {
2533
				$wpa .= "ieee8021x=1\n";
2534

    
2535
			if (!empty($wlcfg['auth_server_addr']) && !empty($wlcfg['auth_server_shared_secret'])) {
2536
				$auth_server_port = "1812";
2537
				if (!empty($wlcfg['auth_server_port']) && is_numeric($wlcfg['auth_server_port']))
2538
					$auth_server_port = intval($wlcfg['auth_server_port']);
2539
				$wpa .= <<<EOD
2540

    
2541
auth_server_addr={$wlcfg['auth_server_addr']}
2542
auth_server_port={$auth_server_port}
2543
auth_server_shared_secret={$wlcfg['auth_server_shared_secret']}
2544

    
2545
EOD;
2546
				if (!empty($wlcfg['auth_server_addr2']) && !empty($wlcfg['auth_server_shared_secret2'])) {
2547
					$auth_server_port2 = "1812";
2548
					if (!empty($wlcfg['auth_server_port2']) && is_numeric($wlcfg['auth_server_port2']))
2549
						$auth_server_port2 = intval($wlcfg['auth_server_port2']);
2550

    
2551
					$wpa .= <<<EOD
2552
auth_server_addr={$wlcfg['auth_server_addr2']}
2553
auth_server_port={$auth_server_port2}
2554
auth_server_shared_secret={$wlcfg['auth_server_shared_secret2']}
2555

    
2556
EOD;
2557
					}
2558
				}
2559
			}
2560

    
2561
			@file_put_contents("{$g['varetc_path']}/hostapd_{$if}.conf", $wpa);
2562
			unset($wpa);
2563
		}
2564
		break;
2565
	}
2566

    
2567
	/*
2568
	 *    all variables are set, lets start up everything
2569
	 */
2570

    
2571
	$baseif = interface_get_wireless_base($if);
2572
	preg_match("/^(.*?)([0-9]*)$/", $baseif, $baseif_split);
2573
	$wl_sysctl_prefix = 'dev.' . $baseif_split[1] . '.' . $baseif_split[2];
2574

    
2575
	/* set sysctls for the wireless interface */
2576
	if (!empty($wl_sysctl)) {
2577
		fwrite($fd_set, "# sysctls for {$baseif}\n");
2578
		foreach ($wl_sysctl as $wl_sysctl_line) {
2579
			fwrite($fd_set, "{$sysctl} {$wl_sysctl_prefix}.{$wl_sysctl_line}\n");
2580
		}
2581
	}
2582

    
2583
	/* set ack timers according to users preference (if he/she has any) */
2584
	if($distance) {
2585
		fwrite($fd_set, "# Enable ATH distance settings\n");
2586
		fwrite($fd_set, "/sbin/athctrl.sh -i {$baseif} -d {$distance}\n");
2587
	}
2588

    
2589
	if (isset($wlcfg['wpa']['enable'])) {
2590
		if ($wlcfg['mode'] == "bss") {
2591
			fwrite($fd_set, "{$wpa_supplicant} -B -i {$if} -c {$g['varetc_path']}/wpa_supplicant_{$if}.conf\n");
2592
		}
2593
		if ($wlcfg['mode'] == "hostap") {
2594
			/* add line to script to restore old mac to make hostapd happy */
2595
			if (file_exists("{$g['tmp_path']}/{$if}_oldmac")) {
2596
				$if_oldmac = file_get_contents("{$g['tmp_path']}/{$if}_oldmac");
2597
				if (is_macaddr($if_oldmac))
2598
					fwrite($fd_set, "{$ifconfig} " . escapeshellarg($if) .
2599
						" link " . escapeshellarg($if_oldmac) . "\n");
2600
			}
2601

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

    
2604
			/* add line to script to restore spoofed mac after running hostapd */
2605
			if (file_exists("{$g['tmp_path']}/{$if}_oldmac")) {
2606
				if ($wl['spoofmac'])
2607
					$if_curmac = $wl['spoofmac'];
2608
				else
2609
					$if_curmac = get_interface_mac($if);
2610
				if (is_macaddr($if_curmac))
2611
					fwrite($fd_set, "{$ifconfig} " . escapeshellarg($if) .
2612
						" link " . escapeshellarg($if_curmac) . "\n");
2613
			}
2614
		}
2615
	}
2616

    
2617
	fclose($fd_set);
2618
	conf_mount_ro();
2619

    
2620
	/* Making sure regulatory settings have actually changed
2621
	 * before applying, because changing them requires bringing
2622
	 * down all wireless networks on the interface. */
2623
	exec("{$ifconfig} " . escapeshellarg($if), $output);
2624
	$ifconfig_str = implode($output);
2625
	unset($output);
2626
	$reg_changing = false;
2627

    
2628
	/* special case for the debug country code */
2629
	if ($wlcfg['regcountry'] == 'DEBUG' && !preg_match("/\sregdomain\s+DEBUG\s/si", $ifconfig_str))
2630
		$reg_changing = true;
2631
	else if ($wlcfg['regdomain'] && !preg_match("/\sregdomain\s+{$wlcfg['regdomain']}\s/si", $ifconfig_str))
2632
		$reg_changing = true;
2633
	else if ($wlcfg['regcountry'] && !preg_match("/\scountry\s+{$wlcfg['regcountry']}\s/si", $ifconfig_str))
2634
		$reg_changing = true;
2635
	else if ($wlcfg['reglocation'] == 'anywhere' && preg_match("/\s(indoor|outdoor)\s/si", $ifconfig_str))
2636
		$reg_changing = true;
2637
	else if ($wlcfg['reglocation'] && $wlcfg['reglocation'] != 'anywhere' && !preg_match("/\s{$wlcfg['reglocation']}\s/si", $ifconfig_str))
2638
		$reg_changing = true;
2639

    
2640
	if ($reg_changing) {
2641
		/* set regulatory domain */
2642
		if($wlcfg['regdomain'])
2643
			$wlregcmd[] = "regdomain " . escapeshellarg($wlcfg['regdomain']);
2644

    
2645
		/* set country */
2646
		if($wlcfg['regcountry'])
2647
			$wlregcmd[] = "country " . escapeshellarg($wlcfg['regcountry']);
2648

    
2649
		/* set location */
2650
		if($wlcfg['reglocation'])
2651
			$wlregcmd[] = escapeshellarg($wlcfg['reglocation']);
2652

    
2653
		$wlregcmd_args = implode(" ", $wlregcmd);
2654

    
2655
		/* build a complete list of the wireless clones for this interface */
2656
		$clone_list = array();
2657
		if (does_interface_exist(interface_get_wireless_clone($baseif)))
2658
			$clone_list[] = interface_get_wireless_clone($baseif);
2659
		if (isset($config['wireless']['clone']) && is_array($config['wireless']['clone'])) {
2660
			foreach ($config['wireless']['clone'] as $clone) {
2661
				if ($clone['if'] == $baseif)
2662
					$clone_list[] = $clone['cloneif'];
2663
			}
2664
		}
2665

    
2666
		/* find which clones are up and bring them down */
2667
		$clones_up = array();
2668
		foreach ($clone_list as $clone_if) {
2669
			$clone_status = pfSense_get_interface_addresses($clone_if);
2670
			if ($clone_status['status'] == 'up') {
2671
				$clones_up[] = $clone_if;
2672
				mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " down");
2673
			}
2674
		}
2675

    
2676
		/* apply the regulatory settings */
2677
		mwexec("{$ifconfig} " . escapeshellarg($if) . " {$wlregcmd_args}");
2678

    
2679
		/* bring the clones back up that were previously up */
2680
		foreach ($clones_up as $clone_if) {
2681
			mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " up");
2682

    
2683
			/*
2684
			 * Rerun the setup script for the interface if it isn't this interface, the interface
2685
			 * is in infrastructure mode, and WPA is enabled.
2686
			 * This can be removed if wpa_supplicant stops dying when you bring the interface down.
2687
			 */
2688
			if ($clone_if != $if) {
2689
				$friendly_if = convert_real_interface_to_friendly_interface_name($clone_if);
2690
				if ( !empty($friendly_if)
2691
				    && $config['interfaces'][$friendly_if]['wireless']['mode'] == "bss"
2692
				    && isset($config['interfaces'][$friendly_if]['wireless']['wpa']['enable']) ) {
2693
					mwexec("/bin/sh {$g['tmp_path']}/" . escapeshellarg($clone_if) . "_setup.sh");
2694
				}
2695
			}
2696
		}
2697
	}
2698

    
2699
	/* The mode must be specified in a separate command before ifconfig
2700
	 * will allow the mode and channel at the same time in the next. */
2701
	mwexec("/sbin/ifconfig " . escapeshellarg($if) . " mode " . escapeshellarg($standard));
2702

    
2703
	/* configure wireless */
2704
	$wlcmd_args = implode(" ", $wlcmd);
2705
	mwexec("/sbin/ifconfig " . escapeshellarg($if) . " " . $wlcmd_args, false);
2706
	unset($wlcmd_args, $wlcmd);
2707

    
2708

    
2709
	sleep(1);
2710
	/* execute hostapd and wpa_supplicant if required in shell */
2711
	mwexec("/bin/sh {$g['tmp_path']}/" . escapeshellarg($if) . "_setup.sh");
2712

    
2713
	return 0;
2714

    
2715
}
2716

    
2717
function kill_hostapd($interface) {
2718
	global $g;
2719

    
2720
	if (isvalidpid("{$g['varrun_path']}/hostapd_{$interface}.pid"))
2721
		return killbypid("{$g['varrun_path']}/hostapd_{$interface}.pid");
2722
}
2723

    
2724
function kill_wpasupplicant($interface) {
2725
	return "/bin/pkill -f \"wpa_supplicant .*{$interface}\\.conf\"\n";
2726
}
2727

    
2728
function find_dhclient_process($interface) {
2729
	if ($interface)
2730
		$pid = `/bin/pgrep -axf "dhclient: {$interface}"`;
2731
	else
2732
		$pid = 0;
2733

    
2734
	return intval($pid);
2735
}
2736

    
2737
function kill_dhclient_process($interface) {
2738
	if (empty($interface) || !does_interface_exist($interface))
2739
		return;
2740

    
2741
	$i = 0;
2742
	while ((($pid = find_dhclient_process($interface)) != 0) && ($i < 3)) {
2743
		/* 3rd time make it die for sure */
2744
		$sig = ($i == 2 ? SIGKILL : SIGTERM);
2745
		posix_kill($pid, $sig);
2746
		sleep(1);
2747
		$i++;
2748
	}
2749
	unset($i);
2750
}
2751

    
2752
function find_dhcp6c_process($interface) {
2753
	global $g;
2754

    
2755
	if ($interface && isvalidpid("{$g['varrun_path']}/dhcp6c_{$interface}.pid"))
2756
		$pid = trim(file_get_contents("{$g['varrun_path']}/dhcp6c_{$interface}.pid"), " \n");
2757
	else
2758
		return(false);
2759

    
2760
	return intval($pid);
2761
}
2762

    
2763
function interface_vlan_mtu_configured($realhwif, $mtu) {
2764
	global $config;
2765

    
2766
	if (is_array($config['vlans']) && is_array($config['vlans']['vlan'])) {
2767
		foreach ($config['vlans']['vlan'] as $vlan) {
2768
			if ($vlan['if'] != $realhwif)
2769
				continue;
2770
			$assignedport = convert_real_interface_to_friendly_interface_name($vlan['vlanif']);
2771
			if (!empty($assignedport) && !empty($config['interfaces'][$assignedport]['mtu'])) {
2772
				if (intval($config['interfaces'][$assignedport]['mtu']) > $mtu)
2773
					$mtu = $portmtu;
2774
			}
2775
		}
2776
	}
2777

    
2778
	return $mtu;
2779
}
2780

    
2781
function interface_virtual_create($interface) {
2782
	global $config;
2783

    
2784
	if (strstr($interface, "_vlan")) {
2785
		interfaces_vlan_configure($vlan);
2786
	} else if (substr($interface, 0, 3) == "gre") {
2787
		interfaces_gre_configure(0, $interface);
2788
	} else if (substr($interface, 0, 3) == "gif") {
2789
		interfaces_gif_configure(0, $interface);
2790
	} else if (substr($interface, 0, 5) == "ovpns") {
2791
		if (is_array($config['openvpn']) && is_array($config['openvpn']['openvpn-server'])) {
2792
			foreach ($config['openvpn']['openvpn-server'] as $server) {
2793
				if ($interface == "ovpns{$server['vpnid']}") {
2794
					if (!function_exists('openvpn_resync'))
2795
						require_once('openvpn.inc');
2796
					log_error("OpenVPN: Resync server {$server['description']}");
2797
					openvpn_resync('server', $server);
2798
				}
2799
			}
2800
			unset($server);
2801
		}
2802
	} else if (substr($interface, 0, 5) == "ovpnc") {
2803
		if (is_array($config['openvpn']) && is_array($config['openvpn']['openvpn-client'])) {
2804
			foreach ($config['openvpn']['openvpn-client'] as $client) {
2805
				if ($interface == "ovpnc{$client['vpnid']}") {
2806
					if (!function_exists('openvpn_resync'))
2807
						require_once('openvpn.inc');
2808
					log_error("OpenVPN: Resync server {$client['description']}");
2809
					openvpn_resync('client', $client);
2810
				}
2811
			}
2812
			unset($client);
2813
		}
2814
	} else if (substr($interface, 0, 4) == "lagg") {
2815
		interfaces_lagg_configure($interface);
2816
	} else if (substr($interface, 0, 6) == "bridge") {
2817
		interfaces_bridge_configure(0, $interface);
2818
	}
2819
}
2820

    
2821
function interface_vlan_adapt_mtu($vlanifs, $mtu) {
2822
	global $config;
2823

    
2824
	if (!is_array($vlanifs))
2825
		return;
2826

    
2827
	/* All vlans need to use the same mtu value as their parent. */
2828
	foreach ($vlanifs as $vlan) {
2829
		$assignedport = convert_real_interface_to_friendly_interface_name($vlan['vlanif']);
2830
		if (!empty($assignedport)) {
2831
			if (!empty($config['interfaces'][$assignedport]['mtu'])) {
2832
				pfSense_interface_mtu($vlan['vlanif'], $mtu);
2833
			} else {
2834
				if (get_interface_mtu($vlan['vlanif']) != $mtu)
2835
					pfSense_interface_mtu($vlan['vlanif'], $mtu);
2836
			}
2837
		} else if (get_interface_mtu($vlan['vlanif']) != $mtu)
2838
			pfSense_interface_mtu($vlan['vlanif'], $mtu);
2839
	}
2840
}
2841

    
2842
function interface_configure($interface = "wan", $reloadall = false, $linkupevent = false) {
2843
	global $config, $g;
2844
	global $interface_sn_arr_cache, $interface_ip_arr_cache;
2845
	global $interface_snv6_arr_cache, $interface_ipv6_arr_cache;
2846

    
2847
	$wancfg = $config['interfaces'][$interface];
2848

    
2849
	if (!isset($wancfg['enable']))
2850
		return;
2851

    
2852
	$realif = get_real_interface($interface);
2853
	$realhwif_array = get_parent_interface($interface);
2854
	// Need code to handle MLPPP if we ever use $realhwif for MLPPP handling
2855
	$realhwif = $realhwif_array[0];
2856

    
2857
	if (!platform_booting() && !(substr($realif, 0, 4) == "ovpn")) {
2858
		/* remove all IPv4 and IPv6 addresses */
2859
		$tmpifaces = pfSense_getall_interface_addresses($realif);
2860
		if (is_array($tmpifaces)) {
2861
			foreach ($tmpifaces as $tmpiface) {
2862
				if (is_ipaddrv6($tmpiface) || is_subnetv6($tmpiface)) {
2863
					if (!is_linklocal($tmpiface))
2864
						mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 {$tmpiface} delete");
2865
				} else {
2866
					if (is_subnetv4($tmpiface)) {
2867
						$tmpip = explode('/', $tmpiface);
2868
						$tmpip = $tmpip[0];
2869
					} else
2870
						$tmpip = $tmpiface;
2871
					pfSense_interface_deladdress($realif, $tmpip);
2872
				}
2873
			}
2874
		}
2875

    
2876
		/* only bring down the interface when both v4 and v6 are set to NONE */
2877
		if (empty($wancfg['ipaddr']) && empty($wancfg['ipaddrv6']))
2878
			interface_bring_down($interface);
2879
	}
2880

    
2881
	$interface_to_check = $realif;
2882
	switch ($wancfg['ipaddr']) {
2883
	case 'pppoe':
2884
	case 'l2tp':
2885
	case 'pptp':
2886
	case 'ppp':
2887
		$interface_to_check = $realhwif;
2888
		break;
2889
	}
2890

    
2891
	/* Need to check that the interface exists or not in the case where its coming back from disabled state see #3270 */
2892
	if (in_array(substr($realif, 0, 3), array("gre", "gif")) || !does_interface_exist($interface_to_check))
2893
		interface_virtual_create($interface_to_check);
2894

    
2895
	/* Disable Accepting router advertisements unless specifically requested */
2896
	if ($g['debug'])
2897
		log_error("Deny router advertisements for interface {$interface}");
2898
	mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 -accept_rtadv");
2899

    
2900
	/* wireless configuration? */
2901
	if (is_array($wancfg['wireless']))
2902
		interface_wireless_configure($realif, $wancfg, $wancfg['wireless']);
2903

    
2904
	$mac = get_interface_mac($realhwif);
2905
	/*
2906
	 * Don't try to reapply the spoofed MAC if it's already applied.
2907
	 * When ifconfig link is used, it cycles the interface down/up, which triggers
2908
	 * the interface config again, which attempts to spoof the MAC again,
2909
	 * which cycles the link again...
2910
	 */
2911
	if ($wancfg['spoofmac'] && ($wancfg['spoofmac'] != $mac)) {
2912
		mwexec("/sbin/ifconfig " . escapeshellarg($realhwif) .
2913
			" link " . escapeshellarg($wancfg['spoofmac']));
2914
	}  else {
2915

    
2916
		if ($mac == "ff:ff:ff:ff:ff:ff") {
2917
			/*   this is not a valid mac address.  generate a
2918
			 *   temporary mac address so the machine can get online.
2919
			 */
2920
			echo gettext("Generating new MAC address.");
2921
			$random_mac = generate_random_mac_address();
2922
			mwexec("/sbin/ifconfig " . escapeshellarg($realhwif) .
2923
				" link " . escapeshellarg($random_mac));
2924
			$wancfg['spoofmac'] = $random_mac;
2925
			write_config();
2926
			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");
2927
		}
2928
	}
2929

    
2930
	/* media */
2931
	if ($wancfg['media'] || $wancfg['mediaopt']) {
2932
		$cmd = "/sbin/ifconfig " . escapeshellarg($realhwif);
2933
		if ($wancfg['media'])
2934
			$cmd .= " media " . escapeshellarg($wancfg['media']);
2935
		if ($wancfg['mediaopt'])
2936
			$cmd .= " mediaopt " . escapeshellarg($wancfg['mediaopt']);
2937
		mwexec($cmd);
2938
	}
2939

    
2940
	/* Apply hw offloading policies as configured */
2941
	enable_hardware_offloading($interface);
2942

    
2943
	/* invalidate interface/ip/sn cache */
2944
	get_interface_arr(true);
2945
	unset($interface_ip_arr_cache[$realif]);
2946
	unset($interface_sn_arr_cache[$realif]);
2947
	unset($interface_ipv6_arr_cache[$realif]);
2948
	unset($interface_snv6_arr_cache[$realif]);
2949

    
2950
	$tunnelif = substr($realif, 0, 3);
2951
	switch ($wancfg['ipaddr']) {
2952
	case 'dhcp':
2953
		interface_dhcp_configure($interface);
2954
		break;
2955
	case 'pppoe':
2956
	case 'l2tp':
2957
	case 'pptp':
2958
	case 'ppp':
2959
		interface_ppps_configure($interface);
2960
		break;
2961
	default:
2962
		/* XXX: Kludge for now related to #3280 */
2963
		if (!in_array($tunnelif, array("gif", "gre", "ovp"))) {
2964
			if (is_ipaddrv4($wancfg['ipaddr']) && $wancfg['subnet'] <> "")
2965
				pfSense_interface_setaddress($realif, "{$wancfg['ipaddr']}/{$wancfg['subnet']}");
2966
		}
2967
		break;
2968
	}
2969

    
2970
	switch ($wancfg['ipaddrv6']) {
2971
	case 'slaac':
2972
	case 'dhcp6':
2973
		interface_dhcpv6_configure($interface, $wancfg);
2974
		break;
2975
	case '6rd':
2976
		interface_6rd_configure($interface, $wancfg);
2977
		break;
2978
	case '6to4':
2979
		interface_6to4_configure($interface, $wancfg);
2980
		break;
2981
	case 'track6':
2982
		interface_track6_configure($interface, $wancfg, $linkupevent);
2983
		break;
2984
	default:
2985
		/* XXX: Kludge for now related to #3280 */
2986
		if (!in_array($tunnelif, array("gif", "gre", "ovp"))) {
2987
			if (is_ipaddrv6($wancfg['ipaddrv6']) && $wancfg['subnetv6'] <> "") {
2988
				//pfSense_interface_setaddress($realif, "{$wancfg['ipaddrv6']}/{$wancfg['subnetv6']}");
2989
				// FIXME: Add IPv6 Support to the pfSense module
2990
				mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 {$wancfg['ipaddrv6']} prefixlen " . escapeshellarg($wancfg['subnetv6']));
2991
			}
2992
		}
2993
		break;
2994
	}
2995

    
2996
	if (!empty($wancfg['mtu'])) {
2997
		if (stristr($realif, "_vlan")) {
2998
			$assignedparent = convert_real_interface_to_friendly_interface_name($realhwif);
2999
			if (!empty($assignedparent) && !empty($config['interfaces'][$assignedparent]['mtu']))
3000
				$parentmtu = $config['interfaces'][$assignedparent]['mtu'];
3001
			else {
3002
				$parentmtu = get_interface_mtu($realhwif);
3003
				$parentmtu = interface_vlan_mtu_configured($realhwif, $parentmtu);
3004
			}
3005

    
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
				interface_vlan_adapt_mtu(link_interface_to_vlans($realhwif), $wancfg['mtu']);
3012
			} else
3013
				pfSense_interface_mtu($realif, $wancfg['mtu']);
3014
		} else if (substr($realif, 0, 4) == 'lagg') {
3015
			/* LAGG interface must be destroyed and re-created to change MTU */
3016
			if ($wancfg['mtu'] != get_interface_mtu($realif)) {
3017
				if (isset($config['laggs']['lagg']) && is_array($config['laggs']['lagg'])) {
3018
					foreach ($config['laggs']['lagg'] as $lagg) {
3019
						if ($lagg['laggif'] == $realif) {
3020
							interface_lagg_configure($lagg);
3021
							break;
3022
						}
3023
					}
3024
				}
3025
			}
3026
		} else {
3027
			if ($wancfg['mtu'] != get_interface_mtu($realif))
3028
				pfSense_interface_mtu($realif, $wancfg['mtu']);
3029

    
3030
			/* This case is needed when the parent of vlans is being configured */
3031
			interface_vlan_adapt_mtu(link_interface_to_vlans($realif), $wancfg['mtu']);
3032
		}
3033
		/* XXX: What about gre/gif/.. ? */
3034
	}
3035

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

    
3039
	interface_netgraph_needed($interface);
3040

    
3041
	if (!platform_booting()) {
3042
		link_interface_to_vips($interface, "update");
3043

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

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

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

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

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

    
3069
		if ($reloadall == true) {
3070

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

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

    
3077
			/* restart dnsmasq or unbound */
3078
			if (isset($config['dnsmasq']['enable']))
3079
				services_dnsmasq_configure();
3080
			elseif (isset($config['unbound']['enable']))
3081
				services_unbound_configure();
3082

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

    
3086
			/* XXX: which CPZONE? Needed? */
3087
			/* reload captive portal */
3088
			captiveportal_init_rules();
3089
		}
3090
	}
3091

    
3092
	interfaces_staticarp_configure($interface);
3093
	return 0;
3094
}
3095

    
3096
function interface_track6_configure($interface = "lan", $wancfg, $linkupevent = false) {
3097
	global $config, $g;
3098

    
3099
	if (!is_array($wancfg))
3100
		return;
3101

    
3102
	if (!isset($wancfg['enable']))
3103
		return;
3104

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

    
3109
	/* always configure a link-local of fe80::1:1 on the track6 interfaces */
3110
	$realif = get_real_interface($interface);
3111
	$linklocal = find_interface_ipv6_ll($realif);
3112
	if (!empty($linklocal))
3113
		mwexec("/sbin/ifconfig {$realif} inet6 {$linklocal} delete");
3114
	/* XXX: This might break for good on a carp installation using link-local as network ips */
3115
	/* XXX: Probably should remove? */
3116
	mwexec("/sbin/ifconfig {$realif} inet6 fe80::1:1%{$realif}");
3117

    
3118
	$trackcfg = $config['interfaces'][$wancfg['track6-interface']];
3119
	if (!isset($trackcfg['enable'])) {
3120
		log_error("Interface {$interface} tracking non-existant interface {$wancfg['track6-interface']}");
3121
		return;
3122
	}
3123

    
3124
	switch($trackcfg['ipaddrv6']) {
3125
	case "6to4":
3126
		if ($g['debug'])
3127
			log_error("Interface {$interface} configured via {$wancfg['track6-interface']}  type {$type}");
3128
		interface_track6_6to4_configure($interface, $wancfg);
3129
		break;
3130
	case "6rd":
3131
		if ($g['debug'])
3132
			log_error("Interface {$interface} configured via {$wancfg['track6-interface']}  type {$type}");
3133
		interface_track6_6rd_configure($interface, $wancfg);
3134
		break;
3135
	case "dhcp6":
3136
		if ($linkupevent == true) {
3137
			/* 
3138
			 * NOTE: Usually come here from rc.linkup calling so just call directly intead of generating event
3139
			 * 	Instead of disrupting all other v4 configuration just restart DHCPv6 client for now
3140
			 *
3141
			 * XXX: Probably DHCPv6 client should handle this autmagically itself?
3142
			 */
3143
			$parentrealif = get_real_interface($wancfg['track6-interface']);
3144
			$pidv6 = find_dhcp6c_process($parentrealif);
3145
			if($pidv6)
3146
				posix_kill($pidv6, SIGHUP);
3147
		}
3148
		break;
3149
	}
3150

    
3151
	if (!platform_booting() && $linkupevent == false) {
3152
		if (!function_exists('services_dhcpd_configure'))
3153
			require_once("services.inc");
3154

    
3155
		services_dhcpd_configure("inet6");
3156
	}
3157

    
3158
	return 0;
3159
}
3160

    
3161
function interface_track6_6rd_configure($interface = "lan", $lancfg) {
3162
	global $config, $g;
3163
	global $interface_ipv6_arr_cache;
3164
	global $interface_snv6_arr_cache;
3165

    
3166
	if (!is_array($lancfg))
3167
		return;
3168

    
3169
	/* If the interface is not configured via another, exit */
3170
	if (empty($lancfg['track6-interface']))
3171
		return;
3172

    
3173
	$wancfg = $config['interfaces'][$lancfg['track6-interface']];
3174
	if (empty($wancfg)) {
3175
		log_error("Interface {$interface} tracking non-existant interface {$lancfg['track6-interface']}");
3176
		return;
3177
	}
3178

    
3179
	$ip4address = get_interface_ip($lancfg['track6-interface']);
3180
	if (!is_ipaddrv4($ip4address)) { /* XXX: This should not be needed by 6rd || (is_private_ip($ip4address))) { */
3181
		log_error("The interface IPv4 '{$ip4address}' address on interface '{$lancfg['track6-interface']}' is not valid, not configuring 6RD tunnel");
3182
		return;
3183
	}
3184
	$hexwanv4 = return_hex_ipv4($ip4address);
3185

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

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

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

    
3199
	/* add the custom prefix id, max 32bits long? (64 bits - (prefixlen + (32 - v4plen)) */
3200
	/* 64 - (37 + (32 - 17)) = 8 == /52 */
3201
	$restbits = 64 - ($rd6prefixlen + (32 - $wancfg['prefix-6rd-v4plen']));
3202
	// echo "64 - (prefixlen {$rd6prefixlen} + v4len (32 - {$wancfg['prefix-6rd-v4plen']})) = {$restbits} \n";
3203
	$rd6lanbin .= substr(sprintf("%032b", str_pad($lancfg['track6-prefix-id'], 32, "0", STR_PAD_LEFT)), (32 - $restbits), 32);
3204
	/* fill the rest out with zeros */
3205
	$rd6lanbin = str_pad($rd6lanbin, 128, "0", STR_PAD_RIGHT);
3206

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

    
3210
	$lanif = get_real_interface($interface);
3211
	$oip = find_interface_ipv6($lanif);
3212
	if (is_ipaddrv6($oip))
3213
		mwexec("/sbin/ifconfig {$lanif} inet6 {$oip} delete");
3214
	unset($interface_ipv6_arr_cache[$lanif]);
3215
	unset($interface_snv6_arr_cache[$lanif]);
3216
	log_error("rd6 {$interface} with ipv6 address {$rd6lan} based on {$lancfg['track6-interface']} ipv4 {$ip4address}");
3217
	mwexec("/sbin/ifconfig {$lanif} inet6 {$rd6lan} prefixlen 64");
3218

    
3219
	return 0;
3220
}
3221

    
3222
function interface_track6_6to4_configure($interface = "lan", $lancfg) {
3223
	global $config, $g;
3224
	global $interface_ipv6_arr_cache;
3225
	global $interface_snv6_arr_cache;
3226

    
3227
	if (!is_array($lancfg))
3228
		return;
3229

    
3230
	/* If the interface is not configured via another, exit */
3231
	if (empty($lancfg['track6-interface']))
3232
		return;
3233

    
3234
	$wancfg = $config['interfaces'][$lancfg['track6-interface']];
3235
	if (empty($wancfg)) {
3236
		log_error("Interface {$interface} tracking non-existant interface {$lancfg['track6-interface']}");
3237
		return;
3238
	}
3239

    
3240
	$ip4address = get_interface_ip($lancfg['track6-interface']);
3241
	if (!is_ipaddrv4($ip4address) || is_private_ip($ip4address)) {
3242
		log_error("The interface IPv4 '{$ip4address}' address on interface '{$lancfg['track6-interface']}' is not public, not configuring 6RD tunnel");
3243
		return;
3244
	}
3245
	$hexwanv4 = return_hex_ipv4($ip4address);
3246

    
3247
	/* create the long prefix notation for math, save the prefix length */
3248
	$sixto4prefix = "2002::";
3249
	$sixto4prefixlen = 16;
3250
	$sixto4prefix = Net_IPv6::uncompress($sixto4prefix);
3251

    
3252
	/* binary presentation of the prefix for all 128 bits. */
3253
	$sixto4lanbin = convert_ipv6_to_128bit($sixto4prefix);
3254

    
3255
	/* just save the left prefix length bits */
3256
	$sixto4lanbin = substr($sixto4lanbin, 0, $sixto4prefixlen);
3257
	/* add the v4 address */
3258
	$sixto4lanbin .= sprintf("%032b", hexdec($hexwanv4));
3259
	/* add the custom prefix id */
3260
	$sixto4lanbin .= sprintf("%016b", $lancfg['track6-prefix-id']);
3261
	/* fill the rest out with zeros */
3262
	$sixto4lanbin = str_pad($sixto4lanbin, 128, "0", STR_PAD_RIGHT);
3263

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

    
3267
	$lanif = get_real_interface($interface);
3268
	$oip = find_interface_ipv6($lanif);
3269
	if (is_ipaddrv6($oip))
3270
		mwexec("/sbin/ifconfig {$lanif} inet6 {$oip} delete");
3271
	unset($interface_ipv6_arr_cache[$lanif]);
3272
	unset($interface_snv6_arr_cache[$lanif]);
3273
	log_error("sixto4 {$interface} with ipv6 address {$sixto4lan} based on {$lancfg['track6-interface']} ipv4 {$ip4address}");
3274
	mwexec("/sbin/ifconfig {$lanif} inet6 {$sixto4lan} prefixlen 64");
3275

    
3276
	return 0;
3277
}
3278

    
3279
function interface_6rd_configure($interface = "wan", $wancfg) {
3280
	global $config, $g;
3281

    
3282
	/* because this is a tunnel interface we can only function
3283
	 *	with a public IPv4 address on the interface */
3284

    
3285
	if (!is_array($wancfg))
3286
		return;
3287

    
3288
	if (!is_module_loaded('if_stf.ko'))
3289
		mwexec('/sbin/kldload if_stf.ko');
3290

    
3291
	$wanif = get_real_interface($interface);
3292
	$ip4address = find_interface_ip($wanif);
3293
	if (!is_ipaddrv4($ip4address)) {
3294
		log_error("The interface IPv4 '{$ip4address}' address on interface '{$wanif}' is not public, not configuring 6RD tunnel");
3295
		return false;
3296
	}
3297
	$hexwanv4 = return_hex_ipv4($ip4address);
3298

    
3299
	if (!is_numeric($wancfg['prefix-6rd-v4plen']))
3300
		$wancfg['prefix-6rd-v4plen'] = 0;
3301

    
3302
	/* create the long prefix notation for math, save the prefix length */
3303
	$rd6prefix = explode("/", $wancfg['prefix-6rd']);
3304
	$rd6prefixlen = $rd6prefix[1];
3305
	$brgw = explode('.', $wancfg['gateway-6rd']);
3306
	$rd6brgw = rtrim($rd6prefix[0], ':') . ':' . dechex($brgw[0]) . dechex($brgw[1]) . ':' . dechex($brgw[2]) . dechex($brgw[3]) . '::';
3307
	unset($brgw);
3308
	$rd6prefix = Net_IPv6::uncompress($rd6prefix[0]);
3309

    
3310
	/* binary presentation of the prefix for all 128 bits. */
3311
	$rd6prefixbin = convert_ipv6_to_128bit($rd6prefix);
3312

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

    
3320
	/* convert the 128 bits for the broker address back into a valid IPv6 address */
3321
	$rd6prefix = convert_128bit_to_ipv6($rd6prefixbin);
3322

    
3323

    
3324
	/* XXX: need to extend to support variable prefix size for v4 */
3325
	if (!is_module_loaded("if_stf"))
3326
		mwexec("/sbin/kldload if_stf.ko");
3327
	$stfiface = "{$interface}_stf";
3328
	if (does_interface_exist($stfiface))
3329
		pfSense_interface_destroy($stfiface);
3330
	$tmpstfiface = pfSense_interface_create("stf");
3331
	pfSense_interface_rename($tmpstfiface, $stfiface);
3332
	pfSense_interface_flags($stfiface, IFF_LINK2);
3333
	mwexec("/sbin/ifconfig {$stfiface} inet6 {$rd6prefix}/{$rd6prefixlen}");
3334
	mwexec("/sbin/ifconfig {$stfiface} stfv4br " . escapeshellarg($wancfg['gateway-6rd']));
3335
	if ($wancfg['prefix-6rd-v4plen'] >= 0 && $wancfg['prefix-6rd-v4plen'] <= 32)
3336
		mwexec("/sbin/ifconfig {$stfiface} stfv4net {$ip4address}/" . escapeshellarg($wancfg['prefix-6rd-v4plen']));
3337
	if ($g['debug'])
3338
		log_error("Created 6rd interface {$stfiface} {$rd6prefix}/{$rd6prefixlen}");
3339

    
3340
	/* write out a default router file */
3341
	file_put_contents("{$g['tmp_path']}/{$wanif}_routerv6", "{$rd6brgw}\n");
3342
	file_put_contents("{$g['tmp_path']}/{$wanif}_defaultgwv6", "{$rd6brgw}\n");
3343

    
3344
	$ip4gateway = get_interface_gateway($interface);
3345
	if (is_ipaddrv4($ip4gateway))
3346
		mwexec("/sbin/route change -host " . escapeshellarg($wancfg['gateway-6rd']) . " {$ip4gateway}");
3347

    
3348
	/* configure dependent interfaces */
3349
	if (!platform_booting())
3350
		link_interface_to_track6($interface, "update");
3351

    
3352
	return 0;
3353
}
3354

    
3355
function interface_6to4_configure($interface = "wan", $wancfg){
3356
	global $config, $g;
3357

    
3358
	/* because this is a tunnel interface we can only function
3359
	 *	with a public IPv4 address on the interface */
3360

    
3361
	if (!is_array($wancfg))
3362
		return;
3363

    
3364
	$wanif = get_real_interface($interface);
3365
	$ip4address = find_interface_ip($wanif);
3366
	if((!is_ipaddrv4($ip4address)) || (is_private_ip($ip4address))) {
3367
		log_error("The interface IPv4 '{$ip4address}' address on interface '{$wanif}' is not public, not configuring 6RD tunnel");
3368
		return false;
3369
	}
3370

    
3371
	/* create the long prefix notation for math, save the prefix length */
3372
	$stfprefixlen = 16;
3373
	$stfprefix = Net_IPv6::uncompress("2002::");
3374
	$stfarr = explode(":", $stfprefix);
3375
	$v4prefixlen = "0";
3376

    
3377
	/* we need the hex form of the interface IPv4 address */
3378
	$ip4arr = explode(".", $ip4address);
3379
	$hexwanv4 = "";
3380
	foreach($ip4arr as $octet)
3381
		$hexwanv4 .= sprintf("%02x", $octet);
3382

    
3383
	/* we need the hex form of the broker IPv4 address */
3384
	$ip4arr = explode(".", "192.88.99.1");
3385
	$hexbrv4 = "";
3386
	foreach($ip4arr as $octet)
3387
		$hexbrv4 .= sprintf("%02x", $octet);
3388

    
3389
	/* binary presentation of the prefix for all 128 bits. */
3390
	$stfprefixbin = "";
3391
	foreach($stfarr as $element) {
3392
		$stfprefixbin .= sprintf("%016b", hexdec($element));
3393
	}
3394
	/* just save the left prefix length bits */
3395
	$stfprefixstartbin = substr($stfprefixbin, 0, $stfprefixlen);
3396

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

    
3401
	/* for the local subnet too. */
3402
	$stflanbin = substr(sprintf("%032b", hexdec($hexwanv4)), $v4prefixlen, 32);
3403
	$stflanbin = str_pad($stfprefixstartbin . $stflanbin, 128, "0", STR_PAD_RIGHT);
3404

    
3405
	/* convert the 128 bits for the broker address back into a valid IPv6 address */
3406
	$stfbrarr = array();
3407
	$stfbrbinarr = array();
3408
	$stfbrbinarr = str_split($stfbrokerbin, 16);
3409
	foreach($stfbrbinarr as $bin)
3410
		$stfbrarr[] = dechex(bindec($bin));
3411
	$stfbrgw = Net_IPv6::compress(implode(":", $stfbrarr));
3412

    
3413
	/* convert the 128 bits for the broker address back into a valid IPv6 address */
3414
	$stflanarr = array();
3415
	$stflanbinarr = array();
3416
	$stflanbinarr = str_split($stflanbin, 16);
3417
	foreach($stflanbinarr as $bin)
3418
		$stflanarr[] = dechex(bindec($bin));
3419
	$stflanpr = Net_IPv6::compress(implode(":", $stflanarr));
3420
	$stflanarr[7] = 1;
3421
	$stflan = Net_IPv6::compress(implode(":", $stflanarr));
3422

    
3423
	/* setup the stf interface */
3424
	if (!is_module_loaded("if_stf"))
3425
		mwexec("/sbin/kldload if_stf.ko");
3426
	$stfiface = "{$interface}_stf";
3427
	if (does_interface_exist($stfiface))
3428
		pfSense_interface_destroy($stfiface);
3429
	$tmpstfiface = pfSense_interface_create("stf");
3430
	pfSense_interface_rename($tmpstfiface, $stfiface);
3431
	pfSense_interface_flags($stfiface, IFF_LINK2);
3432
	mwexec("/sbin/ifconfig {$stfiface} inet6 {$stflanpr} prefixlen 16");
3433

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

    
3437
	/* write out a default router file */
3438
	file_put_contents("{$g['tmp_path']}/{$wanif}_routerv6", "{$stfbrgw}");
3439
	file_put_contents("{$g['tmp_path']}/{$wanif}_defaultgwv6", "{$stfbrgw}");
3440

    
3441
	$ip4gateway = get_interface_gateway($interface);
3442
	if (is_ipaddrv4($ip4gateway))
3443
		mwexec("/sbin/route change -host 192.88.99.1 {$ip4gateway}");
3444

    
3445
	if (!platform_booting())
3446
		link_interface_to_track6($interface, "update");
3447

    
3448
	return 0;
3449
}
3450

    
3451
function interface_dhcpv6_configure($interface = "wan", $wancfg) {
3452
	global $config, $g;
3453

    
3454
	if (!is_array($wancfg))
3455
		return;
3456

    
3457
	$wanif = get_real_interface($interface, "inet6");
3458
	$dhcp6cconf = "";
3459
	$dhcp6cconf .= "interface {$wanif} {\n";
3460

    
3461
	/* for SLAAC interfaces we do fire off a dhcp6 client for just our name servers */
3462
	if($wancfg['ipaddrv6'] == "slaac") {
3463
		$dhcp6cconf .= "	information-only;\n";
3464
		$dhcp6cconf .= "	request domain-name-servers;\n";
3465
		$dhcp6cconf .= "	request domain-name;\n";
3466
		$dhcp6cconf .= "	script \"{$g['varetc_path']}/dhcp6c_{$interface}_script.sh\"; # we'd like some nameservers please\n";
3467
		$dhcp6cconf .= "};\n";
3468
	} else {
3469
		/* skip address request if this is set */
3470
		if(!isset($wancfg['dhcp6prefixonly']))
3471
			$dhcp6cconf .= "        send ia-na 0;   # request stateful address\n";
3472
		if(is_numeric($wancfg['dhcp6-ia-pd-len']))
3473
			$dhcp6cconf .= "	send ia-pd 0;	# request prefix delegation\n";
3474

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

    
3479
		$dhcp6cconf .= "};\n";
3480

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

    
3484
		if(is_numeric($wancfg['dhcp6-ia-pd-len'])) {
3485
			/* Setup the prefix delegation */
3486
			$dhcp6cconf .= "id-assoc pd 0 {\n";
3487
			$preflen = 64 - $wancfg['dhcp6-ia-pd-len'];
3488
			if (isset($wancfg['dhcp6-ia-pd-send-hint']))
3489
				$dhcp6cconf .= "	prefix ::/{$preflen} infinity;\n";
3490
			$iflist = link_interface_to_track6($interface);
3491
			foreach ($iflist as $friendly => $ifcfg) {
3492
				if (is_numeric($ifcfg['track6-prefix-id'])) {
3493
					if ($g['debug'])
3494
						log_error("setting up $ifdescr - {$ifcfg['track6-prefix-id']}");
3495
					$realif = get_real_interface($friendly);
3496
					$dhcp6cconf .= "	prefix-interface {$realif} {\n";
3497
					$dhcp6cconf .= "		sla-id {$ifcfg['track6-prefix-id']};\n";
3498
					$dhcp6cconf .= "		sla-len {$wancfg['dhcp6-ia-pd-len']};\n";
3499
					$dhcp6cconf .= "	};\n";
3500
				}
3501
			}
3502
			unset($preflen, $iflist, $ifcfg);
3503
			$dhcp6cconf .= "};\n";
3504
		}
3505
	}
3506

    
3507
	// DHCP6 Config File Advanced
3508
	if ($wancfg['adv_dhcp6_config_advanced']) { $dhcp6cconf = DHCP6_Config_File_Advanced($interface, $wancfg, $wanif); }
3509

    
3510
	// DHCP6 Config File Override
3511
	if ($wancfg['adv_dhcp6_config_file_override']) { $dhcp6cconf = DHCP6_Config_File_Override($wancfg, $wanif); }
3512

    
3513
	/* wide-dhcp6c works for now. */
3514
	if (!@file_put_contents("{$g['varetc_path']}/dhcp6c_{$interface}.conf", $dhcp6cconf)) {
3515
		printf("Error: cannot open dhcp6c_{$interface}.conf in interface_dhcpv6_configure() for writing.\n");
3516
		unset($dhcp6cconf);
3517
		return 1;
3518
	}
3519
	unset($dhcp6cconf);
3520

    
3521
	$dhcp6cscript = "#!/bin/sh\n";
3522
	$dhcp6cscript .= "# This shell script launches /etc/rc.newwanipv6 with a interface argument.\n";
3523
	$dhcp6cscript .= "dmips=\${new_domain_name_servers}\n";
3524
	$dhcp6cscript .= "dmnames=\${new_domain_name}\n";
3525
	$dhcp6cscript .= "/usr/local/sbin/fcgicli -f /etc/rc.newwanipv6 -d \"interface={$wanif}&dmnames=\${dmnames}&dmips=\${dmips}\"\n";
3526
	/* Add wide-dhcp6c shell script here. Because we can not pass a argument to it. */
3527
	if (!@file_put_contents("{$g['varetc_path']}/dhcp6c_{$interface}_script.sh", $dhcp6cscript)) {
3528
		printf("Error: cannot open dhcp6c_{$interface}_script.sh in interface_dhcpv6_configure() for writing.\n");
3529
		unset($dhcp6cscript);
3530
		return 1;
3531
	}
3532
	unset($dhcp6cscript);
3533
	@chmod("{$g['varetc_path']}/dhcp6c_{$interface}_script.sh", 0755);
3534

    
3535
	$rtsoldscript = "#!/bin/sh\n";
3536
	$rtsoldscript .= "# This shell script launches dhcp6c and configured gateways for this interface.\n";
3537
	$rtsoldscript .= "echo $2 > {$g['tmp_path']}/{$wanif}_routerv6\n";
3538
	$rtsoldscript .= "echo $2 > {$g['tmp_path']}/{$wanif}_defaultgwv6\n";
3539
	$rtsoldscript .= "/usr/bin/logger -t rtsold \"Recieved RA specifying route \$2 for interface {$interface}({$wanif})\"\n";
3540
	$rtsoldscript .= "if [ -f {$g['varrun_path']}/dhcp6c_{$wanif}.pid ]; then\n";
3541
	$rtsoldscript .= "\t/bin/pkill -F {$g['varrun_path']}/dhcp6c_{$wanif}.pid\n";
3542
	$rtsoldscript .= "\t/bin/sleep 1\n";
3543
	$rtsoldscript .= "fi\n";
3544
	$rtsoldscript .= "/usr/local/sbin/dhcp6c -d -c {$g['varetc_path']}/dhcp6c_{$interface}.conf -p {$g['varrun_path']}/dhcp6c_{$wanif}.pid {$wanif}\n";
3545
	$rtsoldscript .= "/usr/bin/logger -t rtsold \"Starting dhcp6 client for interface {$interface}({$wanif})\"\n";
3546
	/* Add wide-dhcp6c shell script here. Because we can not pass a argument to it. */
3547
	if (!@file_put_contents("{$g['varetc_path']}/rtsold_{$wanif}_script.sh", $rtsoldscript)) {
3548
		printf("Error: cannot open rtsold_{$interface}_script.sh in interface_dhcpv6_configure() for writing.\n");
3549
		unset($rtsoldscript);
3550
		return 1;
3551
	}
3552
	unset($rtsoldscript);
3553
	@chmod("{$g['varetc_path']}/rtsold_{$wanif}_script.sh", 0755);
3554

    
3555
	/* accept router advertisements for this interface */
3556
	set_single_sysctl("net.inet6.ip6.accept_rtadv", "1");
3557
	log_error("Accept router advertisements on interface {$wanif} ");
3558
	mwexec("/sbin/ifconfig {$wanif} inet6 accept_rtadv");
3559

    
3560
	/* fire up rtsold for IPv6 RAs first, this backgrounds immediately. It will call dhcp6c */
3561
	if (isvalidpid("{$g['varrun_path']}/rtsold_{$wanif}.pid")) {
3562
		killbypid("{$g['varrun_path']}/rtsold_{$wanif}.pid");
3563
		sleep(2);
3564
	}
3565
	mwexec("/usr/sbin/rtsold -1 -p {$g['varrun_path']}/rtsold_{$wanif}.pid -O {$g['varetc_path']}/rtsold_{$wanif}_script.sh {$wanif}");
3566

    
3567
	/* NOTE: will be called from rtsold invoked script
3568
	 * link_interface_to_track6($interface, "update");
3569
	 */
3570

    
3571
	return 0;
3572
}
3573

    
3574
function DHCP6_Config_File_Advanced($interface, $wancfg, $wanif) {
3575
	global $g;
3576

    
3577
	$send_options = "";
3578
	if ($wancfg['adv_dhcp6_interface_statement_send_options'] != '') {
3579
		$options = split(",", $wancfg['adv_dhcp6_interface_statement_send_options']);
3580
		foreach ($options as $option) {
3581
			$send_options .= "\tsend " . trim($option) . ";\n";
3582
		}
3583
	}
3584

    
3585
	$request_options = "";
3586
	if ($wancfg['adv_dhcp6_interface_statement_request_options'] != '') {
3587
		$options = split(",", $wancfg['adv_dhcp6_interface_statement_request_options']);
3588
		foreach ($options as $option) {
3589
			$request_options .= "\trequest " . trim($option) . ";\n";
3590
		}
3591
	}
3592

    
3593
	$information_only = "";
3594
	if ($wancfg['adv_dhcp6_interface_statement_information_only_enable'] != '') 
3595
		$information_only = "\tinformation-only;\n";
3596

    
3597
	$script = "\tscript \"{$g['varetc_path']}/dhcp6c_{$interface}_script.sh\";\n";
3598
	if ($wancfg['adv_dhcp6_interface_statement_script'] != '')
3599
		$script = "\tscript \"{$wancfg['adv_dhcp6_interface_statement_script']}\";\n";
3600

    
3601
	$interface_statement  = "interface";
3602
	$interface_statement .= " {$wanif}";
3603
	$interface_statement .= " {\n";
3604
	$interface_statement .= "$send_options";
3605
	$interface_statement .= "$request_options";
3606
	$interface_statement .= "$information_only";
3607
	$interface_statement .= "$script";
3608
	$interface_statement .= "};\n";
3609

    
3610
	$id_assoc_statement_address = "";
3611
	if ($wancfg['adv_dhcp6_id_assoc_statement_address_enable'] != '') {
3612
		$id_assoc_statement_address .= "id-assoc";
3613
		$id_assoc_statement_address .= " na";
3614
		if (is_numeric($wancfg['adv_dhcp6_id_assoc_statement_address_id'])) 
3615
			$id_assoc_statement_address .= " {$wancfg['adv_dhcp6_id_assoc_statement_address_id']}";
3616
		$id_assoc_statement_address .= " { ";
3617

    
3618
		if ( ($wancfg['adv_dhcp6_id_assoc_statement_address'] != '') && 
3619
			 (is_numeric($wancfg['adv_dhcp6_id_assoc_statement_address_pltime']) || 
3620
			 ($wancfg['adv_dhcp6_id_assoc_statement_address_pltime'] == 'infinity')) ) {
3621
			$id_assoc_statement_address .= "\n\taddress";
3622
			$id_assoc_statement_address .= " {$wancfg['adv_dhcp6_id_assoc_statement_address']}";
3623
			$id_assoc_statement_address .= " {$wancfg['adv_dhcp6_id_assoc_statement_address_pltime']}";
3624
			if ( (is_numeric($wancfg['adv_dhcp6_id_assoc_statement_address_vltime'])) || 
3625
							($wancfg['adv_dhcp6_id_assoc_statement_address_vltime'] == 'infinity') ) 
3626
				$id_assoc_statement_address .= " {$wancfg['adv_dhcp6_id_assoc_statement_address_vltime']}";
3627
			$id_assoc_statement_address .= ";\n";
3628
		}
3629

    
3630
		$id_assoc_statement_address  .= "};\n";
3631
	}
3632

    
3633
	$id_assoc_statement_prefix = "";
3634
	if ($wancfg['adv_dhcp6_id_assoc_statement_prefix_enable'] != '') {
3635
		$id_assoc_statement_prefix .= "id-assoc";
3636
		$id_assoc_statement_prefix .= " pd";
3637
		if (is_numeric($wancfg['adv_dhcp6_id_assoc_statement_prefix_id'])) 
3638
			$id_assoc_statement_prefix .= " {$wancfg['adv_dhcp6_id_assoc_statement_prefix_id']}";
3639
		$id_assoc_statement_prefix .= " { ";
3640

    
3641
		if ( ($wancfg['adv_dhcp6_id_assoc_statement_prefix'] != '') && 
3642
			 (is_numeric($wancfg['adv_dhcp6_id_assoc_statement_prefix_pltime']) || 
3643
			 ($wancfg['adv_dhcp6_id_assoc_statement_prefix_pltime'] == 'infinity')) ) {
3644
			$id_assoc_statement_prefix .= "\n\tprefix";
3645
			$id_assoc_statement_prefix .= " {$wancfg['adv_dhcp6_id_assoc_statement_prefix']}";
3646
			$id_assoc_statement_prefix .= " {$wancfg['adv_dhcp6_id_assoc_statement_prefix_pltime']}";
3647
			if ( (is_numeric($wancfg['adv_dhcp6_id_assoc_statement_prefix_vltime'])) || 
3648
						  ($wancfg['adv_dhcp6_id_assoc_statement_prefix_vltime'] == 'infinity') ) 
3649
				$id_assoc_statement_prefix .= " {$wancfg['adv_dhcp6_id_assoc_statement_prefix_vltime']}";
3650
			$id_assoc_statement_prefix .= ";";
3651
		}
3652

    
3653
		if (is_numeric($wancfg['adv_dhcp6_prefix_interface_statement_sla_id'])) {
3654
			$id_assoc_statement_prefix .= "\n\tprefix-interface";
3655
			$id_assoc_statement_prefix .= " {$wanif}";
3656
			$id_assoc_statement_prefix .= " {\n";
3657
			$id_assoc_statement_prefix .= "\t\tsla-id {$wancfg['adv_dhcp6_prefix_interface_statement_sla_id']};\n";
3658
			if ( ($wancfg['adv_dhcp6_prefix_interface_statement_sla_len'] >= 0) && 
3659
				 ($wancfg['adv_dhcp6_prefix_interface_statement_sla_len'] <= 128) ) 
3660
				 $id_assoc_statement_prefix .= "\t\tsla-len {$wancfg['adv_dhcp6_prefix_interface_statement_sla_len']};\n";
3661
			$id_assoc_statement_prefix .= "\t};";
3662
		}
3663

    
3664
		if ( ($wancfg['adv_dhcp6_id_assoc_statement_prefix'] != '') || 
3665
			 (is_numeric($wancfg['adv_dhcp6_prefix_interface_statement_sla_id'])) ) { 
3666
			$id_assoc_statement_prefix .= "\n";
3667
		}
3668

    
3669
		$id_assoc_statement_prefix  .= "};\n";
3670
	}
3671

    
3672
	$authentication_statement = "";
3673
	if ( ($wancfg['adv_dhcp6_authentication_statement_authname'] != '') && 
3674
		 ($wancfg['adv_dhcp6_authentication_statement_protocol'] == 'delayed') ) {
3675
		$authentication_statement .= "authentication";
3676
		$authentication_statement .= " {$wancfg['adv_dhcp6_authentication_statement_authname']}";
3677
		$authentication_statement .= " {\n";
3678
		$authentication_statement .= "\tprotocol {$wancfg['adv_dhcp6_authentication_statement_protocol']};\n";
3679
		if (preg_match("/(hmac(-)?md5)||(HMAC(-)?MD5)/", $wancfg['adv_dhcp6_authentication_statement_algorithm'])) 
3680
			$authentication_statement .= "\talgorithm {$wancfg['adv_dhcp6_authentication_statement_algorithm']};\n";
3681
		if ($wancfg['adv_dhcp6_authentication_statement_rdm'] == 'monocounter') 
3682
			$authentication_statement .= "\trdm {$wancfg['adv_dhcp6_authentication_statement_rdm']};\n";
3683
		$authentication_statement .= "};\n";
3684
	}
3685

    
3686
	$key_info_statement = "";
3687
	if ( ($wancfg['adv_dhcp6_key_info_statement_keyname'] != '') && 
3688
		 ($wancfg['adv_dhcp6_key_info_statement_realm'] != '') && 
3689
		 (is_numeric($wancfg['adv_dhcp6_key_info_statement_keyid'])) && 
3690
		 ($wancfg['adv_dhcp6_key_info_statement_secret'] != '') ) {
3691
		$key_info_statement .= "keyinfo";
3692
		$key_info_statement .= " {$wancfg['adv_dhcp6_key_info_statement_keyname']}";
3693
		$key_info_statement .= " {\n";
3694
		$key_info_statement .= "\trealm \"{$wancfg['adv_dhcp6_key_info_statement_realm']}\";\n";
3695
		$key_info_statement .= "\tkeyid {$wancfg['adv_dhcp6_key_info_statement_keyid']};\n";
3696
		$key_info_statement .= "\tsecret \"{$wancfg['adv_dhcp6_key_info_statement_secret']}\";\n";
3697
		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'])) 
3698
			$key_info_statement .= "\texpire \"{$wancfg['adv_dhcp6_key_info_statement_expire']}\";\n";
3699
		$key_info_statement .= "};\n";
3700
	}
3701

    
3702
	$dhcp6cconf  = $interface_statement;
3703
	$dhcp6cconf .= $id_assoc_statement_address;
3704
	$dhcp6cconf .= $id_assoc_statement_prefix;
3705
	$dhcp6cconf .= $authentication_statement;
3706
	$dhcp6cconf .= $key_info_statement;
3707

    
3708
	$dhcp6cconf = DHCP6_Config_File_Substitutions($wancfg, $wanif, $dhcp6cconf);
3709

    
3710
	return $dhcp6cconf;
3711
}
3712

    
3713

    
3714
function DHCP6_Config_File_Override($wancfg, $wanif) {
3715

    
3716
	$dhcp6cconf = file_get_contents($wancfg['adv_dhcp6_config_file_override_path']);
3717
	$dhcp6cconf = DHCP6_Config_File_Substitutions($wancfg, $wanif, $dhcp6cconf);
3718

    
3719
	return $dhcp6cconf;
3720
}
3721

    
3722

    
3723
function DHCP6_Config_File_Substitutions($wancfg, $wanif, $dhcp6cconf) {
3724

    
3725
	$dhcp6cconf = DHCP_Config_File_Substitutions($wancfg, $wanif, $dhcp6cconf);
3726

    
3727
	return $dhcp6cconf;
3728
}
3729

    
3730

    
3731
function interface_dhcp_configure($interface = "wan") {
3732
	global $config, $g;
3733

    
3734
	$wancfg = $config['interfaces'][$interface];
3735
	$wanif = $wancfg['if'];
3736
	if (empty($wancfg))
3737
		$wancfg = array();
3738

    
3739
	/* generate dhclient_wan.conf */
3740
	$fd = fopen("{$g['varetc_path']}/dhclient_{$interface}.conf", "w");
3741
	if (!$fd) {
3742
		printf(printf(gettext("Error: cannot open dhclient_%s.conf in interface_dhcp_configure() for writing.%s"), $interface, "\n"));
3743
		return 1;
3744
	}
3745

    
3746
	if ($wancfg['dhcphostname']) {
3747
		$dhclientconf_hostname = "send dhcp-client-identifier \"{$wancfg['dhcphostname']}\";\n";
3748
		$dhclientconf_hostname .= "\tsend host-name \"{$wancfg['dhcphostname']}\";\n";
3749
	} else {
3750
		$dhclientconf_hostname = "";
3751
	}
3752

    
3753
	$wanif = get_real_interface($interface);
3754
	if (empty($wanif)) {
3755
		log_error(sprintf(gettext("Invalid interface \"%s\" in interface_dhcp_configure()"), $interface));
3756
		return 0;
3757
	}
3758
	$dhclientconf = "";
3759

    
3760
	$dhclientconf .= <<<EOD
3761
interface "{$wanif}" {
3762
timeout 60;
3763
retry 15;
3764
select-timeout 0;
3765
initial-interval 1;
3766
	{$dhclientconf_hostname}
3767
	script "/sbin/dhclient-script";
3768
EOD;
3769

    
3770
if (is_ipaddrv4($wancfg['dhcprejectfrom'])) {
3771
	$dhclientconf .= <<<EOD
3772

    
3773
	reject {$wancfg['dhcprejectfrom']};
3774
EOD;
3775
}
3776
	$dhclientconf .= <<<EOD
3777

    
3778
}
3779

    
3780
EOD;
3781

    
3782
	// DHCP Config File Advanced
3783
	if ($wancfg['adv_dhcp_config_advanced']) { $dhclientconf = DHCP_Config_File_Advanced($interface, $wancfg, $wanif); }
3784

    
3785
if(is_ipaddr($wancfg['alias-address'])) {
3786
	$subnetmask = gen_subnet_mask($wancfg['alias-subnet']);
3787
	$dhclientconf .= <<<EOD
3788
alias {
3789
	interface  "{$wanif}";
3790
	fixed-address {$wancfg['alias-address']};
3791
	option subnet-mask {$subnetmask};
3792
}
3793

    
3794
EOD;
3795
}
3796

    
3797
	// DHCP Config File Override
3798
	if ($wancfg['adv_dhcp_config_file_override']) { $dhclientconf = DHCP_Config_File_Override($wancfg, $wanif); }
3799

    
3800
	fwrite($fd, $dhclientconf);
3801
	fclose($fd);
3802

    
3803
	/* bring wan interface up before starting dhclient */
3804
	if($wanif)
3805
		interfaces_bring_up($wanif);
3806
	else
3807
		log_error(printf(gettext("Could not bring up %s interface in interface_dhcp_configure()"), $wanif));
3808

    
3809
	/* Make sure dhclient is not running */
3810
	kill_dhclient_process($wanif);
3811

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

    
3815
	return 0;
3816
}
3817

    
3818
function DHCP_Config_File_Advanced($interface, $wancfg, $wanif) {
3819

    
3820
	$hostname = "";
3821
	if ($wancfg['dhcphostname'] != '') {
3822
		$hostname = "\tsend host-name \"{$wancfg['dhcphostname']}\";\n";
3823
	}
3824

    
3825
	/* DHCP Protocol Timings */
3826
	$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");
3827
	foreach ($protocol_timings as $Protocol_Timing => $PT_Name) {
3828
		$pt_variable = "{$Protocol_Timing}";
3829
		${$pt_variable} = "";
3830
		if ($wancfg[$Protocol_Timing] != "") {
3831
			${$pt_variable} = "{$PT_Name} {$wancfg[$Protocol_Timing]};\n";
3832
		}
3833
	}
3834

    
3835
	$send_options = "";
3836
	if ($wancfg['adv_dhcp_send_options'] != '') {
3837
		$options = split(",", $wancfg['adv_dhcp_send_options']);
3838
		foreach ($options as $option) {
3839
			$send_options .= "\tsend " . trim($option) . ";\n";
3840
		}
3841
	}
3842

    
3843
	$request_options = "";
3844
	if ($wancfg['adv_dhcp_request_options'] != '') {
3845
		$request_options = "\trequest {$wancfg['adv_dhcp_request_options']};\n";
3846
	}
3847

    
3848
	$required_options = "";
3849
	if ($wancfg['adv_dhcp_required_options'] != '') {
3850
		$required_options = "\trequire {$wancfg['adv_dhcp_required_options']};\n";
3851
	}
3852

    
3853
	$option_modifiers = "";
3854
	if ($wancfg['adv_dhcp_option_modifiers'] != '') {
3855
		$modifiers = split(",", $wancfg['adv_dhcp_option_modifiers']);
3856
		foreach ($modifiers as $modifier) {
3857
			$option_modifiers .= "\t" . trim($modifier) . ";\n";
3858
		}
3859
	}
3860

    
3861
 	$dhclientconf  = "interface \"{$wanif}\" {\n";
3862
 	$dhclientconf .= "\n";
3863
 	$dhclientconf .= "# DHCP Protocol Timing Values\n";
3864
 	$dhclientconf .= "{$adv_dhcp_pt_timeout}";
3865
 	$dhclientconf .= "{$adv_dhcp_pt_retry}";
3866
 	$dhclientconf .= "{$adv_dhcp_pt_select_timeout}";
3867
 	$dhclientconf .= "{$adv_dhcp_pt_reboot}";
3868
 	$dhclientconf .= "{$adv_dhcp_pt_backoff_cutoff}";
3869
 	$dhclientconf .= "{$adv_dhcp_pt_initial_interval}";
3870
 	$dhclientconf .= "\n";
3871
 	$dhclientconf .= "# DHCP Protocol Options\n";
3872
 	$dhclientconf .= "{$hostname}";
3873
 	$dhclientconf .= "{$send_options}";
3874
 	$dhclientconf .= "{$request_options}";
3875
 	$dhclientconf .= "{$required_options}";
3876
 	$dhclientconf .= "{$option_modifiers}";
3877
 	$dhclientconf .= "\n";
3878
 	$dhclientconf .= "\tscript \"/sbin/dhclient-script\";\n";
3879
 	$dhclientconf .= "}\n";
3880

    
3881
	$dhclientconf = DHCP_Config_File_Substitutions($wancfg, $wanif, $dhclientconf);
3882

    
3883
	return $dhclientconf;
3884
}
3885

    
3886

    
3887
function DHCP_Config_File_Override($wancfg, $wanif) {
3888

    
3889
	$dhclientconf = file_get_contents($wancfg['adv_dhcp_config_file_override_path']);
3890
	$dhclientconf = DHCP_Config_File_Substitutions($wancfg, $wanif, $dhclientconf);
3891

    
3892
	return $dhclientconf;
3893
}
3894

    
3895

    
3896
function DHCP_Config_File_Substitutions($wancfg, $wanif, $dhclientconf) {
3897

    
3898
	/* Apply Interface Substitutions */
3899
	$dhclientconf = str_replace("{interface}", "{$wanif}", $dhclientconf);
3900

    
3901
	/* Apply Hostname Substitutions */
3902
	$dhclientconf = str_replace("{hostname}", $wancfg['dhcphostname'], $dhclientconf);
3903

    
3904
	/* Arrays of MAC Address Types, Cases, Delimiters */
3905
	/* ASCII or HEX, Upper or Lower Case, Various Delimiters (none, space, colon, hyphen, period) */
3906
	$various_mac_types      = array("mac_addr_ascii", "mac_addr_hex");
3907
	$various_mac_cases      = array("U", "L");
3908
	$various_mac_delimiters = array("", " ", ":", "-", ".");
3909

    
3910
	/* Apply MAC Address Substitutions */
3911
	foreach ($various_mac_types as $various_mac_type) {
3912
		foreach ($various_mac_cases as $various_mac_case) {
3913
			foreach ($various_mac_delimiters as $various_mac_delimiter) {
3914

    
3915
				$res = stripos($dhclientconf, $various_mac_type . $various_mac_case . $various_mac_delimiter);
3916
				if ($res !== false) {
3917

    
3918
					/* Get MAC Address as ASCII String With Colon (:) Celimiters */
3919
					if ("$various_mac_case" == "U") $dhcpclientconf_mac = strtoupper(get_interface_mac($wanif));
3920
					if ("$various_mac_case" == "L") $dhcpclientconf_mac = strtolower(get_interface_mac($wanif));
3921

    
3922
					if ("$various_mac_type" == "mac_addr_hex") {
3923
						/* Convert MAC ascii string to HEX with colon (:) delimiters. */
3924
						$dhcpclientconf_mac = str_replace(":", "", $dhcpclientconf_mac);
3925
						$dhcpclientconf_mac_hex = "";
3926
						$delimiter = "";
3927
						for($i = 0; $i < strlen($dhcpclientconf_mac); $i++) {
3928
							$dhcpclientconf_mac_hex .= $delimiter. bin2hex($dhcpclientconf_mac[$i]);
3929
							$delimiter = ":";
3930
						}
3931
						$dhcpclientconf_mac = $dhcpclientconf_mac_hex;
3932
					}
3933

    
3934
					/* MAC Address Delimiter Substitutions */
3935
					$dhcpclientconf_mac = str_replace(":", $various_mac_delimiter, $dhcpclientconf_mac);
3936

    
3937
					/* Apply MAC Address Substitutions */
3938
					$dhclientconf = str_replace("{" . $various_mac_type . $various_mac_case . $various_mac_delimiter . "}", $dhcpclientconf_mac, $dhclientconf);
3939
				}
3940
			}
3941
		}
3942
	}
3943

    
3944
	return $dhclientconf;
3945
}
3946

    
3947
function interfaces_group_setup() {
3948
	global $config;
3949

    
3950
	if (!is_array($config['ifgroups']['ifgroupentry']))
3951
		return;
3952

    
3953
	foreach ($config['ifgroups']['ifgroupentry'] as $groupar)
3954
		interface_group_setup($groupar);
3955

    
3956
	return;
3957
}
3958

    
3959
function interface_group_setup(&$groupname /* The parameter is an array */) {
3960
	global $config;
3961

    
3962
	if (!is_array($groupname))
3963
		return;
3964
	$members = explode(" ", $groupname['members']);
3965
	foreach($members as $ifs) {
3966
		$realif = get_real_interface($ifs);
3967
		if ($realif)
3968
			mwexec("/sbin/ifconfig {$realif} group {$groupname['ifname']}");
3969
	}
3970

    
3971
	return;
3972
}
3973

    
3974
function is_interface_group($if) {
3975
	global $config;
3976

    
3977
	if (is_array($config['ifgroups']['ifgroupentry']))
3978
		foreach ($config['ifgroups']['ifgroupentry'] as $groupentry) {
3979
			if ($groupentry['ifname'] === $if)
3980
				return true;
3981
		}
3982

    
3983
	return false;
3984
}
3985

    
3986
function interface_group_add_member($interface, $groupname) {
3987
	$interface = get_real_interface($interface);
3988
	mwexec("/sbin/ifconfig {$interface} group " . escapeshellarg($groupname), true);
3989
}
3990

    
3991
/* COMPAT Function */
3992
function convert_friendly_interface_to_real_interface_name($interface) {
3993
	return get_real_interface($interface);
3994
}
3995

    
3996
/* COMPAT Function */
3997
function get_real_wan_interface($interface = "wan") {
3998
	return get_real_interface($interface);
3999
}
4000

    
4001
/* COMPAT Function */
4002
function get_current_wan_address($interface = "wan") {
4003
	return get_interface_ip($interface);
4004
}
4005

    
4006
/*
4007
 * convert_real_interface_to_friendly_interface_name($interface): convert fxp0 -> wan, etc.
4008
 */
4009
function convert_real_interface_to_friendly_interface_name($interface = "wan") {
4010
	global $config;
4011

    
4012
	if (stripos($interface, "_vip")) {
4013
		foreach ($config['virtualip']['vip'] as $counter => $vip) {
4014
			if ($vip['mode'] == "carp")  {
4015
				if ($interface == "{$vip['interface']}_vip{$vip['vhid']}")
4016
				return $vip['interface'];
4017
			}
4018
		}
4019
	}
4020

    
4021
	/* XXX: For speed reasons reference directly the interface array */
4022
	$ifdescrs = &$config['interfaces'];
4023
	//$ifdescrs = get_configured_interface_list(false, true);
4024

    
4025
	foreach ($ifdescrs as $if => $ifname) {
4026
		if ($if == $interface || $ifname['if'] == $interface)
4027
			return $if;
4028

    
4029
		if (get_real_interface($if) == $interface)
4030
			return $if;
4031

    
4032
		$int = get_parent_interface($if, true);
4033
		if (is_array($int)) {
4034
			foreach ($int as $iface) {
4035
				if ($iface == $interface)
4036
					return $if;
4037
			}
4038
		}
4039
	}
4040

    
4041
	if ($interface == "enc0")
4042
		return 'IPsec';
4043
}
4044

    
4045
/* attempt to resolve interface to friendly descr */
4046
function convert_friendly_interface_to_friendly_descr($interface) {
4047
	global $config;
4048

    
4049
	switch ($interface) {
4050
	case "l2tp":
4051
		$ifdesc = "L2TP";
4052
		break;
4053
	case "pptp":
4054
		$ifdesc = "PPTP";
4055
		break;
4056
	case "pppoe":
4057
		$ifdesc = "PPPoE";
4058
		break;
4059
	case "openvpn":
4060
		$ifdesc = "OpenVPN";
4061
		break;
4062
	case "enc0":
4063
	case "ipsec":
4064
	case "IPsec":
4065
		$ifdesc = "IPsec";
4066
		break;
4067
	default:
4068
		if (isset($config['interfaces'][$interface])) {
4069
			if (empty($config['interfaces'][$interface]['descr']))
4070
				$ifdesc = strtoupper($interface);
4071
			else
4072
				$ifdesc = strtoupper($config['interfaces'][$interface]['descr']);
4073
			break;
4074
		} else if (stristr($interface, "_vip")) {
4075
			if (is_array($config['virtualip']['vip'])) {
4076
				foreach ($config['virtualip']['vip'] as $counter => $vip) {
4077
					if ($vip['mode'] == "carp")  {
4078
						if ($interface == "{$vip['interface']}_vip{$vip['vhid']}")
4079
							return "{$vip['subnet']} - {$vip['descr']}";
4080
					}
4081
				}
4082
			}
4083
		} else {
4084
			/* if list */
4085
			$ifdescrs = get_configured_interface_with_descr(false, true);
4086
			foreach ($ifdescrs as $if => $ifname) {
4087
				if ($if == $interface || $ifname == $interface)
4088
					return $ifname;
4089
			}
4090
		}
4091
		break;
4092
	}
4093

    
4094
	return $ifdesc;
4095
}
4096

    
4097
function convert_real_interface_to_friendly_descr($interface) {
4098

    
4099
	$ifdesc = convert_real_interface_to_friendly_interface_name("{$interface}");
4100

    
4101
	if (!empty($ifdesc))
4102
		return convert_friendly_interface_to_friendly_descr($ifdesc);
4103

    
4104
	return $interface;
4105
}
4106

    
4107
/*
4108
 *  get_parent_interface($interface):
4109
 *			--returns the (real or virtual) parent interface(s) array for a given interface friendly name (i.e. wan)
4110
 *				or virtual interface (i.e. vlan)
4111
 *				(We need array because MLPPP and bridge interfaces have more than one parent.)
4112
 *			-- returns $interface passed in if $interface parent is not found
4113
 *			-- returns empty array if an invalid interface is passed
4114
 *	(Only handles ppps and vlans now.)
4115
 */
4116
function get_parent_interface($interface, $avoidrecurse = false) {
4117
	global $config;
4118

    
4119
	$parents = array();
4120
	//Check that we got a valid interface passed
4121
	$realif = get_real_interface($interface);
4122
	if ($realif == NULL)
4123
		return $parents;
4124

    
4125
	// If we got a real interface, find it's friendly assigned name
4126
	if ($interface == $realif && $avoidrecurse == false)
4127
		$interface = convert_real_interface_to_friendly_interface_name($interface);
4128

    
4129
	if (!empty($interface) && isset($config['interfaces'][$interface])) {
4130
		$ifcfg = $config['interfaces'][$interface];
4131
		switch ($ifcfg['ipaddr']) {
4132
			case "ppp":
4133
			case "pppoe":
4134
			case "pptp":
4135
			case "l2tp":
4136
				if (empty($parents))
4137
					if (is_array($config['ppps']['ppp']))
4138
						foreach ($config['ppps']['ppp'] as $pppidx => $ppp) {
4139
							if ($ifcfg['if'] == $ppp['if']) {
4140
								$ports = explode(',', $ppp['ports']);
4141
								foreach ($ports as $pid => $parent_if)
4142
									$parents[$pid] = get_real_interface($parent_if);
4143
								break;
4144
							}
4145
						}
4146
				break;
4147
			case "dhcp":
4148
			case "static":
4149
			default:
4150
				// Handle _vlans
4151
				if (strpos($realif, '_vlan') !== FALSE) {
4152
					if (is_array($config['vlans']['vlan'])) {
4153
						foreach ($config['vlans']['vlan'] as $vlanidx => $vlan) {
4154
							if ($ifcfg['if'] == $vlan['vlanif']) {
4155
								$parents[0] = $vlan['if'];
4156
								break;
4157
							}
4158
						}
4159
					}
4160
				}
4161
				break;
4162
		}
4163
	}
4164

    
4165
	if (empty($parents))
4166
		$parents[0] = $realif;
4167

    
4168
	return $parents;
4169
}
4170

    
4171
function interface_is_wireless_clone($wlif) {
4172
	if(!stristr($wlif, "_wlan")) {
4173
		return false;
4174
	} else {
4175
		return true;
4176
	}
4177
}
4178

    
4179
function interface_get_wireless_base($wlif) {
4180
	if(!stristr($wlif, "_wlan")) {
4181
		return $wlif;
4182
	} else {
4183
		return substr($wlif, 0, stripos($wlif, "_wlan"));
4184
	}
4185
}
4186

    
4187
function interface_get_wireless_clone($wlif) {
4188
	if(!stristr($wlif, "_wlan")) {
4189
		return $wlif . "_wlan0";
4190
	} else {
4191
		return $wlif;
4192
	}
4193
}
4194

    
4195
function get_real_interface($interface = "wan", $family = "all", $realv6iface = false, $flush = true) {
4196
	global $config, $g;
4197

    
4198
	$wanif = NULL;
4199

    
4200
	switch ($interface) {
4201
	case "l2tp":
4202
		$wanif = "l2tp";
4203
		break;
4204
	case "pptp":
4205
		$wanif = "pptp";
4206
		break;
4207
	case "pppoe":
4208
		$wanif = "pppoe";
4209
		break;
4210
	case "openvpn":
4211
		$wanif = "openvpn";
4212
		break;
4213
	case "ipsec":
4214
	case "enc0":
4215
		$wanif = "enc0";
4216
		break;
4217
	case "ppp":
4218
		$wanif = "ppp";
4219
		break;
4220
	default:
4221
		// If a real interface was alread passed simply
4222
		// pass the real interface back.  This encourages
4223
		// the usage of this function in more cases so that
4224
		// we can combine logic for more flexibility.
4225
		if(does_interface_exist($interface, $flush)) {
4226
			$wanif = $interface;
4227
			break;
4228
		}
4229

    
4230
		if (empty($config['interfaces'][$interface]))
4231
			break;
4232

    
4233
		$cfg = &$config['interfaces'][$interface];
4234

    
4235
		if ($family == "inet6") {
4236
			switch ($cfg['ipaddrv6']) {
4237
			case "6rd":
4238
			case "6to4":
4239
				$wanif = "{$interface}_stf";
4240
				break;
4241
			case 'pppoe':
4242
			case 'ppp':
4243
			case 'l2tp':
4244
			case 'pptp':
4245
				if( is_array($cfg['wireless']) || preg_match($g['wireless_regex'], $cfg['if']))
4246
					$wanif = interface_get_wireless_clone($cfg['if']);
4247
				else
4248
					$wanif = $cfg['if'];
4249
				break;
4250
			default:
4251
				switch ($cfg['ipaddr']) {
4252
				case 'pppoe':
4253
				case 'ppp':
4254
				case 'l2tp':
4255
				case 'pptp':
4256
					if (isset($cfg['dhcp6usev4iface']) && $realv6iface === false)
4257
						$wanif = $cfg['if'];
4258
					else {
4259
						$parents = get_parent_interface($interface);
4260
						if (!empty($parents[0]))
4261
							$wanif = $parents[0];
4262
						else
4263
							$wanif = $cfg['if'];
4264
					}
4265
					break;
4266
				default:
4267
					if( is_array($cfg['wireless']) || preg_match($g['wireless_regex'], $cfg['if']))
4268
						$wanif = interface_get_wireless_clone($cfg['if']);
4269
					else
4270
						$wanif = $cfg['if'];
4271
					break;
4272
				}
4273
				break;
4274
			}
4275
		} else {
4276
			// Wireless cloned NIC support (FreeBSD 8+)
4277
			// interface name format: $parentnic_wlanparentnic#
4278
			// example: ath0_wlan0
4279
			if( is_array($cfg['wireless']) || preg_match($g['wireless_regex'], $cfg['if']))
4280
				$wanif = interface_get_wireless_clone($cfg['if']);
4281
			else
4282
				$wanif = $cfg['if'];
4283
		}
4284
		break;
4285
	}
4286

    
4287
	return $wanif;
4288
}
4289

    
4290
/* Guess the physical interface by providing a IP address */
4291
function guess_interface_from_ip($ipaddress) {
4292

    
4293
	$family = '';
4294
	if(is_ipaddrv4($ipaddress))
4295
		$family = 'inet';
4296
	if (empty($family) && is_ipaddrv6($ipaddress))
4297
		$family = 'inet6';
4298

    
4299
	if (empty($family))
4300
		return false;
4301

    
4302
	/* create a route table we can search */
4303
	$output = '';
4304
	$_gb = exec("/sbin/route -n get -{$family} " . escapeshellarg($ipaddress) . " | /usr/bin/awk '/interface/ { print \$2; };'", $output);
4305
	$output[0] = trim($output[0], " \n");
4306
	if (!empty($output[0]))
4307
		return $output[0];
4308

    
4309
	return false;
4310
}
4311

    
4312
/*
4313
 * find_ip_interface($ip): return the interface where an ip is defined
4314
 *   (or if $bits is specified, where an IP within the subnet is defined)
4315
 */
4316
function find_ip_interface($ip, $bits = null) {
4317
	if (!is_ipaddr($ip))
4318
		return false;
4319

    
4320
	$isv6ip = is_ipaddrv6($ip);
4321

    
4322
	/* if list */
4323
	$ifdescrs = get_configured_interface_list();
4324

    
4325
	foreach ($ifdescrs as $ifdescr => $ifname) {
4326
		$ifip = ($isv6ip) ? get_interface_ipv6($ifname) : get_interface_ip($ifname);
4327
		if (is_null($ifip))
4328
			continue;
4329
		if (is_null($bits)) {
4330
			if ($ip == $ifip) {
4331
				$int = get_real_interface($ifname);
4332
				return $int;
4333
			}
4334
		}
4335
		else {
4336
			if (ip_in_subnet($ifip, $ip . "/" . $bits)) {
4337
				$int = get_real_interface($ifname);
4338
				return $int;
4339
			}
4340
		}
4341
	}
4342

    
4343
	return false;
4344
}
4345

    
4346
/*
4347
 * find_virtual_ip_alias($ip): return the virtual IP alias where an IP is found
4348
 *   (or if $bits is specified, where an IP within the subnet is found)
4349
 */
4350
function find_virtual_ip_alias($ip, $bits = null) {
4351
	global $config;
4352

    
4353
	if (!is_array($config['virtualip']['vip'])) {
4354
		return false;
4355
	}
4356
	if (!is_ipaddr($ip))
4357
		return false;
4358

    
4359
	$isv6ip = is_ipaddrv6($ip);
4360

    
4361
	foreach ($config['virtualip']['vip'] as $vip) {
4362
		if ($vip['mode'] === "ipalias") {
4363
			if (is_ipaddrv6($vip['subnet']) != $isv6ip)
4364
				continue;
4365
			if (is_null($bits)) {
4366
				if (ip_in_subnet($ip, $vip['subnet'] . "/" . $vip['subnet_bits'])) {
4367
					return $vip;
4368
				}
4369
			}
4370
			else {
4371
				if (($isv6ip && check_subnetsv6_overlap($ip, $bits, $vip['subnet'], $vip['subnet_bits']))
4372
					|| (!$isv6ip && check_subnets_overlap($ip, $bits, $vip['subnet'], $vip['subnet_bits']))) {
4373
					return $vip;
4374
				}
4375
			}
4376
		}
4377
	}
4378
	return false;
4379
}
4380

    
4381
/*
4382
 *   find_number_of_created_carp_interfaces: return the number of carp interfaces
4383
 */
4384
function find_number_of_created_carp_interfaces() {
4385
	return `/sbin/ifconfig | grep "carp:" | wc -l`;
4386
}
4387

    
4388
/*
4389
 * find_carp_interface($ip): return the carp interface where an ip is defined
4390
 */
4391
function find_carp_interface($ip) {
4392
	global $config;
4393
	if (is_array($config['virtualip']['vip'])) {
4394
		foreach ($config['virtualip']['vip'] as $vip) {
4395
			if ($vip['mode'] == "carp") {
4396
				if(is_ipaddrv4($ip)) {
4397
					$carp_ip = get_interface_ip($vip['interface']);
4398
				}
4399
				if(is_ipaddrv6($ip)) {
4400
					$carp_ip = get_interface_ipv6($vip['interface']);
4401
				}
4402
				exec("/sbin/ifconfig", $output, $return);
4403
				foreach($output as $line) {
4404
					$elements = preg_split("/[ ]+/i", $line);
4405
					if(strstr($elements[0], "vip"))
4406
						$curif = str_replace(":", "", $elements[0]);
4407
					if(stristr($line, $ip)) {
4408
						$if = $curif;
4409
						continue;
4410
					}
4411
				}
4412

    
4413
				if ($if)
4414
					return $if;
4415
			}
4416
		}
4417
	}
4418
}
4419

    
4420
function link_carp_interface_to_parent($interface) {
4421
	global $config;
4422

    
4423
	if (empty($interface))
4424
		return;
4425

    
4426
	$carp_ip = get_interface_ip($interface);
4427
	$carp_ipv6 = get_interface_ipv6($interface);
4428

    
4429
	if((!is_ipaddrv4($carp_ip)) && (!is_ipaddrv6($carp_ipv6)))
4430
		return;
4431

    
4432
	/* if list */
4433
	$ifdescrs = get_configured_interface_list();
4434
	foreach ($ifdescrs as $ifdescr => $ifname) {
4435
		/* check IPv4 */
4436
		if(is_ipaddrv4($carp_ip)) {
4437
			$interfaceip = get_interface_ip($ifname);
4438
			$subnet_bits = get_interface_subnet($ifname);
4439
			$subnet_ip = gen_subnet("{$interfaceip}", "{$subnet_bits}");
4440
			if(ip_in_subnet($carp_ip, "{$subnet_ip}/{$subnet_bits}"))
4441
				return $ifname;
4442
		}
4443
		/* Check IPv6 */
4444
		if(is_ipaddrv6($carp_ipv6)) {
4445
			$interfaceipv6 = get_interface_ipv6($ifname);
4446
			$prefixlen = get_interface_subnetv6($ifname);
4447
			if(ip_in_subnet($carp_ipv6, "{$interfaceipv6}/{$prefixlen}"))
4448
				return $ifname;
4449
		}
4450
	}
4451
	return "";
4452
}
4453

    
4454

    
4455
/****f* interfaces/link_ip_to_carp_interface
4456
 * NAME
4457
 *   link_ip_to_carp_interface - Find where a CARP interface links to.
4458
 * INPUTS
4459
 *   $ip
4460
 * RESULT
4461
 *   $carp_ints
4462
 ******/
4463
function link_ip_to_carp_interface($ip) {
4464
	global $config;
4465

    
4466
	if (!is_ipaddr($ip))
4467
		return;
4468

    
4469
	$carp_ints = "";
4470
	if (is_array($config['virtualip']['vip'])) {
4471
		$first = 0;
4472
		$carp_int = array();
4473
		foreach ($config['virtualip']['vip'] as $vip) {
4474
			if ($vip['mode'] == "carp") {
4475
				$carp_ip = $vip['subnet'];
4476
				$carp_sn = $vip['subnet_bits'];
4477
				$carp_nw = gen_subnet($carp_ip, $carp_sn);
4478
				if (ip_in_subnet($ip, "{$carp_nw}/{$carp_sn}")) {
4479
					$carp_int[] = get_real_interface($vip['interface']);
4480
				}
4481
			}
4482
		}
4483
		if (!empty($carp_int))
4484
			$carp_ints = implode(" ", array_unique($carp_int));
4485
	}
4486

    
4487
	return $carp_ints;
4488
}
4489

    
4490
function link_interface_to_track6($int, $action = "") {
4491
	global $config;
4492

    
4493
	if (empty($int))
4494
		return;
4495

    
4496
	if (is_array($config['interfaces'])) {
4497
		$list = array();
4498
		foreach ($config['interfaces'] as $ifname => $ifcfg) {
4499
			if (!isset($ifcfg['enable']))
4500
				continue;
4501
			if (!empty($ifcfg['ipaddrv6']) && $ifcfg['track6-interface'] == $int) {
4502
				if ($action == "update")
4503
					interface_track6_configure($ifname, $ifcfg);
4504
				else if ($action == "")
4505
					$list[$ifname] = $ifcfg;
4506
			}
4507
		}
4508
		return $list;
4509
	}
4510
}
4511

    
4512
function interface_find_child_cfgmtu($realiface) {
4513
	global $config;
4514

    
4515
	$interface = convert_real_interface_to_friendly_interface_name($realiface);
4516
	$vlans = link_interface_to_vlans($realiface);
4517
	$bridge = link_interface_to_bridge($realiface);
4518
	if (!empty($interface)) {
4519
		$gifs = link_interface_to_gif($interface);
4520
		$gres = link_interface_to_gre($interface);
4521
	} else {
4522
		$gifs = array();
4523
		$gres = array();
4524
	}
4525

    
4526
	$mtu = 0;
4527
	foreach ($vlans as $vlan) {
4528
		$ifass = convert_real_interface_to_friendly_interface_name($vlan['vlanif']);
4529
		if (empty($ifass))
4530
			continue;
4531
		if (!empty($config['interfaces'][$ifass]['mtu'])) {
4532
			if (intval($config['interfaces'][$ifass]['mtu']) > $mtu)
4533
				$mtu = intval($config['interfaces'][$ifass]['mtu']);
4534
		}
4535
	}
4536
	foreach ($gifs as $vlan) {
4537
		$ifass = convert_real_interface_to_friendly_interface_name($vlan['gifif']);
4538
		if (empty($ifass))
4539
			continue;
4540
		if (!empty($config['interfaces'][$ifass]['mtu'])) {
4541
			if (intval($config['interfaces'][$ifass]['mtu']) > $mtu)
4542
				$mtu = intval($config['interfaces'][$ifass]['mtu']);
4543
		}
4544
	}
4545
	foreach ($gres as $vlan) {
4546
		$ifass = convert_real_interface_to_friendly_interface_name($vlan['greif']);
4547
		if (empty($ifass))
4548
			continue;
4549
		if (!empty($config['interfaces'][$ifass]['mtu'])) {
4550
			if (intval($config['interfaces'][$ifass]['mtu']) > $mtu)
4551
				$mtu = intval($config['interfaces'][$ifass]['mtu']);
4552
		}
4553
	}
4554
	$ifass = convert_real_interface_to_friendly_interface_name($bridge);
4555
	if (!empty($ifass) && !empty($config['interfaces'][$ifass]['mtu'])) {
4556
		if (intval($config['interfaces'][$ifass]['mtu']) > $mtu)
4557
			$mtu = intval($config['interfaces'][$ifass]['mtu']);
4558
	}
4559
	unset($vlans, $bridge, $gifs, $gres, $ifass, $vlan);
4560

    
4561
	return $mtu;
4562
}
4563

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

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

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

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

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

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

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

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

    
4624
	$result = array();
4625

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

    
4633
	return $result;
4634
}
4635

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

    
4639
	$result = array();
4640

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

    
4647
	return $result;
4648
}
4649

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

    
4653
	$result = array();
4654

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

    
4661
	return $result;
4662
}
4663

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
4791
	return false;
4792
}
4793

    
4794
function get_interface_ip($interface = "wan") {
4795
	$realif = get_failover_interface($interface);
4796
	if (!$realif) {
4797
		if (strstr($interface, "_vip"))
4798
			return get_configured_carp_interface_list($interface);
4799
		else
4800
			return null;
4801
	}
4802

    
4803
	$curip = find_interface_ip($realif);
4804
	if ($curip && is_ipaddr($curip) && ($curip != "0.0.0.0"))
4805
		return $curip;
4806
	else
4807
		return null;
4808
}
4809

    
4810
function get_interface_ipv6($interface = "wan", $flush = false) {
4811
	global $config;
4812

    
4813
	$realif = get_failover_interface($interface, "inet6");
4814
	if (!$realif) {
4815
		if (strstr($interface, "_vip"))
4816
			return get_configured_carp_interface_list($interface, "inet6");
4817
		else
4818
			return null;
4819
	}
4820

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

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

    
4849
function get_interface_linklocal($interface = "wan") {
4850

    
4851
	$realif = get_failover_interface($interface, "inet6");
4852
	if (!$realif) {
4853
		if (strstr($interface, "_vip")) {
4854
			list($interface, $vhid) = explode("_vip", $interface);
4855
			$realif = get_real_interface($interface);
4856
		} else
4857
			return null;
4858
	}
4859

    
4860
	$curip = find_interface_ipv6_ll($realif);
4861
	if ($curip && is_ipaddrv6($curip) && ($curip != "::"))
4862
		return $curip;
4863
	else
4864
		return null;
4865
}
4866

    
4867
function get_interface_subnet($interface = "wan") {
4868
	$realif = get_real_interface($interface);
4869
	if (!$realif) {
4870
		if (strstr($interface, "_vip")) {
4871
			list($interface, $vhid) = explode("_vip", $interface);
4872
			$realif = get_real_interface($interface);
4873
		} else
4874
			return null;
4875
	}
4876

    
4877
	$cursn = find_interface_subnet($realif);
4878
	if (!empty($cursn))
4879
		return $cursn;
4880

    
4881
	return null;
4882
}
4883

    
4884
function get_interface_subnetv6($interface = "wan") {
4885
	global $config;
4886

    
4887
	$realif = get_real_interface($interface, "inet6");
4888
	if (!$realif) {
4889
		if (strstr($interface, "_vip")) {
4890
			list($interface, $vhid) = explode("_vip", $interface);
4891
			$realif = get_real_interface($interface);
4892
		} else
4893
			return null;
4894
	}
4895

    
4896
	$cursn = find_interface_subnetv6($realif);
4897
	if (!empty($cursn))
4898
		return $cursn;
4899

    
4900
	return null;
4901
}
4902

    
4903
/* return outside interfaces with a gateway */
4904
function get_interfaces_with_gateway() {
4905
	global $config;
4906

    
4907
	$ints = array();
4908

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

    
4930
/* return true if interface has a gateway */
4931
function interface_has_gateway($friendly) {
4932
	global $config;
4933

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

    
4956
	return false;
4957
}
4958

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

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

    
4984
	return false;
4985
}
4986

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

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

    
5009
	$int_family = remove_ifindex($int);
5010

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

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

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

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

    
5048
	$cloned_interface = get_real_interface($interface);
5049

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

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

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

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

    
5092
	$cloned_interface = get_real_interface($interface);
5093

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

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

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

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

    
5122
function get_interface_mac($interface) {
5123

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

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

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

    
5155
	if (isset($capable['caps']['vlanmtu']))
5156
		return true;
5157

    
5158
	return false;
5159
}
5160

    
5161
function interface_setup_pppoe_reset_file($pppif, $iface="") {
5162
	global $g;
5163

    
5164
	$cron_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
5165

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

    
5172
EOD;
5173

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

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

    
5198
	/* Never reached */
5199
	return 1500;
5200
}
5201

    
5202
function get_vip_descr($ipaddress) {
5203
	global $config;
5204

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

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

    
5220
	$ifcfg = $config['interfaces'][$if];
5221

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

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

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

    
5234
			}
5235

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

    
5249
	return 0;
5250
}
5251

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

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

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

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

    
5278
?>
(26-26/68)