Project

General

Profile

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

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

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

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

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

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

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

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

    
42
*/
43

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

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

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

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

    
68
	return $interface_arr_cache;
69
}
70

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

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

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

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

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

    
98

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

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

    
124
	return false;
125
}
126

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
267
	interfaces_bring_up($vlanif);
268

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

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

    
275
	return $vlanif;
276
}
277

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

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

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

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

    
298
	$vlanif = interface_vlan_configure($vlan);
299

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

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

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

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

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

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

    
351
	return $vlanif;
352
}
353

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

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

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

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

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

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

    
394
	return $vlanif;
395
}
396

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

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

    
403
	$iflist = get_configured_interface_list();
404

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

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

    
424
}
425

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

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

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

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

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

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

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

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

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

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

    
533
	$checklist = get_configured_interface_list();
534

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
754
	$checklist = get_interface_list();
755

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

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

    
768
	interfaces_bring_up($laggif);
769

    
770
	return $laggif;
771
}
772

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

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

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

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

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

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

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

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

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

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

    
844
	return $greif;
845
}
846

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

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

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

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

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

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

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

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

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

    
938

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

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

    
951
	return $gifif;
952
}
953

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

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

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

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

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

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

    
972
	interfaces_qinq_configure();
973

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

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

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

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

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

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

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

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

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

    
1030
		interface_configure($if, $reload);
1031

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

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

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

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

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

    
1051
		interface_configure($if, $reload);
1052

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

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

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

    
1066
		interface_configure($if, $reload);
1067

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

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

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

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

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

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

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

    
1093
	return 0;
1094
}
1095

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

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

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

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

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

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

    
1136
	if ($ifacecfg === false) {
1137
		$ifcfg = $config['interfaces'][$interface];
1138
		$ppps = $config['ppps']['ppp'];
1139
		$realif = get_real_interface($interface);
1140
	} elseif (!is_array($ifacecfg)) {
1141
		log_error(gettext("Wrong parameters used during interface_bring_down"));
1142
	} else {
1143
		$ifcfg = $ifacecfg['ifcfg'];
1144
		$ppps = $ifacecfg['ppps'];
1145
		if (isset($ifacecfg['ifcfg']['realif']))
1146
			$realif = $ifacecfg['ifcfg']['realif'];
1147
		else
1148
			$realif = get_real_interface($interface);
1149
	}
1150

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

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

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

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

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

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

    
1267
	return;
1268
}
1269

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

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

    
1278
	return false;
1279
}
1280

    
1281
function interfaces_ptpid_next() {
1282

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

    
1287
	return $ptpid;
1288
}
1289

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

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

    
1301
	return NULL;
1302
}
1303

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

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

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

    
1313
	$itemhash = getMPDCRONSettings($pppif);
1314

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

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

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

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

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

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

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

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

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

    
1464
				if(!is_ipaddr($localips[$pid])){
1465
					log_error("Could not get a Local IP address for PPTP/L2TP link on {$port} in interfaces_ppps_configure. Using 0.0.0.0 ip!");
1466
					$localips[$pid] = "0.0.0.0";
1467
				}
1468
				if(!is_ipaddr($gateways[$pid])){
1469
					log_error(sprintf(gettext('Could not get a PPTP/L2TP Remote IP address from %1$s for %2$s in interfaces_ppps_configure.'), $dhcp_gateway, $gway));
1470
					return 0;
1471
				}
1472
				pfSense_ngctl_attach(".", $port);
1473
				break;
1474
			case "ppp":
1475
				if (!file_exists("{$port}")) {
1476
					log_error(sprintf(gettext("Device %s does not exist. PPP link cannot start without the modem device."), $port));
1477
					return 0;
1478
				}
1479
				break;
1480
			default:
1481
				log_error(sprintf(gettext("Unkown %s configured as ppp interface."), $type));
1482
				break;
1483
		}
1484
	}
1485

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1574
EOD;
1575

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

    
1580
EOD;
1581

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

    
1589
EOD;
1590

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

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

    
1601
EOD;
1602

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

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

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

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

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

    
1629
EOD;
1630

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

    
1635
EOD;
1636

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

    
1641
EOD;
1642

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

    
1648
EOD;
1649

    
1650

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

    
1655
EOD;
1656

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

    
1662
EOD;
1663

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

    
1668
EOD;
1669

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

    
1674
EOD;
1675

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

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

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

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

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

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

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

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

    
1733
EOD;
1734

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

    
1740
EOD;
1741
		}
1742

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

    
1746

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

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

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

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

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

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

    
1821
	return 1;
1822
}
1823

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

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

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

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

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

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

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

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

    
1870
		sleep(1);
1871

    
1872
		/* XXX: Handle an issue with pfsync(4) and carp(4). In a cluster carp will come up before pfsync(4) has updated and so will cause issues
1873
		 * for existing sessions.
1874
		 */
1875
		log_error("waiting for pfsync...");
1876
		$i = 0;
1877
		while (intval(trim(`/sbin/ifconfig pfsync0 | /usr/bin/grep 'syncok: 0' | /usr/bin/grep -v grep | /usr/bin/wc -l`)) == 0 && $i < 30) {
1878
			$i++;
1879
			sleep(1);
1880
		}
1881
		log_error("pfsync done in $i seconds.");
1882
		log_error("Configuring CARP settings finalize...");
1883
	} else {
1884
		mwexec("/sbin/ifconfig pfsync0 -syncdev -syncpeer down", false);
1885
	}
1886

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

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

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

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

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

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

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

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

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

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

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

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

    
2016
function interface_reload_carps($cif) {
2017
	global $config;
2018

    
2019
	$carpifs = link_ip_to_carp_interface(find_interface_ip($cif));
2020
	if (empty($carpifs))
2021
		return;
2022

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

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

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

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

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

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

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

    
2096
	/* invalidate interface cache */
2097
	get_interface_arr(true);
2098

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

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

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

    
2118
	interfaces_bring_up($vipif);
2119

    
2120
	return $vipif;
2121
}
2122

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

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

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

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

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

    
2194
	if(!is_interface_wireless($ifcfg['if']))
2195
		return;
2196

    
2197
	$baseif = interface_get_wireless_base($ifcfg['if']);
2198

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

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

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

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

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

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

    
2269
	// Clone wireless nic if needed.
2270
	interface_wireless_clone($if, $wl);
2271

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2421
	kill_hostapd($if);
2422
	mwexec(kill_wpasupplicant("{$if}"));
2423

    
2424
	/* generate wpa_supplicant/hostap config if wpa is enabled */
2425
	conf_mount_rw();
2426

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

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

    
2481
EOD;
2482

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

    
2489
EOD;
2490

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

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

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

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

    
2518
			}
2519
			break;
2520
	}
2521

    
2522
	/*
2523
	 *    all variables are set, lets start up everything
2524
	 */
2525

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

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

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

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

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

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

    
2572
	fclose($fd_set);
2573
	conf_mount_ro();
2574

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

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

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

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

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

    
2608
		$wlregcmd_args = implode(" ", $wlregcmd);
2609

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

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

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

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

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

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

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

    
2662

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

    
2667
	return 0;
2668

    
2669
}
2670

    
2671
function kill_hostapd($interface) {
2672
	global $g;
2673

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

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

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

    
2688
	return intval($pid);
2689
}
2690

    
2691
function find_dhcp6c_process($interface) {
2692
	global $g;
2693

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

    
2699
	return intval($pid);
2700
}
2701

    
2702
function interface_vlan_mtu_configured($realhwif, $mtu) {
2703
	global $config;
2704

    
2705
	if (is_array($config['vlans']['vlan'])) {
2706
		foreach ($config['vlans']['vlan'] as $vlan) {
2707
			if ($vlan['if'] != $realhwif)
2708
				continue;
2709
			$assignedport = convert_real_interface_to_friendly_interface_name($vlan['vlanif']);
2710
			if (!empty($assignedport)) {
2711
				$portmtu = $config['interfaces'][$assignedport]['mtu'];
2712
				if (!empty($portmtu) && $portmtu > $mtu)
2713
					$mtu = $portmtu;
2714
			}
2715
		}
2716
	}
2717

    
2718
	return $mtu;
2719
}
2720

    
2721
function interface_configure($interface = "wan", $reloadall = false, $linkupevent = false) {
2722
	global $config, $g;
2723
	global $interface_sn_arr_cache, $interface_ip_arr_cache;
2724
	global $interface_snv6_arr_cache, $interface_ipv6_arr_cache;
2725

    
2726
	$wancfg = $config['interfaces'][$interface];
2727

    
2728
	if (!isset($wancfg['enable']))
2729
		return;
2730

    
2731
	$realif = get_real_interface($interface);
2732
	$realhwif_array = get_parent_interface($interface);
2733
	// Need code to handle MLPPP if we ever use $realhwif for MLPPP handling
2734
	$realhwif = $realhwif_array[0];
2735

    
2736
	/* Disable Accepting router advertisements unless specifically requested */
2737
	if ($g['debug'])
2738
		log_error("Deny router advertisements for interface {$interface}");
2739
	mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 -accept_rtadv");
2740

    
2741
	if (!$g['booting'] && !(substr($realif, 0, 4) == "ovpn")) {
2742
		/* remove all IPv4 and IPv6 addresses */
2743
		while (mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " -alias", true) == 0);
2744
		while (mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 -alias", true) == 0);
2745

    
2746
		/* only bring down the interface when both v4 and v6 are set to NONE */
2747
		if(empty($wancfg['ipaddr']) && empty($wancfg['ipaddrv6'])) {
2748
			interface_bring_down($interface);
2749
		}
2750
	}
2751

    
2752
	/* wireless configuration? */
2753
	if (is_array($wancfg['wireless']))
2754
		interface_wireless_configure($realif, $wancfg, $wancfg['wireless']);
2755

    
2756
	$mac = get_interface_mac($realhwif);
2757
	/*
2758
	 * Don't try to reapply the spoofed MAC if it's already applied.
2759
	 * When ifconfig link is used, it cycles the interface down/up, which triggers
2760
	 * the interface config again, which attempts to spoof the MAC again,
2761
	 * which cycles the link again...
2762
	 */
2763
	if ($wancfg['spoofmac'] && ($wancfg['spoofmac'] != $mac)) {
2764
		mwexec("/sbin/ifconfig " . escapeshellarg($realhwif) .
2765
			" link " . escapeshellarg($wancfg['spoofmac']));
2766

    
2767
		/*
2768
		 * All vlans need to spoof their parent mac address, too.  see
2769
		 * ticket #1514: http://cvstrac.pfsense.com/tktview?tn=1514,33
2770
		 */
2771
		if (is_array($config['vlans']['vlan'])) {
2772
			foreach ($config['vlans']['vlan'] as $vlan) {
2773
				if ($vlan['if'] == $realhwif)
2774
					mwexec("/sbin/ifconfig " . escapeshellarg($vlan['vlanif']) .
2775
					" link " . escapeshellarg($wancfg['spoofmac']));
2776
			}
2777
		}
2778
	}  else {
2779

    
2780
		if ($mac == "ff:ff:ff:ff:ff:ff") {
2781
			/*   this is not a valid mac address.  generate a
2782
			 *   temporary mac address so the machine can get online.
2783
			 */
2784
			echo gettext("Generating new MAC address.");
2785
			$random_mac = generate_random_mac_address();
2786
			mwexec("/sbin/ifconfig " . escapeshellarg($realhwif) .
2787
				" link " . escapeshellarg($random_mac));
2788
			$wancfg['spoofmac'] = $random_mac;
2789
			write_config();
2790
			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");
2791
		}
2792
	}
2793

    
2794
	/* media */
2795
	if ($wancfg['media'] || $wancfg['mediaopt']) {
2796
		$cmd = "/sbin/ifconfig " . escapeshellarg($realhwif);
2797
		if ($wancfg['media'])
2798
			$cmd .= " media " . escapeshellarg($wancfg['media']);
2799
		if ($wancfg['mediaopt'])
2800
			$cmd .= " mediaopt " . escapeshellarg($wancfg['mediaopt']);
2801
		mwexec($cmd);
2802
	}
2803
	$options = pfSense_get_interface_addresses($realhwif);
2804
	if (is_array($options) && isset($options['caps']['polling'])) {
2805
		if (isset($config['system']['polling']))
2806
			pfSense_interface_capabilities($realif, IFCAP_POLLING);
2807
		else
2808
			pfSense_interface_capabilities($realif, -IFCAP_POLLING);
2809
	}
2810

    
2811
	/* skip vlans for checksumming and polling */
2812
	if (!stristr($realif, "_vlan") && is_array($options)) {
2813
		$flags = 0;
2814
		if(isset($config['system']['disablechecksumoffloading'])) {
2815
			if (isset($options['encaps']['txcsum']))
2816
				$flags |= IFCAP_TXCSUM;
2817
			if (isset($options['encaps']['rxcsum']))
2818
				$flags |= IFCAP_RXCSUM;
2819
		} else {
2820
			if (!isset($options['caps']['txcsum']))
2821
				$flags |= IFCAP_TXCSUM;
2822
			if (!isset($options['caps']['rxcsum']))
2823
				$flags |= IFCAP_RXCSUM;
2824
		}
2825

    
2826
		if(isset($config['system']['disablesegmentationoffloading'])) {
2827
			if (isset($options['encaps']['tso4']))
2828
				$flags |= IFCAP_TSO;
2829
			if (isset($options['encaps']['tso6']))
2830
				$flags |= IFCAP_TSO;
2831
		} else {
2832
			if (!isset($options['caps']['tso4']))
2833
				$flags |= IFCAP_TSO;
2834
			if (!isset($options['caps']['tso6']))
2835
				$flags |= IFCAP_TSO;
2836
		}
2837

    
2838
		if(isset($config['system']['disablelargereceiveoffloading'])) {
2839
			if (isset($options['encaps']['lro']))
2840
				$flags |= IFCAP_LRO;
2841
		} else {
2842
			if (!isset($options['caps']['lro']))
2843
				$flags |= IFCAP_LRO;
2844
		}
2845

    
2846
		/* if the NIC supports polling *AND* it is enabled in the GUI */
2847
		if (!isset($config['system']['polling']) || !isset($options['caps']['polling'])) {
2848
			$flags |= IFCAP_POLLING;
2849
		}
2850
		pfSense_interface_capabilities($realhwif, -$flags);
2851
	}
2852

    
2853
	/* invalidate interface/ip/sn cache */
2854
	get_interface_arr(true);
2855
	unset($interface_ip_arr_cache[$realif]);
2856
	unset($interface_sn_arr_cache[$realif]);
2857
	unset($interface_ipv6_arr_cache[$realif]);
2858
	unset($interface_snv6_arr_cache[$realif]);
2859

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

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

    
2914
	$mtu = get_interface_default_mtu(remove_ifindex($realhwif));
2915
	$assignedparent = convert_real_interface_to_friendly_interface_name($realhwif);
2916
	if (!empty($assignedparent) && !empty($config['interfaces'][$assignedparent]['mtu']))
2917
		$mtu = $config['interfaces'][$assignedparent]['mtu'];
2918

    
2919
	$vlanifs = link_interface_to_vlans($realhwif);
2920
	if (empty($vlanifs))
2921
		$vlanifs = array();
2922

    
2923
	if (!empty($wancfg['mtu'])) {
2924
		if (stristr($realif, "_vlan")) {
2925
			if (!empty($assignedparent)) {
2926
				$parentmtu = $config['interfaces'][$assignedparent]['mtu'];
2927
				if (empty($parentmtu))
2928
					$parentmtu = interface_vlan_mtu_configured($realhwif, $wancfg['mtu']);
2929
				if ($wancfg['mtu'] > $parentmtu) {
2930
					if (get_interface_mtu($realhwif) != $wancfg['mtu'])
2931
						pfSense_interface_mtu($realhwif, $wancfg['mtu']);
2932

    
2933
					/* All vlans need to use the same mtu value as their parent. */
2934
					foreach ($vlanifs as $vlan) {
2935
						if ($vlan['vlanif'] == $realif)
2936
							continue;
2937
						$assignedport = convert_real_interface_to_friendly_interface_name($vlan['vlanif']);
2938
						if (!empty($assignedport)) {
2939
							$portmtu = $config['interfaces'][$assignedport]['mtu'];
2940
							if (empty($portmtu) && (get_interface_mtu($vlan['vlanif']) != $wancfg['mtu']))
2941
								pfSense_interface_mtu($vlan['vlanif'], $wancfg['mtu']);
2942
						} else if (get_interface_mtu($vlan['vlanif']) != $wancfg['mtu'])
2943
							pfSense_interface_mtu($vlan['vlanif'], $wancfg['mtu']);
2944
					}
2945
				}
2946
			} else {
2947
				/* Parent is not assigned, back to default */
2948
				if (get_interface_mtu($realhwif) != $mtu)
2949
					pfSense_interface_mtu($realhwif, $mtu);
2950

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

    
2964
				if (get_interface_mtu($realif) != $wancfg['mtu'])
2965
					pfSense_interface_mtu($realif, $wancfg['mtu']);
2966
			}
2967
		} else {
2968
			foreach ($vlanifs as $vlan) {
2969
				$assignedport = convert_real_interface_to_friendly_interface_name($vlan['vlanif']);
2970
				if (empty($assignedport)) {
2971
					if (get_interface_mtu($vlan['vlanif']) != $wancfg['mtu'])
2972
						pfSense_interface_mtu($vlan['vlanif'], $wancfg['mtu']);
2973
				} else {
2974
					$vlanmtu = $config['interfaces'][$assignedport]['mtu'];
2975
					if ((empty($vlanmtu) || ($vlanmtu >= $wancfg['mtu'])) && (get_interface_mtu($vlan['vlanif']) != $wancfg['mtu']))
2976
						pfSense_interface_mtu($vlan['vlanif'], $wancfg['mtu']);
2977
				}
2978
			}
2979
		}
2980
		if ($wancfg['mtu'] != get_interface_mtu($realif))
2981
			pfSense_interface_mtu($realif, $wancfg['mtu']);
2982
	} else if (stristr($realif, "_vlan")) {
2983
		/* XXX: This is really dangerous for example with vlans changing their parent mtu! */
2984
		$bigmtu = interface_vlan_mtu_configured($realhwif, $mtu);
2985
		if ($mtu < $bigmtu)
2986
			$mtu = $bigmtu;
2987

    
2988
		if (get_interface_mtu($realhwif) != $mtu)
2989
			pfSense_interface_mtu($realhwif, $mtu);
2990

    
2991
		/* All vlans need to use the same mtu value as their parent. */
2992
		foreach ($vlanifs as $vlan) {
2993
			if ($vlan['vlanif'] == $realif)
2994
				continue;
2995
			$assignedport = convert_real_interface_to_friendly_interface_name($vlan['vlanif']);
2996
			if (!empty($assignedport)) {
2997
				$portmtu = $config['interfaces'][$assignedport]['mtu'];
2998
				if (empty($portmtu) && (get_interface_mtu($vlan['vlanif']) != $mtu))
2999
					pfSense_interface_mtu($vlan['vlanif'], $mtu);
3000
			} else if (get_interface_mtu($vlan['vlanif']) != $mtu)
3001
				pfSense_interface_mtu($vlan['vlanif'], $mtu);
3002
		}
3003
		if (get_interface_mtu($realif) != $mtu)
3004
			pfSense_interface_mtu($realif, $mtu);
3005
	} else {
3006
		/* All vlans need to use the same mtu value as their parent. */
3007
		foreach ($vlanifs as $vlan) {
3008
			$assignedport = convert_real_interface_to_friendly_interface_name($vlan['vlanif']);
3009
			if (!empty($assignedport)) {
3010
				$portmtu = $config['interfaces'][$assignedport]['mtu'];
3011
				if (empty($portmtu) && (get_interface_mtu($vlan['vlanif']) != $mtu))
3012
					pfSense_interface_mtu($vlan['vlanif'], $mtu);
3013
			} else if (get_interface_mtu($vlan['vlanif']) != $mtu)
3014
				pfSense_interface_mtu($vlan['vlanif'], $mtu);
3015
		}
3016
		if ($mtu != get_interface_mtu($realhwif))
3017
			pfSense_interface_mtu($realhwif, $mtu);
3018
	}
3019

    
3020
	unset($vlanifs);
3021

    
3022
	if(does_interface_exist($wancfg['if']))
3023
		interfaces_bring_up($wancfg['if']);
3024

    
3025
	interface_netgraph_needed($interface);
3026

    
3027
	if (!$g['booting']) {
3028
		link_interface_to_vips($interface, "update");
3029

    
3030
		unset($gre);
3031
		$gre = link_interface_to_gre($interface);
3032
		if (!empty($gre))
3033
			array_walk($gre, 'interface_gre_configure');
3034

    
3035
		unset($gif);
3036
		$gif = link_interface_to_gif($interface);
3037
		if (!empty($gif))
3038
			array_walk($gif, 'interface_gif_configure');
3039

    
3040
		if ($linkupevent == false || substr($realif, 0, 4) == "ovpn") {
3041
			unset($bridgetmp);
3042
			$bridgetmp = link_interface_to_bridge($interface);
3043
			if (!empty($bridgetmp))
3044
				interface_bridge_add_member($bridgetmp, $realif);
3045
		}
3046

    
3047
		$grouptmp = link_interface_to_group($interface);
3048
		if (!empty($grouptmp))
3049
			array_walk($grouptmp, 'interface_group_add_member');
3050

    
3051
		if ($interface == "lan")
3052
			/* make new hosts file */
3053
			system_hosts_generate();
3054

    
3055
		if ($reloadall == true) {
3056

    
3057
			/* reconfigure static routes (kernel may have deleted them) */
3058
			system_routing_configure($interface);
3059

    
3060
			/* reload ipsec tunnels */
3061
			vpn_ipsec_configure();
3062

    
3063
			/* restart dnsmasq */
3064
			services_dnsmasq_configure();
3065

    
3066
			/* update dyndns */
3067
			send_event("service reload dyndns {$interface}");
3068

    
3069
			/* reload captive portal */
3070
			captiveportal_init_rules();
3071
		}
3072
	}
3073

    
3074
	interfaces_staticarp_configure($interface);
3075
	return 0;
3076
}
3077

    
3078
function interface_track6_configure($interface = "lan", $wancfg) {
3079
	global $config, $g;
3080

    
3081
	if (!is_array($wancfg))
3082
		return;
3083

    
3084
	if (!isset($wancfg['enable']))
3085
		return;
3086

    
3087
	/* If the interface is not configured via another, exit */
3088
	if (empty($wancfg['track6-interface']))
3089
		return;
3090

    
3091
	/* always configure a link-local of fe80::1:1 on the track6 interfaces */
3092
	$realif = get_real_interface($interface);
3093
	$linklocal = find_interface_ipv6_ll($realif);
3094
	if (!empty($linklocal))
3095
		mwexec("/sbin/ifconfig {$realif} inet6 {$linklocal} delete");
3096
	mwexec("/sbin/ifconfig {$realif} inet6 fe80::1:1%{$realif}");
3097

    
3098
	$trackcfg = $config['interfaces'][$wancfg['track6-interface']];
3099
	if (!isset($trackcfg['enable'])) {
3100
		log_error("Interface {$interface} tracking non-existant interface {$wancfg['track6-interface']}");
3101
		return;
3102
	}
3103

    
3104
	switch($trackcfg['ipaddrv6']) {
3105
	case "6to4":
3106
		if ($g['debug'])
3107
			log_error("Interface {$interface} configured via {$wancfg['track6-interface']}  type {$type}");
3108
		interface_track6_6to4_configure($interface, $wancfg);
3109
		break;
3110
	case "6rd":
3111
		if ($g['debug'])
3112
			log_error("Interface {$interface} configured via {$wancfg['track6-interface']}  type {$type}");
3113
		interface_track6_6rd_configure($interface, $wancfg);
3114
		break;
3115
	}
3116

    
3117
	if (!$g['booting']) {
3118
		if (!function_exists('services_dhcpd_configure'))
3119
			require_once("services.inc");
3120

    
3121
		services_dhcpd_configure("inet6");
3122
	}
3123

    
3124
	return 0;
3125
}
3126

    
3127
function interface_track6_6rd_configure($interface = "lan", $lancfg) {
3128
	global $config, $g;
3129
	global $interface_ipv6_arr_cache;
3130
	global $interface_snv6_arr_cache;
3131

    
3132
	if (!is_array($lancfg))
3133
		return;
3134

    
3135
	/* If the interface is not configured via another, exit */
3136
	if (empty($lancfg['track6-interface']))
3137
		return;
3138

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

    
3145
	$ip4address = get_interface_ip($lancfg['track6-interface']);
3146
	if (!is_ipaddrv4($ip4address)) { /* XXX: This should not be needed by 6rd || (is_private_ip($ip4address))) { */
3147
		log_error("The interface IPv4 '{$ip4address}' address on interface '{$lancfg['track6-interface']}' is not public, not configuring 6RD tunnel");
3148
		return;
3149
	}
3150
	$hexwanv4 = return_hex_ipv4($ip4address);
3151

    
3152
	/* create the long prefix notation for math, save the prefix length */
3153
	$rd6prefix = explode("/", $wancfg['prefix-6rd']);
3154
	$rd6prefixlen = $rd6prefix[1];
3155
	$rd6prefix = Net_IPv6::uncompress($rd6prefix[0]);
3156

    
3157
	/* binary presentation of the prefix for all 128 bits. */
3158
	$rd6lanbin = convert_ipv6_to_128bit($rd6prefix);
3159

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

    
3165
	/* add the custom prefix id, max 32bits long? (64 bits - (prefixlen + (32 - v4plen)) */
3166
	/* 64 - (37 + (32 - 17)) = 8 == /52 */
3167
	$restbits = 64 - ($rd6prefixlen + (32 - $wancfg['prefix-6rd-v4plen']));
3168
	// echo "64 - (prefixlen {$rd6prefixlen} + v4len (32 - {$wancfg['prefix-6rd-v4plen']})) = {$restbits} \n";
3169
	$rd6lanbin .= substr(sprintf("%032b", str_pad($lancfg['track6-prefix-id'], 32, "0", STR_PAD_LEFT)), (32 - $restbits), 32);
3170
	/* fill the rest out with zeros */
3171
	$rd6lanbin = str_pad($rd6lanbin, 128, "0", STR_PAD_RIGHT);;
3172

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

    
3176
	$lanif = get_real_interface($interface);
3177
	$oip = find_interface_ipv6($lanif);
3178
	if (is_ipaddrv6($oip))
3179
		mwexec("/sbin/ifconfig {$lanif} inet6 {$oip} delete");
3180
	unset($interface_ipv6_arr_cache[$lanif]);
3181
	unset($interface_snv6_arr_cache[$lanif]);
3182
	log_error("rd6 {$interface} with ipv6 address {$rd6lan} based on {$lancfg['track6-interface']} ipv4 {$ip4address}");
3183
	mwexec("/sbin/ifconfig {$lanif} inet6 {$rd6lan} prefixlen 64");
3184

    
3185
	return 0;
3186
}
3187

    
3188
function interface_track6_6to4_configure($interface = "lan", $lancfg) {
3189
	global $config, $g;
3190
	global $interface_ipv6_arr_cache;
3191
	global $interface_snv6_arr_cache;
3192

    
3193
	if (!is_array($lancfg))
3194
		return;
3195

    
3196
	/* If the interface is not configured via another, exit */
3197
	if (empty($lancfg['track6-interface']))
3198
		return;
3199

    
3200
	$wancfg = $config['interfaces'][$lancfg['track6-interface']];
3201
	if (empty($wancfg)) {
3202
		log_error("Interface {$interface} tracking non-existant interface {$lancfg['track6-interface']}");
3203
		return;
3204
	}
3205

    
3206
	$ip4address = get_interface_ip($lancfg['track6-interface']);
3207
	if (!is_ipaddrv4($ip4address) || is_private_ip($ip4address)) {
3208
		log_error("The interface IPv4 '{$ip4address}' address on interface '{$lancfg['track6-interface']}' is not public, not configuring 6RD tunnel");
3209
		return;
3210
	}
3211
	$hexwanv4 = return_hex_ipv4($ip4address);
3212

    
3213
	/* create the long prefix notation for math, save the prefix length */
3214
	$sixto4prefix = "2002::";
3215
	$sixto4prefixlen = 16;
3216
	$sixto4prefix = Net_IPv6::uncompress($sixto4prefix);
3217

    
3218
	/* binary presentation of the prefix for all 128 bits. */
3219
	$sixto4lanbin = convert_ipv6_to_128bit($sixto4prefix);
3220

    
3221
	/* just save the left prefix length bits */
3222
	$sixto4lanbin = substr($sixto4lanbin, 0, $sixto4prefixlen);
3223
	/* add the v4 address */
3224
	$sixto4lanbin .= sprintf("%032b", hexdec($hexwanv4));
3225
	/* add the custom prefix id */
3226
	$sixto4lanbin .= sprintf("%016b", $lancfg['track6-prefix-id']);
3227
	/* fill the rest out with zeros */
3228
	$sixto4lanbin = str_pad($sixto4lanbin, 128, "0", STR_PAD_RIGHT);;
3229

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

    
3233
	$lanif = get_real_interface($interface);
3234
	$oip = find_interface_ipv6($lanif);
3235
	if (is_ipaddrv6($oip))
3236
		mwexec("/sbin/ifconfig {$lanif} inet6 {$oip} delete");
3237
	unset($interface_ipv6_arr_cache[$lanif]);
3238
	unset($interface_snv6_arr_cache[$lanif]);
3239
	log_error("sixto4 {$interface} with ipv6 address {$sixto4lan} based on {$lancfg['track6-interface']} ipv4 {$ip4address}");
3240
	mwexec("/sbin/ifconfig {$lanif} inet6 {$sixto4lan} prefixlen 64");
3241

    
3242
	return 0;
3243
}
3244

    
3245
function interface_6rd_configure($interface = "wan", $wancfg) {
3246
	global $config, $g;
3247

    
3248
	/* because this is a tunnel interface we can only function
3249
	 *	with a public IPv4 address on the interface */
3250

    
3251
	if (!is_array($wancfg))
3252
		return;
3253

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

    
3262
	if (!is_numeric($wancfg['prefix-6rd-v4plen']))
3263
		$wancfg['prefix-6rd-v4plen'] = 0;
3264

    
3265
	/* create the long prefix notation for math, save the prefix length */
3266
	$rd6prefix = explode("/", $wancfg['prefix-6rd']);
3267
	$rd6prefixlen = $rd6prefix[1];
3268
	$rd6prefix = Net_IPv6::uncompress($rd6prefix[0]);
3269

    
3270
	/* binary presentation of the prefix for all 128 bits. */
3271
	$rd6prefixbin = convert_ipv6_to_128bit($rd6prefix);
3272

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

    
3280
	/* convert the 128 bits for the broker address back into a valid IPv6 address */
3281
	$rd6prefix = convert_128bit_to_ipv6($rd6prefixbin);
3282

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

    
3285
	/* XXX: need to extend to support variable prefix size for v4 */
3286
	if (!is_module_loaded("if_stf"))
3287
		mwexec("/sbin/kldload if_stf.ko");
3288
	$stfiface = "{$interface}_stf";
3289
	if (does_interface_exist($stfiface))
3290
		pfSense_interface_destroy($stfiface);
3291
	$tmpstfiface = pfSense_interface_create("stf");
3292
	pfSense_interface_rename($tmpstfiface, $stfiface);
3293
	pfSense_interface_flags($stfiface, IFF_LINK2);
3294
	mwexec("/sbin/ifconfig {$stfiface} inet6 {$rd6prefix}/{$rd6prefixlen}");
3295
	mwexec("/sbin/ifconfig {$stfiface} stfv4br " . escapeshellarg($wancfg['gateway-6rd']));
3296
	if ($wancfg['prefix-6rd-v4plen'] > 0 && $wancfg['prefix-6rd-v4plen'] < 32)
3297
		mwexec("/sbin/ifconfig {$stfiface} stfv4net {$ip4address}/{$wancfg['prefix-6rd-v4plen']}");
3298
	if ($g['debug'])
3299
		log_error("Created 6rd interface {$stfiface} {$rd6prefix}/{$rd6prefixlen}");
3300

    
3301
	/* write out a default router file */
3302
	file_put_contents("{$g['tmp_path']}/{$wanif}_routerv6", "{$rd6brgw}\n");
3303
	file_put_contents("{$g['tmp_path']}/{$wanif}_defaultgwv6", "{$rd6brgw}\n");
3304

    
3305
	$ip4gateway = get_interface_gateway($interface);
3306
	if (is_ipaddrv4($ip4gateway))
3307
		mwexec("/sbin/route change -host " . escapeshellarg($wancfg['gateway-6rd']) . " {$ip4gateway}");
3308

    
3309
	/* configure dependent interfaces */
3310
	if (!$g['booting'])
3311
		link_interface_to_track6($interface, "update");
3312

    
3313
	return 0;
3314
}
3315

    
3316
function interface_6to4_configure($interface = "wan", $wancfg){
3317
	global $config, $g;
3318

    
3319
	/* because this is a tunnel interface we can only function
3320
	 *	with a public IPv4 address on the interface */
3321

    
3322
	if (!is_array($wancfg))
3323
		return;
3324

    
3325
	$wanif = get_real_interface($interface);
3326
	$ip4address = find_interface_ip($wanif);
3327
	if((!is_ipaddrv4($ip4address)) || (is_private_ip($ip4address))) {
3328
		log_error("The interface IPv4 '{$ip4address}' address on interface '{$wanif}' is not public, not configuring 6RD tunnel");
3329
		return false;
3330
	}
3331

    
3332
	/* create the long prefix notation for math, save the prefix length */
3333
	$stfprefixlen = 16;
3334
	$stfprefix = Net_IPv6::uncompress("2002::");
3335
	$stfarr = explode(":", $stfprefix);
3336
	$v4prefixlen = "0";
3337

    
3338
	/* we need the hex form of the interface IPv4 address */
3339
	$ip4arr = explode(".", $ip4address);
3340
	$hexwanv4 = "";
3341
	foreach($ip4arr as $octet)
3342
		$hexwanv4 .= sprintf("%02x", $octet);
3343

    
3344
	/* we need the hex form of the broker IPv4 address */
3345
	$ip4arr = explode(".", "192.88.99.1");
3346
	$hexbrv4 = "";
3347
	foreach($ip4arr as $octet)
3348
		$hexbrv4 .= sprintf("%02x", $octet);
3349

    
3350
	/* binary presentation of the prefix for all 128 bits. */
3351
	$stfprefixbin = "";
3352
	foreach($stfarr as $element) {
3353
		$stfprefixbin .= sprintf("%016b", hexdec($element));
3354
	}
3355
	/* just save the left prefix length bits */
3356
	$stfprefixstartbin = substr($stfprefixbin, 0, $stfprefixlen);
3357

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

    
3362
	/* for the local subnet too. */
3363
	$stflanbin = substr(sprintf("%032b", hexdec($hexwanv4)), $v4prefixlen, 32);
3364
	$stflanbin = str_pad($stfprefixstartbin . $stflanbin, 128, "0", STR_PAD_RIGHT);;
3365

    
3366
	/* convert the 128 bits for the broker address back into a valid IPv6 address */
3367
	$stfbrarr = array();
3368
	$stfbrbinarr = array();
3369
	$stfbrbinarr = str_split($stfbrokerbin, 16);
3370
	foreach($stfbrbinarr as $bin)
3371
		$stfbrarr[] = dechex(bindec($bin));
3372
	$stfbrgw = Net_IPv6::compress(implode(":", $stfbrarr));
3373

    
3374
	/* convert the 128 bits for the broker address back into a valid IPv6 address */
3375
	$stflanarr = array();
3376
	$stflanbinarr = array();
3377
	$stflanbinarr = str_split($stflanbin, 16);
3378
	foreach($stflanbinarr as $bin)
3379
		$stflanarr[] = dechex(bindec($bin));
3380
	$stflanpr = Net_IPv6::compress(implode(":", $stflanarr));
3381
	$stflanarr[7] = 1;
3382
	$stflan = Net_IPv6::compress(implode(":", $stflanarr));
3383

    
3384
	/* setup the stf interface */
3385
	if (!is_module_loaded("if_stf"))
3386
		mwexec("/sbin/kldload if_stf.ko");
3387
	$stfiface = "{$interface}_stf";
3388
	if (does_interface_exist($stfiface))
3389
		pfSense_interface_destroy($stfiface);
3390
	$tmpstfiface = pfSense_interface_create("stf");
3391
	pfSense_interface_rename($tmpstfiface, $stfiface);
3392
	pfSense_interface_flags($stfiface, IFF_LINK2);
3393
	mwexec("/sbin/ifconfig {$stfiface} inet6 {$stflanpr} prefixlen 16");
3394

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

    
3398
	/* write out a default router file */
3399
	file_put_contents("{$g['tmp_path']}/{$wanif}_routerv6", "{$stfbrgw}");
3400
	file_put_contents("{$g['tmp_path']}/{$wanif}_defaultgwv6", "{$stfbrgw}");
3401

    
3402
	$ip4gateway = get_interface_gateway($interface);
3403
	if (is_ipaddrv4($ip4gateway))
3404
		mwexec("/sbin/route change -host 192.88.99.1 {$ip4gateway}");
3405

    
3406
	if (!$g['booting'])
3407
		link_interface_to_track6($interface, "update");
3408

    
3409
	return 0;
3410
}
3411

    
3412
function interface_dhcpv6_configure($interface = "wan", $wancfg) {
3413
	global $config, $g;
3414

    
3415
	if (!is_array($wancfg))
3416
		return;
3417

    
3418
	$wanif = get_real_interface($interface, "inet6");
3419
	$dhcp6cconf = "";
3420
	$dhcp6cconf .= "interface {$wanif} {\n";
3421

    
3422
	/* for SLAAC interfaces we do fire off a dhcp6 client for just our name servers */
3423
	if($wancfg['ipaddrv6'] == "slaac") {
3424
		$dhcp6cconf .= "	information-only;\n";
3425
		$dhcp6cconf .= "	request domain-name-servers;\n";
3426
		$dhcp6cconf .= "	request domain-name;\n";
3427
		$dhcp6cconf .= "	script \"{$g['varetc_path']}/dhcp6c_{$interface}_script.sh\"; # we'd like some nameservers please\n";
3428
		$dhcp6cconf .= "};\n";
3429
	} else {
3430
		/* skip address request if this is set */
3431
		if(!isset($wancfg['dhcp6prefixonly']))
3432
			$dhcp6cconf .= "        send ia-na 0;   # request stateful address\n";
3433
		$dhcp6cconf .= " 	send ia-na 0;	# request stateful address\n";
3434
		if(is_numeric($wancfg['dhcp6-ia-pd-len']))
3435
			$dhcp6cconf .= "	send ia-pd 0;	# request prefix delegation\n";
3436

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

    
3441
		$dhcp6cconf .= "};\n";
3442

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

    
3446
		if(is_numeric($wancfg['dhcp6-ia-pd-len'])) {
3447
			/* Setup the prefix delegation */
3448
			$dhcp6cconf .= "id-assoc pd 0 {\n";
3449
			$iflist = link_interface_to_track6($interface);
3450
			foreach ($iflist as $friendly => $ifcfg) {
3451
				if (is_numeric($ifcfg['track6-prefix-id'])) {
3452
					if ($g['debug'])
3453
						log_error("setting up $ifdescr - {$ifcfg['track6-prefix-id']}");
3454
					$realif = get_real_interface($friendly);
3455
					$dhcp6cconf .= "	prefix-interface {$realif} {\n";
3456
					$dhcp6cconf .= "		sla-id {$ifcfg['track6-prefix-id']};\n";
3457
					$dhcp6cconf .= "		sla-len {$wancfg['dhcp6-ia-pd-len']};\n";
3458
					$dhcp6cconf .= "	};\n";
3459
				}
3460
			}
3461
			unset($iflist, $ifcfg);
3462
			$dhcp6cconf .= "};\n";
3463
		}
3464
	}
3465

    
3466
	// DHCP6 Config File Advanced
3467
	if ($wancfg['adv_dhcp6_config_advanced']) { $dhcp6cconf = DHCP6_Config_File_Advanced($interface, $wancfg, $wanif); }
3468

    
3469
	// DHCP6 Config File Override
3470
	if ($wancfg['adv_dhcp6_config_file_override']) { $dhcp6cconf = DHCP6_Config_File_Override($wancfg, $wanif); }
3471

    
3472
	/* wide-dhcp6c works for now. */
3473
	if (!@file_put_contents("{$g['varetc_path']}/dhcp6c_{$interface}.conf", $dhcp6cconf)) {
3474
		printf("Error: cannot open dhcp6c_{$interface}.conf in interface_dhcpv6_configure() for writing.\n");
3475
		unset($dhcp6cconf);
3476
		return 1;
3477
	}
3478
	unset($dhcp6cconf);
3479

    
3480
	$dhcp6cscript = "#!/bin/sh\n";
3481
	$dhcp6cscript .= "# This shell script launches /etc/rc.newwanipv6 with a interface argument.\n";
3482
	$dhcp6cscript .= "/etc/rc.newwanipv6 {$wanif} \n";
3483
	/* Add wide-dhcp6c shell script here. Because we can not pass a argument to it. */
3484
	if (!@file_put_contents("{$g['varetc_path']}/dhcp6c_{$interface}_script.sh", $dhcp6cscript)) {
3485
		printf("Error: cannot open dhcp6c_{$interface}_script.sh in interface_dhcpv6_configure() for writing.\n");
3486
		unset($dhcp6cscript);
3487
		return 1;
3488
	}
3489
	unset($dhcp6cscript);
3490
	@chmod("{$g['varetc_path']}/dhcp6c_{$interface}_script.sh", 0755);
3491

    
3492
	$rtsoldscript = "#!/bin/sh\n";
3493
	$rtsoldscript .= "# This shell script launches dhcp6c and configured gateways for this interface.\n";
3494
	$rtsoldscript .= "echo $2 > {$g['tmp_path']}/{$wanif}_routerv6\n";
3495
	$rtsoldscript .= "echo $2 > {$g['tmp_path']}/{$wanif}_defaultgwv6\n";
3496
	$rtsoldscript .= "if [ -f {$g['varrun_path']}/dhcp6c_{$wanif}.pid ]; then\n";
3497
	$rtsoldscript .= "\t/bin/pkill -F {$g['varrun_path']}/dhcp6c_{$wanif}.pid\n";
3498
	$rtsoldscript .= "\t/bin/sleep 1\n";
3499
	$rtsoldscript .= "fi\n";
3500
	$rtsoldscript .= "/usr/local/sbin/dhcp6c -d -c {$g['varetc_path']}/dhcp6c_{$interface}.conf -p {$g['varrun_path']}/dhcp6c_{$wanif}.pid {$wanif}\n";
3501
	/* Add wide-dhcp6c shell script here. Because we can not pass a argument to it. */
3502
	if (!@file_put_contents("{$g['varetc_path']}/rtsold_{$wanif}_script.sh", $rtsoldscript)) {
3503
		printf("Error: cannot open rtsold_{$interface}_script.sh in interface_dhcpv6_configure() for writing.\n");
3504
		unset($rtsoldscript);
3505
		return 1;
3506
	}
3507
	unset($rtsoldscript);
3508
	@chmod("{$g['varetc_path']}/rtsold_{$wanif}_script.sh", 0755);
3509

    
3510
	/* accept router advertisements for this interface */
3511
	mwexec("/sbin/sysctl -w net.inet6.ip6.accept_rtadv=1");
3512
	log_error("Accept router advertisements on interface {$wanif} ");
3513
	mwexec("/sbin/ifconfig {$wanif} inet6 accept_rtadv");
3514

    
3515
	/* fire up rtsold for IPv6 RAs first, this backgrounds immediately. It will call dhcp6c */
3516
	if (isvalidpid("{$g['varrun_path']}/rtsold_{$wanif}.pid")) {
3517
		killbypid("{$g['varrun_path']}/rtsold_{$wanif}.pid");
3518
		sleep(2);
3519
	}
3520
	mwexec("/usr/sbin/rtsold -1 -p {$g['varrun_path']}/rtsold_{$wanif}.pid -O {$g['varetc_path']}/rtsold_{$wanif}_script.sh {$wanif}");
3521

    
3522
	/* NOTE: will be called from rtsold invoked script
3523
	 * link_interface_to_track6($interface, "update");
3524
	 */
3525

    
3526
	return 0;
3527
}
3528

    
3529
function DHCP6_Config_File_Advanced($interface, $wancfg, $wanif) {
3530
	global $g;
3531

    
3532
	$send_options = "";
3533
	if ($wancfg['adv_dhcp6_interface_statement_send_options'] != '') {
3534
		$options = split(",", $wancfg['adv_dhcp6_interface_statement_send_options']);
3535
		foreach ($options as $option) {
3536
			$send_options .= "\tsend " . trim($option) . ";\n";
3537
		}
3538
	}
3539

    
3540
	$request_options = "";
3541
	if ($wancfg['adv_dhcp6_interface_statement_request_options'] != '') {
3542
		$options = split(",", $wancfg['adv_dhcp6_interface_statement_request_options']);
3543
		foreach ($options as $option) {
3544
			$request_options .= "\trequest " . trim($option) . ";\n";
3545
		}
3546
	}
3547

    
3548
	$information_only = "";
3549
	if ($wancfg['adv_dhcp6_interface_statement_information_only_enable'] != '') 
3550
		$information_only = "\tinformation-only;\n";
3551

    
3552
	$script = "\tscript \"{$g['varetc_path']}/dhcp6c_{$interface}_script.sh\";\n";
3553
	if ($wancfg['adv_dhcp6_interface_statement_script'] != '')
3554
		$script = "\tscript \"{$wancfg['adv_dhcp6_interface_statement_script']}\";\n";
3555

    
3556
	$interface_statement  = "interface";
3557
	$interface_statement .= " {$wanif}";
3558
	$interface_statement .= " {\n";
3559
	$interface_statement .= "$send_options";
3560
	$interface_statement .= "$request_options";
3561
	$interface_statement .= "$information_only";
3562
	$interface_statement .= "$script";
3563
	$interface_statement .= "};\n";
3564

    
3565
	$id_assoc_statement_address = "";
3566
	if ($wancfg['adv_dhcp6_id_assoc_statement_address_enable'] != '') {
3567
		$id_assoc_statement_address .= "id-assoc";
3568
		$id_assoc_statement_address .= " na";
3569
		if (is_numeric($wancfg['adv_dhcp6_id_assoc_statement_address_id'])) 
3570
			$id_assoc_statement_address .= " {$wancfg['adv_dhcp6_id_assoc_statement_address_id']}";
3571
		$id_assoc_statement_address .= " { ";
3572

    
3573
		if ( ($wancfg['adv_dhcp6_id_assoc_statement_address'] != '') && 
3574
			 (is_numeric($wancfg['adv_dhcp6_id_assoc_statement_address_pltime']) || 
3575
			 ($wancfg['adv_dhcp6_id_assoc_statement_address_pltime'] == 'infinity')) ) {
3576
			$id_assoc_statement_address .= "\n\taddress";
3577
			$id_assoc_statement_address .= " {$wancfg['adv_dhcp6_id_assoc_statement_address']}";
3578
			$id_assoc_statement_address .= " {$wancfg['adv_dhcp6_id_assoc_statement_address_pltime']}";
3579
			if ( (is_numeric($wancfg['adv_dhcp6_id_assoc_statement_address_vltime'])) || 
3580
							($wancfg['adv_dhcp6_id_assoc_statement_address_vltime'] == 'infinity') ) 
3581
				$id_assoc_statement_address .= " {$wancfg['adv_dhcp6_id_assoc_statement_address_vltime']}";
3582
			$id_assoc_statement_address .= ";\n";
3583
		}
3584

    
3585
		$id_assoc_statement_address  .= "};\n";
3586
	}
3587

    
3588
	$id_assoc_statement_prefix = "";
3589
	if ($wancfg['adv_dhcp6_id_assoc_statement_prefix_enable'] != '') {
3590
		$id_assoc_statement_prefix .= "id-assoc";
3591
		$id_assoc_statement_prefix .= " pd";
3592
		if (is_numeric($wancfg['adv_dhcp6_id_assoc_statement_prefix_id'])) 
3593
			$id_assoc_statement_prefix .= " {$wancfg['adv_dhcp6_id_assoc_statement_prefix_id']}";
3594
		$id_assoc_statement_prefix .= " { ";
3595

    
3596
		if ( ($wancfg['adv_dhcp6_id_assoc_statement_prefix'] != '') && 
3597
			 (is_numeric($wancfg['adv_dhcp6_id_assoc_statement_prefix_pltime']) || 
3598
			 ($wancfg['adv_dhcp6_id_assoc_statement_prefix_pltime'] == 'infinity')) ) {
3599
			$id_assoc_statement_prefix .= "\n\tprefix";
3600
			$id_assoc_statement_prefix .= " {$wancfg['adv_dhcp6_id_assoc_statement_prefix']}";
3601
			$id_assoc_statement_prefix .= " {$wancfg['adv_dhcp6_id_assoc_statement_prefix_pltime']}";
3602
			if ( (is_numeric($wancfg['adv_dhcp6_id_assoc_statement_prefix_vltime'])) || 
3603
						  ($wancfg['adv_dhcp6_id_assoc_statement_prefix_vltime'] == 'infinity') ) 
3604
				$id_assoc_statement_prefix .= " {$wancfg['adv_dhcp6_id_assoc_statement_prefix_vltime']}";
3605
			$id_assoc_statement_prefix .= ";";
3606
		}
3607

    
3608
		if (is_numeric($wancfg['adv_dhcp6_prefix_interface_statement_sla_id'])) {
3609
			$id_assoc_statement_prefix .= "\n\tprefix-interface";
3610
			$id_assoc_statement_prefix .= " {$wanif}";
3611
			$id_assoc_statement_prefix .= " {\n";
3612
			$id_assoc_statement_prefix .= "\t\tsla-id {$wancfg['adv_dhcp6_prefix_interface_statement_sla_id']};\n";
3613
			if ( ($wancfg['adv_dhcp6_prefix_interface_statement_sla_len'] >= 0) && 
3614
				 ($wancfg['adv_dhcp6_prefix_interface_statement_sla_len'] <= 128) ) 
3615
				 $id_assoc_statement_prefix .= "\t\tsla-len {$wancfg['adv_dhcp6_prefix_interface_statement_sla_len']};\n";
3616
			$id_assoc_statement_prefix .= "\t};";
3617
		}
3618

    
3619
		if ( ($wancfg['adv_dhcp6_id_assoc_statement_prefix'] != '') || 
3620
			 (is_numeric($wancfg['adv_dhcp6_prefix_interface_statement_sla_id'])) ) { 
3621
			$id_assoc_statement_prefix .= "\n";
3622
		}
3623

    
3624
		$id_assoc_statement_prefix  .= "};\n";
3625
	}
3626

    
3627
	$authentication_statement = "";
3628
	if ( ($wancfg['adv_dhcp6_authentication_statement_authname'] != '') && 
3629
		 ($wancfg['adv_dhcp6_authentication_statement_protocol'] == 'delayed') ) {
3630
		$authentication_statement .= "authentication";
3631
		$authentication_statement .= " {$wancfg['adv_dhcp6_authentication_statement_authname']}";
3632
		$authentication_statement .= " {\n";
3633
		$authentication_statement .= "\tprotocol {$wancfg['adv_dhcp6_authentication_statement_protocol']};\n";
3634
		if (preg_match("/(hmac(-)?md5)||(HMAC(-)?MD5)/", $wancfg['adv_dhcp6_authentication_statement_algorithm'])) 
3635
			$authentication_statement .= "\talgorithm {$wancfg['adv_dhcp6_authentication_statement_algorithm']};\n";
3636
		if ($wancfg['adv_dhcp6_authentication_statement_rdm'] == 'monocounter') 
3637
			$authentication_statement .= "\trdm {$wancfg['adv_dhcp6_authentication_statement_rdm']};\n";
3638
		$authentication_statement .= "};\n";
3639
	}
3640

    
3641
	$key_info_statement = "";
3642
	if ( ($wancfg['adv_dhcp6_key_info_statement_keyname'] != '') && 
3643
		 ($wancfg['adv_dhcp6_key_info_statement_realm'] != '') && 
3644
		 (is_numeric($wancfg['adv_dhcp6_key_info_statement_keyid'])) && 
3645
		 ($wancfg['adv_dhcp6_key_info_statement_secret'] != '') ) {
3646
		$key_info_statement .= "keyinfo";
3647
		$key_info_statement .= " {$wancfg['adv_dhcp6_key_info_statement_keyname']}";
3648
		$key_info_statement .= " {\n";
3649
		$key_info_statement .= "\trealm \"{$wancfg['adv_dhcp6_key_info_statement_realm']}\";\n";
3650
		$key_info_statement .= "\tkeyid {$wancfg['adv_dhcp6_key_info_statement_keyid']};\n";
3651
		$key_info_statement .= "\tsecret \"{$wancfg['adv_dhcp6_key_info_statement_secret']}\";\n";
3652
		if (preg_match("/((([0-9]{4}-)?[0-9]{2}[0-9]{2} )?[0-9]{2}:[0-9]{2})||(foreever)/", $wancfg['adv_dhcp6_key_info_statement_expire'])) 
3653
			$key_info_statement .= "\texpire \"{$wancfg['adv_dhcp6_key_info_statement_expire']}\";\n";
3654
		$key_info_statement .= "};\n";
3655
	}
3656

    
3657
	$dhcp6cconf  = $interface_statement;
3658
	$dhcp6cconf .= $id_assoc_statement_address;
3659
	$dhcp6cconf .= $id_assoc_statement_prefix;
3660
	$dhcp6cconf .= $authentication_statement;
3661
	$dhcp6cconf .= $key_info_statement;
3662

    
3663
	$dhcp6cconf = DHCP6_Config_File_Substitutions($wancfg, $wanif, $dhcp6cconf);
3664

    
3665
	return $dhcp6cconf;
3666
}
3667

    
3668

    
3669
function DHCP6_Config_File_Override($wancfg, $wanif) {
3670

    
3671
	$dhcp6cconf = file_get_contents($wancfg['adv_dhcp6_config_file_override_path']);
3672
	$dhcp6cconf = DHCP6_Config_File_Substitutions($wancfg, $wanif, $dhcp6cconf);
3673

    
3674
	return $dhcp6cconf;
3675
}
3676

    
3677

    
3678
function DHCP6_Config_File_Substitutions($wancfg, $wanif, $dhcp6cconf) {
3679

    
3680
	$dhcp6cconf = DHCP_Config_File_Substitutions($wancfg, $wanif, $dhcp6cconf);
3681

    
3682
	return $dhcp6cconf;
3683
}
3684

    
3685

    
3686
function interface_dhcp_configure($interface = "wan") {
3687
	global $config, $g;
3688

    
3689
	$wancfg = $config['interfaces'][$interface];
3690
	$wanif = $wancfg['if'];
3691
	if (empty($wancfg))
3692
		$wancfg = array();
3693

    
3694
	/* generate dhclient_wan.conf */
3695
	$fd = fopen("{$g['varetc_path']}/dhclient_{$interface}.conf", "w");
3696
	if (!$fd) {
3697
		printf(printf(gettext("Error: cannot open dhclient_%s.conf in interface_dhcp_configure() for writing.%s"), $interface, "\n"));
3698
		return 1;
3699
	}
3700

    
3701
	if ($wancfg['dhcphostname']) {
3702
		$dhclientconf_hostname = "send dhcp-client-identifier \"{$wancfg['dhcphostname']}\";\n";
3703
		$dhclientconf_hostname .= "\tsend host-name \"{$wancfg['dhcphostname']}\";\n";
3704
	} else {
3705
		$dhclientconf_hostname = "";
3706
	}
3707

    
3708
	$wanif = get_real_interface($interface);
3709
	if (empty($wanif)) {
3710
		log_error(sprintf(gettext("Invalid interface \"%s\" in interface_dhcp_configure()"), $interface));
3711
		return 0;
3712
	}
3713
	$dhclientconf = "";
3714

    
3715
	$dhclientconf .= <<<EOD
3716
interface "{$wanif}" {
3717
timeout 60;
3718
retry 15;
3719
select-timeout 0;
3720
initial-interval 1;
3721
	{$dhclientconf_hostname}
3722
	script "/sbin/dhclient-script";
3723
EOD;
3724

    
3725
if (is_ipaddrv4($wancfg['dhcprejectfrom'])) {
3726
	$dhclientconf .= <<<EOD
3727

    
3728
	reject {$wancfg['dhcprejectfrom']};
3729
EOD;
3730
}
3731
	$dhclientconf .= <<<EOD
3732

    
3733
}
3734

    
3735
EOD;
3736

    
3737
	// DHCP Config File Advanced
3738
	if ($wancfg['adv_dhcp_config_advanced']) { $dhclientconf = DHCP_Config_File_Advanced($interface, $wancfg, $wanif); }
3739

    
3740
if(is_ipaddr($wancfg['alias-address'])) {
3741
	$subnetmask = gen_subnet_mask($wancfg['alias-subnet']);
3742
	$dhclientconf .= <<<EOD
3743
alias {
3744
	interface  "{$wanif}";
3745
	fixed-address {$wancfg['alias-address']};
3746
	option subnet-mask {$subnetmask};
3747
}
3748

    
3749
EOD;
3750
}
3751

    
3752
	// DHCP Config File Override
3753
	if ($wancfg['adv_dhcp_config_file_override']) { $dhclientconf = DHCP_Config_File_Override($wancfg, $wanif); }
3754

    
3755
	fwrite($fd, $dhclientconf);
3756
	fclose($fd);
3757

    
3758
	/* bring wan interface up before starting dhclient */
3759
	if($wanif)
3760
		interfaces_bring_up($wanif);
3761
	else
3762
		log_error(printf(gettext("Could not bring up %s interface in interface_dhcp_configure()"), $wanif));
3763

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

    
3767
	return 0;
3768
}
3769

    
3770
function DHCP_Config_File_Advanced($interface, $wancfg, $wanif) {
3771

    
3772
	$hostname = "";
3773
	if ($wancfg['dhcphostname'] != '') {
3774
		$hostname = "\tsend host-name \"{$wancfg['dhcphostname']}\";\n";
3775
	}
3776

    
3777
	/* DHCP Protocol Timings */
3778
	$protocol_timings = array ('adv_dhcp_pt_timeout' => "timeout", 'adv_dhcp_pt_retry' => "retry", 'adv_dhcp_pt_select_timeout' => "select-timeout", 'adv_dhcp_pt_reboot' => "reboot", 'adv_dhcp_pt_backoff_cutoff' => "backoff-cutoff", 'adv_dhcp_pt_initial_interval' => "initial-interval");
3779
	foreach ($protocol_timings as $Protocol_Timing => $PT_Name) {
3780
		$pt_variable = "{$Protocol_Timing}";
3781
		${$pt_variable} = "";
3782
		if ($wancfg[$Protocol_Timing] != "") {
3783
			${$pt_variable} = "{$PT_Name} {$wancfg[$Protocol_Timing]};\n";
3784
		}
3785
	}
3786

    
3787
	$send_options = "";
3788
	if ($wancfg['adv_dhcp_send_options'] != '') {
3789
		$options = split(",", $wancfg['adv_dhcp_send_options']);
3790
		foreach ($options as $option) {
3791
			$send_options .= "\tsend " . trim($option) . ";\n";
3792
		}
3793
	}
3794

    
3795
	$request_options = "";
3796
	if ($wancfg['adv_dhcp_request_options'] != '') {
3797
		$request_options = "\trequest {$wancfg['adv_dhcp_request_options']};\n";
3798
	}
3799

    
3800
	$required_options = "";
3801
	if ($wancfg['adv_dhcp_required_options'] != '') {
3802
		$required_options = "\trequire {$wancfg['adv_dhcp_required_options']};\n";
3803
	}
3804

    
3805
	$option_modifiers = "";
3806
	if ($wancfg['adv_dhcp_option_modifiers'] != '') {
3807
		$modifiers = split(",", $wancfg['adv_dhcp_option_modifiers']);
3808
		foreach ($modifiers as $modifier) {
3809
			$option_modifiers .= "\t" . trim($modifier) . ";\n";
3810
		}
3811
	}
3812

    
3813
 	$dhclientconf  = "interface \"{$wanif}\" {\n";
3814
 	$dhclientconf .= "\n";
3815
 	$dhclientconf .= "# DHCP Protocol Timing Values\n";
3816
 	$dhclientconf .= "{$adv_dhcp_pt_timeout}";
3817
 	$dhclientconf .= "{$adv_dhcp_pt_retry}";
3818
 	$dhclientconf .= "{$adv_dhcp_pt_select_timeout}";
3819
 	$dhclientconf .= "{$adv_dhcp_pt_reboot}";
3820
 	$dhclientconf .= "{$adv_dhcp_pt_backoff_cutoff}";
3821
 	$dhclientconf .= "{$adv_dhcp_pt_initial_interval}";
3822
 	$dhclientconf .= "\n";
3823
 	$dhclientconf .= "# DHCP Protocol Options\n";
3824
 	$dhclientconf .= "{$hostname}";
3825
 	$dhclientconf .= "{$send_options}";
3826
 	$dhclientconf .= "{$request_options}";
3827
 	$dhclientconf .= "{$required_options}";
3828
 	$dhclientconf .= "{$option_modifiers}";
3829
 	$dhclientconf .= "\n";
3830
 	$dhclientconf .= "\tscript \"/sbin/dhclient-script\";\n";
3831
 	$dhclientconf .= "}\n";
3832

    
3833
	$dhclientconf = DHCP_Config_File_Substitutions($wancfg, $wanif, $dhclientconf);
3834

    
3835
	return $dhclientconf;
3836
}
3837

    
3838

    
3839
function DHCP_Config_File_Override($wancfg, $wanif) {
3840

    
3841
	$dhclientconf = file_get_contents($wancfg['adv_dhcp_config_file_override_path']);
3842
	$dhclientconf = DHCP_Config_File_Substitutions($wancfg, $wanif, $dhclientconf);
3843

    
3844
	return $dhclientconf;
3845
}
3846

    
3847

    
3848
function DHCP_Config_File_Substitutions($wancfg, $wanif, $dhclientconf) {
3849

    
3850
	/* Apply Interface Substitutions */
3851
	$dhclientconf = str_replace("{interface}", "{$wanif}", $dhclientconf);
3852

    
3853
	/* Apply Hostname Substitutions */
3854
	$dhclientconf = str_replace("{hostname}", $wancfg['dhcphostname'], $dhclientconf);
3855

    
3856
	/* Arrays of MAC Address Types, Cases, Delimiters */
3857
	/* ASCII or HEX, Upper or Lower Case, Various Delimiters (none, space, colon, hyphen, period) */
3858
	$various_mac_types      = array("mac_addr_ascii", "mac_addr_hex");
3859
	$various_mac_cases      = array("U", "L");
3860
	$various_mac_delimiters = array("", " ", ":", "-", ".");
3861

    
3862
	/* Apply MAC Address Substitutions */
3863
	foreach ($various_mac_types as $various_mac_type) {
3864
		foreach ($various_mac_cases as $various_mac_case) {
3865
			foreach ($various_mac_delimiters as $various_mac_delimiter) {
3866

    
3867
				$res = stripos($dhclientconf, $various_mac_type . $various_mac_case . $various_mac_delimiter);
3868
				if ($res !== false) {
3869

    
3870
					/* Get MAC Address as ASCII String With Colon (:) Celimiters */
3871
					if ("$various_mac_case" == "U") $dhcpclientconf_mac = strtoupper(get_interface_mac($wanif));
3872
					if ("$various_mac_case" == "L") $dhcpclientconf_mac = strtolower(get_interface_mac($wanif));
3873

    
3874
					if ("$various_mac_type" == "mac_addr_hex") {
3875
						/* Convert MAC ascii string to HEX with colon (:) delimiters. */
3876
						$dhcpclientconf_mac = str_replace(":", "", $dhcpclientconf_mac);
3877
						$dhcpclientconf_mac_hex = "";
3878
						$delimiter = "";
3879
						for($i = 0; $i < strlen($dhcpclientconf_mac); $i++) {
3880
							$dhcpclientconf_mac_hex .= $delimiter. bin2hex($dhcpclientconf_mac[$i]);
3881
							$delimiter = ":";
3882
						}
3883
						$dhcpclientconf_mac = $dhcpclientconf_mac_hex;
3884
					}
3885

    
3886
					/* MAC Address Delimiter Substitutions */
3887
					$dhcpclientconf_mac = str_replace(":", $various_mac_delimiter, $dhcpclientconf_mac);
3888

    
3889
					/* Apply MAC Address Substitutions */
3890
					$dhclientconf = str_replace("{" . $various_mac_type . $various_mac_case . $various_mac_delimiter . "}", $dhcpclientconf_mac, $dhclientconf);
3891
				}
3892
			}
3893
		}
3894
	}
3895

    
3896
	return $dhclientconf;
3897
}
3898

    
3899
function interfaces_group_setup() {
3900
	global $config;
3901

    
3902
	if (!is_array($config['ifgroups']['ifgroupentry']))
3903
		return;
3904

    
3905
	foreach ($config['ifgroups']['ifgroupentry'] as $groupar)
3906
		interface_group_setup($groupar);
3907

    
3908
	return;
3909
}
3910

    
3911
function interface_group_setup(&$groupname /* The parameter is an array */) {
3912
	global $config;
3913

    
3914
	if (!is_array($groupname))
3915
		return;
3916
	$members = explode(" ", $groupname['members']);
3917
	foreach($members as $ifs) {
3918
		$realif = get_real_interface($ifs);
3919
		if ($realif)
3920
			mwexec("/sbin/ifconfig {$realif} group {$groupname['ifname']}");
3921
	}
3922

    
3923
	return;
3924
}
3925

    
3926
function is_interface_group($if) {
3927
	global $config;
3928

    
3929
	if (is_array($config['ifgroups']['ifgroupentry']))
3930
		foreach ($config['ifgroups']['ifgroupentry'] as $groupentry) {
3931
			if ($groupentry['ifname'] === $if)
3932
				return true;
3933
		}
3934

    
3935
	return false;
3936
}
3937

    
3938
function interface_group_add_member($interface, $groupname) {
3939
	$interface = get_real_interface($interface);
3940
	mwexec("/sbin/ifconfig {$interface} group {$groupname}", true);
3941
}
3942

    
3943
/* COMPAT Function */
3944
function convert_friendly_interface_to_real_interface_name($interface) {
3945
	return get_real_interface($interface);
3946
}
3947

    
3948
/* COMPAT Function */
3949
function get_real_wan_interface($interface = "wan") {
3950
	return get_real_interface($interface);
3951
}
3952

    
3953
/* COMPAT Function */
3954
function get_current_wan_address($interface = "wan") {
3955
	return get_interface_ip($interface);
3956
}
3957

    
3958
/*
3959
 * convert_real_interface_to_friendly_interface_name($interface): convert fxp0 -> wan, etc.
3960
 */
3961
function convert_real_interface_to_friendly_interface_name($interface = "wan") {
3962
	global $config;
3963

    
3964
	if (stristr($interface, "_vip")) {
3965
		foreach ($config['virtualip']['vip'] as $counter => $vip) {
3966
			if ($vip['mode'] == "carp")  {
3967
				if ($interface == "{$vip['interface']}_vip{$vip['vhid']}")
3968
					return $vip['interface'];
3969
			}
3970
		}
3971
	}
3972

    
3973
	/* XXX: For speed reasons reference directly the interface array */
3974
	$ifdescrs = &$config['interfaces'];
3975
	//$ifdescrs = get_configured_interface_list(false, true);
3976

    
3977
	foreach ($ifdescrs as $if => $ifname) {
3978
		if ($if == $interface || $config['interfaces'][$if]['if'] == $interface)
3979
			return $if;
3980

    
3981
		if (get_real_interface($if) == $interface)
3982
			return $if;
3983

    
3984
		// XXX: This case doesn't work anymore (segfaults - recursion?) - should be replaced with something else or just removed.
3985
		//      Not to be replaced with get_real_interface - causes slow interface listings here because of recursion!
3986
		/*
3987
		$int = get_parent_interface($if);
3988
		if ($int[0] == $interface)
3989
			return $ifname;
3990
		*/
3991
	}
3992

    
3993
	return NULL;
3994
}
3995

    
3996
/* attempt to resolve interface to friendly descr */
3997
function convert_friendly_interface_to_friendly_descr($interface) {
3998
	global $config;
3999

    
4000
	switch ($interface) {
4001
	case "l2tp":
4002
		$ifdesc = "L2TP";
4003
		break;
4004
	case "pptp":
4005
		$ifdesc = "PPTP";
4006
		break;
4007
	case "pppoe":
4008
		$ifdesc = "PPPoE";
4009
		break;
4010
	case "openvpn":
4011
		$ifdesc = "OpenVPN";
4012
		break;
4013
	case "enc0":
4014
	case "ipsec":
4015
		$ifdesc = "IPsec";
4016
		break;
4017
	default:
4018
		if (isset($config['interfaces'][$interface])) {
4019
			if (empty($config['interfaces'][$interface]['descr']))
4020
				$ifdesc = strtoupper($interface);
4021
			else
4022
				$ifdesc = strtoupper($config['interfaces'][$interface]['descr']);
4023
			break;
4024
		} else if (stristr($interface, "_vip")) {
4025
			if (is_array($config['virtualip']['vip'])) {
4026
				foreach ($config['virtualip']['vip'] as $counter => $vip) {
4027
					if ($vip['mode'] == "carp")  {
4028
						if ($interface == "{$vip['interface']}_vip{$vip['vhid']}")
4029
							return "{$vip['subnet']} - {$vip['descr']}";
4030
					}
4031
				}
4032
			}
4033
		} else {
4034
			/* if list */
4035
			$ifdescrs = get_configured_interface_with_descr(false, true);
4036
			foreach ($ifdescrs as $if => $ifname) {
4037
				if ($if == $interface || $ifname == $interface)
4038
					return $ifname;
4039
			}
4040
		}
4041
		break;
4042
	}
4043

    
4044
	return $ifdesc;
4045
}
4046

    
4047
function convert_real_interface_to_friendly_descr($interface) {
4048
	global $config;
4049

    
4050
	$ifdesc = convert_real_interface_to_friendly_interface_name("{$interface}");
4051

    
4052
	if ($ifdesc) {
4053
		$iflist = get_configured_interface_with_descr(false, true);
4054
		return $iflist[$ifdesc];
4055
	}
4056

    
4057
	return $interface;
4058
}
4059

    
4060
/*
4061
 *  get_parent_interface($interface):
4062
 *			--returns the (real or virtual) parent interface(s) array for a given interface friendly name (i.e. wan)
4063
 *				or virtual interface (i.e. vlan)
4064
 *				(We need array because MLPPP and bridge interfaces have more than one parent.)
4065
 *			-- returns $interface passed in if $interface parent is not found
4066
 *			-- returns empty array if an invalid interface is passed
4067
 *	(Only handles ppps and vlans now.)
4068
 */
4069
function get_parent_interface($interface) {
4070
	global $config;
4071

    
4072
	$parents = array();
4073
	//Check that we got a valid interface passed
4074
	$realif = get_real_interface($interface);
4075
	if ($realif == NULL)
4076
		return $parents;
4077

    
4078
	// If we got a real interface, find it's friendly assigned name
4079
	$interface = convert_real_interface_to_friendly_interface_name($interface);
4080

    
4081
	if (!empty($interface) && isset($config['interfaces'][$interface])) {
4082
		$ifcfg = $config['interfaces'][$interface];
4083
		switch ($ifcfg['ipaddr']) {
4084
			case "ppp":
4085
			case "pppoe":
4086
			case "pptp":
4087
			case "l2tp":
4088
				if (empty($parents))
4089
					if (is_array($config['ppps']['ppp']))
4090
						foreach ($config['ppps']['ppp'] as $pppidx => $ppp) {
4091
							if ($ifcfg['if'] == $ppp['if']) {
4092
								$ports = explode(',', $ppp['ports']);
4093
								foreach ($ports as $pid => $parent_if)
4094
									$parents[$pid] = get_real_interface($parent_if);
4095
								break;
4096
							}
4097
						}
4098
				break;
4099
			case "dhcp":
4100
			case "static":
4101
			default:
4102
				// Handle _vlans
4103
				if (stristr($realif,"_vlan"))
4104
					if (is_array($config['vlans']['vlan']))
4105
						foreach ($config['vlans']['vlan'] as $vlanidx => $vlan)
4106
							if ($ifcfg['if'] == $vlan['vlanif']){
4107
								$parents[0] = $vlan['if'];
4108
								break;
4109
							}
4110
				break;
4111
		}
4112
	}
4113

    
4114
	if (empty($parents))
4115
		$parents[0] = $realif;
4116

    
4117
	return $parents;
4118
}
4119

    
4120
function interface_is_wireless_clone($wlif) {
4121
	if(!stristr($wlif, "_wlan")) {
4122
		return false;
4123
	} else {
4124
		return true;
4125
	}
4126
}
4127

    
4128
function interface_get_wireless_base($wlif) {
4129
	if(!stristr($wlif, "_wlan")) {
4130
		return $wlif;
4131
	} else {
4132
		return substr($wlif, 0, stripos($wlif, "_wlan"));
4133
	}
4134
}
4135

    
4136
function interface_get_wireless_clone($wlif) {
4137
	if(!stristr($wlif, "_wlan")) {
4138
		return $wlif . "_wlan0";
4139
	} else {
4140
		return $wlif;
4141
	}
4142
}
4143

    
4144
function get_real_interface($interface = "wan", $family = "all") {
4145
	global $config, $g;
4146

    
4147
	$wanif = NULL;
4148

    
4149
	switch ($interface) {
4150
	case "l2tp":
4151
		$wanif = "l2tp";
4152
		break;
4153
	case "pptp":
4154
		$wanif = "pptp";
4155
		break;
4156
	case "pppoe":
4157
		$wanif = "pppoe";
4158
		break;
4159
	case "openvpn":
4160
		$wanif = "openvpn";
4161
		break;
4162
	case "ipsec":
4163
	case "enc0":
4164
		$wanif = "enc0";
4165
		break;
4166
	case "ppp":
4167
		$wanif = "ppp";
4168
		break;
4169
	default:
4170
		// If a real interface was alread passed simply
4171
		// pass the real interface back.  This encourages
4172
		// the usage of this function in more cases so that
4173
		// we can combine logic for more flexibility.
4174
		if(does_interface_exist($interface)) {
4175
			$wanif = $interface;
4176
			break;
4177
		}
4178

    
4179
		if (empty($config['interfaces'][$interface]))
4180
			break;
4181

    
4182
		$cfg = &$config['interfaces'][$interface];
4183

    
4184
		if ($family == "inet6") {
4185
			switch ($cfg['ipaddrv6']) {
4186
			case "6rd":
4187
			case "6to4":
4188
				$wanif = "{$interface}_stf";
4189
				break;
4190
			default:
4191
				if( is_array($cfg['wireless']) || preg_match($g['wireless_regex'], $cfg['if']))
4192
					$wanif = interface_get_wireless_clone($cfg['if']);
4193
				else
4194
					$wanif = $cfg['if'];
4195
				break;
4196
			}
4197
		} else {
4198
			// Wireless cloned NIC support (FreeBSD 8+)
4199
			// interface name format: $parentnic_wlanparentnic#
4200
			// example: ath0_wlan0
4201
			if( is_array($cfg['wireless']) || preg_match($g['wireless_regex'], $cfg['if']))
4202
				$wanif = interface_get_wireless_clone($cfg['if']);
4203
			else
4204
				$wanif = $cfg['if'];
4205
		}
4206
		break;
4207
	}
4208

    
4209
	return $wanif;
4210
}
4211

    
4212
/* Guess the physical interface by providing a IP address */
4213
function guess_interface_from_ip($ipaddress) {
4214
	if(! is_ipaddr($ipaddress)) {
4215
		return false;
4216
	}
4217
	if(is_ipaddrv4($ipaddress)) {
4218
		/* create a route table we can search */
4219
		exec("netstat -rnWf inet", $output, $ret);
4220
		foreach($output as $line) {
4221
			if(preg_match("/^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\/[0-9]+[ ]+link[#]/", $line)) {
4222
				$fields = preg_split("/[ ]+/", $line);
4223
				if(ip_in_subnet($ipaddress, $fields[0])) {
4224
					return $fields[6];
4225
				}
4226
			}
4227
		}
4228
	}
4229
	/* FIXME: This works from cursory testing, regexp might need fine tuning */
4230
	if(is_ipaddrv6($ipaddress)) {
4231
		/* create a route table we can search */
4232
		exec("netstat -rnWf inet6", $output, $ret);
4233
		foreach($output as $line) {
4234
			if(preg_match("/[0-9a-f]+[:]+[0-9a-f]+[:]+[\/][0-9]+/", $line)) {
4235
				$fields = preg_split("/[ ]+/", $line);
4236
				if(ip_in_subnet($ipaddress, $fields[0])) {
4237
					return $fields[6];
4238
				}
4239
			}
4240
		}
4241
	}
4242
	$ret = exec_command("/sbin/route -n get {$ipaddress} | /usr/bin/awk '/interface/ { print \$2; };'");
4243
	if(empty($ret)) {
4244
		return false;
4245
	}
4246
	return $ret;
4247
}
4248

    
4249
/*
4250
 * find_ip_interface($ip): return the interface where an ip is defined
4251
 *   (or if $bits is specified, where an IP within the subnet is defined)
4252
 */
4253
function find_ip_interface($ip, $bits = null) {
4254
	if (!is_ipaddr($ip))
4255
		return false;
4256

    
4257
	$isv6ip = is_ipaddrv6($ip);
4258

    
4259
	/* if list */
4260
	$ifdescrs = get_configured_interface_list();
4261

    
4262
	foreach ($ifdescrs as $ifdescr => $ifname) {
4263
		$ifip = ($isv6ip) ? get_interface_ipv6($ifname) : get_interface_ip($ifname);
4264
		if (is_null($ifip))
4265
			continue;
4266
		if (is_null($bits)) {
4267
			if ($ip == $ifip) {
4268
				$int = get_real_interface($ifname);
4269
				return $int;
4270
			}
4271
		}
4272
		else {
4273
			if (ip_in_subnet($ifip, $ip . "/" . $bits)) {
4274
				$int = get_real_interface($ifname);
4275
				return $int;
4276
			}
4277
		}
4278
	}
4279

    
4280
	return false;
4281
}
4282

    
4283
/*
4284
 * find_virtual_ip_alias($ip): return the virtual IP alias where an IP is found
4285
 *   (or if $bits is specified, where an IP within the subnet is found)
4286
 */
4287
function find_virtual_ip_alias($ip, $bits = null) {
4288
	global $config;
4289

    
4290
	if (!is_array($config['virtualip']['vip'])) {
4291
		return false;
4292
	}
4293
	if (!is_ipaddr($ip))
4294
		return false;
4295

    
4296
	$isv6ip = is_ipaddrv6($ip);
4297

    
4298
	foreach ($config['virtualip']['vip'] as $vip) {
4299
		if ($vip['mode'] === "ipalias") {
4300
			if (is_ipaddrv6($vip['subnet']) != $isv6ip)
4301
				continue;
4302
			if (is_null($bits)) {
4303
				if (ip_in_subnet($ip, $vip['subnet'] . "/" . $vip['subnet_bits'])) {
4304
					return $vip;
4305
				}
4306
			}
4307
			else {
4308
				if (($isv6ip && check_subnetsv6_overlap($ip, $bits, $vip['subnet'], $vip['subnet_bits']))
4309
					|| (!$isv6ip && check_subnets_overlap($ip, $bits, $vip['subnet'], $vip['subnet_bits']))) {
4310
					return $vip;
4311
				}
4312
			}
4313
		}
4314
	}
4315
	return false;
4316
}
4317

    
4318
/*
4319
 *   find_number_of_created_carp_interfaces: return the number of carp interfaces
4320
 */
4321
function find_number_of_created_carp_interfaces() {
4322
	return `/sbin/ifconfig | grep "carp:" | wc -l`;
4323
}
4324

    
4325
function get_all_carp_interfaces() {
4326
	$ints = str_replace("\n", " ", `ifconfig | grep "carp:" -B2 | grep ": flag" | cut -d: -f1`);
4327
	$ints = explode(" ", $ints);
4328
	return $ints;
4329
}
4330

    
4331
/*
4332
 * find_carp_interface($ip): return the carp interface where an ip is defined
4333
 */
4334
function find_carp_interface($ip) {
4335
	global $config;
4336
	if (is_array($config['virtualip']['vip'])) {
4337
		foreach ($config['virtualip']['vip'] as $vip) {
4338
			if ($vip['mode'] == "carp") {
4339
				if(is_ipaddrv4($ip)) {
4340
					$carp_ip = get_interface_ip($vip['interface']);
4341
				}
4342
				if(is_ipaddrv6($ip)) {
4343
					$carp_ip = get_interface_ipv6($vip['interface']);
4344
				}
4345
				exec("/sbin/ifconfig", $output, $return);
4346
				foreach($output as $line) {
4347
					$elements = preg_split("/[ ]+/i", $line);
4348
					if(strstr($elements[0], "vip"))
4349
						$curif = str_replace(":", "", $elements[0]);
4350
					if(stristr($line, $ip)) {
4351
						$if = $curif;
4352
						continue;
4353
					}
4354
				}
4355

    
4356
				if ($if)
4357
					return $if;
4358
			}
4359
		}
4360
	}
4361
}
4362

    
4363
function link_carp_interface_to_parent($interface) {
4364
	global $config;
4365

    
4366
	if ($interface == "")
4367
		return;
4368

    
4369
	$carp_ip = get_interface_ip($interface);
4370
	$carp_ipv6 = get_interface_ipv6($interface);
4371

    
4372
	if((!is_ipaddrv4($carp_ip)) && (!is_ipaddrv6($carp_ipv6)))
4373
		return;
4374

    
4375
	/* if list */
4376
	$ifdescrs = get_configured_interface_list();
4377
	foreach ($ifdescrs as $ifdescr => $ifname) {
4378
		/* check IPv4 */
4379
		if(is_ipaddrv4($carp_ip)) {
4380
			$interfaceip = get_interface_ip($ifname);
4381
			$subnet_bits = get_interface_subnet($ifname);
4382
			$subnet_ip = gen_subnet("{$interfaceip}", "{$subnet_bits}");
4383
			if(ip_in_subnet($carp_ip, "{$subnet_ip}/{$subnet_bits}"))
4384
				return $ifname;
4385
		}
4386
		/* Check IPv6 */
4387
		if(is_ipaddrv6($carp_ipv6)) {
4388
			$interfaceipv6 = get_interface_ipv6($ifname);
4389
			$prefixlen = get_interface_subnetv6($ifname);
4390
			if(ip_in_subnet($carp_ipv6, "{$interfaceipv6}/{$prefixlen}"))
4391
				return $ifname;
4392
		}
4393
	}
4394
	return "";
4395
}
4396

    
4397

    
4398
/****f* interfaces/link_ip_to_carp_interface
4399
 * NAME
4400
 *   link_ip_to_carp_interface - Find where a CARP interface links to.
4401
 * INPUTS
4402
 *   $ip
4403
 * RESULT
4404
 *   $carp_ints
4405
 ******/
4406
function link_ip_to_carp_interface($ip) {
4407
	global $config;
4408

    
4409
	if (!is_ipaddr($ip))
4410
		return;
4411

    
4412
	$carp_ints = "";
4413
	if (is_array($config['virtualip']['vip'])) {
4414
		$first = 0;
4415
		$carp_int = array();
4416
		foreach ($config['virtualip']['vip'] as $vip) {
4417
			if ($vip['mode'] == "carp") {
4418
				$carp_ip = $vip['subnet'];
4419
				$carp_sn = $vip['subnet_bits'];
4420
				$carp_nw = gen_subnet($carp_ip, $carp_sn);
4421
				if (ip_in_subnet($ip, "{$carp_nw}/{$carp_sn}")) {
4422
					$carp_int[] = "{$vip['interface']}_vip{$vip['vhid']}";
4423
				}
4424
			}
4425
		}
4426
		if (!empty($carp_int))
4427
			$carp_ints = implode(" ", array_unique($carp_int));
4428
	}
4429

    
4430
	return $carp_ints;
4431
}
4432

    
4433
function link_interface_to_track6($int, $action = "") {
4434
	global $config;
4435

    
4436
	if (empty($int))
4437
		return;
4438

    
4439
	if (is_array($config['interfaces'])) {
4440
		$list = array();
4441
		foreach ($config['interfaces'] as $ifname => $ifcfg) {
4442
			if (!isset($ifcfg['enable']))
4443
				continue;
4444
			if (!empty($ifcfg['ipaddrv6']) && $ifcfg['track6-interface'] == $int) {
4445
				if ($action == "update")
4446
					interface_track6_configure($ifname, $ifcfg);
4447
				else if ($action == "")
4448
					$list[$ifname] = $ifcfg;
4449
			}
4450
		}
4451
		return $list;
4452
	}
4453
}
4454

    
4455
function link_interface_to_vlans($int, $action = "") {
4456
	global $config;
4457

    
4458
	if (empty($int))
4459
		return;
4460

    
4461
	if (is_array($config['vlans']['vlan'])) {
4462
		$ifaces = array();
4463
		foreach ($config['vlans']['vlan'] as $vlan) {
4464
			if ($int == $vlan['if']) {
4465
				if ($action == "update") {
4466
					interfaces_bring_up($int);
4467
				} else if ($action == "")
4468
					$ifaces[$vlan['tag']] = $vlan;
4469
			}
4470
		}
4471
		if (!empty($ifaces))
4472
			return $ifaces;
4473
	}
4474
}
4475

    
4476
function link_interface_to_vips($int, $action = "") {
4477
	global $config;
4478

    
4479
	if (is_array($config['virtualip']['vip'])) {
4480
		$result = array();
4481
		foreach ($config['virtualip']['vip'] as $vip) {
4482
			if ($int == $vip['interface']) {
4483
				if ($action == "update")
4484
					interfaces_vips_configure($int);
4485
				else
4486
					$result[] = $vip;
4487
			}
4488
		}
4489
		return $result;
4490
	}
4491
}
4492

    
4493
/****f* interfaces/link_interface_to_bridge
4494
 * NAME
4495
 *   link_interface_to_bridge - Finds out a bridge group for an interface
4496
 * INPUTS
4497
 *   $ip
4498
 * RESULT
4499
 *   bridge[0-99]
4500
 ******/
4501
function link_interface_to_bridge($int) {
4502
	global $config;
4503

    
4504
	if (is_array($config['bridges']['bridged'])) {
4505
		foreach ($config['bridges']['bridged'] as $bridge) {
4506
			if (in_array($int, explode(',', $bridge['members'])))
4507
				return "{$bridge['bridgeif']}";
4508
		}
4509
	}
4510
}
4511

    
4512
function link_interface_to_group($int) {
4513
	global $config;
4514

    
4515
	$result = array();
4516

    
4517
	if (is_array($config['ifgroups']['ifgroupentry'])) {
4518
		foreach ($config['ifgroups']['ifgroupentry'] as $group) {
4519
			if (in_array($int, explode(" ", $group['members'])))
4520
				$result[$group['ifname']] = $int;
4521
		}
4522
	}
4523

    
4524
	return $result;
4525
}
4526

    
4527
function link_interface_to_gre($interface) {
4528
	global $config;
4529

    
4530
	$result = array();
4531

    
4532
	if (is_array($config['gres']['gre'])) {
4533
		foreach ($config['gres']['gre'] as $gre)
4534
			if($gre['if'] == $interface)
4535
				$result[] = $gre;
4536
	}
4537

    
4538
	return $result;
4539
}
4540

    
4541
function link_interface_to_gif($interface) {
4542
	global $config;
4543

    
4544
	$result = array();
4545

    
4546
	if (is_array($config['gifs']['gif'])) {
4547
		foreach ($config['gifs']['gif'] as $gif)
4548
			if($gif['if'] == $interface)
4549
				$result[] = $gif;
4550
	}
4551

    
4552
	return $result;
4553
}
4554

    
4555
/*
4556
 * find_interface_ip($interface): return the interface ip (first found)
4557
 */
4558
function find_interface_ip($interface, $flush = false) {
4559
	global $interface_ip_arr_cache;
4560
	global $interface_sn_arr_cache;
4561

    
4562
	$interface = str_replace("\n", "", $interface);
4563

    
4564
	if (!does_interface_exist($interface))
4565
		return;
4566

    
4567
	/* Setup IP cache */
4568
	if (!isset($interface_ip_arr_cache[$interface]) or $flush) {
4569
		$ifinfo = pfSense_get_interface_addresses($interface);
4570
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
4571
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
4572
	}
4573

    
4574
	return $interface_ip_arr_cache[$interface];
4575
}
4576

    
4577
/*
4578
 * find_interface_ipv6($interface): return the interface ip (first found)
4579
 */
4580
function find_interface_ipv6($interface, $flush = false) {
4581
	global $interface_ipv6_arr_cache;
4582
	global $interface_snv6_arr_cache;
4583
	global $config;
4584

    
4585
	$interface = trim($interface);
4586
	$interface = get_real_interface($interface);
4587

    
4588
	if (!does_interface_exist($interface))
4589
		return;
4590

    
4591
	/* Setup IP cache */
4592
	if (!isset($interface_ipv6_arr_cache[$interface]) or $flush) {
4593
		// FIXME: Add IPv6 support to the pfSense module
4594
		$ifinfo = array();
4595
		exec("/sbin/ifconfig {$interface} inet6", $output);
4596
		foreach($output as $line) {
4597
			if(preg_match("/inet6/", $line)) {
4598
				$parts = explode(" ", $line);
4599
				if(!is_linklocal($parts[1])) {
4600
					$ifinfo['ipaddrv6'] = $parts[1];
4601
					if($parts[2] == "-->") {
4602
						$parts[5] = "126";
4603
						$ifinfo['subnetbitsv6'] = $parts[5];
4604
					} else {
4605
						$ifinfo['subnetbitsv6'] = $parts[3];
4606
					}
4607
					break;
4608
				}
4609
			}
4610
		}
4611
		$interface_ipv6_arr_cache[$interface] = $ifinfo['ipaddrv6'];
4612
		$interface_snv6_arr_cache[$interface] = $ifinfo['subnetbitsv6'];
4613
	}
4614

    
4615
	return $interface_ipv6_arr_cache[$interface];
4616
}
4617

    
4618
/*
4619
 * find_interface_ipv6_ll($interface): return the interface ipv6 link local (first found)
4620
 */
4621
function find_interface_ipv6_ll($interface, $flush = false) {
4622
	global $interface_llv6_arr_cache;
4623
	global $config;
4624

    
4625
	$interface = str_replace("\n", "", $interface);
4626

    
4627
	if (!does_interface_exist($interface))
4628
		return;
4629

    
4630
	/* Setup IP cache */
4631
	if (!isset($interface_llv6_arr_cache[$interface]) or $flush) {
4632
		$ifinfo = pfSense_get_interface_addresses($interface);
4633
		// FIXME: Add IPv6 support to the pfSense module
4634
		exec("/sbin/ifconfig {$interface} inet6", $output);
4635
		foreach($output as $line) {
4636
			if(preg_match("/inet6/", $line)) {
4637
				$parts = explode(" ", $line);
4638
				if(is_linklocal($parts[1])) {
4639
					$partsaddress = explode("%", $parts[1]);
4640
					$ifinfo['linklocal'] = $partsaddress[0];
4641
				}
4642
			}
4643
		}
4644
		$interface_llv6_arr_cache[$interface] = $ifinfo['linklocal'];
4645
	}
4646
	return $interface_llv6_arr_cache[$interface];
4647
}
4648

    
4649
function find_interface_subnet($interface, $flush = false) {
4650
	global $interface_sn_arr_cache;
4651
	global $interface_ip_arr_cache;
4652

    
4653
	$interface = str_replace("\n", "", $interface);
4654
	if (does_interface_exist($interface) == false)
4655
		return;
4656

    
4657
	if (!isset($interface_sn_arr_cache[$interface]) or $flush) {
4658
		$ifinfo = pfSense_get_interface_addresses($interface);
4659
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
4660
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
4661
	}
4662

    
4663
	return $interface_sn_arr_cache[$interface];
4664
}
4665

    
4666
function find_interface_subnetv6($interface, $flush = false) {
4667
	global $interface_snv6_arr_cache;
4668
	global $interface_ipv6_arr_cache;
4669

    
4670
	$interface = str_replace("\n", "", $interface);
4671
	if (does_interface_exist($interface) == false)
4672
		return;
4673

    
4674
	$foundv6 = false;
4675
	if (!isset($interface_snv6_arr_cache[$interface]) or $flush) {
4676
		$ifinfo = array();
4677
		// FIXME: Add IPv6 support to the pfSense module
4678
		unset($output);
4679
		exec("/sbin/ifconfig {$interface} inet6", $output);
4680
		foreach($output as $line) {
4681
			$line = trim($line);
4682
			if(preg_match("/inet6/", $line)) {
4683
				$parts = explode(" ", $line);
4684
				if(!is_linklocal($parts[1])) {
4685
					$ifinfo['ipaddrv6'] = $parts[1];
4686
					if($parts[2] == "-->") {
4687
						$parts[5] = "126";
4688
						$ifinfo['subnetbitsv6'] = $parts[5];
4689
					} else {
4690
						$ifinfo['subnetbitsv6'] = $parts[3];
4691
					}
4692
					$foundv6 = true;
4693
					break;
4694
				}
4695
			}
4696
		}
4697
		if ($foundv6 === true) {
4698
			$interface_ipv6_arr_cache[$interface] = $ifinfo['ipaddrv6'];
4699
			$interface_snv6_arr_cache[$interface] = $ifinfo['subnetbitsv6'];
4700
		} else
4701
			unset($interface_ipv6_arr_cache[$interface], $interface_snv6_arr_cache[$interface]);
4702
	}
4703

    
4704
	return $interface_snv6_arr_cache[$interface];
4705
}
4706

    
4707
function ip_in_interface_alias_subnet($interface, $ipalias) {
4708
	global $config;
4709

    
4710
	if (empty($interface) || !is_ipaddr($ipalias))
4711
		return false;
4712
	if (is_array($config['virtualip']['vip'])) {
4713
		foreach ($config['virtualip']['vip'] as $vip) {
4714
			switch ($vip['mode']) {
4715
			case "ipalias":
4716
				if ($vip['interface'] <> $interface)
4717
					break;
4718
				if (ip_in_subnet($ipalias, gen_subnet($vip['subnet'], $vip['subnet_bits']) . "/" . $vip['subnet_bits']))
4719
					return true;
4720
				break;
4721
			}
4722
		}
4723
	}
4724

    
4725
	return false;
4726
}
4727

    
4728
function get_interface_ip($interface = "wan") {
4729
	$realif = get_failover_interface($interface);
4730
	if (!$realif) {
4731
		if (preg_match("/^carp/i", $interface))
4732
			$realif = $interface;
4733
		else if (preg_match("/^[a-z0-9]+_vip/i", $interface))
4734
			$realif = $interface;
4735
		else
4736
			return null;
4737
	}
4738

    
4739
	$curip = find_interface_ip($realif);
4740
	if ($curip && is_ipaddr($curip) && ($curip != "0.0.0.0"))
4741
		return $curip;
4742
	else
4743
		return null;
4744
}
4745

    
4746
function get_interface_ipv6($interface = "wan", $flush = false) {
4747
	global $config;
4748

    
4749
	$realif = get_failover_interface($interface, "inet6");
4750
	if (!$realif) {
4751
		if (preg_match("/^[a-z0-9]+_vip/i", $interface))
4752
			$realif = $interface;
4753
		else
4754
			return null;
4755
	}
4756

    
4757
	$curip = find_interface_ipv6($realif, $flush);
4758
	if ($curip && is_ipaddrv6($curip) && ($curip != "::"))
4759
		return $curip;
4760
	else
4761
		return null;
4762
}
4763

    
4764
function get_interface_linklocal($interface = "wan") {
4765

    
4766
	$realif = get_failover_interface($interface, "inet6");
4767
	if (!$realif) {
4768
		if (preg_match("/^carp/i", $interface))
4769
			$realif = $interface;
4770
		else if (preg_match("/^[a-z0-9]+_vip/i", $interface))
4771
			$realif = $interface;
4772
		else
4773
			return null;
4774
	}
4775

    
4776
	$curip = find_interface_ipv6_ll($realif);
4777
	if ($curip && is_ipaddrv6($curip) && ($curip != "::"))
4778
		return $curip;
4779
	else
4780
		return null;
4781
}
4782

    
4783
function get_interface_subnet($interface = "wan") {
4784
	$realif = get_real_interface($interface);
4785
	if (!$realif) {
4786
		if (preg_match("/^carp/i", $interface))
4787
			$realif = $interface;
4788
		else if (preg_match("/^[a-z0-9]+_vip/i", $interface))
4789
			$realif = $interface;
4790
		else
4791
			return null;
4792
	}
4793

    
4794
	$cursn = find_interface_subnet($realif);
4795
	if (!empty($cursn))
4796
		return $cursn;
4797

    
4798
	return null;
4799
}
4800

    
4801
function get_interface_subnetv6($interface = "wan") {
4802
	global $config;
4803

    
4804
	$realif = get_real_interface($interface, "inet6");
4805
	if (!$realif) {
4806
		if (preg_match("/^[a-z0-9]+_vip/i", $interface))
4807
			$realif = $interface;
4808
		else
4809
			return null;
4810
	}
4811

    
4812
	$cursn = find_interface_subnetv6($realif);
4813
	if (!empty($cursn))
4814
		return $cursn;
4815

    
4816
	return null;
4817
}
4818

    
4819
/* return outside interfaces with a gateway */
4820
function get_interfaces_with_gateway() {
4821
	global $config;
4822

    
4823
	$ints = array();
4824

    
4825
	/* loop interfaces, check config for outbound */
4826
	foreach($config['interfaces'] as $ifdescr => $ifname) {
4827
		switch ($ifname['ipaddr']) {
4828
			case "dhcp":
4829
			case "ppp";
4830
			case "pppoe":
4831
			case "pptp":
4832
			case "l2tp":
4833
			case "ppp";
4834
				$ints[$ifdescr] = $ifdescr;
4835
			break;
4836
			default:
4837
				if (substr($ifname['if'], 0, 4) ==  "ovpn" ||
4838
				    !empty($ifname['gateway']))
4839
					$ints[$ifdescr] = $ifdescr;
4840
			break;
4841
		}
4842
	}
4843
	return $ints;
4844
}
4845

    
4846
/* return true if interface has a gateway */
4847
function interface_has_gateway($friendly) {
4848
	global $config;
4849

    
4850
	if (!empty($config['interfaces'][$friendly])) {
4851
		$ifname = &$config['interfaces'][$friendly];
4852
		switch ($ifname['ipaddr']) {
4853
			case "dhcp":
4854
			case "pppoe":
4855
			case "pptp":
4856
			case "l2tp":
4857
			case "ppp";
4858
				return true;
4859
			break;
4860
			default:
4861
				if (substr($ifname['if'], 0, 4) ==  "ovpn")
4862
					return true;
4863
				if (!empty($ifname['gateway']))
4864
					return true;
4865
			break;
4866
		}
4867
	}
4868

    
4869
	return false;
4870
}
4871

    
4872
/* return true if interface has a gateway */
4873
function interface_has_gatewayv6($friendly) {
4874
	global $config;
4875

    
4876
	if (!empty($config['interfaces'][$friendly])) {
4877
		$ifname = &$config['interfaces'][$friendly];
4878
		switch ($ifname['ipaddrv6']) {
4879
			case "slaac":
4880
			case "dhcp6":
4881
			case "6to4":
4882
			case "6rd":
4883
				return true;
4884
				break;
4885
			default:
4886
				if (substr($ifname['if'], 0, 4) ==  "ovpn")
4887
					return true;
4888
				if (!empty($ifname['gatewayv6']))
4889
					return true;
4890
				break;
4891
		}
4892
	}
4893

    
4894
	return false;
4895
}
4896

    
4897
/****f* interfaces/is_altq_capable
4898
 * NAME
4899
 *   is_altq_capable - Test if interface is capable of using ALTQ
4900
 * INPUTS
4901
 *   $int            - string containing interface name
4902
 * RESULT
4903
 *   boolean         - true or false
4904
 ******/
4905

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

    
4919
	$int_family = remove_ifindex($int);
4920

    
4921
	if (in_array($int_family, $capable))
4922
		return true;
4923
	else if (stristr($int, "l2tp")) /* VLANs are name $parent_$vlan now */
4924
		return true;
4925
	else if (stristr($int, "_vlan")) /* VLANs are name $parent_$vlan now */
4926
		return true;
4927
	else if (stristr($int, "_wlan")) /* WLANs are name $parent_$wlan now */
4928
		return true;
4929
	else
4930
		return false;
4931
}
4932

    
4933
/****f* interfaces/is_interface_wireless
4934
 * NAME
4935
 *   is_interface_wireless - Returns if an interface is wireless
4936
 * RESULT
4937
 *   $tmp       - Returns if an interface is wireless
4938
 ******/
4939
function is_interface_wireless($interface) {
4940
	global $config, $g;
4941

    
4942
	$friendly = convert_real_interface_to_friendly_interface_name($interface);
4943
	if(!isset($config['interfaces'][$friendly]['wireless'])) {
4944
		if (preg_match($g['wireless_regex'], $interface)) {
4945
			if (isset($config['interfaces'][$friendly]))
4946
				$config['interfaces'][$friendly]['wireless'] = array();
4947
			return true;
4948
		}
4949
		return false;
4950
	} else
4951
		return true;
4952
}
4953

    
4954
function get_wireless_modes($interface) {
4955
	/* return wireless modes and channels */
4956
	$wireless_modes = array();
4957

    
4958
	$cloned_interface = get_real_interface($interface);
4959

    
4960
	if($cloned_interface && is_interface_wireless($cloned_interface)) {
4961
		$chan_list = "/sbin/ifconfig {$cloned_interface} list chan";
4962
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
4963
		$format_list = "/usr/bin/awk '{print \$5 \" \" \$6 \",\" \$1}'";
4964

    
4965
		$interface_channels = "";
4966
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
4967
		$interface_channel_count = count($interface_channels);
4968

    
4969
		$c = 0;
4970
		while ($c < $interface_channel_count) {
4971
			$channel_line = explode(",", $interface_channels["$c"]);
4972
			$wireless_mode = trim($channel_line[0]);
4973
			$wireless_channel = trim($channel_line[1]);
4974
			if(trim($wireless_mode) != "") {
4975
				/* if we only have 11g also set 11b channels */
4976
				if($wireless_mode == "11g") {
4977
					if(!isset($wireless_modes["11b"]))
4978
						$wireless_modes["11b"] = array();
4979
				} else if($wireless_mode == "11g ht") {
4980
					if(!isset($wireless_modes["11b"]))
4981
						$wireless_modes["11b"] = array();
4982
					if(!isset($wireless_modes["11g"]))
4983
						$wireless_modes["11g"] = array();
4984
					$wireless_mode = "11ng";
4985
				} else if($wireless_mode == "11a ht") {
4986
					if(!isset($wireless_modes["11a"]))
4987
						$wireless_modes["11a"] = array();
4988
					$wireless_mode = "11na";
4989
				}
4990
				$wireless_modes["$wireless_mode"]["$c"] = $wireless_channel;
4991
			}
4992
			$c++;
4993
		}
4994
	}
4995
	return($wireless_modes);
4996
}
4997

    
4998
/* return channel numbers, frequency, max txpower, and max regulation txpower */
4999
function get_wireless_channel_info($interface) {
5000
	$wireless_channels = array();
5001

    
5002
	$cloned_interface = get_real_interface($interface);
5003

    
5004
	if($cloned_interface && is_interface_wireless($cloned_interface)) {
5005
		$chan_list = "/sbin/ifconfig {$cloned_interface} list txpower";
5006
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
5007
		$format_list = "/usr/bin/awk '{print \$1 \",\" \$3 \" \" \$4 \",\" \$5 \",\" \$7}'";
5008

    
5009
		$interface_channels = "";
5010
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
5011

    
5012
		foreach ($interface_channels as $channel_line) {
5013
			$channel_line = explode(",", $channel_line);
5014
			if(!isset($wireless_channels[$channel_line[0]]))
5015
				$wireless_channels[$channel_line[0]] = $channel_line;
5016
		}
5017
	}
5018
	return($wireless_channels);
5019
}
5020

    
5021
/****f* interfaces/get_interface_mtu
5022
 * NAME
5023
 *   get_interface_mtu - Return the mtu of an interface
5024
 * RESULT
5025
 *   $tmp       - Returns the mtu of an interface
5026
 ******/
5027
function get_interface_mtu($interface) {
5028
	$mtu = pfSense_get_interface_addresses($interface);
5029
	return $mtu['mtu'];
5030
}
5031

    
5032
function get_interface_mac($interface) {
5033

    
5034
	$macinfo = pfSense_get_interface_addresses($interface);
5035
	return $macinfo["macaddr"];
5036
}
5037

    
5038
/****f* pfsense-utils/generate_random_mac_address
5039
 * NAME
5040
 *   generate_random_mac - generates a random mac address
5041
 * INPUTS
5042
 *   none
5043
 * RESULT
5044
 *   $mac - a random mac address
5045
 ******/
5046
function generate_random_mac_address() {
5047
	$mac = "02";
5048
	for($x=0; $x<5; $x++)
5049
		$mac .= ":" . dechex(rand(16, 255));
5050
	return $mac;
5051
}
5052

    
5053
/****f* interfaces/is_jumbo_capable
5054
 * NAME
5055
 *   is_jumbo_capable - Test if interface is jumbo frame capable.  Useful for determining VLAN capability.
5056
 * INPUTS
5057
 *   $int             - string containing interface name
5058
 * RESULT
5059
 *   boolean          - true or false
5060
 ******/
5061
function is_jumbo_capable($iface) {
5062
	$iface = trim($iface);
5063
	$capable = pfSense_get_interface_addresses($iface);
5064

    
5065
	if (isset($capable['caps']['vlanmtu']))
5066
		return true;
5067

    
5068
	return false;
5069
}
5070

    
5071
function interface_setup_pppoe_reset_file($pppif, $iface="") {
5072
	global $g;
5073

    
5074
	$cron_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
5075

    
5076
	if(!empty($iface) && !empty($pppif)){
5077
		$cron_cmd = <<<EOD
5078
#!/bin/sh
5079
/usr/local/sbin/pfSctl -c 'interface reload {$iface}'
5080
/usr/bin/logger -t {$pppif} "PPPoE periodic reset executed on {$iface}"
5081

    
5082
EOD;
5083

    
5084
		@file_put_contents($cron_file, $cron_cmd);
5085
		chmod($cron_file, 0755);
5086
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
5087
	} else
5088
		unlink_if_exists($cron_file);
5089
}
5090

    
5091
function get_interface_default_mtu($type = "ethernet") {
5092
	switch ($type) {
5093
	case "gre":
5094
		return 1476;
5095
		break;
5096
	case "gif":
5097
		return 1280;
5098
		break;
5099
	case "tun":
5100
	case "vlan":
5101
	case "tap":
5102
	case "ethernet":
5103
	default:
5104
		return 1500;
5105
		break;
5106
	}
5107

    
5108
	/* Never reached */
5109
	return 1500;
5110
}
5111

    
5112
function get_vip_descr($ipaddress) {
5113
	global $config;
5114

    
5115
	foreach ($config['virtualip']['vip'] as $vip) {
5116
		if ($vip['subnet'] == $ipaddress) {
5117
			return ($vip['descr']);
5118
		}
5119
	}
5120
	return "";
5121
}
5122

    
5123
function interfaces_staticarp_configure($if) {
5124
	global $config, $g;
5125
	if(isset($config['system']['developerspew'])) {
5126
		$mt = microtime();
5127
		echo "interfaces_staticarp_configure($if) being called $mt\n";
5128
	}
5129

    
5130
	$ifcfg = $config['interfaces'][$if];
5131

    
5132
	if (empty($if) || empty($ifcfg['if']) || !isset($ifcfg['enable']))
5133
		return 0;
5134

    
5135
	/* Enable staticarp, if enabled */
5136
	if(isset($config['dhcpd'][$if]['staticarp'])) {
5137
		mwexec("/sbin/ifconfig " . escapeshellarg($ifcfg['if']) . " staticarp " );
5138
		mwexec("/usr/sbin/arp -d -i " . escapeshellarg($ifcfg['if']) . " -a > /dev/null 2>&1 ");
5139
		if (is_array($config['dhcpd'][$if]['staticmap'])) {
5140

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

    
5144
			}
5145

    
5146
		}
5147
	} else {
5148
		mwexec("/sbin/ifconfig " . escapeshellarg($ifcfg['if']) . " -staticarp " );
5149
		mwexec("/usr/sbin/arp -d -i " . escapeshellarg($ifcfg['if']) . " -a > /dev/null 2>&1 ");
5150
		if (is_array($config['dhcpd'][$if]) && is_array($config['dhcpd'][$if]['staticmap'])) {
5151
			foreach ($config['dhcpd'][$if]['staticmap'] as $arpent) {
5152
				if (isset($arpent['arp_table_static_entry'])) {
5153
					mwexec("/usr/sbin/arp -s " . escapeshellarg($arpent['ipaddr']) . " " . escapeshellarg($arpent['mac']));
5154
				}
5155
			}
5156
		}
5157
	}
5158

    
5159
	return 0;
5160
}
5161

    
5162
function get_failover_interface($interface, $family = "all") {
5163
	global $config;
5164

    
5165
	/* shortcut to get_real_interface if we find it in the config */
5166
	if (is_array($config['interfaces'][$interface])) {
5167
		return get_real_interface($interface, $family);
5168
	}
5169

    
5170
	/* compare against gateway groups */
5171
	$a_groups = return_gateway_groups_array();
5172
	if (is_array($a_groups[$interface])) {
5173
		/* we found a gateway group, fetch the interface or vip */
5174
		if ($a_groups[$interface][0]['vip'] <> "")
5175
			return $a_groups[$interface][0]['vip'];
5176
		else
5177
			return $a_groups[$interface][0]['int'];
5178
	}
5179
	/* fall through to get_real_interface */
5180
	/* XXX: Really needed? */
5181
	return get_real_interface($interface, $family);
5182
}
5183

    
5184
function remove_ifindex($ifname) {
5185
	return preg_replace("/[0-9]+$/", "", $ifname);
5186
}
5187

    
5188
?>
(25-25/66)