Project

General

Profile

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

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

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

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

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

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

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

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

    
42
*/
43

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

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

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

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

    
68
	return $interface_arr_cache;
69
}
70

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

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

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

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

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

    
98

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

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

    
124
	return false;
125
}
126

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
267
	interfaces_bring_up($vlanif);
268

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

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

    
275
	return $vlanif;
276
}
277

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

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

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

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

    
298
	$vlanif = interface_vlan_configure($vlan);
299

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

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

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

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

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

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

    
351
	return $vlanif;
352
}
353

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

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

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

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

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

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

    
394
	return $vlanif;
395
}
396

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

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

    
403
	$iflist = get_configured_interface_list();
404

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

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

    
424
}
425

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

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

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

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

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

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

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

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

    
512
	$flags_on = 0;
513
	$flags_off = 0;
514
	if (isset($config['system']['disablechecksumoffloading']) || ($commonrx === false))
515
		$flags_off |= IFCAP_RXCSUM;
516
	else
517
		$flags_on |= IFCAP_RXCSUM;
518
	if (isset($config['system']['disablechecksumoffloading']) || ($commontx === false))
519
		$flags_off |= IFCAP_TXCSUM;
520
	else
521
		$flags_on |= IFCAP_TXCSUM;
522
	if (isset($config['system']['disablesegmentationoffloading']) || ($commontso4 === false))
523
		$flags_off |= IFCAP_TSO4;
524
	else
525
		$flags_on |= IFCAP_TSO4;
526
	if (isset($config['system']['disablesegmentationoffloading']) || ($commontso6 === false))
527
		$flags_off |= IFCAP_TSO6;
528
	else
529
		$flags_on |= IFCAP_TSO6;
530
	if (isset($config['system']['disablelargereceiveoffloading']) || ($commonlro === false))
531
		$flags_off |= IFCAP_LRO;
532
	else
533
		$flags_on |= IFCAP_LRO;
534

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

    
544
	$checklist = get_configured_interface_list();
545

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
794
	$checklist = get_interface_list();
795

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

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

    
809
	interfaces_bring_up($laggif);
810

    
811
	return $laggif;
812
}
813

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

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

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

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

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

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

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

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

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

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

    
885
	return $greif;
886
}
887

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

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

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

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

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

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

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

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

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

    
979

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

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

    
992
	return $gifif;
993
}
994

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

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

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

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

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

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

    
1013
	interfaces_qinq_configure();
1014

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

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

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

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

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

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

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

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

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

    
1071
		interface_configure($if, $reload);
1072

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

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

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

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

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

    
1092
		interface_configure($if, $reload);
1093

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

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

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

    
1107
		interface_configure($if, $reload);
1108

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

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

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

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

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

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

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

    
1134
	return 0;
1135
}
1136

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

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

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

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

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

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

    
1177
	if ($ifacecfg === false) {
1178
		$ifcfg = $config['interfaces'][$interface];
1179
		$ppps = $config['ppps']['ppp'];
1180
		$realif = get_real_interface($interface);
1181
	} elseif (!is_array($ifacecfg)) {
1182
		log_error(gettext("Wrong parameters used during interface_bring_down"));
1183
	} else {
1184
		$ifcfg = $ifacecfg['ifcfg'];
1185
		$ppps = $ifacecfg['ppps'];
1186
		if (isset($ifacecfg['ifcfg']['realif']))
1187
			$realif = $ifacecfg['ifcfg']['realif'];
1188
		else
1189
			$realif = get_real_interface($interface);
1190
	}
1191

    
1192
	switch ($ifcfg['ipaddr']) {
1193
	case "ppp":
1194
	case "pppoe":
1195
	case "pptp":
1196
	case "l2tp":
1197
		if (is_array($ppps) && count($ppps)) {
1198
			foreach ($ppps as $pppid => $ppp) {
1199
				if ($realif == $ppp['if']) {
1200
					if (isset($ppp['ondemand']) && !$destroy){
1201
						send_event("interface reconfigure {$interface}");
1202
						break;
1203
					}
1204
					if (file_exists("{$g['varrun_path']}/{$ppp['type']}_{$interface}.pid")) {
1205
						killbypid("{$g['varrun_path']}/{$ppp['type']}_{$interface}.pid");
1206
						sleep(2);
1207
					}
1208
					unlink_if_exists("{$g['varetc_path']}/mpd_{$interface}.conf");
1209
					break;
1210
				}
1211
			}
1212
		}
1213
		break;
1214
	case "dhcp":
1215
		$pid = find_dhclient_process($realif);
1216
		if($pid)
1217
			posix_kill($pid, SIGTERM);
1218
		sleep(1);
1219
		unlink_if_exists("{$g['varetc_path']}/dhclient_{$interface}.conf");
1220
		if(does_interface_exist("$realif")) {
1221
			mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete", true);
1222
			if ($destroy == true)
1223
				pfSense_interface_flags($realif, -IFF_UP);
1224
			mwexec("/usr/sbin/arp -d -i {$realif} -a");
1225
		}
1226
		break;
1227
	default:
1228
		if(does_interface_exist("$realif")) {
1229
			mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete", true);
1230
			if ($destroy == true)
1231
				pfSense_interface_flags($realif, -IFF_UP);
1232
			mwexec("/usr/sbin/arp -d -i {$realif} -a");
1233
		}
1234
		break;
1235
	}
1236

    
1237
	switch ($ifcfg['ipaddrv6']) {
1238
	case "slaac":
1239
	case "dhcp6":
1240
		$pidv6 = find_dhcp6c_process($realif);
1241
		if($pidv6)
1242
			posix_kill($pidv6, SIGTERM);
1243
		sleep(3);
1244
		unlink_if_exists("{$g['varetc_path']}/dhcp6c_{$interface}.conf");
1245
		if (does_interface_exist("$realif")) {
1246
			$ip6 = get_interface_ipv6($interface);
1247
			if (is_ipaddrv6($ip6))
1248
				mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 {$ip6} delete", true);
1249
			if ($destroy == true)
1250
				pfSense_interface_flags($realif, -IFF_UP);
1251
			mwexec("/usr/sbin/arp -d -i {$realif} -a");
1252
		}
1253
		break;
1254
	case "6rd":
1255
	case "6to4":
1256
		$realif = "{$interface}_stf";
1257
		if(does_interface_exist("$realif")) {
1258
			$ip6 = get_interface_ipv6($interface);
1259
			if (is_ipaddrv6($ip6))
1260
				mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 {$ip6} delete", true);
1261
			if ($destroy == true)
1262
				pfSense_interface_flags($realif, -IFF_UP);
1263
		}
1264
		break;
1265
	default:
1266
		if(does_interface_exist("$realif")) {
1267
			$ip6 = get_interface_ipv6($interface);
1268
			if (is_ipaddrv6($ip6))
1269
				mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 {$ip6} delete", true);
1270
			if (!empty($ifcfg['ipaddrv6']) && is_ipaddrv6($ifcfg['ipaddrv6']))
1271
				mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 {$ifcfg['ipaddrv6']} delete", true);
1272
			if ($destroy == true)
1273
				pfSense_interface_flags($realif, -IFF_UP);
1274
			mwexec("/usr/sbin/arp -d -i {$realif} -a");
1275
		}
1276
		break;
1277
	}
1278

    
1279
	if (file_exists("{$g['tmp_path']}/{$realif}_router"))
1280
		$old_router = trim(file_get_contents("{$g['tmp_path']}/{$realif}_router"));
1281
//	log_error("Checking for old router states: {$g['tmp_path']}/{$realif}_router = {$old_router}");
1282
	if (!empty($old_router)) {
1283
		log_error("Clearing states to old gateway {$old_router}.");
1284
		mwexec("/sbin/pfctl -i {$realif} -Fs -G {$old_router}");
1285
	}
1286

    
1287
	/* remove interface up file if it exists */
1288
	unlink_if_exists("{$g['tmp_path']}/{$realif}up");
1289
	unlink_if_exists("{$g['vardb_path']}/{$interface}ip");
1290
	unlink_if_exists("{$g['vardb_path']}/{$interface}ipv6");
1291
	unlink_if_exists("{$g['tmp_path']}/{$realif}_router");
1292
	unlink_if_exists("{$g['tmp_path']}/{$realif}_routerv6");
1293
	unlink_if_exists("{$g['varetc_path']}/nameserver_{$realif}");
1294
	unlink_if_exists("{$g['varetc_path']}/searchdomain_{$realif}");
1295

    
1296
	/* hostapd and wpa_supplicant do not need to be running when the interface is down.
1297
	 * They will also use 100% CPU if running after the wireless clone gets deleted. */
1298
	if (is_array($ifcfg['wireless'])) {
1299
		kill_hostapd($realif);
1300
		mwexec(kill_wpasupplicant($realif));
1301
	}
1302

    
1303
	if ($destroy == true) {
1304
		if (preg_match("/^[a-z0-9]+_vip|^tun|^ovpn|^gif|^gre|^lagg|^bridge|vlan|_stf$/i", $realif))
1305
			pfSense_interface_destroy($realif);
1306
	}
1307

    
1308
	return;
1309
}
1310

    
1311
function interfaces_ptpid_used($ptpid) {
1312
	global $config;
1313

    
1314
	if (is_array($config['ppps']['ppp']))
1315
		foreach ($config['ppps']['ppp'] as & $settings)
1316
			if ($ptpid == $settings['ptpid'])
1317
				return true;
1318

    
1319
	return false;
1320
}
1321

    
1322
function interfaces_ptpid_next() {
1323

    
1324
	$ptpid = 0;
1325
	while(interfaces_ptpid_used($ptpid))
1326
		$ptpid++;
1327

    
1328
	return $ptpid;
1329
}
1330

    
1331
function getMPDCRONSettings($pppif) {
1332
	global $config;
1333

    
1334
	$cron_cmd_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
1335
	if (is_array($config['cron']['item'])) {
1336
		foreach ($config['cron']['item'] as $i => $item) {
1337
			if (stripos($item['command'], $cron_cmd_file) !== false)
1338
				return array("ID" => $i, "ITEM" => $item);
1339
		}
1340
	}
1341

    
1342
	return NULL;
1343
}
1344

    
1345
function handle_pppoe_reset($post_array) {
1346
	global $config, $g;
1347

    
1348
	$pppif = "{$post_array['type']}{$post_array['ptpid']}";
1349
	$cron_cmd_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
1350

    
1351
	if (!is_array($config['cron']['item']))
1352
		$config['cron']['item'] = array();
1353

    
1354
	$itemhash = getMPDCRONSettings($pppif);
1355

    
1356
	// reset cron items if necessary and return
1357
	if (empty($post_array['pppoe-reset-type'])) {
1358
		if (isset($itemhash))
1359
			unset($config['cron']['item'][$itemhash['ID']]);
1360
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
1361
		return;
1362
	}
1363

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

    
1423
/*
1424
 * This function can configure PPPoE, MLPPP (PPPoE), PPTP.
1425
 * It writes the mpd config file to /var/etc every time the link is opened.
1426
 */
1427
function interface_ppps_configure($interface) {
1428
	global $config, $g;
1429

    
1430
	/* Return for unassigned interfaces. This is a minimum requirement. */
1431
	if (empty($config['interfaces'][$interface]))
1432
		return 0;
1433
	$ifcfg = $config['interfaces'][$interface];
1434
	if (!isset($ifcfg['enable']))
1435
		return 0;
1436

    
1437
	// mpd5 requires a /var/spool/lock directory for PPP modem links.
1438
	if(!is_dir("/var/spool/lock")) {
1439
		exec("/bin/mkdir -p /var/spool/lock");
1440
		exec("/bin/chmod a+rw /var/spool/lock/.");
1441
	}
1442
	// mpd5 modem chat script expected in the same directory as the mpd_xxx.conf files
1443
	if (!file_exists("{$g['varetc_path']}/mpd.script"))
1444
		mwexec("/bin/ln -s /usr/local/sbin/mpd.script {$g['varetc_path']}/.");
1445

    
1446
	if (is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) {
1447
		foreach ($config['ppps']['ppp'] as $pppid => $ppp) {
1448
			if ($ifcfg['if'] == $ppp['if'])
1449
				break;
1450
		}
1451
	}
1452
	if (!$ppp || $ifcfg['if'] != $ppp['if']){
1453
		log_error(sprintf(gettext("Can't find PPP config for %s in interface_ppps_configure()."), $ifcfg['if']));
1454
		return 0;
1455
	}
1456
	$pppif = $ifcfg['if'];
1457
	if ($ppp['type'] == "ppp")
1458
		$type = "modem";
1459
	else
1460
		$type = $ppp['type'];
1461
	$upper_type = strtoupper($ppp['type']);
1462

    
1463
	if($g['booting']) {
1464
		$descr = isset($ifcfg['descr']) ? $ifcfg['descr'] : strtoupper($interface);
1465
		echo "starting {$pppif} link...";
1466
		// Do not re-configure the interface if we are booting and it's already been started
1467
		if(file_exists("{$g['varrun_path']}/{$ppp['type']}_{$interface}.pid"))
1468
			return 0;
1469
	}
1470

    
1471
	$ports = explode(',',$ppp['ports']);
1472
	if ($type != "modem") {
1473
		foreach ($ports as $pid => $port) {
1474
			$ports[$pid] = get_real_interface($port);
1475
			if (empty($ports[$pid]))
1476
				return 0;
1477
		}
1478
	}
1479
	$localips = explode(',',$ppp['localip']);
1480
	$gateways = explode(',',$ppp['gateway']);
1481
	$subnets = explode(',',$ppp['subnet']);
1482

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

    
1505
				if(!is_ipaddr($localips[$pid])){
1506
					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!");
1507
					$localips[$pid] = "0.0.0.0";
1508
				}
1509
				if(!is_ipaddr($gateways[$pid])){
1510
					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));
1511
					return 0;
1512
				}
1513
				pfSense_ngctl_attach(".", $port);
1514
				break;
1515
			case "ppp":
1516
				if (!file_exists("{$port}")) {
1517
					log_error(sprintf(gettext("Device %s does not exist. PPP link cannot start without the modem device."), $port));
1518
					return 0;
1519
				}
1520
				break;
1521
			default:
1522
				log_error(sprintf(gettext("Unkown %s configured as ppp interface."), $type));
1523
				break;
1524
		}
1525
	}
1526

    
1527
	if (is_array($ports) && count($ports) > 1)
1528
		$multilink = "enable";
1529
	else
1530
		$multilink = "disable";
1531

    
1532
	if ($type == "modem"){
1533
		if (is_ipaddr($ppp['localip']))
1534
			$localip = $ppp['localip'];
1535
		else
1536
			$localip = '0.0.0.0';
1537

    
1538
		if (is_ipaddr($ppp['gateway']))
1539
			$gateway = $ppp['gateway'];
1540
		else
1541
			$gateway = "10.64.64.{$pppid}";
1542
		$ranges = "{$localip}/0 {$gateway}/0";
1543

    
1544
		if (empty($ppp['apnum']))
1545
			$ppp['apnum'] = 1;
1546
	} else
1547
		$ranges = "0.0.0.0/0 0.0.0.0/0";
1548

    
1549
	if (isset($ppp['ondemand']))
1550
		$ondemand = "enable";
1551
	else
1552
		$ondemand = "disable";
1553
	if (!isset($ppp['idletimeout']))
1554
		$ppp['idletimeout'] = 0;
1555

    
1556
	if (empty($ppp['username']) && $type == "modem"){
1557
		$ppp['username'] = "user";
1558
		$ppp['password'] = "none";
1559
	}
1560
	if (empty($ppp['password']) && $type == "modem")
1561
		$passwd = "none";
1562
	else
1563
		$passwd = base64_decode($ppp['password']);
1564

    
1565
	$bandwidths = explode(',',$ppp['bandwidth']);
1566
	$defaultmtu = "1492";
1567
	if (!empty($ifcfg['mtu']))
1568
		$defaultmtu = intval($ifcfg['mtu']);
1569
	$mtus = explode(',',$ppp['mtu']);
1570
	$mrus = explode(',',$ppp['mru']);
1571

    
1572
	if (isset($ppp['mrru']))
1573
		$mrrus = explode(',',$ppp['mrru']);
1574

    
1575
	// Construct the mpd.conf file
1576
	$mpdconf = <<<EOD
1577
startup:
1578
	# configure the console
1579
	set console close
1580
	# configure the web server
1581
	set web close
1582

    
1583
default:
1584
{$ppp['type']}client:
1585
	create bundle static {$interface}
1586
	set bundle enable ipv6cp
1587
	set iface name {$pppif}
1588

    
1589
EOD;
1590
	$setdefaultgw = false;
1591
	$founddefaultgw = false;
1592
	if (is_array($config['gateways']['gateway_item'])) {
1593
		foreach($config['gateways']['gateway_item'] as $gateway) {
1594
			if($interface == $gateway['interface'] && isset($gateway['defaultgw'])) {
1595
				$setdefaultgw = true;
1596
				break;
1597
			} else if (isset($gateway['defaultgw']) && !empty($gateway['interface'])) {
1598
				$founddefaultgw = true;
1599
				break;
1600
			}
1601
		}
1602
	}
1603

    
1604
	if (($interface == "wan" && $founddefaultgw == false) || $setdefaultgw == true){
1605
		$setdefaultgw = true;
1606
		$mpdconf .= <<<EOD
1607
	set iface route default
1608

    
1609
EOD;
1610
	}
1611
	$mpdconf .= <<<EOD
1612
	set iface {$ondemand} on-demand
1613
	set iface idle {$ppp['idletimeout']}
1614

    
1615
EOD;
1616

    
1617
	if (isset($ppp['ondemand']))
1618
		$mpdconf .= <<<EOD
1619
	set iface addrs 10.10.1.1 10.10.1.2
1620

    
1621
EOD;
1622

    
1623
	if (isset($ppp['tcpmssfix']))
1624
		$tcpmss = "disable";
1625
	else
1626
		$tcpmss = "enable";
1627
		$mpdconf .= <<<EOD
1628
	set iface {$tcpmss} tcpmssfix
1629

    
1630
EOD;
1631

    
1632
	$mpdconf .= <<<EOD
1633
	set iface up-script /usr/local/sbin/ppp-linkup
1634
	set iface down-script /usr/local/sbin/ppp-linkdown
1635
	set ipcp ranges {$ranges}
1636

    
1637
EOD;
1638
	if (isset($ppp['vjcomp']))
1639
		$mpdconf .= <<<EOD
1640
	set ipcp no vjcomp
1641

    
1642
EOD;
1643

    
1644
	if (isset($config['system']['dnsallowoverride']))
1645
		$mpdconf .= <<<EOD
1646
	set ipcp enable req-pri-dns
1647
	set ipcp enable req-sec-dns
1648

    
1649
EOD;
1650
	if (!isset($ppp['verbose_log']))
1651
		$mpdconf .= <<<EOD
1652
	#log -bund -ccp -chat -iface -ipcp -lcp -link
1653

    
1654
EOD;
1655
	foreach($ports as $pid => $port){
1656
		$port = get_real_interface($port);
1657
		$mpdconf .= <<<EOD
1658

    
1659
	create link static {$interface}_link{$pid} {$type}
1660
	set link action bundle {$interface}
1661
	set link {$multilink} multilink
1662
	set link keep-alive 10 60
1663
	set link max-redial 0
1664

    
1665
EOD;
1666
		if (isset($ppp['shortseq']))
1667
			$mpdconf .= <<<EOD
1668
	set link no shortseq
1669

    
1670
EOD;
1671

    
1672
		if (isset($ppp['acfcomp']))
1673
			$mpdconf .= <<<EOD
1674
	set link no acfcomp
1675

    
1676
EOD;
1677

    
1678
		if (isset($ppp['protocomp']))
1679
			$mpdconf .= <<<EOD
1680
	set link no protocomp
1681

    
1682
EOD;
1683

    
1684
		$mpdconf .= <<<EOD
1685
	set link disable chap pap
1686
	set link accept chap pap eap
1687
	set link disable incoming
1688

    
1689
EOD;
1690

    
1691

    
1692
		if (!empty($bandwidths[$pid]))
1693
			$mpdconf .= <<<EOD
1694
	set link bandwidth {$bandwidths[$pid]}
1695

    
1696
EOD;
1697

    
1698
		if (empty($mtus[$pid]))
1699
			$mtus[$pid] = $defaultmtu;
1700
			$mpdconf .= <<<EOD
1701
	set link mtu {$mtus[$pid]}
1702

    
1703
EOD;
1704

    
1705
		if (!empty($mrus[$pid]))
1706
			$mpdconf .= <<<EOD
1707
	set link mru {$mrus[$pid]}
1708

    
1709
EOD;
1710

    
1711
		if (!empty($mrrus[$pid]))
1712
			$mpdconf .= <<<EOD
1713
	set link mrru {$mrrus[$pid]}
1714

    
1715
EOD;
1716

    
1717
		$mpdconf .= <<<EOD
1718
	set auth authname "{$ppp['username']}"
1719
	set auth password {$passwd}
1720

    
1721
EOD;
1722
		if ($type == "modem") {
1723
			$mpdconf .= <<<EOD
1724
	set modem device {$ppp['ports']}
1725
	set modem script DialPeer
1726
	set modem idle-script Ringback
1727
	set modem watch -cd
1728
	set modem var \$DialPrefix "DT"
1729
	set modem var \$Telephone "{$ppp['phone']}"
1730

    
1731
EOD;
1732
		}
1733
		if (isset($ppp['connect-timeout']) && $type == "modem") {
1734
			$mpdconf .= <<<EOD
1735
	set modem var \$ConnectTimeout "{$ppp['connect-timeout']}"
1736

    
1737
EOD;
1738
		}
1739
		if (isset($ppp['initstr']) && $type == "modem") {
1740
			$initstr = base64_decode($ppp['initstr']);
1741
			$mpdconf .= <<<EOD
1742
	set modem var \$InitString "{$initstr}"
1743

    
1744
EOD;
1745
		}
1746
		if (isset($ppp['simpin']) && $type == "modem") {
1747
			if($ppp['pin-wait'] == "")
1748
				$ppp['pin-wait'] = 0;
1749
			$mpdconf .= <<<EOD
1750
	set modem var \$SimPin "{$ppp['simpin']}"
1751
	set modem var \$PinWait "{$ppp['pin-wait']}"
1752

    
1753
EOD;
1754
		}
1755
		if (isset($ppp['apn']) && $type == "modem") {
1756
			$mpdconf .= <<<EOD
1757
	set modem var \$APN "{$ppp['apn']}"
1758
	set modem var \$APNum "{$ppp['apnum']}"
1759

    
1760
EOD;
1761
		}
1762
		if ($type == "pppoe") {
1763
			// Send a null service name if none is set.
1764
			$provider = isset($ppp['provider']) ? $ppp['provider'] : "";
1765
			$mpdconf .= <<<EOD
1766
	set pppoe service "{$provider}"
1767

    
1768
EOD;
1769
		}
1770
		if ($type == "pppoe")
1771
			$mpdconf .= <<<EOD
1772
	set pppoe iface {$port}
1773

    
1774
EOD;
1775

    
1776
		if ($type == "pptp" || $type == "l2tp") {
1777
			$mpdconf .= <<<EOD
1778
	set {$type} self {$localips[$pid]}
1779
	set {$type} peer {$gateways[$pid]}
1780

    
1781
EOD;
1782
		}
1783

    
1784
		$mpdconf .= "\topen\n";
1785
	} //end foreach($port)
1786

    
1787

    
1788
	/* Generate mpd.conf. If mpd_[interface].conf exists in the conf path, then link to it instead of generating a fresh conf file. */
1789
	if (file_exists("{$g['conf_path']}/mpd_{$interface}.conf"))
1790
		mwexec("/bin/ln -s {$g['conf_path']}/mpd_{$interface}.conf {$g['varetc_path']}/.");
1791
	else {
1792
		$fd = fopen("{$g['varetc_path']}/mpd_{$interface}.conf", "w");
1793
		if (!$fd) {
1794
			log_error(sprintf(gettext("Error: cannot open mpd_%s.conf in interface_ppps_configure().%s"), $interface, "\n"));
1795
			return 0;
1796
		}
1797
		// Write out mpd_ppp.conf
1798
		fwrite($fd, $mpdconf);
1799
		fclose($fd);
1800
		unset($mpdconf);
1801
	}
1802

    
1803
	// Create the uptime log if requested and if it doesn't exist already, or delete it if it is no longer requested.
1804
	if (isset($ppp['uptime'])) {
1805
		if (!file_exists("/conf/{$pppif}.log")) {
1806
			conf_mount_rw();
1807
			mwexec("echo /dev/null > /conf/{$pppif}.log");
1808
			conf_mount_ro();
1809
		}
1810
	} else {
1811
		if (file_exists("/conf/{$pppif}.log")) {
1812
			conf_mount_rw();
1813
			mwexec("rm -f /conf/{$pppif}.log");
1814
			conf_mount_ro();
1815
		}
1816
	}
1817

    
1818
	/* clean up old lock files */
1819
	foreach($ports as $port) {
1820
		if(file_exists("{$g['var_path']}/spool/lock/LCK..{$port}"))
1821
			unlink("{$g['var_path']}/spool/lock/LCK..{$port}");
1822
	}
1823

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

    
1827
	// Check for PPPoE periodic reset request
1828
	if ($type == "pppoe") {
1829
		if (!empty($ppp['pppoe-reset-type']))
1830
			interface_setup_pppoe_reset_file($ppp['if'], $interface);
1831
		else
1832
			interface_setup_pppoe_reset_file($ppp['if']);
1833
	}
1834
	/* wait for upto 10 seconds for the interface to appear (ppp(oe)) */
1835
	$i = 0;
1836
	while($i < 10) {
1837
		exec("/sbin/ifconfig {$ppp['if']} 2>&1", $out, $ret);
1838
		if($ret == 0)
1839
			break;
1840
		sleep(1);
1841
		$i++;
1842
	}
1843

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

    
1862
	return 1;
1863
}
1864

    
1865
function interfaces_carp_setup() {
1866
	global $g, $config;
1867

    
1868
	if (isset($config['system']['developerspew'])) {
1869
		$mt = microtime();
1870
		echo "interfaces_carp_setup() being called $mt\n";
1871
	}
1872

    
1873
	if ($g['booting']) {
1874
		echo gettext("Configuring CARP settings...");
1875
		mute_kernel_msgs();
1876
	}
1877

    
1878
	/* suck in configuration items */
1879
	if ($config['hasync']) {
1880
		$pfsyncenabled = $config['hasync']['pfsyncenabled'];
1881
		$balanacing = $config['hasync']['balancing'];
1882
		$pfsyncinterface = $config['hasync']['pfsyncinterface'];
1883
		$pfsyncpeerip = $config['hasync']['pfsyncpeerip'];
1884
	} else {
1885
		unset($pfsyncinterface);
1886
		unset($balanacing);
1887
		unset($pfsyncenabled);
1888
	}
1889

    
1890
	if ($balanacing) {
1891
		mwexec("/sbin/sysctl net.inet.carp.arpbalance=1", true);
1892
		mwexec("/sbin/sysctl net.inet.carp.preempt=0", true);
1893
	} else
1894
		mwexec("/sbin/sysctl net.inet.carp.preempt=1", true);
1895

    
1896
	mwexec("sbin/sysctl net.inet.carp.log=1", true);
1897
	if (!empty($pfsyncinterface))
1898
		$carp_sync_int = get_real_interface($pfsyncinterface);
1899
	else
1900
		unset($carp_sync_int);
1901

    
1902
	/* setup pfsync interface */
1903
	if ($carp_sync_int and $pfsyncenabled) {
1904
		if (is_ipaddr($pfsyncpeerip))
1905
			$syncpeer = "syncpeer {$pfsyncpeerip}";
1906
		else
1907
			$syncpeer = "-syncpeer";
1908

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

    
1911
		sleep(1);
1912

    
1913
		/* 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
1914
		 * for existing sessions.
1915
		 */
1916
		log_error("waiting for pfsync...");
1917
		$i = 0;
1918
		while (intval(trim(`/sbin/ifconfig pfsync0 | /usr/bin/grep 'syncok: 0' | /usr/bin/grep -v grep | /usr/bin/wc -l`)) == 0 && $i < 30) {
1919
			$i++;
1920
			sleep(1);
1921
		}
1922
		log_error("pfsync done in $i seconds.");
1923
		log_error("Configuring CARP settings finalize...");
1924
	} else {
1925
		mwexec("/sbin/ifconfig pfsync0 -syncdev -syncpeer down", false);
1926
	}
1927

    
1928
	if($config['virtualip']['vip'])
1929
		mwexec("/sbin/sysctl net.inet.carp.allow=1", true);
1930
	else
1931
		mwexec("/sbin/sysctl net.inet.carp.allow=0", true);
1932

    
1933
	if ($g['booting']) {
1934
		unmute_kernel_msgs();
1935
		echo gettext("done.") . "\n";
1936
	}
1937
}
1938

    
1939
function interface_proxyarp_configure($interface = "") {
1940
	global $config, $g;
1941
	if(isset($config['system']['developerspew'])) {
1942
		$mt = microtime();
1943
		echo "interface_proxyarp_configure() being called $mt\n";
1944
	}
1945

    
1946
	/* kill any running choparp */
1947
	if (empty($interface))
1948
		killbyname("choparp");
1949
	else {
1950
		$vipif = get_real_interface($interface);
1951
		if (file_exists("{$g['varrun_path']}/choparp_{$vipif}.pid"))
1952
			killbypid("{$g['varrun_path']}/choparp_{$vipif}.pid");
1953
	}
1954

    
1955
	$paa = array();
1956
	if (!empty($config['virtualip']) && is_array($config['virtualip']['vip'])) {
1957

    
1958
		/* group by interface */
1959
		foreach ($config['virtualip']['vip'] as $vipent) {
1960
			if ($vipent['mode'] === "proxyarp") {
1961
				if ($vipent['interface'])
1962
					$proxyif = $vipent['interface'];
1963
				else
1964
					$proxyif = "wan";
1965

    
1966
				if (!empty($interface) && $interface != $proxyif)
1967
					continue;
1968

    
1969
				if (!is_array($paa[$proxyif]))
1970
					$paa[$proxyif] = array();
1971

    
1972
				$paa[$proxyif][] = $vipent;
1973
			}
1974
		}
1975
	}
1976

    
1977
	if (!empty($interface)) {
1978
		if (is_array($paa[$interface])) {
1979
			$paaifip = get_interface_ip($interface);
1980
			if (!is_ipaddr($paaifip))
1981
				return;
1982
			$args = get_real_interface($interface) . " auto";
1983
			foreach ($paa[$interface] as $paent) {
1984
				if (isset($paent['subnet']))
1985
					$args .= " " . escapeshellarg("{$paent['subnet']}/{$paent['subnet_bits']}");
1986
				else if (isset($paent['range']))
1987
					$args .= " " . escapeshellarg($paent['range']['from'] . "-" . $paent['range']['to']);
1988
			}
1989
			mwexec_bg("/usr/local/sbin/choparp " . $args);
1990
		}
1991
	} else if (count($paa) > 0) {
1992
		foreach ($paa as $paif => $paents)  {
1993
			$paaifip = get_interface_ip($paif);
1994
			if (!is_ipaddr($paaifip))
1995
				continue;
1996
			$args = get_real_interface($paif) . " auto";
1997
			foreach ($paents as $paent) {
1998
				if (isset($paent['subnet']))
1999
					$args .= " " . escapeshellarg("{$paent['subnet']}/{$paent['subnet_bits']}");
2000
				else if (isset($paent['range']))
2001
					$args .= " " . escapeshellarg($paent['range']['from'] . "-" . $paent['range']['to']);
2002
			}
2003
			mwexec_bg("/usr/local/sbin/choparp " . $args);
2004
		}
2005
	}
2006
}
2007

    
2008
function interface_ipalias_cleanup($interface, $inet = "inet4") {
2009
	global $g, $config;
2010

    
2011
	if (is_array($config['virtualip']['vip'])) {
2012
		foreach ($config['virtualip']['vip'] as $vip) {
2013
			if ($vip['mode'] == "ipalias" && $vip['interface'] == $interface) {
2014
				if ($inet == "inet6" && is_ipaddrv6($vip['subnet']))
2015
					interface_vip_bring_down($vip);
2016
				else if ($inet == "inet4" && is_ipaddrv4($vip['subnet']))
2017
					interface_vip_bring_down($vip);
2018
			}
2019
		}
2020
	}
2021
}
2022

    
2023
function interfaces_vips_configure($interface = "") {
2024
	global $g, $config;
2025
	if(isset($config['system']['developerspew'])) {
2026
		$mt = microtime();
2027
		echo "interfaces_vips_configure() being called $mt\n";
2028
	}
2029
	$paa = array();
2030
	if(is_array($config['virtualip']['vip'])) {
2031
		$carp_setuped = false;
2032
		$anyproxyarp = false;
2033
		foreach ($config['virtualip']['vip'] as $vip) {
2034
			switch ($vip['mode']) {
2035
			case "proxyarp":
2036
				/* nothing it is handled on interface_proxyarp_configure() */
2037
				if ($interface <> "" && $vip['interface'] <> $interface)
2038
					continue;
2039
				$anyproxyarp = true;
2040
				break;
2041
			case "ipalias":
2042
				if ($interface <> "" && $vip['interface'] <> $interface)
2043
					continue;
2044
				interface_ipalias_configure($vip);
2045
				break;
2046
			case "carp":
2047
				if ($interface <> "" && $vip['interface'] <> $interface)
2048
					continue;
2049
				if ($carp_setuped == false)
2050
					$carp_setuped = true;
2051
				interface_carp_configure($vip);
2052
				break;
2053
			}
2054
		}
2055
		if ($carp_setuped == true)
2056
			interfaces_carp_setup();
2057
		if ($anyproxyarp == true)
2058
			interface_proxyarp_configure();
2059
	}
2060
}
2061

    
2062
function interface_ipalias_configure(&$vip) {
2063
	if ($vip['mode'] == "ipalias") {
2064
		$if = get_real_interface($vip['interface']);
2065
		$af = "inet";
2066
		if(is_ipaddrv6($vip['subnet']))
2067
			$af = "inet6";
2068
		mwexec("/sbin/ifconfig " . escapeshellarg($if) ." {$af} ". escapeshellarg($vip['subnet']) ."/" . escapeshellarg($vip['subnet_bits']) . " alias");
2069
	}
2070
}
2071

    
2072
function interface_reload_carps($cif) {
2073
	global $config;
2074

    
2075
	$carpifs = link_ip_to_carp_interface(find_interface_ip($cif));
2076
	if (empty($carpifs))
2077
		return;
2078

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

    
2101
function interface_carp_configure(&$vip) {
2102
	global $config, $g;
2103
	if(isset($config['system']['developerspew'])) {
2104
		$mt = microtime();
2105
		echo "interface_carp_configure() being called $mt\n";
2106
	}
2107

    
2108
	if ($vip['mode'] != "carp")
2109
		return;
2110

    
2111
	/*
2112
	 * ensure the interface containing the VIP really exists
2113
	 * prevents a panic if the interface is missing or invalid
2114
	 */
2115
	$realif = get_real_interface($vip['interface']);
2116
	if (!does_interface_exist($realif)) {
2117
		file_notice("CARP", sprintf(gettext("Interface specified for the virtual IP address %s does not exist. Skipping this VIP."), $vip['subnet']), "Firewall: Virtual IP", "");
2118
		return;
2119
	}
2120

    
2121
	if(is_ipaddrv4($vip['subnet'])) {
2122
		/* Ensure CARP IP really exists prior to loading up. */
2123
		$ww_subnet_ip = find_interface_ip($realif);
2124
		$ww_subnet_bits = find_interface_subnet($realif);
2125
		if (!ip_in_subnet($vip['subnet'], gen_subnet($ww_subnet_ip, $ww_subnet_bits) . "/" . $ww_subnet_bits) && !ip_in_interface_alias_subnet($vip['interface'], $vip['subnet'])) {
2126
			file_notice("CARP", sprintf(gettext("Sorry but we could not find a matching real interface subnet for the virtual IP address %s."), $vip['subnet']), "Firewall: Virtual IP", "");
2127
			return;
2128
		}
2129
	}
2130
	if(is_ipaddrv6($vip['subnet'])) {
2131
		/* Ensure CARP IP really exists prior to loading up. */
2132
		$ww_subnet_ip = find_interface_ipv6($realif);
2133
		$ww_subnet_bits = find_interface_subnetv6($realif);
2134
		if (!ip_in_subnet($vip['subnet'], gen_subnetv6($ww_subnet_ip, $ww_subnet_bits) . "/" . $ww_subnet_bits) && !ip_in_interface_alias_subnet($vip['interface'], $vip['subnet'])) {
2135
			file_notice("CARP", sprintf(gettext("Sorry but we could not find a matching real interface subnet for the virtual IPv6 address %s."), $vip['subnet']), "Firewall: Virtual IP", "");
2136
			return;
2137
		}
2138
	}
2139

    
2140
	// set the vip interface to the vhid
2141
	$vipif = "{$vip['interface']}_vip{$vip['vhid']}";
2142

    
2143
	/* create the carp interface and setup */
2144
	if (does_interface_exist($vipif)) {
2145
		pfSense_interface_flags($vipif, -IFF_UP);
2146
	} else {
2147
		$carpif = pfSense_interface_create("carp");
2148
		pfSense_interface_rename($carpif, $vipif);
2149
		pfSense_ngctl_name("{$carpif}:", $vipif);
2150
	}
2151

    
2152
	/* invalidate interface cache */
2153
	get_interface_arr(true);
2154

    
2155
	$vip_password = $vip['password'];
2156
	$vip_password = escapeshellarg(addslashes(str_replace(" ", "", $vip_password)));
2157
	if ($vip['password'] != "")
2158
		$password = " pass {$vip_password}";
2159

    
2160
	$broadcast_address = gen_subnet_max($vip['subnet'], $vip['subnet_bits']);
2161
	$advbase = "";
2162
	if (!empty($vip['advbase']))
2163
		$advbase = "advbase {$vip['advbase']}";
2164

    
2165
	if(is_ipaddrv4($vip['subnet'])) {
2166
		$broadcast_address = gen_subnet_max($vip['subnet'], $vip['subnet_bits']);
2167
		mwexec("/sbin/ifconfig {$vipif} {$vip['subnet']}/{$vip['subnet_bits']} vhid {$vip['vhid']} advskew {$vip['advskew']} {$advbase} {$password}");
2168
	}
2169
	if(is_ipaddrv6($vip['subnet'])) {
2170
		$broadcast_address = gen_subnet_max($vip['subnet'], $vip['subnet_bits']);
2171
		mwexec("/sbin/ifconfig {$vipif} inet6 {$vip['subnet']} prefixlen {$vip['subnet_bits']} vhid {$vip['vhid']} advskew {$vip['advskew']} {$advbase} {$password}");
2172
	}
2173

    
2174
	interfaces_bring_up($vipif);
2175

    
2176
	return $vipif;
2177
}
2178

    
2179
function interface_wireless_clone($realif, $wlcfg) {
2180
	global $config, $g;
2181
	/*   Check to see if interface has been cloned as of yet.
2182
	 *   If it has not been cloned then go ahead and clone it.
2183
	 */
2184
	$needs_clone = false;
2185
	if(is_array($wlcfg['wireless']))
2186
		$wlcfg_mode = $wlcfg['wireless']['mode'];
2187
	else
2188
		$wlcfg_mode = $wlcfg['mode'];
2189
	switch($wlcfg_mode) {
2190
	case "hostap":
2191
		$mode = "wlanmode hostap";
2192
		break;
2193
	case "adhoc":
2194
		$mode = "wlanmode adhoc";
2195
		break;
2196
	default:
2197
		$mode = "";
2198
		break;
2199
	}
2200
	$baseif = interface_get_wireless_base($wlcfg['if']);
2201
	if(does_interface_exist($realif)) {
2202
		exec("/sbin/ifconfig {$realif}", $output, $ret);
2203
		$ifconfig_str = implode($output);
2204
		if(($wlcfg_mode == "hostap") && (! preg_match("/hostap/si", $ifconfig_str))) {
2205
			log_error(sprintf(gettext("Interface %s changed to hostap mode"), $realif));
2206
			$needs_clone = true;
2207
		}
2208
		if(($wlcfg_mode == "adhoc") && (! preg_match("/adhoc/si", $ifconfig_str))) {
2209
			log_error(sprintf(gettext("Interface %s changed to adhoc mode"), $realif));
2210
			$needs_clone = true;
2211
		}
2212
		if(($wlcfg_mode == "bss") && (preg_match("/hostap|adhoc/si", $ifconfig_str))) {
2213
			log_error(sprintf(gettext("Interface %s changed to infrastructure mode"), $realif));
2214
			$needs_clone = true;
2215
		}
2216
	} else {
2217
		$needs_clone = true;
2218
	}
2219

    
2220
	if($needs_clone == true) {
2221
		/* remove previous instance if it exists */
2222
		if(does_interface_exist($realif))
2223
			pfSense_interface_destroy($realif);
2224

    
2225
		log_error(sprintf(gettext("Cloning new wireless interface %s"), $realif));
2226
		// Create the new wlan interface. FreeBSD returns the new interface name.
2227
		// example:  wlan2
2228
		exec("/sbin/ifconfig wlan create wlandev {$baseif} {$mode} bssid 2>&1", $out, $ret);
2229
		if($ret <> 0) {
2230
			log_error(sprintf(gettext('Failed to clone interface %1$s with error code %2$s, output %3$s'), $baseif, $ret, $out[0]));
2231
			return false;
2232
		}
2233
		$newif = trim($out[0]);
2234
		// Rename the interface to {$parentnic}_wlan{$number}#: EX: ath0_wlan0
2235
		pfSense_interface_rename($newif, $realif);
2236
		// FIXME: not sure what ngctl is for. Doesn't work.
2237
		// mwexec("/usr/sbin/ngctl name {$newif}: {$realif}", false);
2238
		file_put_contents("{$g['tmp_path']}/{$realif}_oldmac", get_interface_mac($realif));
2239
	}
2240
	return true;
2241
}
2242

    
2243
function interface_sync_wireless_clones(&$ifcfg, $sync_changes = false) {
2244
	global $config, $g;
2245

    
2246
	$shared_settings = array('standard', 'turbo', 'protmode', 'txpower', 'channel',
2247
				 'diversity', 'txantenna', 'rxantenna', 'distance',
2248
				 'regdomain', 'regcountry', 'reglocation');
2249

    
2250
	if(!is_interface_wireless($ifcfg['if']))
2251
		return;
2252

    
2253
	$baseif = interface_get_wireless_base($ifcfg['if']);
2254

    
2255
	// Sync shared settings for assigned clones
2256
	$iflist = get_configured_interface_list(false, true);
2257
	foreach ($iflist as $if) {
2258
		if ($baseif == interface_get_wireless_base($config['interfaces'][$if]['if']) && $ifcfg['if'] != $config['interfaces'][$if]['if']) {
2259
			if (isset($config['interfaces'][$if]['wireless']['standard']) || $sync_changes) {
2260
				foreach ($shared_settings as $setting) {
2261
					if ($sync_changes) {
2262
						if (isset($ifcfg['wireless'][$setting]))
2263
							$config['interfaces'][$if]['wireless'][$setting] = $ifcfg['wireless'][$setting];
2264
						else if (isset($config['interfaces'][$if]['wireless'][$setting]))
2265
							unset($config['interfaces'][$if]['wireless'][$setting]);
2266
					} else {
2267
						if (isset($config['interfaces'][$if]['wireless'][$setting]))
2268
							$ifcfg['wireless'][$setting] = $config['interfaces'][$if]['wireless'][$setting];
2269
						else if (isset($ifcfg['wireless'][$setting]))
2270
							unset($ifcfg['wireless'][$setting]);
2271
					}
2272
				}
2273
				if (!$sync_changes)
2274
					break;
2275
			}
2276
		}
2277
	}
2278

    
2279
	// Read or write settings at shared area
2280
	if (isset($config['wireless']['interfaces'][$baseif]) && is_array($config['wireless']['interfaces'][$baseif])) {
2281
		foreach ($shared_settings as $setting) {
2282
			if ($sync_changes) {
2283
				if (isset($ifcfg['wireless'][$setting]))
2284
					$config['wireless']['interfaces'][$baseif][$setting] = $ifcfg['wireless'][$setting];
2285
				else if (isset($config['wireless']['interfaces'][$baseif][$setting]))
2286
					unset($config['wireless']['interfaces'][$baseif][$setting]);
2287
			} else if (isset($config['wireless']['interfaces'][$baseif][$setting])) {
2288
				if (isset($config['wireless']['interfaces'][$baseif][$setting]))
2289
					$ifcfg['wireless'][$setting] = $config['wireless']['interfaces'][$baseif][$setting];
2290
				else if (isset($ifcfg['wireless'][$setting]))
2291
					unset($ifcfg['wireless'][$setting]);
2292
			}
2293
		}
2294
	}
2295

    
2296
	// Sync the mode on the clone creation page with the configured mode on the interface
2297
	if (interface_is_wireless_clone($ifcfg['if']) && isset($config['wireless']['clone']) && is_array($config['wireless']['clone'])) {
2298
		foreach ($config['wireless']['clone'] as &$clone) {
2299
			if ($clone['cloneif'] == $ifcfg['if']) {
2300
				if ($sync_changes) {
2301
					$clone['mode'] = $ifcfg['wireless']['mode'];
2302
				} else {
2303
					$ifcfg['wireless']['mode'] = $clone['mode'];
2304
				}
2305
				break;
2306
			}
2307
		}
2308
		unset($clone);
2309
	}
2310
}
2311

    
2312
function interface_wireless_configure($if, &$wl, &$wlcfg) {
2313
	global $config, $g;
2314

    
2315
	/*    open up a shell script that will be used to output the commands.
2316
	 *    since wireless is changing a lot, these series of commands are fragile
2317
	 *    and will sometimes need to be verified by a operator by executing the command
2318
	 *    and returning the output of the command to the developers for inspection.  please
2319
	 *    do not change this routine from a shell script to individual exec commands.  -sullrich
2320
	 */
2321

    
2322
	// Remove script file
2323
	unlink_if_exists("{$g['tmp_path']}/{$if}_setup.sh");
2324

    
2325
	// Clone wireless nic if needed.
2326
	interface_wireless_clone($if, $wl);
2327

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

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

    
2335
	/* set values for /path/program */
2336
	$hostapd = "/usr/sbin/hostapd";
2337
	$wpa_supplicant = "/usr/sbin/wpa_supplicant";
2338
	$ifconfig = "/sbin/ifconfig";
2339
	$sysctl = "/sbin/sysctl";
2340
	$killall = "/usr/bin/killall";
2341

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

    
2344
	$wlcmd = array();
2345
	$wl_sysctl = array();
2346
	/* Make sure it's up */
2347
	$wlcmd[] = "up";
2348
	/* Set a/b/g standard */
2349
	$standard = str_replace(" Turbo", "", $wlcfg['standard']);
2350
	$wlcmd[] = "mode " . escapeshellarg($standard);
2351

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

    
2357
	/* Set ssid */
2358
	if($wlcfg['ssid'])
2359
		$wlcmd[] = "ssid " .escapeshellarg($wlcfg['ssid']);
2360

    
2361
	/* Set 802.11g protection mode */
2362
	$wlcmd[] = "protmode " . escapeshellarg($wlcfg['protmode']);
2363

    
2364
	/* set wireless channel value */
2365
	if(isset($wlcfg['channel'])) {
2366
		if($wlcfg['channel'] == "0") {
2367
			$wlcmd[] = "channel any";
2368
		} else {
2369
			$wlcmd[] = "channel " . escapeshellarg($wlcfg['channel']);
2370
		}
2371
	}
2372

    
2373
	/* Set antenna diversity value */
2374
	if(isset($wlcfg['diversity']))
2375
		$wl_sysctl[] = "diversity=" . escapeshellarg($wlcfg['diversity']);
2376

    
2377
	/* Set txantenna value */
2378
	if(isset($wlcfg['txantenna']))
2379
		$wl_sysctl[] = "txantenna=" . escapeshellarg($wlcfg['txantenna']);
2380

    
2381
	/* Set rxantenna value */
2382
	if(isset($wlcfg['rxantenna']))
2383
		$wl_sysctl[] = "rxantenna=" . escapeshellarg($wlcfg['rxantenna']);
2384

    
2385
	/* set Distance value */
2386
	if($wlcfg['distance'])
2387
		$distance = escapeshellarg($wlcfg['distance']);
2388

    
2389
	/* Set wireless hostap mode */
2390
	if ($wlcfg['mode'] == "hostap") {
2391
		$wlcmd[] = "mediaopt hostap";
2392
	} else {
2393
		$wlcmd[] = "-mediaopt hostap";
2394
	}
2395

    
2396
	/* Set wireless adhoc mode */
2397
	if ($wlcfg['mode'] == "adhoc") {
2398
		$wlcmd[] = "mediaopt adhoc";
2399
	} else {
2400
		$wlcmd[] = "-mediaopt adhoc";
2401
	}
2402

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

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

    
2412
	/* handle pureg (802.11g) only option */
2413
	if(isset($wlcfg['pureg']['enable'])) {
2414
		$wlcmd[] = "mode 11g pureg";
2415
	} else {
2416
		$wlcmd[] = "-pureg";
2417
	}
2418

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

    
2426
	/* enable apbridge option */
2427
	if(isset($wlcfg['apbridge']['enable'])) {
2428
		$wlcmd[] = "apbridge";
2429
	} else {
2430
		$wlcmd[] = "-apbridge";
2431
	}
2432

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

    
2440
	/* handle txpower setting */
2441
	/* if($wlcfg['txpower'] <> "")
2442
		$wlcmd[] = "txpower " . escapeshellarg($wlcfg['txpower']);
2443
	*/
2444
	/* handle wme option */
2445
	if(isset($wlcfg['wme']['enable'])) {
2446
		$wlcmd[] = "wme";
2447
	} else {
2448
		$wlcmd[] = "-wme";
2449
	}
2450

    
2451
	/* set up wep if enabled */
2452
	$wepset = "";
2453
	if (isset($wlcfg['wep']['enable']) && is_array($wlcfg['wep']['key'])) {
2454
		switch($wlcfg['wpa']['auth_algs']) {
2455
			case "1":
2456
				$wepset .= "authmode open wepmode on ";
2457
				break;
2458
			case "2":
2459
				$wepset .= "authmode shared wepmode on ";
2460
				break;
2461
			case "3":
2462
				$wepset .= "authmode mixed wepmode on ";
2463
		}
2464
		$i = 1;
2465
		foreach ($wlcfg['wep']['key'] as $wepkey) {
2466
			$wepset .= "wepkey " . escapeshellarg("{$i}:{$wepkey['value']}") . " ";
2467
			if (isset($wepkey['txkey'])) {
2468
				$wlcmd[] = "weptxkey {$i} ";
2469
			}
2470
			$i++;
2471
		}
2472
		$wlcmd[] = $wepset;
2473
	} else {
2474
		$wlcmd[] = "authmode open wepmode off ";
2475
	}
2476

    
2477
	kill_hostapd($if);
2478
	mwexec(kill_wpasupplicant("{$if}"));
2479

    
2480
	/* generate wpa_supplicant/hostap config if wpa is enabled */
2481
	conf_mount_rw();
2482

    
2483
	switch ($wlcfg['mode']) {
2484
		case 'bss':
2485
			if (isset($wlcfg['wpa']['enable'])) {
2486
				$wpa .= <<<EOD
2487
ctrl_interface={$g['varrun_path']}/wpa_supplicant
2488
ctrl_interface_group=0
2489
ap_scan=1
2490
#fast_reauth=1
2491
network={
2492
ssid="{$wlcfg['ssid']}"
2493
scan_ssid=1
2494
priority=5
2495
key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
2496
psk="{$wlcfg['wpa']['passphrase']}"
2497
pairwise={$wlcfg['wpa']['wpa_pairwise']}
2498
group={$wlcfg['wpa']['wpa_pairwise']}
2499
}
2500
EOD;
2501

    
2502
				$fd = fopen("{$g['varetc_path']}/wpa_supplicant_{$if}.conf", "w");
2503
				fwrite($fd, "{$wpa}");
2504
				fclose($fd);
2505
			}
2506
			break;
2507
		case 'hostap':
2508
			if($wlcfg['wpa']['passphrase'])
2509
				$wpa_passphrase = "wpa_passphrase={$wlcfg['wpa']['passphrase']}\n";
2510
			else
2511
				$wpa_passphrase = "";
2512
			if (isset($wlcfg['wpa']['enable'])) {
2513
				$wpa .= <<<EOD
2514
interface={$if}
2515
driver=bsd
2516
logger_syslog=-1
2517
logger_syslog_level=0
2518
logger_stdout=-1
2519
logger_stdout_level=0
2520
dump_file={$g['tmp_path']}/hostapd_{$if}.dump
2521
ctrl_interface={$g['varrun_path']}/hostapd
2522
ctrl_interface_group=wheel
2523
#accept_mac_file={$g['tmp_path']}/hostapd_{$if}.accept
2524
#deny_mac_file={$g['tmp_path']}/hostapd_{$if}.deny
2525
#macaddr_acl={$wlcfg['wpa']['macaddr_acl']}
2526
ssid={$wlcfg['ssid']}
2527
debug={$wlcfg['wpa']['debug_mode']}
2528
auth_algs={$wlcfg['wpa']['auth_algs']}
2529
wpa={$wlcfg['wpa']['wpa_mode']}
2530
wpa_key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
2531
wpa_pairwise={$wlcfg['wpa']['wpa_pairwise']}
2532
wpa_group_rekey={$wlcfg['wpa']['wpa_group_rekey']}
2533
wpa_gmk_rekey={$wlcfg['wpa']['wpa_gmk_rekey']}
2534
wpa_strict_rekey={$wlcfg['wpa']['wpa_strict_rekey']}
2535
{$wpa_passphrase}
2536

    
2537
EOD;
2538

    
2539
if (isset($wlcfg['wpa']['rsn_preauth'])) {
2540
	$wpa .= <<<EOD
2541
# Enable the next lines for preauth when roaming. Interface = wired or wireless interface talking to the AP you want to roam from/to
2542
rsn_preauth=1
2543
rsn_preauth_interfaces={$if}
2544

    
2545
EOD;
2546

    
2547
}
2548
				if($wlcfg['auth_server_addr'] && $wlcfg['auth_server_shared_secret']) {
2549
					$auth_server_port = "1812";
2550
					if($wlcfg['auth_server_port'])
2551
						$auth_server_port = $wlcfg['auth_server_port'];
2552
					$auth_server_port2 = "1812";
2553
					if($wlcfg['auth_server_port2'])
2554
						$auth_server_port2 = $wlcfg['auth_server_port2'];
2555
					$wpa .= <<<EOD
2556

    
2557
ieee8021x=1
2558
auth_server_addr={$wlcfg['auth_server_addr']}
2559
auth_server_port={$auth_server_port}
2560
auth_server_shared_secret={$wlcfg['auth_server_shared_secret']}
2561
auth_server_addr={$wlcfg['auth_server_addr2']}
2562
auth_server_port={$auth_server_port2}
2563
auth_server_shared_secret={$wlcfg['auth_server_shared_secret2']}
2564

    
2565
EOD;
2566
				} else {
2567
					$wpa .= "ieee8021x={$wlcfg['wpa']['ieee8021x']}\n";
2568
				}
2569

    
2570
				$fd = fopen("{$g['varetc_path']}/hostapd_{$if}.conf", "w");
2571
				fwrite($fd, "{$wpa}");
2572
				fclose($fd);
2573

    
2574
			}
2575
			break;
2576
	}
2577

    
2578
	/*
2579
	 *    all variables are set, lets start up everything
2580
	 */
2581

    
2582
	$baseif = interface_get_wireless_base($if);
2583
	preg_match("/^(.*?)([0-9]*)$/", $baseif, $baseif_split);
2584
	$wl_sysctl_prefix = 'dev.' . $baseif_split[1] . '.' . $baseif_split[2];
2585

    
2586
	/* set sysctls for the wireless interface */
2587
	if (!empty($wl_sysctl)) {
2588
		fwrite($fd_set, "# sysctls for {$baseif}\n");
2589
		foreach ($wl_sysctl as $wl_sysctl_line) {
2590
			fwrite($fd_set, "{$sysctl} {$wl_sysctl_prefix}.{$wl_sysctl_line}\n");
2591
		}
2592
	}
2593

    
2594
	/* set ack timers according to users preference (if he/she has any) */
2595
	if($distance) {
2596
		fwrite($fd_set, "# Enable ATH distance settings\n");
2597
		fwrite($fd_set, "/sbin/athctrl.sh -i {$baseif} -d {$distance}\n");
2598
	}
2599

    
2600
	if (isset($wlcfg['wpa']['enable'])) {
2601
		if ($wlcfg['mode'] == "bss") {
2602
			fwrite($fd_set, "{$wpa_supplicant} -B -i {$if} -c {$g['varetc_path']}/wpa_supplicant_{$if}.conf\n");
2603
		}
2604
		if ($wlcfg['mode'] == "hostap") {
2605
			/* add line to script to restore old mac to make hostapd happy */
2606
			if (file_exists("{$g['tmp_path']}/{$if}_oldmac")) {
2607
				$if_oldmac = file_get_contents("{$g['tmp_path']}/{$if}_oldmac");
2608
				if (is_macaddr($if_oldmac))
2609
					fwrite($fd_set, "{$ifconfig} " . escapeshellarg($if) .
2610
						" link " . escapeshellarg($if_oldmac) . "\n");
2611
			}
2612

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

    
2615
			/* add line to script to restore spoofed mac after running hostapd */
2616
			if (file_exists("{$g['tmp_path']}/{$if}_oldmac")) {
2617
				if ($wl['spoofmac'])
2618
					$if_curmac = $wl['spoofmac'];
2619
				else
2620
					$if_curmac = get_interface_mac($if);
2621
				if (is_macaddr($if_curmac))
2622
					fwrite($fd_set, "{$ifconfig} " . escapeshellarg($if) .
2623
						" link " . escapeshellarg($if_curmac) . "\n");
2624
			}
2625
		}
2626
	}
2627

    
2628
	fclose($fd_set);
2629
	conf_mount_ro();
2630

    
2631
	/* Making sure regulatory settings have actually changed
2632
	 * before applying, because changing them requires bringing
2633
	 * down all wireless networks on the interface. */
2634
	exec("{$ifconfig} " . escapeshellarg($if), $output);
2635
	$ifconfig_str = implode($output);
2636
	unset($output);
2637
	$reg_changing = false;
2638

    
2639
	/* special case for the debug country code */
2640
	if ($wlcfg['regcountry'] == 'DEBUG' && !preg_match("/\sregdomain\s+DEBUG\s/si", $ifconfig_str))
2641
		$reg_changing = true;
2642
	else if ($wlcfg['regdomain'] && !preg_match("/\sregdomain\s+{$wlcfg['regdomain']}\s/si", $ifconfig_str))
2643
		$reg_changing = true;
2644
	else if ($wlcfg['regcountry'] && !preg_match("/\scountry\s+{$wlcfg['regcountry']}\s/si", $ifconfig_str))
2645
		$reg_changing = true;
2646
	else if ($wlcfg['reglocation'] == 'anywhere' && preg_match("/\s(indoor|outdoor)\s/si", $ifconfig_str))
2647
		$reg_changing = true;
2648
	else if ($wlcfg['reglocation'] && $wlcfg['reglocation'] != 'anywhere' && !preg_match("/\s{$wlcfg['reglocation']}\s/si", $ifconfig_str))
2649
		$reg_changing = true;
2650

    
2651
	if ($reg_changing) {
2652
		/* set regulatory domain */
2653
		if($wlcfg['regdomain'])
2654
			$wlregcmd[] = "regdomain " . escapeshellarg($wlcfg['regdomain']);
2655

    
2656
		/* set country */
2657
		if($wlcfg['regcountry'])
2658
			$wlregcmd[] = "country " . escapeshellarg($wlcfg['regcountry']);
2659

    
2660
		/* set location */
2661
		if($wlcfg['reglocation'])
2662
			$wlregcmd[] = escapeshellarg($wlcfg['reglocation']);
2663

    
2664
		$wlregcmd_args = implode(" ", $wlregcmd);
2665

    
2666
		/* build a complete list of the wireless clones for this interface */
2667
		$clone_list = array();
2668
		if (does_interface_exist(interface_get_wireless_clone($baseif)))
2669
			$clone_list[] = interface_get_wireless_clone($baseif);
2670
		if (isset($config['wireless']['clone']) && is_array($config['wireless']['clone'])) {
2671
			foreach ($config['wireless']['clone'] as $clone) {
2672
				if ($clone['if'] == $baseif)
2673
					$clone_list[] = $clone['cloneif'];
2674
			}
2675
		}
2676

    
2677
		/* find which clones are up and bring them down */
2678
		$clones_up = array();
2679
		foreach ($clone_list as $clone_if) {
2680
			$clone_status = pfSense_get_interface_addresses($clone_if);
2681
			if ($clone_status['status'] == 'up') {
2682
				$clones_up[] = $clone_if;
2683
				mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " down");
2684
			}
2685
		}
2686

    
2687
		/* apply the regulatory settings */
2688
		mwexec("{$ifconfig} " . escapeshellarg($if) . " {$wlregcmd_args}");
2689

    
2690
		/* bring the clones back up that were previously up */
2691
		foreach ($clones_up as $clone_if) {
2692
			mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " up");
2693

    
2694
			/*
2695
			 * Rerun the setup script for the interface if it isn't this interface, the interface
2696
			 * is in infrastructure mode, and WPA is enabled.
2697
			 * This can be removed if wpa_supplicant stops dying when you bring the interface down.
2698
			 */
2699
			if ($clone_if != $if) {
2700
				$friendly_if = convert_real_interface_to_friendly_interface_name($clone_if);
2701
				if ( !empty($friendly_if)
2702
				    && $config['interfaces'][$friendly_if]['wireless']['mode'] == "bss"
2703
				    && isset($config['interfaces'][$friendly_if]['wireless']['wpa']['enable']) ) {
2704
					mwexec("/bin/sh {$g['tmp_path']}/{$clone_if}_setup.sh");
2705
				}
2706
			}
2707
		}
2708
	}
2709

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

    
2714
	/* configure wireless */
2715
	$wlcmd_args = implode(" ", $wlcmd);
2716
	mwexec("/sbin/ifconfig {$if} $wlcmd_args", false);
2717

    
2718

    
2719
	sleep(1);
2720
	/* execute hostapd and wpa_supplicant if required in shell */
2721
	mwexec("/bin/sh {$g['tmp_path']}/{$if}_setup.sh");
2722

    
2723
	return 0;
2724

    
2725
}
2726

    
2727
function kill_hostapd($interface) {
2728
	global $g;
2729

    
2730
	if (isvalidpid("{$g['varrun_path']}/hostapd_{$interface}.pid"))
2731
		return killbypid("{$g['varrun_path']}/hostapd_{$interface}.pid");
2732
}
2733

    
2734
function kill_wpasupplicant($interface) {
2735
	return "/bin/pkill -f \"wpa_supplicant .*{$interface}\\.conf\"\n";
2736
}
2737

    
2738
function find_dhclient_process($interface) {
2739
	if ($interface)
2740
		$pid = `/bin/pgrep -axf "dhclient: {$interface}"`;
2741
	else
2742
		$pid = 0;
2743

    
2744
	return intval($pid);
2745
}
2746

    
2747
function find_dhcp6c_process($interface) {
2748
	global $g;
2749

    
2750
	if ($interface && isvalidpid("{$g['varrun_path']}/dhcp6c_{$interface}.pid"))
2751
		$pid = trim(file_get_contents("{$g['varrun_path']}/dhcp6c_{$interface}.pid"), " \n");
2752
	else
2753
		return(false);
2754

    
2755
	return intval($pid);
2756
}
2757

    
2758
function interface_vlan_mtu_configured($realhwif, $mtu) {
2759
	global $config;
2760

    
2761
	if (is_array($config['vlans']['vlan'])) {
2762
		foreach ($config['vlans']['vlan'] as $vlan) {
2763
			if ($vlan['if'] != $realhwif)
2764
				continue;
2765
			$assignedport = convert_real_interface_to_friendly_interface_name($vlan['vlanif']);
2766
			if (!empty($assignedport)) {
2767
				$portmtu = $config['interfaces'][$assignedport]['mtu'];
2768
				if (!empty($portmtu) && $portmtu > $mtu)
2769
					$mtu = $portmtu;
2770
			}
2771
		}
2772
	}
2773

    
2774
	return $mtu;
2775
}
2776

    
2777
function interface_configure($interface = "wan", $reloadall = false, $linkupevent = false) {
2778
	global $config, $g;
2779
	global $interface_sn_arr_cache, $interface_ip_arr_cache;
2780
	global $interface_snv6_arr_cache, $interface_ipv6_arr_cache;
2781

    
2782
	$wancfg = $config['interfaces'][$interface];
2783

    
2784
	if (!isset($wancfg['enable']))
2785
		return;
2786

    
2787
	$realif = get_real_interface($interface);
2788
	$realhwif_array = get_parent_interface($interface);
2789
	// Need code to handle MLPPP if we ever use $realhwif for MLPPP handling
2790
	$realhwif = $realhwif_array[0];
2791

    
2792
	/* Disable Accepting router advertisements unless specifically requested */
2793
	if ($g['debug'])
2794
		log_error("Deny router advertisements for interface {$interface}");
2795
	mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 -accept_rtadv");
2796

    
2797
	if (!$g['booting'] && !(substr($realif, 0, 4) == "ovpn")) {
2798
		/* remove all IPv4 and IPv6 addresses */
2799
		while (mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " -alias", true) == 0);
2800
		while (mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 -alias", true) == 0);
2801

    
2802
		/* only bring down the interface when both v4 and v6 are set to NONE */
2803
		if(empty($wancfg['ipaddr']) && empty($wancfg['ipaddrv6'])) {
2804
			interface_bring_down($interface);
2805
		}
2806
	}
2807

    
2808
	/* wireless configuration? */
2809
	if (is_array($wancfg['wireless']))
2810
		interface_wireless_configure($realif, $wancfg, $wancfg['wireless']);
2811

    
2812
	$mac = get_interface_mac($realhwif);
2813
	/*
2814
	 * Don't try to reapply the spoofed MAC if it's already applied.
2815
	 * When ifconfig link is used, it cycles the interface down/up, which triggers
2816
	 * the interface config again, which attempts to spoof the MAC again,
2817
	 * which cycles the link again...
2818
	 */
2819
	if ($wancfg['spoofmac'] && ($wancfg['spoofmac'] != $mac)) {
2820
		mwexec("/sbin/ifconfig " . escapeshellarg($realhwif) .
2821
			" link " . escapeshellarg($wancfg['spoofmac']));
2822

    
2823
		/*
2824
		 * All vlans need to spoof their parent mac address, too.  see
2825
		 * ticket #1514: http://cvstrac.pfsense.com/tktview?tn=1514,33
2826
		 */
2827
		if (is_array($config['vlans']['vlan'])) {
2828
			foreach ($config['vlans']['vlan'] as $vlan) {
2829
				if ($vlan['if'] == $realhwif)
2830
					mwexec("/sbin/ifconfig " . escapeshellarg($vlan['vlanif']) .
2831
					" link " . escapeshellarg($wancfg['spoofmac']));
2832
			}
2833
		}
2834
	}  else {
2835

    
2836
		if ($mac == "ff:ff:ff:ff:ff:ff") {
2837
			/*   this is not a valid mac address.  generate a
2838
			 *   temporary mac address so the machine can get online.
2839
			 */
2840
			echo gettext("Generating new MAC address.");
2841
			$random_mac = generate_random_mac_address();
2842
			mwexec("/sbin/ifconfig " . escapeshellarg($realhwif) .
2843
				" link " . escapeshellarg($random_mac));
2844
			$wancfg['spoofmac'] = $random_mac;
2845
			write_config();
2846
			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");
2847
		}
2848
	}
2849

    
2850
	/* media */
2851
	if ($wancfg['media'] || $wancfg['mediaopt']) {
2852
		$cmd = "/sbin/ifconfig " . escapeshellarg($realhwif);
2853
		if ($wancfg['media'])
2854
			$cmd .= " media " . escapeshellarg($wancfg['media']);
2855
		if ($wancfg['mediaopt'])
2856
			$cmd .= " mediaopt " . escapeshellarg($wancfg['mediaopt']);
2857
		mwexec($cmd);
2858
	}
2859
	$options = pfSense_get_interface_addresses($realhwif);
2860

    
2861
	/* skip vlans for checksumming and polling */
2862
	if (!stristr($realif, "_vlan") && is_array($options)) {
2863
		$flags_on = 0;
2864
		$flags_off = 0;
2865
		if(isset($config['system']['disablechecksumoffloading'])) {
2866
			if (isset($options['encaps']['txcsum']))
2867
				$flags_off |= IFCAP_TXCSUM;
2868
			if (isset($options['encaps']['rxcsum']))
2869
				$flags_off |= IFCAP_RXCSUM;
2870
		} else {
2871
			if (isset($options['caps']['txcsum']))
2872
				$flags_on |= IFCAP_TXCSUM;
2873
			if (isset($options['caps']['rxcsum']))
2874
				$flags_on |= IFCAP_RXCSUM;
2875
		}
2876

    
2877
		if(isset($config['system']['disablesegmentationoffloading']))
2878
			$flags_off |= IFCAP_TSO;
2879
		else if (isset($options['caps']['tso']) || isset($options['caps']['tso4']) || isset($options['caps']['tso6']))
2880
			$flags_on |= IFCAP_TSO;
2881

    
2882
		if(isset($config['system']['disablelargereceiveoffloading']))
2883
			$flags_off |= IFCAP_LRO;
2884
		else if (isset($options['caps']['lro']))
2885
			$flags_on |= IFCAP_LRO;
2886

    
2887
		/* if the NIC supports polling *AND* it is enabled in the GUI */
2888
		if (!isset($config['system']['polling']))
2889
			$flags_off |= IFCAP_POLLING;
2890
		else if (isset($options['caps']['polling']))
2891
			$flags_on |= IFCAP_POLLING;
2892

    
2893
		pfSense_interface_capabilities($realhwif, -$flags_off);
2894
		pfSense_interface_capabilities($realhwif, $flags_on);
2895
	}
2896

    
2897
	/* invalidate interface/ip/sn cache */
2898
	get_interface_arr(true);
2899
	unset($interface_ip_arr_cache[$realif]);
2900
	unset($interface_sn_arr_cache[$realif]);
2901
	unset($interface_ipv6_arr_cache[$realif]);
2902
	unset($interface_snv6_arr_cache[$realif]);
2903

    
2904
	switch ($wancfg['ipaddr']) {
2905
		case 'dhcp':
2906
			interface_dhcp_configure($interface);
2907
			break;
2908
		case 'pppoe':
2909
		case 'l2tp':
2910
		case 'pptp':
2911
		case 'ppp':
2912
			interface_ppps_configure($interface);
2913
			break;
2914
		default:
2915
			if (is_ipaddr($wancfg['ipaddr']) && $wancfg['subnet'] <> "") {
2916
				pfSense_interface_setaddress($realif, "{$wancfg['ipaddr']}/{$wancfg['subnet']}");
2917
			} else if (substr($realif, 0, 3) == "gre") {
2918
				if (is_array($config['gres']['gre'])) {
2919
					foreach ($config['gres']['gre'] as $gre)
2920
						if ($gre['greif'] == $realif)
2921
							interface_gre_configure($gre);
2922
				}
2923
			} else if (substr($realif, 0, 3) == "gif") {
2924
				if (is_array($config['gifs']['gif'])) {
2925
					foreach ($config['gifs']['gif'] as $gif)
2926
						if($gif['gifif'] == $realif)
2927
							interface_gif_configure($gif);
2928
				}
2929
			} else if (substr($realif, 0, 4) == "ovpn") {
2930
				/* XXX: Should be done anything?! */
2931
			}
2932
			break;
2933
	}
2934

    
2935
	switch ($wancfg['ipaddrv6']) {
2936
		case 'slaac':
2937
		case 'dhcp6':
2938
			interface_dhcpv6_configure($interface, $wancfg);
2939
			break;
2940
		case '6rd':
2941
			interface_6rd_configure($interface, $wancfg);
2942
			break;
2943
		case '6to4':
2944
			interface_6to4_configure($interface, $wancfg);
2945
			break;
2946
		case 'track6':
2947
			interface_track6_configure($interface, $wancfg);
2948
			break;
2949
		default:
2950
			if (is_ipaddr($wancfg['ipaddrv6']) && $wancfg['subnetv6'] <> "") {
2951
				pfSense_interface_setaddress($realif, "{$wancfg['ipaddrv6']}/{$wancfg['subnetv6']}");
2952
				// FIXME: Add IPv6 Support to the pfSense module
2953
				mwexec("/sbin/ifconfig {$realif} inet6 {$wancfg['ipaddrv6']} prefixlen {$wancfg['subnetv6']} ");
2954
			}
2955
			break;
2956
	}
2957

    
2958
	$mtu = get_interface_default_mtu(remove_ifindex($realhwif));
2959
	$assignedparent = convert_real_interface_to_friendly_interface_name($realhwif);
2960
	if (!empty($assignedparent) && !empty($config['interfaces'][$assignedparent]['mtu']))
2961
		$mtu = $config['interfaces'][$assignedparent]['mtu'];
2962

    
2963
	$vlanifs = link_interface_to_vlans($realhwif);
2964
	if (empty($vlanifs))
2965
		$vlanifs = array();
2966

    
2967
	if (!empty($wancfg['mtu'])) {
2968
		if (stristr($realif, "_vlan")) {
2969
			if (!empty($assignedparent)) {
2970
				$parentmtu = $config['interfaces'][$assignedparent]['mtu'];
2971
				if (empty($parentmtu))
2972
					$parentmtu = interface_vlan_mtu_configured($realhwif, $wancfg['mtu']);
2973
				if ($wancfg['mtu'] > $parentmtu) {
2974
					if (get_interface_mtu($realhwif) != $wancfg['mtu'])
2975
						pfSense_interface_mtu($realhwif, $wancfg['mtu']);
2976

    
2977
					/* All vlans need to use the same mtu value as their parent. */
2978
					foreach ($vlanifs as $vlan) {
2979
						if ($vlan['vlanif'] == $realif)
2980
							continue;
2981
						$assignedport = convert_real_interface_to_friendly_interface_name($vlan['vlanif']);
2982
						if (!empty($assignedport)) {
2983
							$portmtu = $config['interfaces'][$assignedport]['mtu'];
2984
							if (empty($portmtu) && (get_interface_mtu($vlan['vlanif']) != $wancfg['mtu']))
2985
								pfSense_interface_mtu($vlan['vlanif'], $wancfg['mtu']);
2986
						} else if (get_interface_mtu($vlan['vlanif']) != $wancfg['mtu'])
2987
							pfSense_interface_mtu($vlan['vlanif'], $wancfg['mtu']);
2988
					}
2989
				}
2990
			} else {
2991
				/* Parent is not assigned, back to default */
2992
				if (get_interface_mtu($realhwif) != $mtu)
2993
					pfSense_interface_mtu($realhwif, $mtu);
2994

    
2995
				/* All vlans need to use the same mtu value as their parent. */
2996
				foreach ($vlanifs as $vlan) {
2997
					if ($vlan['vlanif'] == $realif)
2998
						continue;
2999
					$assignedport = convert_real_interface_to_friendly_interface_name($vlan['vlanif']);
3000
					if (!empty($assignedport)) {
3001
						$portmtu = $config['interfaces'][$assignedport]['mtu'];
3002
						if (empty($portmtu) && (get_interface_mtu($vlan['vlanif']) != $mtu))
3003
							pfSense_interface_mtu($vlan['vlanif'], $mtu);
3004
					} else if (get_interface_mtu($vlan['vlanif']) != $mtu)
3005
						pfSense_interface_mtu($vlan['vlanif'], $mtu);
3006
				}
3007

    
3008
				if (get_interface_mtu($realif) != $wancfg['mtu'])
3009
					pfSense_interface_mtu($realif, $wancfg['mtu']);
3010
			}
3011
		} else {
3012
			foreach ($vlanifs as $vlan) {
3013
				$assignedport = convert_real_interface_to_friendly_interface_name($vlan['vlanif']);
3014
				if (empty($assignedport)) {
3015
					if (get_interface_mtu($vlan['vlanif']) != $wancfg['mtu'])
3016
						pfSense_interface_mtu($vlan['vlanif'], $wancfg['mtu']);
3017
				} else {
3018
					$vlanmtu = $config['interfaces'][$assignedport]['mtu'];
3019
					if ((empty($vlanmtu) || ($vlanmtu >= $wancfg['mtu'])) && (get_interface_mtu($vlan['vlanif']) != $wancfg['mtu']))
3020
						pfSense_interface_mtu($vlan['vlanif'], $wancfg['mtu']);
3021
				}
3022
			}
3023
		}
3024
		if ($wancfg['mtu'] != get_interface_mtu($realif))
3025
			pfSense_interface_mtu($realif, $wancfg['mtu']);
3026
	} else if (stristr($realif, "_vlan")) {
3027
		/* XXX: This is really dangerous for example with vlans changing their parent mtu! */
3028
		$bigmtu = interface_vlan_mtu_configured($realhwif, $mtu);
3029
		if ($mtu < $bigmtu)
3030
			$mtu = $bigmtu;
3031

    
3032
		if (get_interface_mtu($realhwif) != $mtu)
3033
			pfSense_interface_mtu($realhwif, $mtu);
3034

    
3035
		/* All vlans need to use the same mtu value as their parent. */
3036
		foreach ($vlanifs as $vlan) {
3037
			if ($vlan['vlanif'] == $realif)
3038
				continue;
3039
			$assignedport = convert_real_interface_to_friendly_interface_name($vlan['vlanif']);
3040
			if (!empty($assignedport)) {
3041
				$portmtu = $config['interfaces'][$assignedport]['mtu'];
3042
				if (empty($portmtu) && (get_interface_mtu($vlan['vlanif']) != $mtu))
3043
					pfSense_interface_mtu($vlan['vlanif'], $mtu);
3044
			} else if (get_interface_mtu($vlan['vlanif']) != $mtu)
3045
				pfSense_interface_mtu($vlan['vlanif'], $mtu);
3046
		}
3047
		if (get_interface_mtu($realif) != $mtu)
3048
			pfSense_interface_mtu($realif, $mtu);
3049
	} else {
3050
		/* All vlans need to use the same mtu value as their parent. */
3051
		foreach ($vlanifs as $vlan) {
3052
			$assignedport = convert_real_interface_to_friendly_interface_name($vlan['vlanif']);
3053
			if (!empty($assignedport)) {
3054
				$portmtu = $config['interfaces'][$assignedport]['mtu'];
3055
				if (empty($portmtu) && (get_interface_mtu($vlan['vlanif']) != $mtu))
3056
					pfSense_interface_mtu($vlan['vlanif'], $mtu);
3057
			} else if (get_interface_mtu($vlan['vlanif']) != $mtu)
3058
				pfSense_interface_mtu($vlan['vlanif'], $mtu);
3059
		}
3060
		if ($mtu != get_interface_mtu($realhwif))
3061
			pfSense_interface_mtu($realhwif, $mtu);
3062
	}
3063

    
3064
	unset($vlanifs);
3065

    
3066
	if(does_interface_exist($wancfg['if']))
3067
		interfaces_bring_up($wancfg['if']);
3068

    
3069
	interface_netgraph_needed($interface);
3070

    
3071
	if (!$g['booting']) {
3072
		link_interface_to_vips($interface, "update");
3073

    
3074
		unset($gre);
3075
		$gre = link_interface_to_gre($interface);
3076
		if (!empty($gre))
3077
			array_walk($gre, 'interface_gre_configure');
3078

    
3079
		unset($gif);
3080
		$gif = link_interface_to_gif($interface);
3081
		if (!empty($gif))
3082
			array_walk($gif, 'interface_gif_configure');
3083

    
3084
		if ($linkupevent == false || substr($realif, 0, 4) == "ovpn") {
3085
			unset($bridgetmp);
3086
			$bridgetmp = link_interface_to_bridge($interface);
3087
			if (!empty($bridgetmp))
3088
				interface_bridge_add_member($bridgetmp, $realif);
3089
		}
3090

    
3091
		$grouptmp = link_interface_to_group($interface);
3092
		if (!empty($grouptmp))
3093
			array_walk($grouptmp, 'interface_group_add_member');
3094

    
3095
		if ($interface == "lan")
3096
			/* make new hosts file */
3097
			system_hosts_generate();
3098

    
3099
		if ($reloadall == true) {
3100

    
3101
			/* reconfigure static routes (kernel may have deleted them) */
3102
			system_routing_configure($interface);
3103

    
3104
			/* reload ipsec tunnels */
3105
			vpn_ipsec_configure();
3106

    
3107
			/* restart dnsmasq */
3108
			services_dnsmasq_configure();
3109

    
3110
			/* update dyndns */
3111
			send_event("service reload dyndns {$interface}");
3112

    
3113
			/* reload captive portal */
3114
			captiveportal_init_rules();
3115
		}
3116
	}
3117

    
3118
	interfaces_staticarp_configure($interface);
3119
	return 0;
3120
}
3121

    
3122
function interface_track6_configure($interface = "lan", $wancfg) {
3123
	global $config, $g;
3124

    
3125
	if (!is_array($wancfg))
3126
		return;
3127

    
3128
	if (!isset($wancfg['enable']))
3129
		return;
3130

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

    
3135
	/* always configure a link-local of fe80::1:1 on the track6 interfaces */
3136
	$realif = get_real_interface($interface);
3137
	$linklocal = find_interface_ipv6_ll($realif);
3138
	if (!empty($linklocal))
3139
		mwexec("/sbin/ifconfig {$realif} inet6 {$linklocal} delete");
3140
	mwexec("/sbin/ifconfig {$realif} inet6 fe80::1:1%{$realif}");
3141

    
3142
	$trackcfg = $config['interfaces'][$wancfg['track6-interface']];
3143
	if (!isset($trackcfg['enable'])) {
3144
		log_error("Interface {$interface} tracking non-existant interface {$wancfg['track6-interface']}");
3145
		return;
3146
	}
3147

    
3148
	switch($trackcfg['ipaddrv6']) {
3149
	case "6to4":
3150
		if ($g['debug'])
3151
			log_error("Interface {$interface} configured via {$wancfg['track6-interface']}  type {$type}");
3152
		interface_track6_6to4_configure($interface, $wancfg);
3153
		break;
3154
	case "6rd":
3155
		if ($g['debug'])
3156
			log_error("Interface {$interface} configured via {$wancfg['track6-interface']}  type {$type}");
3157
		interface_track6_6rd_configure($interface, $wancfg);
3158
		break;
3159
	}
3160

    
3161
	if (!$g['booting']) {
3162
		if (!function_exists('services_dhcpd_configure'))
3163
			require_once("services.inc");
3164

    
3165
		services_dhcpd_configure("inet6");
3166
	}
3167

    
3168
	return 0;
3169
}
3170

    
3171
function interface_track6_6rd_configure($interface = "lan", $lancfg) {
3172
	global $config, $g;
3173
	global $interface_ipv6_arr_cache;
3174
	global $interface_snv6_arr_cache;
3175

    
3176
	if (!is_array($lancfg))
3177
		return;
3178

    
3179
	/* If the interface is not configured via another, exit */
3180
	if (empty($lancfg['track6-interface']))
3181
		return;
3182

    
3183
	$wancfg = $config['interfaces'][$lancfg['track6-interface']];
3184
	if (empty($wancfg)) {
3185
		log_error("Interface {$interface} tracking non-existant interface {$lancfg['track6-interface']}");
3186
		return;
3187
	}
3188

    
3189
	$ip4address = get_interface_ip($lancfg['track6-interface']);
3190
	if (!is_ipaddrv4($ip4address)) { /* XXX: This should not be needed by 6rd || (is_private_ip($ip4address))) { */
3191
		log_error("The interface IPv4 '{$ip4address}' address on interface '{$lancfg['track6-interface']}' is not public, not configuring 6RD tunnel");
3192
		return;
3193
	}
3194
	$hexwanv4 = return_hex_ipv4($ip4address);
3195

    
3196
	/* create the long prefix notation for math, save the prefix length */
3197
	$rd6prefix = explode("/", $wancfg['prefix-6rd']);
3198
	$rd6prefixlen = $rd6prefix[1];
3199
	$rd6prefix = Net_IPv6::uncompress($rd6prefix[0]);
3200

    
3201
	/* binary presentation of the prefix for all 128 bits. */
3202
	$rd6lanbin = convert_ipv6_to_128bit($rd6prefix);
3203

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

    
3209
	/* add the custom prefix id, max 32bits long? (64 bits - (prefixlen + (32 - v4plen)) */
3210
	/* 64 - (37 + (32 - 17)) = 8 == /52 */
3211
	$restbits = 64 - ($rd6prefixlen + (32 - $wancfg['prefix-6rd-v4plen']));
3212
	// echo "64 - (prefixlen {$rd6prefixlen} + v4len (32 - {$wancfg['prefix-6rd-v4plen']})) = {$restbits} \n";
3213
	$rd6lanbin .= substr(sprintf("%032b", str_pad($lancfg['track6-prefix-id'], 32, "0", STR_PAD_LEFT)), (32 - $restbits), 32);
3214
	/* fill the rest out with zeros */
3215
	$rd6lanbin = str_pad($rd6lanbin, 128, "0", STR_PAD_RIGHT);;
3216

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

    
3220
	$lanif = get_real_interface($interface);
3221
	$oip = find_interface_ipv6($lanif);
3222
	if (is_ipaddrv6($oip))
3223
		mwexec("/sbin/ifconfig {$lanif} inet6 {$oip} delete");
3224
	unset($interface_ipv6_arr_cache[$lanif]);
3225
	unset($interface_snv6_arr_cache[$lanif]);
3226
	log_error("rd6 {$interface} with ipv6 address {$rd6lan} based on {$lancfg['track6-interface']} ipv4 {$ip4address}");
3227
	mwexec("/sbin/ifconfig {$lanif} inet6 {$rd6lan} prefixlen 64");
3228

    
3229
	return 0;
3230
}
3231

    
3232
function interface_track6_6to4_configure($interface = "lan", $lancfg) {
3233
	global $config, $g;
3234
	global $interface_ipv6_arr_cache;
3235
	global $interface_snv6_arr_cache;
3236

    
3237
	if (!is_array($lancfg))
3238
		return;
3239

    
3240
	/* If the interface is not configured via another, exit */
3241
	if (empty($lancfg['track6-interface']))
3242
		return;
3243

    
3244
	$wancfg = $config['interfaces'][$lancfg['track6-interface']];
3245
	if (empty($wancfg)) {
3246
		log_error("Interface {$interface} tracking non-existant interface {$lancfg['track6-interface']}");
3247
		return;
3248
	}
3249

    
3250
	$ip4address = get_interface_ip($lancfg['track6-interface']);
3251
	if (!is_ipaddrv4($ip4address) || is_private_ip($ip4address)) {
3252
		log_error("The interface IPv4 '{$ip4address}' address on interface '{$lancfg['track6-interface']}' is not public, not configuring 6RD tunnel");
3253
		return;
3254
	}
3255
	$hexwanv4 = return_hex_ipv4($ip4address);
3256

    
3257
	/* create the long prefix notation for math, save the prefix length */
3258
	$sixto4prefix = "2002::";
3259
	$sixto4prefixlen = 16;
3260
	$sixto4prefix = Net_IPv6::uncompress($sixto4prefix);
3261

    
3262
	/* binary presentation of the prefix for all 128 bits. */
3263
	$sixto4lanbin = convert_ipv6_to_128bit($sixto4prefix);
3264

    
3265
	/* just save the left prefix length bits */
3266
	$sixto4lanbin = substr($sixto4lanbin, 0, $sixto4prefixlen);
3267
	/* add the v4 address */
3268
	$sixto4lanbin .= sprintf("%032b", hexdec($hexwanv4));
3269
	/* add the custom prefix id */
3270
	$sixto4lanbin .= sprintf("%016b", $lancfg['track6-prefix-id']);
3271
	/* fill the rest out with zeros */
3272
	$sixto4lanbin = str_pad($sixto4lanbin, 128, "0", STR_PAD_RIGHT);;
3273

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

    
3277
	$lanif = get_real_interface($interface);
3278
	$oip = find_interface_ipv6($lanif);
3279
	if (is_ipaddrv6($oip))
3280
		mwexec("/sbin/ifconfig {$lanif} inet6 {$oip} delete");
3281
	unset($interface_ipv6_arr_cache[$lanif]);
3282
	unset($interface_snv6_arr_cache[$lanif]);
3283
	log_error("sixto4 {$interface} with ipv6 address {$sixto4lan} based on {$lancfg['track6-interface']} ipv4 {$ip4address}");
3284
	mwexec("/sbin/ifconfig {$lanif} inet6 {$sixto4lan} prefixlen 64");
3285

    
3286
	return 0;
3287
}
3288

    
3289
function interface_6rd_configure($interface = "wan", $wancfg) {
3290
	global $config, $g;
3291

    
3292
	/* because this is a tunnel interface we can only function
3293
	 *	with a public IPv4 address on the interface */
3294

    
3295
	if (!is_array($wancfg))
3296
		return;
3297

    
3298
	$wanif = get_real_interface($interface);
3299
	$ip4address = find_interface_ip($wanif);
3300
	if ((!is_ipaddrv4($ip4address)) || (is_private_ip($ip4address))) {
3301
		log_error("The interface IPv4 '{$ip4address}' address on interface '{$wanif}' is not public, not configuring 6RD tunnel");
3302
		return false;
3303
	}
3304
	$hexwanv4 = return_hex_ipv4($ip4address);
3305

    
3306
	if (!is_numeric($wancfg['prefix-6rd-v4plen']))
3307
		$wancfg['prefix-6rd-v4plen'] = 0;
3308

    
3309
	/* create the long prefix notation for math, save the prefix length */
3310
	$rd6prefix = explode("/", $wancfg['prefix-6rd']);
3311
	$rd6prefixlen = $rd6prefix[1];
3312
	$rd6prefix = Net_IPv6::uncompress($rd6prefix[0]);
3313

    
3314
	/* binary presentation of the prefix for all 128 bits. */
3315
	$rd6prefixbin = convert_ipv6_to_128bit($rd6prefix);
3316

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

    
3324
	/* convert the 128 bits for the broker address back into a valid IPv6 address */
3325
	$rd6prefix = convert_128bit_to_ipv6($rd6prefixbin);
3326

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

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

    
3345
	/* write out a default router file */
3346
	file_put_contents("{$g['tmp_path']}/{$wanif}_routerv6", "{$rd6brgw}\n");
3347
	file_put_contents("{$g['tmp_path']}/{$wanif}_defaultgwv6", "{$rd6brgw}\n");
3348

    
3349
	$ip4gateway = get_interface_gateway($interface);
3350
	if (is_ipaddrv4($ip4gateway))
3351
		mwexec("/sbin/route change -host " . escapeshellarg($wancfg['gateway-6rd']) . " {$ip4gateway}");
3352

    
3353
	/* configure dependent interfaces */
3354
	if (!$g['booting'])
3355
		link_interface_to_track6($interface, "update");
3356

    
3357
	return 0;
3358
}
3359

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

    
3363
	/* because this is a tunnel interface we can only function
3364
	 *	with a public IPv4 address on the interface */
3365

    
3366
	if (!is_array($wancfg))
3367
		return;
3368

    
3369
	$wanif = get_real_interface($interface);
3370
	$ip4address = find_interface_ip($wanif);
3371
	if((!is_ipaddrv4($ip4address)) || (is_private_ip($ip4address))) {
3372
		log_error("The interface IPv4 '{$ip4address}' address on interface '{$wanif}' is not public, not configuring 6RD tunnel");
3373
		return false;
3374
	}
3375

    
3376
	/* create the long prefix notation for math, save the prefix length */
3377
	$stfprefixlen = 16;
3378
	$stfprefix = Net_IPv6::uncompress("2002::");
3379
	$stfarr = explode(":", $stfprefix);
3380
	$v4prefixlen = "0";
3381

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

    
3388
	/* we need the hex form of the broker IPv4 address */
3389
	$ip4arr = explode(".", "192.88.99.1");
3390
	$hexbrv4 = "";
3391
	foreach($ip4arr as $octet)
3392
		$hexbrv4 .= sprintf("%02x", $octet);
3393

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

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

    
3406
	/* for the local subnet too. */
3407
	$stflanbin = substr(sprintf("%032b", hexdec($hexwanv4)), $v4prefixlen, 32);
3408
	$stflanbin = str_pad($stfprefixstartbin . $stflanbin, 128, "0", STR_PAD_RIGHT);;
3409

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

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

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

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

    
3442
	/* write out a default router file */
3443
	file_put_contents("{$g['tmp_path']}/{$wanif}_routerv6", "{$stfbrgw}");
3444
	file_put_contents("{$g['tmp_path']}/{$wanif}_defaultgwv6", "{$stfbrgw}");
3445

    
3446
	$ip4gateway = get_interface_gateway($interface);
3447
	if (is_ipaddrv4($ip4gateway))
3448
		mwexec("/sbin/route change -host 192.88.99.1 {$ip4gateway}");
3449

    
3450
	if (!$g['booting'])
3451
		link_interface_to_track6($interface, "update");
3452

    
3453
	return 0;
3454
}
3455

    
3456
function interface_dhcpv6_configure($interface = "wan", $wancfg) {
3457
	global $config, $g;
3458

    
3459
	if (!is_array($wancfg))
3460
		return;
3461

    
3462
	$wanif = get_real_interface($interface, "inet6");
3463
	$dhcp6cconf = "";
3464
	$dhcp6cconf .= "interface {$wanif} {\n";
3465

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

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

    
3484
		$dhcp6cconf .= "};\n";
3485

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

    
3489
		if(is_numeric($wancfg['dhcp6-ia-pd-len'])) {
3490
			/* Setup the prefix delegation */
3491
			$dhcp6cconf .= "id-assoc pd 0 {\n";
3492
			$iflist = link_interface_to_track6($interface);
3493
			foreach ($iflist as $friendly => $ifcfg) {
3494
				if (is_numeric($ifcfg['track6-prefix-id'])) {
3495
					if ($g['debug'])
3496
						log_error("setting up $ifdescr - {$ifcfg['track6-prefix-id']}");
3497
					$realif = get_real_interface($friendly);
3498
					$dhcp6cconf .= "	prefix-interface {$realif} {\n";
3499
					$dhcp6cconf .= "		sla-id {$ifcfg['track6-prefix-id']};\n";
3500
					$dhcp6cconf .= "		sla-len {$wancfg['dhcp6-ia-pd-len']};\n";
3501
					$dhcp6cconf .= "	};\n";
3502
				}
3503
			}
3504
			unset($iflist, $ifcfg);
3505
			$dhcp6cconf .= "};\n";
3506
		}
3507
	}
3508
	/* wide-dhcp6c works for now. */
3509
	if (!@file_put_contents("{$g['varetc_path']}/dhcp6c_{$interface}.conf", $dhcp6cconf)) {
3510
		printf("Error: cannot open dhcp6c_{$interface}.conf in interface_dhcpv6_configure() for writing.\n");
3511
		unset($dhcp6cconf);
3512
		return 1;
3513
	}
3514
	unset($dhcp6cconf);
3515

    
3516
	$dhcp6cscript = "#!/bin/sh\n";
3517
	$dhcp6cscript .= "# This shell script launches /etc/rc.newwanipv6 with a interface argument.\n";
3518
	$dhcp6cscript .= "/etc/rc.newwanipv6 {$wanif} \n";
3519
	/* Add wide-dhcp6c shell script here. Because we can not pass a argument to it. */
3520
	if (!@file_put_contents("{$g['varetc_path']}/dhcp6c_{$interface}_script.sh", $dhcp6cscript)) {
3521
		printf("Error: cannot open dhcp6c_{$interface}_script.sh in interface_dhcpv6_configure() for writing.\n");
3522
		unset($dhcp6cscript);
3523
		return 1;
3524
	}
3525
	unset($dhcp6cscript);
3526
	@chmod("{$g['varetc_path']}/dhcp6c_{$interface}_script.sh", 0755);
3527

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

    
3546
	/* accept router advertisements for this interface */
3547
	mwexec("/sbin/sysctl -w net.inet6.ip6.accept_rtadv=1");
3548
	log_error("Accept router advertisements on interface {$wanif} ");
3549
	mwexec("/sbin/ifconfig {$wanif} inet6 accept_rtadv");
3550

    
3551
	/* fire up rtsold for IPv6 RAs first, this backgrounds immediately. It will call dhcp6c */
3552
	if (isvalidpid("{$g['varrun_path']}/rtsold_{$wanif}.pid")) {
3553
		killbypid("{$g['varrun_path']}/rtsold_{$wanif}.pid");
3554
		sleep(2);
3555
	}
3556
	mwexec("/usr/sbin/rtsold -1 -p {$g['varrun_path']}/rtsold_{$wanif}.pid -O {$g['varetc_path']}/rtsold_{$wanif}_script.sh {$wanif}");
3557

    
3558
	/* NOTE: will be called from rtsold invoked script
3559
	 * link_interface_to_track6($interface, "update");
3560
	 */
3561

    
3562
	return 0;
3563
}
3564

    
3565
function interface_dhcp_configure($interface = "wan") {
3566
	global $config, $g;
3567

    
3568
	$wancfg = $config['interfaces'][$interface];
3569
	$wanif = $wancfg['if'];
3570
	if (empty($wancfg))
3571
		$wancfg = array();
3572

    
3573
	/* generate dhclient_wan.conf */
3574
	$fd = fopen("{$g['varetc_path']}/dhclient_{$interface}.conf", "w");
3575
	if (!$fd) {
3576
		printf(printf(gettext("Error: cannot open dhclient_%s.conf in interface_dhcp_configure() for writing.%s"), $interface, "\n"));
3577
		return 1;
3578
	}
3579

    
3580
	if ($wancfg['dhcphostname']) {
3581
		$dhclientconf_hostname = "send dhcp-client-identifier \"{$wancfg['dhcphostname']}\";\n";
3582
		$dhclientconf_hostname .= "\tsend host-name \"{$wancfg['dhcphostname']}\";\n";
3583
	} else {
3584
		$dhclientconf_hostname = "";
3585
	}
3586

    
3587
	$wanif = get_real_interface($interface);
3588
	if (empty($wanif)) {
3589
		log_error(sprintf(gettext("Invalid interface \"%s\" in interface_dhcp_configure()"), $interface));
3590
		return 0;
3591
	}
3592
	$dhclientconf = "";
3593

    
3594
	$dhclientconf .= <<<EOD
3595
interface "{$wanif}" {
3596
timeout 60;
3597
retry 15;
3598
select-timeout 0;
3599
initial-interval 1;
3600
	{$dhclientconf_hostname}
3601
	script "/sbin/dhclient-script";
3602
EOD;
3603

    
3604
if (is_ipaddrv4($wancfg['dhcprejectfrom'])) {
3605
	$dhclientconf .= <<<EOD
3606

    
3607
	reject {$wancfg['dhcprejectfrom']};
3608
EOD;
3609
}
3610
	$dhclientconf .= <<<EOD
3611

    
3612
}
3613

    
3614
EOD;
3615

    
3616
if(is_ipaddr($wancfg['alias-address'])) {
3617
	$subnetmask = gen_subnet_mask($wancfg['alias-subnet']);
3618
	$dhclientconf .= <<<EOD
3619
alias {
3620
	interface  "{$wanif}";
3621
	fixed-address {$wancfg['alias-address']};
3622
	option subnet-mask {$subnetmask};
3623
}
3624

    
3625
EOD;
3626
}
3627
	fwrite($fd, $dhclientconf);
3628
	fclose($fd);
3629

    
3630
	/* bring wan interface up before starting dhclient */
3631
	if($wanif)
3632
		interfaces_bring_up($wanif);
3633
	else
3634
		log_error(printf(gettext("Could not bring up %s interface in interface_dhcp_configure()"), $wanif));
3635

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

    
3639
	return 0;
3640
}
3641

    
3642
function interfaces_group_setup() {
3643
	global $config;
3644

    
3645
	if (!is_array($config['ifgroups']['ifgroupentry']))
3646
		return;
3647

    
3648
	foreach ($config['ifgroups']['ifgroupentry'] as $groupar)
3649
		interface_group_setup($groupar);
3650

    
3651
	return;
3652
}
3653

    
3654
function interface_group_setup(&$groupname /* The parameter is an array */) {
3655
	global $config;
3656

    
3657
	if (!is_array($groupname))
3658
		return;
3659
	$members = explode(" ", $groupname['members']);
3660
	foreach($members as $ifs) {
3661
		$realif = get_real_interface($ifs);
3662
		if ($realif)
3663
			mwexec("/sbin/ifconfig {$realif} group {$groupname['ifname']}");
3664
	}
3665

    
3666
	return;
3667
}
3668

    
3669
function is_interface_group($if) {
3670
	global $config;
3671

    
3672
	if (is_array($config['ifgroups']['ifgroupentry']))
3673
		foreach ($config['ifgroups']['ifgroupentry'] as $groupentry) {
3674
			if ($groupentry['ifname'] === $if)
3675
				return true;
3676
		}
3677

    
3678
	return false;
3679
}
3680

    
3681
function interface_group_add_member($interface, $groupname) {
3682
	$interface = get_real_interface($interface);
3683
	mwexec("/sbin/ifconfig {$interface} group {$groupname}", true);
3684
}
3685

    
3686
/* COMPAT Function */
3687
function convert_friendly_interface_to_real_interface_name($interface) {
3688
	return get_real_interface($interface);
3689
}
3690

    
3691
/* COMPAT Function */
3692
function get_real_wan_interface($interface = "wan") {
3693
	return get_real_interface($interface);
3694
}
3695

    
3696
/* COMPAT Function */
3697
function get_current_wan_address($interface = "wan") {
3698
	return get_interface_ip($interface);
3699
}
3700

    
3701
/*
3702
 * convert_real_interface_to_friendly_interface_name($interface): convert fxp0 -> wan, etc.
3703
 */
3704
function convert_real_interface_to_friendly_interface_name($interface = "wan") {
3705
	global $config;
3706

    
3707
	if (stristr($interface, "_vip")) {
3708
		foreach ($config['virtualip']['vip'] as $counter => $vip) {
3709
			if ($vip['mode'] == "carp")  {
3710
				if ($interface == "{$vip['interface']}_vip{$vip['vhid']}")
3711
					return $vip['interface'];
3712
			}
3713
		}
3714
	}
3715

    
3716
	/* XXX: For speed reasons reference directly the interface array */
3717
	$ifdescrs = &$config['interfaces'];
3718
	//$ifdescrs = get_configured_interface_list(false, true);
3719

    
3720
	foreach ($ifdescrs as $if => $ifname) {
3721
		if ($if == $interface || $config['interfaces'][$if]['if'] == $interface)
3722
			return $if;
3723

    
3724
		if (get_real_interface($if) == $interface)
3725
			return $if;
3726

    
3727
		// XXX: This case doesn't work anymore (segfaults - recursion?) - should be replaced with something else or just removed.
3728
		//      Not to be replaced with get_real_interface - causes slow interface listings here because of recursion!
3729
		/*
3730
		$int = get_parent_interface($if);
3731
		if ($int[0] == $interface)
3732
			return $ifname;
3733
		*/
3734
	}
3735

    
3736
	return NULL;
3737
}
3738

    
3739
/* attempt to resolve interface to friendly descr */
3740
function convert_friendly_interface_to_friendly_descr($interface) {
3741
	global $config;
3742

    
3743
	switch ($interface) {
3744
	case "l2tp":
3745
		$ifdesc = "L2TP";
3746
		break;
3747
	case "pptp":
3748
		$ifdesc = "PPTP";
3749
		break;
3750
	case "pppoe":
3751
		$ifdesc = "PPPoE";
3752
		break;
3753
	case "openvpn":
3754
		$ifdesc = "OpenVPN";
3755
		break;
3756
	case "enc0":
3757
	case "ipsec":
3758
		$ifdesc = "IPsec";
3759
		break;
3760
	default:
3761
		if (isset($config['interfaces'][$interface])) {
3762
			if (empty($config['interfaces'][$interface]['descr']))
3763
				$ifdesc = strtoupper($interface);
3764
			else
3765
				$ifdesc = strtoupper($config['interfaces'][$interface]['descr']);
3766
			break;
3767
		} else if (stristr($interface, "_vip")) {
3768
			if (is_array($config['virtualip']['vip'])) {
3769
				foreach ($config['virtualip']['vip'] as $counter => $vip) {
3770
					if ($vip['mode'] == "carp")  {
3771
						if ($interface == "{$vip['interface']}_vip{$vip['vhid']}")
3772
							return "{$vip['subnet']} - {$vip['descr']}";
3773
					}
3774
				}
3775
			}
3776
		} else {
3777
			/* if list */
3778
			$ifdescrs = get_configured_interface_with_descr(false, true);
3779
			foreach ($ifdescrs as $if => $ifname) {
3780
				if ($if == $interface || $ifname == $interface)
3781
					return $ifname;
3782
			}
3783
		}
3784
		break;
3785
	}
3786

    
3787
	return $ifdesc;
3788
}
3789

    
3790
function convert_real_interface_to_friendly_descr($interface) {
3791
	global $config;
3792

    
3793
	$ifdesc = convert_real_interface_to_friendly_interface_name("{$interface}");
3794

    
3795
	if ($ifdesc) {
3796
		$iflist = get_configured_interface_with_descr(false, true);
3797
		return $iflist[$ifdesc];
3798
	}
3799

    
3800
	return $interface;
3801
}
3802

    
3803
/*
3804
 *  get_parent_interface($interface):
3805
 *			--returns the (real or virtual) parent interface(s) array for a given interface friendly name (i.e. wan)
3806
 *				or virtual interface (i.e. vlan)
3807
 *				(We need array because MLPPP and bridge interfaces have more than one parent.)
3808
 *			-- returns $interface passed in if $interface parent is not found
3809
 *			-- returns empty array if an invalid interface is passed
3810
 *	(Only handles ppps and vlans now.)
3811
 */
3812
function get_parent_interface($interface) {
3813
	global $config;
3814

    
3815
	$parents = array();
3816
	//Check that we got a valid interface passed
3817
	$realif = get_real_interface($interface);
3818
	if ($realif == NULL)
3819
		return $parents;
3820

    
3821
	// If we got a real interface, find it's friendly assigned name
3822
	$interface = convert_real_interface_to_friendly_interface_name($interface);
3823

    
3824
	if (!empty($interface) && isset($config['interfaces'][$interface])) {
3825
		$ifcfg = $config['interfaces'][$interface];
3826
		switch ($ifcfg['ipaddr']) {
3827
			case "ppp":
3828
			case "pppoe":
3829
			case "pptp":
3830
			case "l2tp":
3831
				if (empty($parents))
3832
					if (is_array($config['ppps']['ppp']))
3833
						foreach ($config['ppps']['ppp'] as $pppidx => $ppp) {
3834
							if ($ifcfg['if'] == $ppp['if']) {
3835
								$ports = explode(',', $ppp['ports']);
3836
								foreach ($ports as $pid => $parent_if)
3837
									$parents[$pid] = get_real_interface($parent_if);
3838
								break;
3839
							}
3840
						}
3841
				break;
3842
			case "dhcp":
3843
			case "static":
3844
			default:
3845
				// Handle _vlans
3846
				if (stristr($realif,"_vlan"))
3847
					if (is_array($config['vlans']['vlan']))
3848
						foreach ($config['vlans']['vlan'] as $vlanidx => $vlan)
3849
							if ($ifcfg['if'] == $vlan['vlanif']){
3850
								$parents[0] = $vlan['if'];
3851
								break;
3852
							}
3853
				break;
3854
		}
3855
	}
3856

    
3857
	if (empty($parents))
3858
		$parents[0] = $realif;
3859

    
3860
	return $parents;
3861
}
3862

    
3863
function interface_is_wireless_clone($wlif) {
3864
	if(!stristr($wlif, "_wlan")) {
3865
		return false;
3866
	} else {
3867
		return true;
3868
	}
3869
}
3870

    
3871
function interface_get_wireless_base($wlif) {
3872
	if(!stristr($wlif, "_wlan")) {
3873
		return $wlif;
3874
	} else {
3875
		return substr($wlif, 0, stripos($wlif, "_wlan"));
3876
	}
3877
}
3878

    
3879
function interface_get_wireless_clone($wlif) {
3880
	if(!stristr($wlif, "_wlan")) {
3881
		return $wlif . "_wlan0";
3882
	} else {
3883
		return $wlif;
3884
	}
3885
}
3886

    
3887
function get_real_interface($interface = "wan", $family = "all") {
3888
	global $config, $g;
3889

    
3890
	$wanif = NULL;
3891

    
3892
	switch ($interface) {
3893
	case "l2tp":
3894
		$wanif = "l2tp";
3895
		break;
3896
	case "pptp":
3897
		$wanif = "pptp";
3898
		break;
3899
	case "pppoe":
3900
		$wanif = "pppoe";
3901
		break;
3902
	case "openvpn":
3903
		$wanif = "openvpn";
3904
		break;
3905
	case "ipsec":
3906
	case "enc0":
3907
		$wanif = "enc0";
3908
		break;
3909
	case "ppp":
3910
		$wanif = "ppp";
3911
		break;
3912
	default:
3913
		// If a real interface was alread passed simply
3914
		// pass the real interface back.  This encourages
3915
		// the usage of this function in more cases so that
3916
		// we can combine logic for more flexibility.
3917
		if(does_interface_exist($interface)) {
3918
			$wanif = $interface;
3919
			break;
3920
		}
3921

    
3922
		if (empty($config['interfaces'][$interface]))
3923
			break;
3924

    
3925
		$cfg = &$config['interfaces'][$interface];
3926

    
3927
		if ($family == "inet6") {
3928
			switch ($cfg['ipaddrv6']) {
3929
			case "6rd":
3930
			case "6to4":
3931
				$wanif = "{$interface}_stf";
3932
				break;
3933
			case 'pppoe':
3934
			case 'ppp':
3935
			case 'l2tp':
3936
			case 'pptp':
3937
				if( is_array($cfg['wireless']) || preg_match($g['wireless_regex'], $cfg['if']))
3938
					$wanif = interface_get_wireless_clone($cfg['if']);
3939
				else
3940
					$wanif = $cfg['if'];
3941
				break;
3942
			default:
3943
				switch ($cfg['ipaddr']) {
3944
				case 'pppoe':
3945
				case 'ppp':
3946
				case 'l2tp':
3947
				case 'pptp':
3948
					if (isset($cfg['dhcp6usev4iface']))
3949
						$wanif = $cfg['if'];
3950
					else {
3951
						$parents = get_parent_interface($interface);
3952
						if (!empty($parents[0]))
3953
							$wanif = $parents[0];
3954
						else
3955
							$wanif = $cfg['if'];
3956
					}
3957
					break;
3958
				default:
3959
					if( is_array($cfg['wireless']) || preg_match($g['wireless_regex'], $cfg['if']))
3960
						$wanif = interface_get_wireless_clone($cfg['if']);
3961
					else
3962
						$wanif = $cfg['if'];
3963
					break;
3964
				}
3965
				break;
3966
			}
3967
		} else {
3968
			// Wireless cloned NIC support (FreeBSD 8+)
3969
			// interface name format: $parentnic_wlanparentnic#
3970
			// example: ath0_wlan0
3971
			if( is_array($cfg['wireless']) || preg_match($g['wireless_regex'], $cfg['if']))
3972
				$wanif = interface_get_wireless_clone($cfg['if']);
3973
			else
3974
				$wanif = $cfg['if'];
3975
		}
3976
		break;
3977
	}
3978

    
3979
	return $wanif;
3980
}
3981

    
3982
/* Guess the physical interface by providing a IP address */
3983
function guess_interface_from_ip($ipaddress) {
3984
	if(! is_ipaddr($ipaddress)) {
3985
		return false;
3986
	}
3987
	if(is_ipaddrv4($ipaddress)) {
3988
		/* create a route table we can search */
3989
		exec("netstat -rnWf inet", $output, $ret);
3990
		foreach($output as $line) {
3991
			if(preg_match("/^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\/[0-9]+[ ]+link[#]/", $line)) {
3992
				$fields = preg_split("/[ ]+/", $line);
3993
				if(ip_in_subnet($ipaddress, $fields[0])) {
3994
					return $fields[6];
3995
				}
3996
			}
3997
		}
3998
	}
3999
	/* FIXME: This works from cursory testing, regexp might need fine tuning */
4000
	if(is_ipaddrv6($ipaddress)) {
4001
		/* create a route table we can search */
4002
		exec("netstat -rnWf inet6", $output, $ret);
4003
		foreach($output as $line) {
4004
			if(preg_match("/[0-9a-f]+[:]+[0-9a-f]+[:]+[\/][0-9]+/", $line)) {
4005
				$fields = preg_split("/[ ]+/", $line);
4006
				if(ip_in_subnet($ipaddress, $fields[0])) {
4007
					return $fields[6];
4008
				}
4009
			}
4010
		}
4011
	}
4012
	$ret = exec_command("/sbin/route -n get {$ipaddress} | /usr/bin/awk '/interface/ { print \$2; };'");
4013
	if(empty($ret)) {
4014
		return false;
4015
	}
4016
	return $ret;
4017
}
4018

    
4019
/*
4020
 * find_ip_interface($ip): return the interface where an ip is defined
4021
 *   (or if $bits is specified, where an IP within the subnet is defined)
4022
 */
4023
function find_ip_interface($ip, $bits = null) {
4024
	if (!is_ipaddr($ip))
4025
		return false;
4026

    
4027
	$isv6ip = is_ipaddrv6($ip);
4028

    
4029
	/* if list */
4030
	$ifdescrs = get_configured_interface_list();
4031

    
4032
	foreach ($ifdescrs as $ifdescr => $ifname) {
4033
		$ifip = ($isv6ip) ? get_interface_ipv6($ifname) : get_interface_ip($ifname);
4034
		if (is_null($ifip))
4035
			continue;
4036
		if (is_null($bits)) {
4037
			if ($ip == $ifip) {
4038
				$int = get_real_interface($ifname);
4039
				return $int;
4040
			}
4041
		}
4042
		else {
4043
			if (ip_in_subnet($ifip, $ip . "/" . $bits)) {
4044
				$int = get_real_interface($ifname);
4045
				return $int;
4046
			}
4047
		}
4048
	}
4049

    
4050
	return false;
4051
}
4052

    
4053
/*
4054
 * find_virtual_ip_alias($ip): return the virtual IP alias where an IP is found
4055
 *   (or if $bits is specified, where an IP within the subnet is found)
4056
 */
4057
function find_virtual_ip_alias($ip, $bits = null) {
4058
	global $config;
4059

    
4060
	if (!is_array($config['virtualip']['vip'])) {
4061
		return false;
4062
	}
4063
	if (!is_ipaddr($ip))
4064
		return false;
4065

    
4066
	$isv6ip = is_ipaddrv6($ip);
4067

    
4068
	foreach ($config['virtualip']['vip'] as $vip) {
4069
		if ($vip['mode'] === "ipalias") {
4070
			if (is_ipaddrv6($vip['subnet']) != $isv6ip)
4071
				continue;
4072
			if (is_null($bits)) {
4073
				if (ip_in_subnet($ip, $vip['subnet'] . "/" . $vip['subnet_bits'])) {
4074
					return $vip;
4075
				}
4076
			}
4077
			else {
4078
				if (($isv6ip && check_subnetsv6_overlap($ip, $bits, $vip['subnet'], $vip['subnet_bits']))
4079
					|| (!$isv6ip && check_subnets_overlap($ip, $bits, $vip['subnet'], $vip['subnet_bits']))) {
4080
					return $vip;
4081
				}
4082
			}
4083
		}
4084
	}
4085
	return false;
4086
}
4087

    
4088
/*
4089
 *   find_number_of_created_carp_interfaces: return the number of carp interfaces
4090
 */
4091
function find_number_of_created_carp_interfaces() {
4092
	return `/sbin/ifconfig | grep "carp:" | wc -l`;
4093
}
4094

    
4095
function get_all_carp_interfaces() {
4096
	$ints = str_replace("\n", " ", `ifconfig | grep "carp:" -B2 | grep ": flag" | cut -d: -f1`);
4097
	$ints = explode(" ", $ints);
4098
	return $ints;
4099
}
4100

    
4101
/*
4102
 * find_carp_interface($ip): return the carp interface where an ip is defined
4103
 */
4104
function find_carp_interface($ip) {
4105
	global $config;
4106
	if (is_array($config['virtualip']['vip'])) {
4107
		foreach ($config['virtualip']['vip'] as $vip) {
4108
			if ($vip['mode'] == "carp") {
4109
				if(is_ipaddrv4($ip)) {
4110
					$carp_ip = get_interface_ip($vip['interface']);
4111
				}
4112
				if(is_ipaddrv6($ip)) {
4113
					$carp_ip = get_interface_ipv6($vip['interface']);
4114
				}
4115
				exec("/sbin/ifconfig", $output, $return);
4116
				foreach($output as $line) {
4117
					$elements = preg_split("/[ ]+/i", $line);
4118
					if(strstr($elements[0], "vip"))
4119
						$curif = str_replace(":", "", $elements[0]);
4120
					if(stristr($line, $ip)) {
4121
						$if = $curif;
4122
						continue;
4123
					}
4124
				}
4125

    
4126
				if ($if)
4127
					return $if;
4128
			}
4129
		}
4130
	}
4131
}
4132

    
4133
function link_carp_interface_to_parent($interface) {
4134
	global $config;
4135

    
4136
	if ($interface == "")
4137
		return;
4138

    
4139
	$carp_ip = get_interface_ip($interface);
4140
	$carp_ipv6 = get_interface_ipv6($interface);
4141

    
4142
	if((!is_ipaddrv4($carp_ip)) && (!is_ipaddrv6($carp_ipv6)))
4143
		return;
4144

    
4145
	/* if list */
4146
	$ifdescrs = get_configured_interface_list();
4147
	foreach ($ifdescrs as $ifdescr => $ifname) {
4148
		/* check IPv4 */
4149
		if(is_ipaddrv4($carp_ip)) {
4150
			$interfaceip = get_interface_ip($ifname);
4151
			$subnet_bits = get_interface_subnet($ifname);
4152
			$subnet_ip = gen_subnet("{$interfaceip}", "{$subnet_bits}");
4153
			if(ip_in_subnet($carp_ip, "{$subnet_ip}/{$subnet_bits}"))
4154
				return $ifname;
4155
		}
4156
		/* Check IPv6 */
4157
		if(is_ipaddrv6($carp_ipv6)) {
4158
			$interfaceipv6 = get_interface_ipv6($ifname);
4159
			$prefixlen = get_interface_subnetv6($ifname);
4160
			if(ip_in_subnet($carp_ipv6, "{$interfaceipv6}/{$prefixlen}"))
4161
				return $ifname;
4162
		}
4163
	}
4164
	return "";
4165
}
4166

    
4167

    
4168
/****f* interfaces/link_ip_to_carp_interface
4169
 * NAME
4170
 *   link_ip_to_carp_interface - Find where a CARP interface links to.
4171
 * INPUTS
4172
 *   $ip
4173
 * RESULT
4174
 *   $carp_ints
4175
 ******/
4176
function link_ip_to_carp_interface($ip) {
4177
	global $config;
4178

    
4179
	if (!is_ipaddr($ip))
4180
		return;
4181

    
4182
	$carp_ints = "";
4183
	if (is_array($config['virtualip']['vip'])) {
4184
		$first = 0;
4185
		$carp_int = array();
4186
		foreach ($config['virtualip']['vip'] as $vip) {
4187
			if ($vip['mode'] == "carp") {
4188
				$carp_ip = $vip['subnet'];
4189
				$carp_sn = $vip['subnet_bits'];
4190
				$carp_nw = gen_subnet($carp_ip, $carp_sn);
4191
				if (ip_in_subnet($ip, "{$carp_nw}/{$carp_sn}")) {
4192
					$carp_int[] = "{$vip['interface']}_vip{$vip['vhid']}";
4193
				}
4194
			}
4195
		}
4196
		if (!empty($carp_int))
4197
			$carp_ints = implode(" ", array_unique($carp_int));
4198
	}
4199

    
4200
	return $carp_ints;
4201
}
4202

    
4203
function link_interface_to_track6($int, $action = "") {
4204
	global $config;
4205

    
4206
	if (empty($int))
4207
		return;
4208

    
4209
	if (is_array($config['interfaces'])) {
4210
		$list = array();
4211
		foreach ($config['interfaces'] as $ifname => $ifcfg) {
4212
			if (!isset($ifcfg['enable']))
4213
				continue;
4214
			if (!empty($ifcfg['ipaddrv6']) && $ifcfg['track6-interface'] == $int) {
4215
				if ($action == "update")
4216
					interface_track6_configure($ifname, $ifcfg);
4217
				else if ($action == "")
4218
					$list[$ifname] = $ifcfg;
4219
			}
4220
		}
4221
		return $list;
4222
	}
4223
}
4224

    
4225
function link_interface_to_vlans($int, $action = "") {
4226
	global $config;
4227

    
4228
	if (empty($int))
4229
		return;
4230

    
4231
	if (is_array($config['vlans']['vlan'])) {
4232
		$ifaces = array();
4233
		foreach ($config['vlans']['vlan'] as $vlan) {
4234
			if ($int == $vlan['if']) {
4235
				if ($action == "update") {
4236
					interfaces_bring_up($int);
4237
				} else if ($action == "")
4238
					$ifaces[$vlan['tag']] = $vlan;
4239
			}
4240
		}
4241
		if (!empty($ifaces))
4242
			return $ifaces;
4243
	}
4244
}
4245

    
4246
function link_interface_to_vips($int, $action = "") {
4247
	global $config;
4248

    
4249
	if (is_array($config['virtualip']['vip'])) {
4250
		$result = array();
4251
		foreach ($config['virtualip']['vip'] as $vip) {
4252
			if ($int == $vip['interface']) {
4253
				if ($action == "update")
4254
					interfaces_vips_configure($int);
4255
				else
4256
					$result[] = $vip;
4257
			}
4258
		}
4259
		return $result;
4260
	}
4261
}
4262

    
4263
/****f* interfaces/link_interface_to_bridge
4264
 * NAME
4265
 *   link_interface_to_bridge - Finds out a bridge group for an interface
4266
 * INPUTS
4267
 *   $ip
4268
 * RESULT
4269
 *   bridge[0-99]
4270
 ******/
4271
function link_interface_to_bridge($int) {
4272
	global $config;
4273

    
4274
	if (is_array($config['bridges']['bridged'])) {
4275
		foreach ($config['bridges']['bridged'] as $bridge) {
4276
			if (in_array($int, explode(',', $bridge['members'])))
4277
				return "{$bridge['bridgeif']}";
4278
		}
4279
	}
4280
}
4281

    
4282
function link_interface_to_group($int) {
4283
	global $config;
4284

    
4285
	$result = array();
4286

    
4287
	if (is_array($config['ifgroups']['ifgroupentry'])) {
4288
		foreach ($config['ifgroups']['ifgroupentry'] as $group) {
4289
			if (in_array($int, explode(" ", $group['members'])))
4290
				$result[$group['ifname']] = $int;
4291
		}
4292
	}
4293

    
4294
	return $result;
4295
}
4296

    
4297
function link_interface_to_gre($interface) {
4298
	global $config;
4299

    
4300
	$result = array();
4301

    
4302
	if (is_array($config['gres']['gre'])) {
4303
		foreach ($config['gres']['gre'] as $gre)
4304
			if($gre['if'] == $interface)
4305
				$result[] = $gre;
4306
	}
4307

    
4308
	return $result;
4309
}
4310

    
4311
function link_interface_to_gif($interface) {
4312
	global $config;
4313

    
4314
	$result = array();
4315

    
4316
	if (is_array($config['gifs']['gif'])) {
4317
		foreach ($config['gifs']['gif'] as $gif)
4318
			if($gif['if'] == $interface)
4319
				$result[] = $gif;
4320
	}
4321

    
4322
	return $result;
4323
}
4324

    
4325
/*
4326
 * find_interface_ip($interface): return the interface ip (first found)
4327
 */
4328
function find_interface_ip($interface, $flush = false) {
4329
	global $interface_ip_arr_cache;
4330
	global $interface_sn_arr_cache;
4331

    
4332
	$interface = str_replace("\n", "", $interface);
4333

    
4334
	if (!does_interface_exist($interface))
4335
		return;
4336

    
4337
	/* Setup IP cache */
4338
	if (!isset($interface_ip_arr_cache[$interface]) or $flush) {
4339
		$ifinfo = pfSense_get_interface_addresses($interface);
4340
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
4341
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
4342
	}
4343

    
4344
	return $interface_ip_arr_cache[$interface];
4345
}
4346

    
4347
/*
4348
 * find_interface_ipv6($interface): return the interface ip (first found)
4349
 */
4350
function find_interface_ipv6($interface, $flush = false) {
4351
	global $interface_ipv6_arr_cache;
4352
	global $interface_snv6_arr_cache;
4353
	global $config;
4354

    
4355
	$interface = trim($interface);
4356
	$interface = get_real_interface($interface);
4357

    
4358
	if (!does_interface_exist($interface))
4359
		return;
4360

    
4361
	/* Setup IP cache */
4362
	if (!isset($interface_ipv6_arr_cache[$interface]) or $flush) {
4363
		$ifinfo = pfSense_get_interface_addresses($interface);
4364
		$interface_ipv6_arr_cache[$interface] = $ifinfo['ipaddr6'];
4365
		$interface_snv6_arr_cache[$interface] = $ifinfo['subnetbits6'];
4366
	}
4367

    
4368
	return $interface_ipv6_arr_cache[$interface];
4369
}
4370

    
4371
/*
4372
 * find_interface_ipv6_ll($interface): return the interface ipv6 link local (first found)
4373
 */
4374
function find_interface_ipv6_ll($interface, $flush = false) {
4375
	global $interface_llv6_arr_cache;
4376
	global $config;
4377

    
4378
	$interface = str_replace("\n", "", $interface);
4379

    
4380
	if (!does_interface_exist($interface))
4381
		return;
4382

    
4383
	/* Setup IP cache */
4384
	if (!isset($interface_llv6_arr_cache[$interface]) or $flush) {
4385
		$ifinfo = pfSense_getall_interface_addresses($interface);
4386
		foreach($ifinfo as $line) {
4387
			if (strstr($line, ":")) {
4388
				$parts = explode("/", $line);
4389
				if(is_linklocal($parts[0])) {
4390
					$ifinfo['linklocal'] = $parts[0];
4391
				}
4392
			}
4393
		}
4394
		$interface_llv6_arr_cache[$interface] = $ifinfo['linklocal'];
4395
	}
4396
	return $interface_llv6_arr_cache[$interface];
4397
}
4398

    
4399
function find_interface_subnet($interface, $flush = false) {
4400
	global $interface_sn_arr_cache;
4401
	global $interface_ip_arr_cache;
4402

    
4403
	$interface = str_replace("\n", "", $interface);
4404
	if (does_interface_exist($interface) == false)
4405
		return;
4406

    
4407
	if (!isset($interface_sn_arr_cache[$interface]) or $flush) {
4408
		$ifinfo = pfSense_get_interface_addresses($interface);
4409
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
4410
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
4411
	}
4412

    
4413
	return $interface_sn_arr_cache[$interface];
4414
}
4415

    
4416
function find_interface_subnetv6($interface, $flush = false) {
4417
	global $interface_snv6_arr_cache;
4418
	global $interface_ipv6_arr_cache;
4419

    
4420
	$interface = str_replace("\n", "", $interface);
4421
	if (does_interface_exist($interface) == false)
4422
		return;
4423

    
4424
	if (!isset($interface_snv6_arr_cache[$interface]) or $flush) {
4425
		$ifinfo = pfSense_get_interface_addresses($interface);
4426
		$interface_ipv6_arr_cache[$interface] = $ifinfo['ipaddr6'];
4427
		$interface_snv6_arr_cache[$interface] = $ifinfo['subnetbits6'];
4428
	}
4429

    
4430
	return $interface_snv6_arr_cache[$interface];
4431
}
4432

    
4433
function ip_in_interface_alias_subnet($interface, $ipalias) {
4434
	global $config;
4435

    
4436
	if (empty($interface) || !is_ipaddr($ipalias))
4437
		return false;
4438
	if (is_array($config['virtualip']['vip'])) {
4439
		foreach ($config['virtualip']['vip'] as $vip) {
4440
			switch ($vip['mode']) {
4441
			case "ipalias":
4442
				if ($vip['interface'] <> $interface)
4443
					break;
4444
				$subnet = is_ipaddrv6($ipalias) ? gen_subnetv6($vip['subnet'], $vip['subnet_bits']) : gen_subnet($vip['subnet'], $vip['subnet_bits']);
4445
				if (ip_in_subnet($ipalias, $subnet . "/" . $vip['subnet_bits']))
4446
					return true;
4447
				break;
4448
			}
4449
		}
4450
	}
4451

    
4452
	return false;
4453
}
4454

    
4455
function get_interface_ip($interface = "wan") {
4456
	$realif = get_failover_interface($interface);
4457
	if (!$realif) {
4458
		if (preg_match("/^carp/i", $interface))
4459
			$realif = $interface;
4460
		else if (preg_match("/^[a-z0-9]+_vip/i", $interface))
4461
			$realif = $interface;
4462
		else
4463
			return null;
4464
	}
4465

    
4466
	$curip = find_interface_ip($realif);
4467
	if ($curip && is_ipaddr($curip) && ($curip != "0.0.0.0"))
4468
		return $curip;
4469
	else
4470
		return null;
4471
}
4472

    
4473
function get_interface_ipv6($interface = "wan", $flush = false) {
4474
	global $config;
4475

    
4476
	$realif = get_failover_interface($interface, "inet6");
4477
	if (!$realif) {
4478
		if (preg_match("/^[a-z0-9]+_vip/i", $interface))
4479
			$realif = $interface;
4480
		else
4481
			return null;
4482
	}
4483

    
4484
	$curip = find_interface_ipv6($realif, $flush);
4485
	if ($curip && is_ipaddrv6($curip) && ($curip != "::"))
4486
		return $curip;
4487
	else
4488
		return null;
4489
}
4490

    
4491
function get_interface_linklocal($interface = "wan") {
4492

    
4493
	$realif = get_failover_interface($interface, "inet6");
4494
	if (!$realif) {
4495
		if (preg_match("/^carp/i", $interface))
4496
			$realif = $interface;
4497
		else if (preg_match("/^[a-z0-9]+_vip/i", $interface))
4498
			$realif = $interface;
4499
		else
4500
			return null;
4501
	}
4502

    
4503
	$curip = find_interface_ipv6_ll($realif);
4504
	if ($curip && is_ipaddrv6($curip) && ($curip != "::"))
4505
		return $curip;
4506
	else
4507
		return null;
4508
}
4509

    
4510
function get_interface_subnet($interface = "wan") {
4511
	$realif = get_real_interface($interface);
4512
	if (!$realif) {
4513
		if (preg_match("/^carp/i", $interface))
4514
			$realif = $interface;
4515
		else if (preg_match("/^[a-z0-9]+_vip/i", $interface))
4516
			$realif = $interface;
4517
		else
4518
			return null;
4519
	}
4520

    
4521
	$cursn = find_interface_subnet($realif);
4522
	if (!empty($cursn))
4523
		return $cursn;
4524

    
4525
	return null;
4526
}
4527

    
4528
function get_interface_subnetv6($interface = "wan") {
4529
	global $config;
4530

    
4531
	$realif = get_real_interface($interface, "inet6");
4532
	if (!$realif) {
4533
		if (preg_match("/^[a-z0-9]+_vip/i", $interface))
4534
			$realif = $interface;
4535
		else
4536
			return null;
4537
	}
4538

    
4539
	$cursn = find_interface_subnetv6($realif);
4540
	if (!empty($cursn))
4541
		return $cursn;
4542

    
4543
	return null;
4544
}
4545

    
4546
/* return outside interfaces with a gateway */
4547
function get_interfaces_with_gateway() {
4548
	global $config;
4549

    
4550
	$ints = array();
4551

    
4552
	/* loop interfaces, check config for outbound */
4553
	foreach($config['interfaces'] as $ifdescr => $ifname) {
4554
		switch ($ifname['ipaddr']) {
4555
			case "dhcp":
4556
			case "ppp";
4557
			case "pppoe":
4558
			case "pptp":
4559
			case "l2tp":
4560
			case "ppp";
4561
				$ints[$ifdescr] = $ifdescr;
4562
			break;
4563
			default:
4564
				if (substr($ifname['if'], 0, 4) ==  "ovpn" ||
4565
				    !empty($ifname['gateway']))
4566
					$ints[$ifdescr] = $ifdescr;
4567
			break;
4568
		}
4569
	}
4570
	return $ints;
4571
}
4572

    
4573
/* return true if interface has a gateway */
4574
function interface_has_gateway($friendly) {
4575
	global $config;
4576

    
4577
	if (!empty($config['interfaces'][$friendly])) {
4578
		$ifname = &$config['interfaces'][$friendly];
4579
		switch ($ifname['ipaddr']) {
4580
			case "dhcp":
4581
			case "pppoe":
4582
			case "pptp":
4583
			case "l2tp":
4584
			case "ppp";
4585
				return true;
4586
			break;
4587
			default:
4588
				if (substr($ifname['if'], 0, 4) ==  "ovpn")
4589
					return true;
4590
				if (!empty($ifname['gateway']))
4591
					return true;
4592
			break;
4593
		}
4594
	}
4595

    
4596
	return false;
4597
}
4598

    
4599
/* return true if interface has a gateway */
4600
function interface_has_gatewayv6($friendly) {
4601
	global $config;
4602

    
4603
	if (!empty($config['interfaces'][$friendly])) {
4604
		$ifname = &$config['interfaces'][$friendly];
4605
		switch ($ifname['ipaddrv6']) {
4606
			case "slaac":
4607
			case "dhcp6":
4608
			case "6to4":
4609
			case "6rd":
4610
				return true;
4611
				break;
4612
			default:
4613
				if (substr($ifname['if'], 0, 4) ==  "ovpn")
4614
					return true;
4615
				if (!empty($ifname['gatewayv6']))
4616
					return true;
4617
				break;
4618
		}
4619
	}
4620

    
4621
	return false;
4622
}
4623

    
4624
/****f* interfaces/is_altq_capable
4625
 * NAME
4626
 *   is_altq_capable - Test if interface is capable of using ALTQ
4627
 * INPUTS
4628
 *   $int            - string containing interface name
4629
 * RESULT
4630
 *   boolean         - true or false
4631
 ******/
4632

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

    
4646
	$int_family = remove_ifindex($int);
4647

    
4648
	if (in_array($int_family, $capable))
4649
		return true;
4650
	else if (stristr($int, "l2tp")) /* VLANs are name $parent_$vlan now */
4651
		return true;
4652
	else if (stristr($int, "_vlan")) /* VLANs are name $parent_$vlan now */
4653
		return true;
4654
	else if (stristr($int, "_wlan")) /* WLANs are name $parent_$wlan now */
4655
		return true;
4656
	else
4657
		return false;
4658
}
4659

    
4660
/****f* interfaces/is_interface_wireless
4661
 * NAME
4662
 *   is_interface_wireless - Returns if an interface is wireless
4663
 * RESULT
4664
 *   $tmp       - Returns if an interface is wireless
4665
 ******/
4666
function is_interface_wireless($interface) {
4667
	global $config, $g;
4668

    
4669
	$friendly = convert_real_interface_to_friendly_interface_name($interface);
4670
	if(!isset($config['interfaces'][$friendly]['wireless'])) {
4671
		if (preg_match($g['wireless_regex'], $interface)) {
4672
			if (isset($config['interfaces'][$friendly]))
4673
				$config['interfaces'][$friendly]['wireless'] = array();
4674
			return true;
4675
		}
4676
		return false;
4677
	} else
4678
		return true;
4679
}
4680

    
4681
function get_wireless_modes($interface) {
4682
	/* return wireless modes and channels */
4683
	$wireless_modes = array();
4684

    
4685
	$cloned_interface = get_real_interface($interface);
4686

    
4687
	if($cloned_interface && is_interface_wireless($cloned_interface)) {
4688
		$chan_list = "/sbin/ifconfig {$cloned_interface} list chan";
4689
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
4690
		$format_list = "/usr/bin/awk '{print \$5 \" \" \$6 \",\" \$1}'";
4691

    
4692
		$interface_channels = "";
4693
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
4694
		$interface_channel_count = count($interface_channels);
4695

    
4696
		$c = 0;
4697
		while ($c < $interface_channel_count) {
4698
			$channel_line = explode(",", $interface_channels["$c"]);
4699
			$wireless_mode = trim($channel_line[0]);
4700
			$wireless_channel = trim($channel_line[1]);
4701
			if(trim($wireless_mode) != "") {
4702
				/* if we only have 11g also set 11b channels */
4703
				if($wireless_mode == "11g") {
4704
					if(!isset($wireless_modes["11b"]))
4705
						$wireless_modes["11b"] = array();
4706
				} else if($wireless_mode == "11g ht") {
4707
					if(!isset($wireless_modes["11b"]))
4708
						$wireless_modes["11b"] = array();
4709
					if(!isset($wireless_modes["11g"]))
4710
						$wireless_modes["11g"] = array();
4711
					$wireless_mode = "11ng";
4712
				} else if($wireless_mode == "11a ht") {
4713
					if(!isset($wireless_modes["11a"]))
4714
						$wireless_modes["11a"] = array();
4715
					$wireless_mode = "11na";
4716
				}
4717
				$wireless_modes["$wireless_mode"]["$c"] = $wireless_channel;
4718
			}
4719
			$c++;
4720
		}
4721
	}
4722
	return($wireless_modes);
4723
}
4724

    
4725
/* return channel numbers, frequency, max txpower, and max regulation txpower */
4726
function get_wireless_channel_info($interface) {
4727
	$wireless_channels = array();
4728

    
4729
	$cloned_interface = get_real_interface($interface);
4730

    
4731
	if($cloned_interface && is_interface_wireless($cloned_interface)) {
4732
		$chan_list = "/sbin/ifconfig {$cloned_interface} list txpower";
4733
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
4734
		$format_list = "/usr/bin/awk '{print \$1 \",\" \$3 \" \" \$4 \",\" \$5 \",\" \$7}'";
4735

    
4736
		$interface_channels = "";
4737
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
4738

    
4739
		foreach ($interface_channels as $channel_line) {
4740
			$channel_line = explode(",", $channel_line);
4741
			if(!isset($wireless_channels[$channel_line[0]]))
4742
				$wireless_channels[$channel_line[0]] = $channel_line;
4743
		}
4744
	}
4745
	return($wireless_channels);
4746
}
4747

    
4748
/****f* interfaces/get_interface_mtu
4749
 * NAME
4750
 *   get_interface_mtu - Return the mtu of an interface
4751
 * RESULT
4752
 *   $tmp       - Returns the mtu of an interface
4753
 ******/
4754
function get_interface_mtu($interface) {
4755
	$mtu = pfSense_get_interface_addresses($interface);
4756
	return $mtu['mtu'];
4757
}
4758

    
4759
function get_interface_mac($interface) {
4760

    
4761
	$macinfo = pfSense_get_interface_addresses($interface);
4762
	return $macinfo["macaddr"];
4763
}
4764

    
4765
/****f* pfsense-utils/generate_random_mac_address
4766
 * NAME
4767
 *   generate_random_mac - generates a random mac address
4768
 * INPUTS
4769
 *   none
4770
 * RESULT
4771
 *   $mac - a random mac address
4772
 ******/
4773
function generate_random_mac_address() {
4774
	$mac = "02";
4775
	for($x=0; $x<5; $x++)
4776
		$mac .= ":" . dechex(rand(16, 255));
4777
	return $mac;
4778
}
4779

    
4780
/****f* interfaces/is_jumbo_capable
4781
 * NAME
4782
 *   is_jumbo_capable - Test if interface is jumbo frame capable.  Useful for determining VLAN capability.
4783
 * INPUTS
4784
 *   $int             - string containing interface name
4785
 * RESULT
4786
 *   boolean          - true or false
4787
 ******/
4788
function is_jumbo_capable($iface) {
4789
	$iface = trim($iface);
4790
	$capable = pfSense_get_interface_addresses($iface);
4791

    
4792
	if (isset($capable['caps']['vlanmtu']))
4793
		return true;
4794

    
4795
	return false;
4796
}
4797

    
4798
function interface_setup_pppoe_reset_file($pppif, $iface="") {
4799
	global $g;
4800

    
4801
	$cron_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
4802

    
4803
	if(!empty($iface) && !empty($pppif)){
4804
		$cron_cmd = <<<EOD
4805
#!/bin/sh
4806
/usr/local/sbin/pfSctl -c 'interface reload {$iface}'
4807
/usr/bin/logger -t {$pppif} "PPPoE periodic reset executed on {$iface}"
4808

    
4809
EOD;
4810

    
4811
		@file_put_contents($cron_file, $cron_cmd);
4812
		chmod($cron_file, 0755);
4813
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
4814
	} else
4815
		unlink_if_exists($cron_file);
4816
}
4817

    
4818
function get_interface_default_mtu($type = "ethernet") {
4819
	switch ($type) {
4820
	case "gre":
4821
		return 1476;
4822
		break;
4823
	case "gif":
4824
		return 1280;
4825
		break;
4826
	case "tun":
4827
	case "vlan":
4828
	case "tap":
4829
	case "ethernet":
4830
	default:
4831
		return 1500;
4832
		break;
4833
	}
4834

    
4835
	/* Never reached */
4836
	return 1500;
4837
}
4838

    
4839
function get_vip_descr($ipaddress) {
4840
	global $config;
4841

    
4842
	foreach ($config['virtualip']['vip'] as $vip) {
4843
		if ($vip['subnet'] == $ipaddress) {
4844
			return ($vip['descr']);
4845
		}
4846
	}
4847
	return "";
4848
}
4849

    
4850
function interfaces_staticarp_configure($if) {
4851
	global $config, $g;
4852
	if(isset($config['system']['developerspew'])) {
4853
		$mt = microtime();
4854
		echo "interfaces_staticarp_configure($if) being called $mt\n";
4855
	}
4856

    
4857
	$ifcfg = $config['interfaces'][$if];
4858

    
4859
	if (empty($if) || empty($ifcfg['if']) || !isset($ifcfg['enable']))
4860
		return 0;
4861

    
4862
	/* Enable staticarp, if enabled */
4863
	if(isset($config['dhcpd'][$if]['staticarp'])) {
4864
		mwexec("/sbin/ifconfig " . escapeshellarg($ifcfg['if']) . " staticarp " );
4865
		mwexec("/usr/sbin/arp -d -i " . escapeshellarg($ifcfg['if']) . " -a > /dev/null 2>&1 ");
4866
		if (is_array($config['dhcpd'][$if]['staticmap'])) {
4867

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

    
4871
			}
4872

    
4873
		}
4874
	} else {
4875
		mwexec("/sbin/ifconfig " . escapeshellarg($ifcfg['if']) . " -staticarp " );
4876
		mwexec("/usr/sbin/arp -d -i " . escapeshellarg($ifcfg['if']) . " -a > /dev/null 2>&1 ");
4877
		if (is_array($config['dhcpd'][$if]) && is_array($config['dhcpd'][$if]['staticmap'])) {
4878
			foreach ($config['dhcpd'][$if]['staticmap'] as $arpent) {
4879
				if (isset($arpent['arp_table_static_entry'])) {
4880
					mwexec("/usr/sbin/arp -s " . escapeshellarg($arpent['ipaddr']) . " " . escapeshellarg($arpent['mac']));
4881
				}
4882
			}
4883
		}
4884
	}
4885

    
4886
	return 0;
4887
}
4888

    
4889
function get_failover_interface($interface, $family = "all") {
4890
	global $config;
4891

    
4892
	/* shortcut to get_real_interface if we find it in the config */
4893
	if (is_array($config['interfaces'][$interface])) {
4894
		return get_real_interface($interface, $family);
4895
	}
4896

    
4897
	/* compare against gateway groups */
4898
	$a_groups = return_gateway_groups_array();
4899
	if (is_array($a_groups[$interface])) {
4900
		/* we found a gateway group, fetch the interface or vip */
4901
		if ($a_groups[$interface][0]['vip'] <> "")
4902
			return $a_groups[$interface][0]['vip'];
4903
		else
4904
			return $a_groups[$interface][0]['int'];
4905
	}
4906
	/* fall through to get_real_interface */
4907
	/* XXX: Really needed? */
4908
	return get_real_interface($interface, $family);
4909
}
4910

    
4911
function remove_ifindex($ifname) {
4912
	return preg_replace("/[0-9]+$/", "", $ifname);
4913
}
4914

    
4915
?>
(25-25/66)