Project

General

Profile

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

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

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

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

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

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

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

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

    
43
*/
44

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

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

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

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

    
69
        return $interface_arr_cache;
70
}
71

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

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

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

    
99

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

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

    
126
	return false;
127
}
128

    
129
function interface_netgraph_needed($interface = "wan") {
130
	global $config;
131

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

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

    
172
				if ($realif == $ppp['if']) {
173
					$found = true;
174
					break;
175
				}
176
*/			
177
				$ports = explode(',',$ppp['ports']);
178
				foreach($ports as $pid => $port){
179
					$port = get_real_interface($port);
180
					if ($realif == $port) {
181
						$found = true;
182
						break;
183
					}
184
					/* Find the parent interfaces of the vlans in the MLPPP configs 
185
					* there should be only one element in the array here 
186
					* -- this could be better . . . */
187
					$parent_if = get_parent_interface($port);
188
					if ($realif == $parent_if[0]) {
189
						$found = true;
190
						break;
191
					}
192
				}
193
			}
194
		}
195
	}
196
	
197
	if ($found == false) {
198
		$realif = get_real_interface($interface);
199
		pfSense_ngctl_detach("{$realif}:", $realif);
200
	}
201
	/* NOTE: We make sure for this on interface_ppps_configure()
202
	 *	no need to do it here agan.
203
	 *	else
204
	 *		pfSense_ngctl_attach(".", $realif);
205
	 */
206
}
207

    
208
function interfaces_loopback_configure() {
209
	global $g;
210

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

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

    
238
function interface_vlan_configure(&$vlan) {
239
        global $config, $g;
240

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

    
249
	if (empty($if)) {
250
		log_error(gettext("interface_vlan_confgure called with if undefined."));
251
		return;
252
	}
253

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

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

    
267
	pfSense_vlan_create($vlanif, $if, $tag);
268

    
269
	interfaces_bring_up($vlanif);
270

    
271
	/* invalidate interface cache */
272
	get_interface_arr(true);
273

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

    
277
	return $vlanif;
278
}
279

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

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

    
288
        $qinqif = $vlan['if'];
289
        $tag = $vlan['tag'];
290
        if(empty($qinqif)) {
291
                log_error(sprintf(gettext("interface_qinq_confgure called with if undefined.%s"), "\n"));
292
                return;
293
        }
294
	$vlanif = interface_vlan_configure($vlan);
295

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

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

    
319
        /* invalidate interface cache */
320
        get_interface_arr(true);
321

    
322
        if (!stristr($qinqif, "vlan"))
323
                mwexec("/sbin/ifconfig {$qinqif} promisc\n");
324

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

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

    
347
        return $vlanif;
348
}
349

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

    
364
function interface_qinq2_configure(&$qinq, $fd, $macaddr) {
365
        global $config, $g;
366

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

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

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

    
387
        /* invalidate interface cache */
388
        get_interface_arr(true);
389

    
390
        return $vlanif;
391
}
392

    
393
function interfaces_create_wireless_clones() {
394
	global $config;
395

    
396
	if($g['booting'])
397
		echo gettext("Creating other wireless clone interfaces...");
398
	if (is_array($config['wireless']['clone']) && count($config['wireless']['clone'])) {
399
		foreach ($config['wireless']['clone'] as $clone) {
400
			if(empty($clone['cloneif']))
401
				continue;
402
			if(does_interface_exist($clone['cloneif']))
403
				continue;
404
			/* XXX: Maybe we should report any errors?! */
405
			if(interface_wireless_clone($clone['cloneif'], $clone))
406
				if($g['booting'])
407
					echo " " . $clone['cloneif'];
408
		}
409
	}
410
	if($g['booting'])
411
		echo " " . gettext("done.") . "\n";
412

    
413
}
414

    
415
function interfaces_bridge_configure($checkmember = 0) {
416
        global $config;
417

    
418
        $i = 0;
419
        if (is_array($config['bridges']['bridged']) && count($config['bridges']['bridged'])) {
420
                foreach ($config['bridges']['bridged'] as $bridge) {
421
                        if(empty($bridge['bridgeif']))
422
                                $bridge['bridgeif'] = "bridge{$i}";
423
                        /* XXX: Maybe we should report any errors?! */
424
                        interface_bridge_configure($bridge, $checkmember);
425
                        $i++;
426
                }
427
        }
428
}
429

    
430
function interface_bridge_configure(&$bridge, $checkmember = 0) {
431
	global $config, $g;
432

    
433
	if (!is_array($bridge))
434
	        return -1;
435

    
436
	if (empty($bridge['members'])) {
437
		log_error(sprintf(gettext("No members found on %s"), $bridge['bridgeif']));
438
		return -1;
439
	}
440

    
441
	$members = explode(',', $bridge['members']);
442
	if (!count($members))
443
		return -1;
444

    
445
	/* Calculate smaller mtu and enforce it */
446
	$smallermtu = 0;
447
	$commonrx = true;
448
	$commontx = true;
449
	$foundgif = false;
450
	foreach ($members as $member) {
451
		$realif = get_real_interface($member);
452
		$opts = pfSense_get_interface_addresses($realif);
453
		$mtu = $opts['mtu'];
454
		if (substr($realif, 0, 3) == "gif") {
455
			$foundgif = true;
456
			if ($checkmember == 1)
457
				return;
458
			if ($mtu <= 1500)
459
				continue;
460
		}
461
		if (!isset($opts['encaps']['txcsum']))
462
			$commontx = false;
463
		if (!isset($opts['encaps']['rxcsum']))
464
			$commonrx = false;
465
		if (!isset($opts['encaps']['tso4']))
466
			$commontso4 = false;
467
		if (!isset($opts['encaps']['tso6']))
468
			$commontso6 = false;
469
		if (!isset($opts['encaps']['lro']))
470
			$commonlro = false;
471
		if ($smallermtu == 0 && !empty($mtu))
472
			$smallermtu = $mtu;
473
		else if (!empty($mtu) && $mtu < $smallermtu)
474
			$smallermtu = $mtu;
475
	}
476
	if ($foundgif == false && $checkmember == 2)
477
		return;
478

    
479
	/* Just in case anything is not working well */
480
	if ($smallermtu == 0)
481
		$smallermtu = 1500; 
482

    
483
	$flags = 0;
484
	if ($commonrx === false)
485
		$flags |= IFCAP_RXCSUM;
486
	if ($commontx === false)
487
		$flags |= IFCAP_TXCSUM;
488
	if ($commontso4 === false)
489
		$flags |= IFCAP_TSO4;
490
	if ($commontso6 === false)
491
		$flags |= IFCAP_TSO6;
492
	if ($commonlro === false)
493
		$flags |= IFCAP_LRO;
494

    
495
	if ($g['booting'] || !empty($bridge['bridgeif'])) {
496
		pfSense_interface_destroy($bridge['bridgeif']);
497
		pfSense_interface_create($bridge['bridgeif']);
498
		$bridgeif = $bridge['bridgeif'];
499
	} else
500
		$bridgeif = pfSense_interface_create("bridge");
501

    
502
	$checklist = get_configured_interface_list();
503

    
504
	/* Add interfaces to bridge */
505
	foreach ($members as $member) {
506
		if (!array_key_exists($member, $checklist))
507
			continue;
508
		$realif1 = get_real_interface($member);
509
		$realif =  escapeshellarg($realif1);
510
		if (!$realif) {
511
			log_error(gettext("realif not defined in interfaces bridge - up"));
512
			continue;
513
		}
514
		/* make sure the parent interface is up */
515
		pfSense_interface_mtu($realif1, $smallermtu);
516
		pfSense_interface_capabilities($realif1, -$flags);
517
		interfaces_bring_up($realif1);
518
		pfSense_bridge_add_member($bridgeif, $realif);
519
	}
520

    
521
	if (isset($bridge['enablestp'])) {
522
		/* Choose spanning tree proto */
523
		mwexec("/sbin/ifconfig {$bridgeif} proto {$bridge['proto']}");	
524
		
525
		if (!empty($bridge['stp'])) {
526
			$stpifs = explode(',', $bridge['stp']);
527
			foreach ($stpifs as $stpif) {
528
				$realif = get_real_interface($stpif);
529
				mwexec("/sbin/ifconfig {$bridgeif} stp {$realif}");
530
			}
531
		}
532
		if (!empty($bridge['maxage']))
533
			mwexec("/sbin/ifconfig {$bridgeif} maxage {$bridge['maxage']}");
534
		if (!empty($bridge['fwdelay']))
535
			mwexec("/sbin/ifconfig {$bridgeif} fwddelay {$bridge['fwdelay']}");
536
		if (!empty($bridge['hellotime']))
537
                        mwexec("/sbin/ifconfig {$bridgeif} hellotime {$bridge['hellotime']}");
538
		if (!empty($bridge['priority']))
539
                        mwexec("/sbin/ifconfig {$bridgeif} priority {$bridge['priority']}");
540
		if (!empty($bridge['holdcount']))
541
                        mwexec("/sbin/ifconfig {$bridgeif} holdcnt {$bridge['holdcnt']}");
542
		if (!empty($bridge['ifpriority'])) {
543
			$pconfig = explode(",", $bridge['ifpriority']);
544
			$ifpriority = array();
545
			foreach ($pconfig as $cfg) {
546
				$embcfg = explode_assoc(":", $cfg);
547
				foreach ($embcfg as $key => $value)
548
					$ifpriority[$key] = $value;
549
			}
550
			foreach ($ifpriority as $key => $value) {
551
				$realif = get_real_interface($key);
552
				mwexec("/sbin/ifconfig ${bridgeif} ifpriority {$realif} {$value}"); 
553
			}
554
		}
555
		if (!empty($bridge['ifpathcost'])) {
556
			$pconfig = explode(",", $bridge['ifpathcost']);
557
			$ifpathcost = array();
558
			foreach ($pconfig as $cfg) {
559
				$embcfg = explode_assoc(":", $cfg);
560
				foreach ($embcfg as $key => $value)
561
					$ifpathcost[$key] = $value;
562
			}
563
			foreach ($ifpathcost as $key => $value) {
564
                        	$realif = get_real_interface($key);
565
                        	mwexec("/sbin/ifconfig ${bridgeif} ifpathcost {$realif} {$value}");
566
                	}
567
		}
568
	}
569

    
570
	if ($bridge['maxaddr'] <> "")
571
		mwexec("/sbin/ifconfig {$bridgeif} maxaddr {$bridge['maxaddr']}");
572
        if ($bridge['timeout'] <> "")
573
                mwexec("/sbin/ifconfig {$bridgeif} timeout {$bridge['timeout']}");
574
        if ($bridge['span'] <> "") {
575
		$realif = get_real_interface($bridge['span']);
576
                mwexec("/sbin/ifconfig {$bridgeif} span {$realif}");
577
	}
578
	if (!empty($bridge['edge'])) {
579
        	$edgeifs = explode(',', $bridge['edge']);
580
        	foreach ($edgeifs as $edgeif) {
581
			$realif = get_real_interface($edgeif);
582
                	mwexec("/sbin/ifconfig {$bridgeif} edge {$realif}");
583
        	}
584
	}
585
	if (!empty($bridge['autoedge'])) {
586
        	$edgeifs = explode(',', $bridge['autoedge']);
587
        	foreach ($edgeifs as $edgeif) {
588
                	$realif = get_real_interface($edgeif);
589
                	mwexec("/sbin/ifconfig {$bridgeif} -autoedge {$realif}");
590
        	}
591
	}
592
	if (!empty($bridge['ptp'])) {
593
        	$ptpifs = explode(',', $bridge['ptp']);
594
        	foreach ($ptpifs as $ptpif) {
595
                	$realif = get_real_interface($ptpif);
596
                	mwexec("/sbin/ifconfig {$bridgeif} ptp {$realif}");
597
        	}
598
	}
599
	if (!empty($bridge['autoptp'])) {
600
        	$ptpifs = explode(',', $bridge['autoptp']);
601
        	foreach ($ptpifs as $ptpif) {
602
                	$realif = get_real_interface($ptpif);
603
                	mwexec("/sbin/ifconfig {$bridgeif} -autoptp {$realif}");
604
        	}
605
	}
606
	if (!empty($bridge['static'])) {
607
        	$stickyifs = explode(',', $bridge['static']);
608
        	foreach ($stickyifs as $stickyif) {
609
                	$realif = get_real_interface($stickyif);
610
                	mwexec("/sbin/ifconfig {$bridgeif} sticky {$realif}");
611
        	}
612
	}
613
	if (!empty($bridge['private'])) {
614
        	$privateifs = explode(',', $bridge['private']);
615
        	foreach ($privateifs as $privateif) {
616
                	$realif = get_real_interface($privateif);
617
               	 	mwexec("/sbin/ifconfig {$bridgeif} private {$realif}");
618
        	}
619
	}
620

    
621
	if($bridgeif)
622
		interfaces_bring_up($bridgeif);	
623
	else 
624
		log_error(gettext("bridgeif not defined -- could not bring interface up"));
625

    
626
	return $bridgeif;
627
}
628

    
629
function interface_bridge_add_member($bridgeif, $interface) {
630

    
631
	if (!does_interface_exist($bridgeif) || !does_interface_exist($interface))
632
		return;
633

    
634
	$mtu = get_interface_mtu($bridgeif);
635
	$mtum = get_interface_mtu($interface);
636
	
637
	if ($mtu != $mtum && !(substr($interface, 0, 3) == "gif" && $mtu <= 1500))
638
		pfSense_interface_mtu($interface, $mtu);
639

    
640
	$options = pfSense_get_interface_addresses($bridgeif);
641
	$flags = 0;
642
	if (!isset($options['encaps']['txcsum']))
643
		$flags |= IFCAP_TXCSUM;
644

    
645
	if (!isset($options['encaps']['rxcsum']))
646
		$flags |= IFCAP_RXCSUM;
647

    
648
	pfSense_interface_capabilities($interface, -$flags);
649

    
650
	interfaces_bring_up($interface);
651
	pfSense_bridge_add_member($bridgeif, $interface);
652
}
653

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

    
673
function interface_lagg_configure(&$lagg) {
674
        global $config, $g;
675

    
676
        if (!is_array($lagg))
677
		return -1;
678

    
679
	$members = explode(',', $lagg['members']);
680
	if (!count($members))
681
		return -1;
682
	
683
	if ($g['booting'] || !(empty($lagg['laggif']))) {
684
		pfSense_interface_destroy($lagg['laggif']);
685
		pfSense_interface_create($lagg['laggif']);
686
                $laggif = $lagg['laggif'];
687
        } else
688
		$laggif = pfSense_interface_create("lagg");
689

    
690
	/* Calculate smaller mtu and enforce it */
691
        $smallermtu = 0;
692
        foreach ($members as $member) {
693
		$opts = pfSense_get_interface_addresses($member);
694
                $mtu = $opts['mtu'];
695
		if (!isset($opts['encaps']['txcsum']))
696
                        $commontx = false;
697
                if (!isset($opts['encaps']['rxcsum']))
698
                        $commonrx = false;
699
		if (!isset($opts['encaps']['tso4']))
700
			$commontso4 = false;
701
		if (!isset($opts['encaps']['tso6']))
702
			$commontso6 = false;
703
		if (!isset($opts['encaps']['lro']))
704
			$commonlro = false;
705
		if ($smallermtu == 0 && !empty($mtu))
706
			$smallermtu = $mtu;
707
                else if (!empty($mtu) && $mtu < $smallermtu)
708
                        $smallermtu = $mtu;
709
        }
710

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

    
715
	$flags = 0;
716
        if ($commonrx === false)
717
                $flags |= IFCAP_RXCSUM;
718
        if ($commontx === false)
719
                $flags |= IFCAP_TXCSUM;
720
	if ($commontso4 === false)
721
                $flags |= IFCAP_TSO4;
722
        if ($commontso6 === false)
723
                $flags |= IFCAP_TSO6;
724
        if ($commonlro === false)
725
                $flags |= IFCAP_LRO;
726

    
727
	$checklist = get_interface_list();
728

    
729
	foreach ($members as $member) {
730
		if (!array_key_exists($member, $checklist))
731
			continue;
732
		/* make sure the parent interface is up */
733
		pfSense_interface_mtu($member, $smallermtu);
734
		pfSense_interface_capabilities($member, -$flags);
735
		interfaces_bring_up($member);
736
		mwexec("/sbin/ifconfig {$laggif} laggport {$member}");
737
	}
738
	
739
	mwexec("/sbin/ifconfig {$laggif} laggproto {$lagg['proto']}");
740

    
741
	interfaces_bring_up($laggif);
742

    
743
	return $laggif;
744
}
745

    
746
function interfaces_gre_configure($checkparent = 0) {
747
        global $config;
748

    
749
        if (is_array($config['gres']['gre']) && count($config['gres']['gre'])) {
750
                foreach ($config['gres']['gre'] as $i => $gre) {
751
                        if(empty($gre['greif']))
752
                                $gre['greif'] = "gre{$i}";
753
			if ($checkparent == 1 && strstr($gre['if'], "vip"))
754
				continue;
755
			if ($checkparent == 2 && !strstr($gre['if'], "vip"))
756
				continue;
757
                        /* XXX: Maybe we should report any errors?! */
758
                        interface_gre_configure($gre);
759
                }
760
        }
761
}
762

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

    
767
	if (!is_array($gre))
768
		return -1;
769

    
770
	$realif = get_real_interface($gre['if']);
771
	$realifip = get_interface_ip($gre['if']);
772

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

    
776
	if ($g['booting'] || !(empty($gre['greif']))) {
777
		pfSense_interface_destroy($gre['greif']);
778
		pfSense_interface_create($gre['greif']);
779
		$greif = $gre['greif'];
780
	} else
781
		$greif = pfSense_interface_create("gre");
782

    
783
	/* Do not change the order here for more see gre(4) NOTES section. */
784
	mwexec("/sbin/ifconfig {$greif} tunnel {$realifip} {$gre['remote-addr']}");
785
	if((is_ipaddrv6($gre['tunnel-local-addr'])) || (is_ipaddrv6($gre['tunnel-remote-addr']))) {
786
		mwexec("/sbin/ifconfig {$greif} inet6 {$gre['tunnel-local-addr']} {$gre['tunnel-remote-addr']} prefixlen /{$gre['tunnel-remote-net']} ");
787
	} else {
788
		mwexec("/sbin/ifconfig {$greif} {$gif['tunnel-local-addr']} {$gre['tunnel-remote-addr']} netmask " . gen_subnet_mask($gre['tunnel-remote-net']));
789
	}
790
	if (isset($gre['link0']) && $gre['link0'])
791
		pfSense_interface_flags($greif, IFF_LINK0);
792
	if (isset($gre['link1']) && $gre['link1'])
793
		pfSense_interface_flags($greif, IFF_LINK1);
794
	if (isset($gre['link2']) && $gre['link2'])
795
		pfSense_interface_flags($greif, IFF_LINK2);
796

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

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

    
809
	return $greif;
810
}
811

    
812
function interfaces_gif_configure($checkparent = 0) {
813
	global $config;
814

    
815
	if (is_array($config['gifs']['gif']) && count($config['gifs']['gif'])) {
816
		foreach ($config['gifs']['gif'] as $i => $gif) {
817
			if(empty($gif['gifif']))
818
				$gre['gifif'] = "gif{$i}";
819
			if ($checkparent == 1 && strstr($gif['if'], "vip"))
820
				continue;
821
			if ($checkparent == 2 && !strstr($gif['if'], "vip"))
822
				continue;
823
			/* XXX: Maybe we should report any errors?! */
824
			interface_gif_configure($gif);
825
		}
826
	}
827
}
828

    
829
/* NOTE: $gifkey is not used but useful for passing this function to array_walk. */
830
function interface_gif_configure(&$gif, $gifkey = "") {
831
	global $config, $g;
832

    
833
	if (!is_array($gif))
834
		return -1;
835

    
836
	$realif = get_real_interface($gif['if']);
837
	$realifip = get_interface_ip($gif['if']);
838

    
839
	/* make sure the parent interface is up */
840
	if($realif)
841
		interfaces_bring_up($realif);
842
	else 
843
		log_error(gettext("could not bring realif up -- variable not defined -- interface_gif_configure()"));
844

    
845
	if ($g['booting'] || !(empty($gif['gifif']))) {
846
		pfSense_interface_destroy($gif['gifif']);
847
		pfSense_interface_create($gif['gifif']);
848
		$gifif = $gif['gifif'];
849
	} else
850
		$gifif = pfSense_interface_create("gif");
851

    
852
	/* Do not change the order here for more see gif(4) NOTES section. */
853
	mwexec("/sbin/ifconfig {$gifif} tunnel {$realifip} {$gif['remote-addr']}");
854
	if((is_ipaddrv6($gif['tunnel-local-addr'])) || (is_ipaddrv6($gif['tunnel-remote-addr']))) {
855
		mwexec("/sbin/ifconfig {$gifif} inet6 {$gif['tunnel-local-addr']} {$gif['tunnel-remote-addr']} prefixlen /{$gif['tunnel-remote-net']} ");
856
	} else {
857
		mwexec("/sbin/ifconfig {$gifif} {$gif['tunnel-local-addr']} {$gif['tunnel-remote-addr']} netmask " . gen_subnet_mask($gif['tunnel-remote-net']));
858
	}
859
	if (isset($gif['link0']) && $gif['link0'])
860
		pfSense_interface_flags($gifif, IFF_LINK0);
861
	if (isset($gif['link1']) && $gif['link1'])
862
		pfSense_interface_flags($gifif, IFF_LINK1);
863
	if($gifif)
864
		interfaces_bring_up($gifif);
865
	else
866
		log_error(gettext("could not bring gifif up -- variable not defined"));
867

    
868
	$iflist = get_configured_interface_list();
869
	foreach($iflist as $ifname) {
870
		if($config['interfaces'][$ifname]['if'] == $gifif) {
871
			if(get_interface_gateway($ifname)) {
872
				system_routing_configure($ifname);
873
				break;
874
			}
875
			if(get_interface_gateway_v6($ifname)) {
876
				system_routing_configure($ifname);
877
				break;
878
			}
879
		}
880
	}
881

    
882

    
883
	if(is_ipaddrv4($gif['tunnel-remote-addr']))
884
		file_put_contents("{$g['tmp_path']}/{$gifif}_router", $gif['tunnel-remote-addr']);
885
	if(is_ipaddrv6($gif['tunnel-remote-addr']))
886
		file_put_contents("{$g['tmp_path']}/{$gifif}_routerv6", $gif['tunnel-remote-addr']);
887

    
888
	return $gifif;
889
}
890

    
891
function interfaces_configure() {
892
	global $config, $g;
893

    
894
	if ($g['platform'] == 'jail')
895
		return;
896

    
897
	/* Set up our loopback interface */
898
	interfaces_loopback_configure();
899

    
900
	/* set up LAGG virtual interfaces */
901
	interfaces_lagg_configure();
902

    
903
	/* set up VLAN virtual interfaces */
904
	interfaces_vlan_configure();
905

    
906
	interfaces_qinq_configure();
907

    
908
	$iflist = get_configured_interface_with_descr();
909
	$delayed_list = array();
910
	$bridge_list = array();
911
	
912
	/* This is needed to speedup interfaces on bootup. */
913
	$reload = false;
914
	if ($g['booting'])
915
		$reload = true;
916

    
917
	foreach($iflist as $if => $ifname) {
918
		$realif = $config['interfaces'][$if]['if'];
919
		if (strstr($realif, "bridge")) 
920
			$bridge_list[$if] = $ifname;
921
		else if (strstr($realif, "gre"))
922
			$delayed_list[$if] = $ifname;
923
		else if (strstr($realif, "gif"))
924
			$delayed_list[$if] = $ifname;
925
		else if (strstr($realif, "ovpn")) {
926
			//echo "Delaying OpenVPN interface configuration...done.\n";
927
			continue;
928
		} else {
929
			if ($g['booting'])
930
				printf(gettext("Configuring %s interface..."), $ifname);
931

    
932
			if($g['debug'])
933
				log_error(sprintf(gettext("Configuring %s"), $ifname));
934
			interface_configure($if, $reload);
935
			if ($g['booting']) 
936
				echo gettext( "done.") . "\n";
937
		}
938
	}
939

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

    
943
	/*
944
	 * NOTE: The following function parameter consists of
945
	 *	1 - Do not load gre/gif/bridge with parent/member as vip
946
	 *	2 - Do load gre/gif/bridge with parent/member as vip
947
	 */
948

    
949
	/* set up GRE virtual interfaces */
950
	interfaces_gre_configure(1);
951

    
952
	/* set up GIF virtual interfaces */
953
	interfaces_gif_configure(1);
954

    
955
	/* set up BRIDGe virtual interfaces */
956
	interfaces_bridge_configure(1);
957

    
958
	/* bring up vip interfaces */
959
	interfaces_vips_configure();
960

    
961
	/* set up GRE virtual interfaces */
962
	interfaces_gre_configure(2);
963

    
964
	/* set up GIF virtual interfaces */
965
	interfaces_gif_configure(2);
966

    
967
	foreach ($delayed_list as $if => $ifname) {
968
		if ($g['booting'])
969
			printf(gettext("Configuring %s interface..."), $ifname);
970
        	if ($g['debug'])
971
        		log_error(sprintf(gettext("Configuring %s"), $ifname));
972

    
973
		interface_configure($if, $reload);
974

    
975
		if ($g['booting'])
976
			echo gettext("done.") . "\n";
977
	}
978

    
979
	/* set up BRIDGe virtual interfaces */
980
	interfaces_bridge_configure(2);
981

    
982
	foreach ($bridge_list as $if => $ifname) {
983
		if ($g['booting'])
984
			printf(gettext("Configuring %s interface..."), $ifname);
985
		if($g['debug'])
986
			log_error(sprintf(gettext("Configuring %s"), $ifname));
987

    
988
		interface_configure($if, $reload);
989

    
990
		if ($g['booting'])
991
			echo gettext("done.") . "\n";
992
	}
993

    
994
	/* configure interface groups */
995
	interfaces_group_setup();
996

    
997
	if (!$g['booting']) {
998
		/* reconfigure static routes (kernel may have deleted them) */
999
		system_routing_configure();
1000

    
1001
		/* reload IPsec tunnels */
1002
		vpn_ipsec_configure();
1003

    
1004
		/* reload dhcpd (interface enabled/disabled status may have changed) */
1005
		services_dhcpd_configure();
1006

    
1007
		/* restart dnsmasq */
1008
		services_dnsmasq_configure();
1009

    
1010
		/* reload captive portal */
1011
		captiveportal_init_rules();
1012
	}
1013

    
1014
	return 0;
1015
}
1016

    
1017
function interface_reconfigure($interface = "wan", $reloadall = false) {
1018
	interface_bring_down($interface);
1019
	interface_configure($interface, $reloadall);
1020
}
1021

    
1022
function interface_vip_bring_down($vip) {
1023
	global $g;
1024

    
1025
	switch ($vip['mode']) {
1026
	case "proxyarp":
1027
		$vipif = get_real_interface($vip['interface']);
1028
		if (file_exists("{$g['varrun_path']}/choparp_{$vipif}.pid"))
1029
			killbypid("{$g['varrun_path']}/choparp_{$vipif}.pid");
1030
		break;
1031
	case "ipalias":
1032
		$vipif = get_real_interface($vip['interface']);
1033
		if(does_interface_exist($vipif))
1034
			pfSense_interface_deladdress($vipif, $vip['subnet']);
1035
		break;
1036
	case "carp":
1037
		$vipif = "vip" . $vip['vhid'];
1038
		if(does_interface_exist($vipif)) 
1039
			pfSense_interface_destroy($vipif);
1040
		break;
1041
	case "carpdev-dhcp":
1042
		$vipif = "vip" . $vip['vhid'];
1043
		if(does_interface_exist($vipif)) 
1044
			pfSense_interface_destroy($vipif);
1045
		break;
1046
	}
1047
}
1048

    
1049
function interface_bring_down($interface = "wan", $destroy = false) {
1050
	global $config, $g;
1051

    
1052
	if (!isset($config['interfaces'][$interface]))
1053
		return; 
1054

    
1055
	log_error("Calling interface down for interface {$interface}, destroy is {$destroy}");
1056

    
1057
	$ifcfg = $config['interfaces'][$interface];
1058

    
1059
	$realif = get_real_interface($interface);
1060

    
1061
	switch ($ifcfg['ipaddr']) {
1062
	case "ppp":
1063
	case "pppoe":
1064
	case "pptp":
1065
	case "l2tp":
1066
		if (is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) {
1067
			foreach ($config['ppps']['ppp'] as $pppid => $ppp) {
1068
				if ($realif == $ppp['if']) {
1069
					if (isset($ppp['ondemand']) && !$destroy){
1070
						send_event("interface reconfigure {$interface}");
1071
						break;
1072
					}
1073
					if (file_exists("{$g['varrun_path']}/{$ppp['type']}_{$interface}.pid")) {
1074
						killbypid("{$g['varrun_path']}/{$ppp['type']}_{$interface}.pid");
1075
						sleep(2);
1076
					}
1077
					unlink_if_exists("{$g['varetc_path']}/mpd_{$interface}.conf");
1078
					break;
1079
				}
1080
			}
1081
		}
1082
		break;
1083
	case "carpdev-dhcp":
1084
		/* 
1085
		 * NB: When carpdev gets enabled it would be better to be handled as all
1086
		 *	   other interfaces! 
1087
		 */
1088
	case "dhcp":
1089
		$pid = find_dhclient_process($realif);
1090
		if($pid)
1091
			mwexec("/bin/kill {$pid}");
1092
		sleep(1);
1093
		unlink_if_exists("{$g['varetc_path']}/dhclient_{$interface}.conf");
1094
		if(does_interface_exist("$realif")) {
1095
			mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete", true);
1096
			if ($destroy == true)
1097
				pfSense_interface_flags($realif, -IFF_UP);
1098
			mwexec("/usr/sbin/arp -d -i {$realif} -a");
1099
		}
1100
		break;
1101
	default:
1102
		if(does_interface_exist("$realif")) {
1103
			mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete", true);
1104
			if ($destroy == true)
1105
				pfSense_interface_flags($realif, -IFF_UP);
1106
			mwexec("/usr/sbin/arp -d -i {$realif} -a");
1107
		}
1108
		break;
1109
	}
1110

    
1111
	switch ($ifcfg['ipaddrv6']) {
1112
	case "dhcp6":
1113
		$pidv6 = find_dhcp6c_process($realif);
1114
		if($pidv6)
1115
			mwexec("/bin/kill {$pidv6}");
1116
		sleep(3);
1117
		unlink_if_exists("{$g['varetc_path']}/dhcp6c_{$interface}.conf");
1118
		if(does_interface_exist("$realif")) {
1119
			mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete", true);
1120
			if ($destroy == true)
1121
				pfSense_interface_flags($realif, -IFF_UP);
1122
			mwexec("/usr/sbin/arp -d -i {$realif} -a");
1123
		}
1124
		break;
1125
	case "6rd":
1126
		$realif = "srd0";
1127
		if(does_interface_exist("$realif")) {
1128
			mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete", true);
1129
			if ($destroy == true)
1130
				pfSense_interface_flags($realif, -IFF_UP);
1131
		}		
1132
		break;
1133
	case "6to4":
1134
		$realif = "stf0";
1135
		if(does_interface_exist("$realif")) {
1136
			mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete", true);
1137
			if ($destroy == true)
1138
				pfSense_interface_flags($realif, -IFF_UP);
1139
		}		
1140
		break;
1141
	default:
1142
		if(does_interface_exist("$realif")) {
1143
			mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete", true);
1144
			if ($destroy == true)
1145
				pfSense_interface_flags($realif, -IFF_UP);
1146
			mwexec("/usr/sbin/arp -d -i {$realif} -a");
1147
		}
1148
		break;
1149
	}
1150

    
1151

    
1152
	/* remove interface up file if it exists */
1153
	unlink_if_exists("{$g['tmp_path']}/{$realif}up");
1154
	unlink_if_exists("{$g['vardb_path']}/{$interface}ip");
1155
	unlink_if_exists("{$g['vardb_path']}/{$interface}ipv6");
1156
	unlink_if_exists("{$g['tmp_path']}/{$realif}_router");
1157
	unlink_if_exists("{$g['tmp_path']}/{$realif}_routerv6");
1158
	unlink_if_exists("{$g['varetc_path']}/nameserver_{$realif}");
1159
	unlink_if_exists("{$g['varetc_path']}/searchdomain_{$realif}");
1160
	
1161
	/* hostapd and wpa_supplicant do not need to be running when the interface is down.
1162
	 * They will also use 100% CPU if running after the wireless clone gets deleted. */
1163
	if (is_array($ifcfg['wireless'])) {
1164
		mwexec(kill_hostapd($realif));
1165
		mwexec(kill_wpasupplicant($realif));
1166
	}
1167

    
1168
	if ($destroy == true) {
1169
		if (preg_match("/^vip|^tun|^ovpn|^gif|^gre|^lagg|^bridge|vlan|^stf|^srd/i", $realif))
1170
			pfSense_interface_destroy($realif);
1171
	}	
1172

    
1173
	return;
1174
}
1175

    
1176
function interfaces_ptpid_used($ptpid) {
1177
	global $config;
1178

    
1179
	if (is_array($config['ppps']['ppp']))
1180
		foreach ($config['ppps']['ppp'] as & $settings)
1181
			if ($ptpid == $settings['ptpid'])
1182
				return true;
1183

    
1184
	return false;
1185
}
1186

    
1187
function interfaces_ptpid_next() {
1188

    
1189
	$ptpid = 0;
1190
	while(interfaces_ptpid_used($ptpid))
1191
		$ptpid++;
1192

    
1193
	return $ptpid;
1194
}
1195

    
1196
function getMPDCRONSettings($pppif_) {
1197
	global $config;
1198
	$cron_cmd_file = "{$g['varetc_path']}/pppoe_restart_";
1199
	if (is_array($config['cron']['item'])) {
1200
		for ($i = 0; $i < count($config['cron']['item']); $i++) {
1201
			$item = $config['cron']['item'][$i];
1202
			if (strpos($item['command'], $cron_cmd_file.$pppif_) !== false) {
1203
				return array("ID" => $i, "ITEM" => $item);
1204
			}
1205
		}
1206
	}
1207
	return NULL;
1208
}
1209

    
1210
function handle_pppoe_reset($post_array) {
1211
	global $config, $g;
1212

    
1213
	$cron_cmd_file = "{$g['varetc_path']}/pppoe_restart_";
1214

    
1215
	$pppif = $post_array['type'].$post_array['ptpid'];
1216
	if (!is_array($config['cron']['item'])) 
1217
		$config['cron']['item'] = array(); 
1218
	$itemhash = getMPDCRONSettings($pppif);
1219
	$item = $itemhash['ITEM'];
1220
	
1221
	// reset cron items if necessary and return
1222
	if (empty($post_array['pppoe-reset-type'])) {
1223
		if (isset($item))
1224
			unset($config['cron']['item'][$itemhash['ID']]);
1225
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
1226
		return;
1227
	}
1228

    
1229
	if (empty($item)) 
1230
		$item = array();
1231
	if (isset($post_array['pppoe-reset-type']) && $post_array['pppoe-reset-type'] == "custom") {
1232
		$item['minute'] = $post_array['pppoe_resetminute'];
1233
		$item['hour'] = $post_array['pppoe_resethour'];
1234
		if (isset($post_array['pppoe_resetdate']) && $post_array['pppoe_resetdate'] <> "") {
1235
			$date = explode("/", $post_array['pppoe_resetdate']);
1236
			$item['mday'] = $date[1];
1237
			$item['month'] = $date[0];
1238
		} else {
1239
			$item['mday'] = "*";
1240
			$item['month'] = "*";
1241
		}
1242
		$item['wday'] = "*";
1243
		$item['who'] = "root";
1244
		$item['command'] = $cron_cmd_file.$pppif;
1245
	} else if (isset($post_array['pppoe-reset-type']) && $post_array['pppoe-reset-type'] == "preset") {
1246
		switch ($post_array['pppoe_pr_preset_val']) {
1247
			case "monthly":
1248
				$item['minute'] = "0";
1249
				$item['hour'] = "0";
1250
				$item['mday'] = "1";
1251
				$item['month'] = "*";
1252
				$item['wday'] = "*";
1253
				$item['who'] = "root";
1254
				$item['command'] = $cron_cmd_file.$pppif;
1255
				break;
1256
	        case "weekly":
1257
				$item['minute'] = "0";
1258
				$item['hour'] = "0";
1259
				$item['mday'] = "*";
1260
				$item['month'] = "*";
1261
				$item['wday'] = "0";
1262
				$item['who'] = "root";
1263
				$item['command'] = $cron_cmd_file.$pppif;
1264
				break;
1265
			case "daily":
1266
				$item['minute'] = "0";
1267
				$item['hour'] = "0";
1268
				$item['mday'] = "*";
1269
				$item['month'] = "*";
1270
				$item['wday'] = "*";
1271
				$item['who'] = "root";
1272
				$item['command'] = $cron_cmd_file.$pppif;
1273
				break;
1274
			case "hourly":
1275
				$item['minute'] = "0";
1276
				$item['hour'] = "*";
1277
				$item['mday'] = "*";
1278
				$item['month'] = "*";
1279
				$item['wday'] = "*";
1280
				$item['who'] = "root";
1281
				$item['command'] = $cron_cmd_file.$pppif;
1282
				break;
1283
		} // end switch
1284
	} else {
1285
		/* test whether a cron item exists and unset() it if necessary */
1286
		$itemhash = getMPDCRONSettings($pppif);
1287
		$item = $itemhash['ITEM'];
1288
		if (isset($item))
1289
			unset($config['cron']['item'][$itemhash['ID']]); 
1290
	}// end if
1291
	if (isset($itemhash['ID'])) 
1292
		$config['cron']['item'][$itemhash['ID']] = $item;
1293
	else 
1294
		$config['cron']['item'][] = $item;
1295
}
1296

    
1297
/*	This function can configure PPPoE, MLPPP (PPPoE), PPTP.
1298
*	It writes the mpd config file to /var/etc every time the link is opened.
1299
*/
1300

    
1301
function interface_ppps_configure($interface) {
1302
	global $config, $g;
1303

    
1304
	/* Return for unassigned interfaces. This is a minimum requirement. */
1305
	if (empty($config['interfaces'][$interface]))
1306
		return 0;
1307
	$ifcfg = $config['interfaces'][$interface];
1308
	if (!isset($ifcfg['enable']))
1309
		return 0;
1310

    
1311
	// mpd5 requires a /var/spool/lock directory for PPP modem links.
1312
	if(!is_dir("/var/spool/lock")) {
1313
		exec("/bin/mkdir -p /var/spool/lock");
1314
		exec("/bin/chmod a+rw /var/spool/lock/.");
1315
	}
1316
	// mpd5 modem chat script expected in the same directory as the mpd_xxx.conf files	
1317
	if (!file_exists("{$g['varetc_path']}/mpd.script"))
1318
		mwexec("/bin/ln -s /usr/local/sbin/mpd.script {$g['varetc_path']}/.");
1319

    
1320
	if (is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) {
1321
		foreach ($config['ppps']['ppp'] as $pppid => $ppp) {
1322
			if ($ifcfg['if'] == $ppp['if'])
1323
				break;
1324
		}
1325
	}
1326
	if (!$ppp || $ifcfg['if'] != $ppp['if']){
1327
		log_error(sprintf(gettext("Can't find PPP config for %s in interface_ppps_configure()."), $ifcfg['if']));
1328
		return 0;
1329
	}
1330
	$pppif = $ifcfg['if'];
1331
	if ($ppp['type'] == "ppp")
1332
		$type = "modem";
1333
	else
1334
		$type = $ppp['type'];
1335
	$upper_type = strtoupper($ppp['type']);	
1336

    
1337
	if($g['booting']) {
1338
		$descr = isset($ifcfg['descr']) ? $ifcfg['descr'] : strtoupper($interface);
1339
		echo "starting {$pppif} link...";
1340
		// Do not re-configure the interface if we are booting and it's already been started
1341
		if(file_exists("{$g['varrun_path']}/{$ppp['type']}_{$interface}.pid"))
1342
			return 0;
1343
	}
1344

    
1345
	$ports = explode(',',$ppp['ports']);
1346
	if ($type != "modem") {
1347
		foreach ($ports as $pid => $port)
1348
			$ports[$pid] = get_real_interface($port);
1349
	}
1350
	$localips = explode(',',$ppp['localip']);
1351
	$gateways = explode(',',$ppp['gateway']);
1352
	$subnets = explode(',',$ppp['subnet']);
1353

    
1354
	/* We bring up the parent interface first because if DHCP is configured on the parent we need
1355
	 * to obtain an address first so we can write it in the mpd .conf file for PPTP and L2TP configs
1356
	 */
1357
	foreach($ports as $pid => $port){
1358
		switch ($ppp['type']) {
1359
			case "pppoe": 
1360
				/* Bring the parent interface up */
1361
				interfaces_bring_up($port);
1362
				pfSense_ngctl_attach(".", $port);
1363
				break;
1364
			case "pptp":
1365
			case "l2tp":
1366
				/* configure interface */
1367
				if(is_ipaddr($localips[$pid])){
1368
					// Manually configure interface IP/subnet
1369
					pfSense_interface_setaddress($port, "{$localips[$pid]}/{$subnets[$pid]}");
1370
					interfaces_bring_up($port);
1371
				} else if (empty($localips[$pid]))
1372
					$localips[$pid] = get_interface_ip($port); // try to get the interface IP from the port
1373
				
1374
				if(!is_ipaddr($localips[$pid])){
1375
					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!");
1376
					$localips[$pid] = "0.0.0.0";
1377
				}
1378
				/* XXX: This needs to go away soon! [It's commented out!] */
1379
				/* Configure the gateway (remote IP ) */
1380
				if (!$g['booting'] && !is_ipaddr($gateways[$pid]) && is_hostname($gateways[$pid])) {
1381
					/* XXX: Fix later 
1382
					$gateways[$pid] = gethostbyname($gateways[$pid]);
1383
					if(!is_ipaddr($gateways[$pid])) {
1384
						log_error("Could not get a valid Gateway IP from {$port} via DNS in interfaces_ppps_configure.");
1385
						return 0;
1386
					}
1387
					*/
1388
				}
1389
				if(!is_ipaddr($gateways[$pid])){
1390
					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));
1391
					return 0;
1392
				}
1393
				pfSense_ngctl_attach(".", $port);
1394
				break;
1395
			case "ppp":
1396
				if (!file_exists("{$port}")) {
1397
					log_error(sprintf(gettext("Device %s does not exist. PPP link cannot start without the modem device."), $port));
1398
					return 0;
1399
				}
1400
				break;
1401
			default:
1402
				log_error(sprintf(gettext("Unkown %s configured as ppp interface."), $type));
1403
				break;
1404
		}
1405
	}
1406
	
1407
	if (is_array($ports) && count($ports) > 1)
1408
		$multilink = "enable";
1409
	else
1410
		$multilink = "disable";
1411
	
1412
	if ($type == "modem"){
1413
		if (is_ipaddr($ppp['localip']))
1414
			$localip = $ppp['localip'];
1415
		else
1416
			$localip = '0.0.0.0';
1417

    
1418
		if (is_ipaddr($ppp['gateway']))
1419
			$gateway = $ppp['gateway'];
1420
		else
1421
			$gateway = "10.64.64.{$pppid}";
1422
		$ranges = "{$localip}/0 {$gateway}/0";
1423
		
1424
		if (empty($ppp['apnum']))	
1425
			$ppp['apnum'] = 1;
1426
	} else
1427
		$ranges = "0.0.0.0/0 0.0.0.0/0";
1428

    
1429
	if (isset($ppp['ondemand'])) 
1430
		$ondemand = "enable";
1431
	else
1432
		$ondemand = "disable";
1433
	if (!isset($ppp['idletimeout']))
1434
		$ppp['idletimeout'] = 0;
1435

    
1436
	if (empty($ppp['username']) && $type == "modem"){
1437
		$ppp['username'] = "user";
1438
		$ppp['password'] = "none";
1439
	}
1440
	if (empty($ppp['password']) && $type == "modem")
1441
		$passwd = "none";
1442
	else
1443
		$passwd = base64_decode($ppp['password']);
1444

    
1445
	$bandwidths = explode(',',$ppp['bandwidth']);
1446
	$mtus = explode(',',$ppp['mtu']);
1447
	$mrus = explode(',',$ppp['mru']);
1448

    
1449
	if (isset($ppp['mrru']))
1450
		$mrrus = explode(',',$ppp['mrru']);
1451

    
1452
	// Construct the mpd.conf file
1453
	$mpdconf = <<<EOD
1454
startup:
1455
	# configure the console
1456
	set console close
1457
	# configure the web server
1458
	set web close
1459

    
1460
default:
1461
{$ppp['type']}client:
1462
	create bundle static {$interface}
1463
	set bundle enable ipv6cp
1464
	set iface name {$pppif}
1465

    
1466
EOD;
1467
	$setdefaultgw = false;
1468
	$founddefaultgw = false;
1469
	if (is_array($config['gateways']['gateway_item'])) {
1470
		foreach($config['gateways']['gateway_item'] as $gateway) {
1471
			if($interface == $gateway['interface'] && isset($gateway['defaultgw'])) {
1472
				$setdefaultgw = true;
1473
				break;
1474
			} else if (isset($gateway['defaultgw']) && !empty($gateway['interface'])) {
1475
				$founddefaultgw = true;
1476
				break;
1477
			}
1478
		}
1479
	}
1480
	
1481
	if (($interface == "wan" && $founddefaultgw == false) || $setdefaultgw == true){
1482
		$setdefaultgw = true;
1483
		$mpdconf .= <<<EOD
1484
	set iface route default
1485

    
1486
EOD;
1487
	}
1488
	$mpdconf .= <<<EOD
1489
	set iface {$ondemand} on-demand
1490
	set iface idle {$ppp['idletimeout']}
1491

    
1492
EOD;
1493

    
1494
	if (isset($ppp['ondemand']))
1495
		$mpdconf .= <<<EOD
1496
	set iface addrs 10.10.1.1 10.10.1.2
1497

    
1498
EOD;
1499
	
1500
	if (isset($ppp['tcpmssfix']))
1501
		$tcpmss = "disable";
1502
	else
1503
		$tcpmss = "enable";
1504
		$mpdconf .= <<<EOD
1505
	set iface {$tcpmss} tcpmssfix
1506

    
1507
EOD;
1508

    
1509
	$mpdconf .= <<<EOD
1510
	set iface up-script /usr/local/sbin/ppp-linkup
1511
	set iface down-script /usr/local/sbin/ppp-linkdown
1512
	set ipcp ranges {$ranges}
1513

    
1514
EOD;
1515
	if (isset($ppp['vjcomp']))
1516
		$mpdconf .= <<<EOD
1517
	set ipcp no vjcomp
1518

    
1519
EOD;
1520

    
1521
	if (isset($config['system']['dnsallowoverride']))
1522
		$mpdconf .= <<<EOD
1523
	set ipcp enable req-pri-dns
1524
	set ipcp enable req-sec-dns
1525

    
1526
EOD;
1527
	if (!isset($ppp['verbose_log']))
1528
		$mpdconf .= <<<EOD
1529
	#log -bund -ccp -chat -iface -ipcp -lcp -link
1530

    
1531
EOD;
1532
	foreach($ports as $pid => $port){
1533
		$port = get_real_interface($port);
1534
		$mpdconf .= <<<EOD
1535

    
1536
	create link static {$interface}_link{$pid} {$type}
1537
	set link action bundle {$interface}
1538
	set link {$multilink} multilink
1539
	set link keep-alive 10 60
1540
	set link max-redial 0
1541

    
1542
EOD;
1543
		if (isset($ppp['shortseq']))
1544
			$mpdconf .= <<<EOD
1545
	set link no shortseq
1546

    
1547
EOD;
1548

    
1549
		if (isset($ppp['acfcomp']))
1550
			$mpdconf .= <<<EOD
1551
	set link no acfcomp
1552

    
1553
EOD;
1554

    
1555
		if (isset($ppp['protocomp']))
1556
			$mpdconf .= <<<EOD
1557
	set link no protocomp
1558

    
1559
EOD;
1560

    
1561
		$mpdconf .= <<<EOD
1562
	set link disable chap pap
1563
	set link accept chap pap eap
1564
	set link disable incoming
1565

    
1566
EOD;
1567

    
1568

    
1569
		if (!empty($bandwidths[$pid]))
1570
			$mpdconf .= <<<EOD
1571
	set link bandwidth {$bandwidths[$pid]}
1572

    
1573
EOD;
1574

    
1575
		if (empty($mtus[$pid]))
1576
			$mtus[$pid] = "1492";
1577
			$mpdconf .= <<<EOD
1578
	set link mtu {$mtus[$pid]}
1579

    
1580
EOD;
1581

    
1582
		if (!empty($mrus[$pid]))
1583
			$mpdconf .= <<<EOD
1584
	set link mru {$mrus[$pid]}
1585

    
1586
EOD;
1587

    
1588
		if (!empty($mrrus[$pid]))
1589
			$mpdconf .= <<<EOD
1590
	set link mrru {$mrrus[$pid]}
1591

    
1592
EOD;
1593

    
1594
		$mpdconf .= <<<EOD
1595
	set auth authname "{$ppp['username']}"
1596
	set auth password {$passwd}
1597

    
1598
EOD;
1599
		if ($type == "modem") {
1600
			$mpdconf .= <<<EOD
1601
	set modem device {$ppp['ports']}
1602
	set modem script DialPeer
1603
	set modem idle-script Ringback
1604
	set modem watch -cd
1605
	set modem var \$DialPrefix "DT"
1606
	set modem var \$Telephone "{$ppp['phone']}"
1607

    
1608
EOD;
1609
		}
1610
		if (isset($ppp['connect-timeout']) && $type == "modem") {
1611
			$mpdconf .= <<<EOD
1612
	set modem var \$ConnectTimeout "{$ppp['connect-timeout']}"
1613

    
1614
EOD;
1615
		}
1616
		if (isset($ppp['initstr']) && $type == "modem") {
1617
			$initstr = base64_decode($ppp['initstr']);
1618
			$mpdconf .= <<<EOD
1619
	set modem var \$InitString "{$initstr}"
1620

    
1621
EOD;
1622
		}
1623
		if (isset($ppp['simpin']) && $type == "modem") {
1624
			$mpdconf .= <<<EOD
1625
	set modem var \$SimPin "{$ppp['simpin']}"
1626
	set modem var \$PinWait "{$ppp['pin-wait']}"
1627

    
1628
EOD;
1629
		}
1630
		if (isset($ppp['apn']) && $type == "modem") {
1631
			$mpdconf .= <<<EOD
1632
	set modem var \$APN "{$ppp['apn']}"
1633
	set modem var \$APNum "{$ppp['apnum']}"
1634

    
1635
EOD;
1636
		}
1637
		if ($type == "pppoe") {
1638
			// Send a null service name if none is set.
1639
			$provider = isset($ppp['provider']) ? $ppp['provider'] : "";
1640
			$mpdconf .= <<<EOD
1641
	set pppoe service "{$provider}"
1642

    
1643
EOD;
1644
		}
1645
		if ($type == "pppoe")
1646
			$mpdconf .= <<<EOD
1647
	set pppoe iface {$port}
1648

    
1649
EOD;
1650

    
1651
		if ($type == "pptp" || $type == "l2tp") {
1652
			$mpdconf .= <<<EOD
1653
	set {$type} self {$localips[$pid]}
1654
	set {$type} peer {$gateways[$pid]}
1655

    
1656
EOD;
1657
		}
1658
		
1659
		$mpdconf .= "\topen\r\n";
1660
	} //end foreach($port)
1661

    
1662

    
1663
	/* Generate mpd.conf. If mpd_[interface].conf exists in the conf path, then link to it instead of generating a fresh conf file. */
1664
	if (file_exists("{$g['conf_path']}/mpd_{$interface}.conf"))
1665
		mwexec("/bin/ln -s {$g['conf_path']}/mpd_{$interface}.conf {$g['varetc_path']}/.");
1666
	else {
1667
		$fd = fopen("{$g['varetc_path']}/mpd_{$interface}.conf", "w");
1668
		if (!$fd) {
1669
			log_error(sprintf(gettext("Error: cannot open mpd_%s.conf in interface_ppps_configure().%s"), $interface, "\n"));
1670
			return 0;
1671
		}
1672
		// Write out mpd_ppp.conf
1673
		fwrite($fd, $mpdconf);
1674
		fclose($fd);
1675
	}
1676

    
1677
	// Create the uptime log if requested and if it doesn't exist already, or delete it if it is no longer requested.
1678
	if (isset($ppp['uptime'])) {
1679
		if (!file_exists("/conf/{$pppif}.log")) {
1680
			conf_mount_rw();
1681
			mwexec("echo /dev/null > /conf/{$pppif}.log");
1682
			conf_mount_ro();
1683
		}
1684
	} else {
1685
		if (file_exists("/conf/{$pppif}.log")) {
1686
			conf_mount_rw();
1687
			mwexec("rm -f /conf/{$pppif}.log");
1688
			conf_mount_ro();
1689
		}
1690
	}
1691

    
1692
	/* fire up mpd */
1693
	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");
1694

    
1695
	// Check for PPPoE periodic reset request 
1696
	if ($type == "pppoe") {
1697
		if (isset($ppp['pppoe-reset-type']))
1698
			setup_pppoe_reset_file($ppp['if'], $interface);
1699
		else
1700
			setup_pppoe_reset_file($ppp['if']);
1701
	}
1702
	/* wait for upto 10 seconds for the interface to appear (ppp(oe)) */
1703
	$i = 0;
1704
	while($i < 10) {
1705
		exec("/sbin/ifconfig {$ppp['if']} 2>&1", $out, $ret);
1706
		if($ret == 0)
1707
			break;
1708
		sleep(1);
1709
		$i++;
1710
	}
1711

    
1712
	return 1;
1713
}
1714

    
1715
function interfaces_carp_setup() {
1716
	global $g, $config;
1717

    
1718
	$balanacing = "";
1719
	$pfsyncinterface = "";
1720
	$pfsyncenabled = "";
1721
	if(isset($config['system']['developerspew'])) {
1722
		$mt = microtime();
1723
		echo "interfaces_carp_setup() being called $mt\n";
1724
	}
1725

    
1726
	// Prepare CmdCHAIN that will be used to execute commands.
1727
	$cmdchain = new CmdCHAIN();	
1728

    
1729
	if ($g['booting']) {
1730
		echo gettext("Configuring CARP settings...");
1731
		mute_kernel_msgs();
1732
	}
1733

    
1734
	/* suck in configuration items */
1735
	if($config['hasync']) {
1736
		$pfsyncenabled = $config['hasync']['pfsyncenabled'];
1737
		$balanacing = $config['hasync']['balancing'];
1738
		$pfsyncinterface = $config['hasync']['pfsyncinterface'];
1739
		$pfsyncpeerip = $config['hasync']['pfsyncpeerip'];
1740
	} else {
1741
		unset($pfsyncinterface);
1742
		unset($balanacing);
1743
		unset($pfsyncenabled);
1744
	}
1745

    
1746
	if($balanacing) {
1747
		$cmdchain->add(gettext("Enable CARP ARP-balancing"), "/sbin/sysctl net.inet.carp.arpbalance=1", true);
1748
		$cmdchain->add(gettext("Disallow CARP preemption"), "/sbin/sysctl net.inet.carp.preempt=0", true);
1749
	} else
1750
		$cmdchain->add(gettext("Enable CARP preemption"), "/sbin/sysctl net.inet.carp.preempt=1", true);		
1751

    
1752
	$cmdchain->add(gettext("Enable CARP logging"), "/sbin/sysctl net.inet.carp.log=1", true);
1753
	if (!empty($pfsyncinterface))
1754
		$carp_sync_int = get_real_interface($pfsyncinterface);
1755

    
1756
	if($g['booting']) {
1757
		/*    install rules to alllow pfsync to sync up during boot
1758
		 *    carp interfaces will remain down until the bootup sequence finishes
1759
		 */
1760
		$fd = fopen("{$g['tmp_path']}/rules.boot", "w");
1761
		if ($fd) {
1762
			fwrite($fd, "block quick proto carp \n");
1763
			fwrite($fd, "block quick proto pfsync \n");
1764
			fwrite($fd, "pass out quick from any to any keep state\n");
1765
			fclose($fd);
1766
			mwexec("/sbin/pfctl -f {$g['tmp_path']}/rules.boot");
1767
		} else
1768
			log_error(gettext("Could not create rules.boot file!"));
1769
	}
1770

    
1771
	/* setup pfsync interface */
1772
	if($carp_sync_int and $pfsyncenabled) {
1773
		if (is_ipaddr($pfsyncpeerip))
1774
			$cmdchain->add(gettext("Bring up pfsync0 syncpeer"), "/sbin/ifconfig pfsync0 syncdev {$carp_sync_int} syncpeer {$pfsyncpeerip} up", false);						
1775
		else
1776
			$cmdchain->add(gettext("Bring up pfsync0 syncdev"), "/sbin/ifconfig pfsync0 syncdev {$carp_sync_int} up", false);			
1777
	} else
1778
		$cmdchain->add(gettext("Bring up pfsync0"), "/sbin/ifconfig pfsync0 syncdev lo0 up", false);						
1779

    
1780
	sleep(1);
1781

    
1782
	/* 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 issuese
1783
	 * for exiting sessions.
1784
	 */
1785
	$i = 0;
1786
	while (intval(trim(`/sbin/ifconfig pfsync0 | /usr/bin/grep 'syncok: 0' | /usr/bin/grep -v grep | /usr/bin/wc -l`)) == 0 && $i < 30) {
1787
		$i++;
1788
		sleep(1);
1789
	}
1790

    
1791
	if($config['virtualip']['vip'])
1792
		$cmdchain->add(gettext("Allow CARP."), "/sbin/sysctl net.inet.carp.allow=1", true);				
1793
	else
1794
		$cmdchain->add(gettext("Disallow CARP."), "/sbin/sysctl net.inet.carp.allow=0", true);		
1795
	
1796
	if($g['debug'])
1797
		$cmdchain->setdebug(); // optional for verbose logging
1798

    
1799
	$cmdchain->execute();
1800
	$cmdchain->clear();
1801

    
1802
	if ($g['booting']) {
1803
		unmute_kernel_msgs();
1804
		echo gettext("done.") . "\n";
1805
	}
1806
}
1807

    
1808
function interface_proxyarp_configure($interface = "") {
1809
	global $config, $g;
1810
	if(isset($config['system']['developerspew'])) {
1811
		$mt = microtime();
1812
		echo "interface_proxyarp_configure() being called $mt\n";
1813
	}
1814

    
1815
	/* kill any running choparp */
1816
	if (empty($interface))
1817
		killbyname("choparp");
1818
	else {
1819
		$vipif = get_real_interface($interface);
1820
		if (file_exists("{$g['varrun_path']}/choparp_{$vipif}.pid"))
1821
			killbypid("{$g['varrun_path']}/choparp_{$vipif}.pid");
1822
	}
1823

    
1824
	$paa = array();
1825
	if (!empty($config['virtualip']) && is_array($config['virtualip']['vip'])) {
1826

    
1827
		/* group by interface */
1828
		foreach ($config['virtualip']['vip'] as $vipent) {
1829
			if ($vipent['mode'] === "proxyarp") {
1830
				if ($vipent['interface'])
1831
					$proxyif = $vipent['interface'];
1832
				else
1833
					$proxyif = "wan";
1834
				
1835
				if (!empty($interface) && $interface != $proxyif)
1836
					continue;
1837

    
1838
				if (!is_array($paa[$proxyif]))
1839
					$paa[$proxyif] = array();
1840

    
1841
				$paa[$proxyif][] = $vipent;
1842
			}
1843
		}
1844
	}
1845

    
1846
	if (!empty($interface)) {
1847
		if (is_array($paa[$interface])) {
1848
			$paaifip = get_interface_ip($interface);
1849
                        if (!is_ipaddr($paaifip))
1850
                                return;
1851
                        $args = get_real_interface($interface) . " auto";
1852
                        foreach ($paa[$interface] as $paent) {
1853
                                if (isset($paent['subnet']))
1854
                                        $args .= " " . escapeshellarg("{$paent['subnet']}/{$paent['subnet_bits']}");
1855
                                else if (isset($paent['range']))
1856
                                        $args .= " " . escapeshellarg($paent['range']['from'] . "-" . $paent['range']['to']);
1857
                        }
1858
                        mwexec_bg("/usr/local/sbin/choparp " . $args);	
1859
		}
1860
	} else if (count($paa) > 0) {
1861
		foreach ($paa as $paif => $paents)  {
1862
			$paaifip = get_interface_ip($paif);
1863
			if (!is_ipaddr($paaifip))
1864
				continue;
1865
			$args = get_real_interface($paif) . " auto";
1866
			foreach ($paents as $paent) {
1867
				if (isset($paent['subnet']))
1868
					$args .= " " . escapeshellarg("{$paent['subnet']}/{$paent['subnet_bits']}");
1869
				else if (isset($paent['range']))
1870
					$args .= " " . escapeshellarg($paent['range']['from'] . "-" . $paent['range']['to']);
1871
			}
1872
			mwexec_bg("/usr/local/sbin/choparp " . $args);
1873
		}
1874
	}
1875
}
1876

    
1877
function interfaces_vips_configure($interface = "") {
1878
	global $g, $config;
1879
	if(isset($config['system']['developerspew'])) {
1880
		$mt = microtime();
1881
		echo "interfaces_vips_configure() being called $mt\n";
1882
	}
1883
	$paa = array();
1884
	if(is_array($config['virtualip']['vip'])) {
1885
		$carp_setuped = false;
1886
		$anyproxyarp = false;
1887
		foreach ($config['virtualip']['vip'] as $vip) {
1888
			switch ($vip['mode']) {
1889
			case "proxyarp":
1890
				/* nothing it is handled on interface_proxyarp_configure() */
1891
				if ($interface <> "" && $vip['interface'] <> $interface)
1892
					continue;
1893
				$anyproxyarp = true;
1894
				break;
1895
			case "ipalias":
1896
				if ($interface <> "" && $vip['interface'] <> $interface)
1897
					continue;
1898
				interface_ipalias_configure(&$vip);
1899
				break;
1900
			case "carp":
1901
				if ($interface <> "" && $vip['interface'] <> $interface)
1902
					continue;
1903
				if ($carp_setuped == false)
1904
					$carp_setuped = true;
1905
				interface_carp_configure($vip);
1906
				break;
1907
			case "carpdev-dhcp":
1908
				if ($interface <> "" && $vip['interface'] <> $interface)
1909
					continue;
1910
				interface_carpdev_configure($vip);
1911
				break;
1912
			}
1913
		}
1914
		if ($carp_setuped == true)
1915
			interfaces_carp_setup();
1916
		if ($anyproxyarp == true)
1917
			interface_proxyarp_configure();
1918
	}
1919
}
1920

    
1921
function interface_ipalias_configure(&$vip) {
1922

    
1923
	if ($vip['mode'] == "ipalias") {
1924
		$if = get_real_interface($vip['interface']);
1925
		mwexec("/sbin/ifconfig " . escapeshellarg($if) . " " . $vip['subnet'] . "/" . escapeshellarg($vip['subnet_bits']) . " alias");
1926
	}
1927
}
1928

    
1929
function interface_reload_carps($cif) {
1930
	global $config;
1931

    
1932
	$carpifs = link_ip_to_carp_interface(find_interface_ip($cif));
1933
	if (empty($carpifs))
1934
		return;
1935

    
1936
	$carps = explode(" ", $carpifs);
1937
	if(is_array($config['virtualip']['vip'])) {
1938
		$viparr = &$config['virtualip']['vip'];
1939
		foreach ($viparr as $vip) {
1940
			if (in_array($vip['carpif'], $carps)) {
1941
				switch ($vip['mode']) {
1942
				case "carp":
1943
					interface_vip_bring_down($vip);
1944
					sleep(1);
1945
					interface_carp_configure($vip);
1946
					break;
1947
				case "carpdev-dhcp":
1948
					interface_vip_bring_down($vip);
1949
					sleep(1);
1950
					interface_carpdev_configure($vip);
1951
					break;
1952
				case "ipalias":
1953
					interface_vip_bring_down($vip);
1954
					sleep(1);
1955
					interface_ipalias_configure($vip);
1956
					break;
1957
				}
1958
			}
1959
		}
1960
	}
1961
}
1962

    
1963
function interface_carp_configure(&$vip) {
1964
	global $config, $g;
1965
	if(isset($config['system']['developerspew'])) {
1966
		$mt = microtime();
1967
		echo "interface_carp_configure() being called $mt\n";
1968
	}
1969

    
1970
	if ($vip['mode'] != "carp")
1971
		return;
1972

    
1973
	$vip_password = $vip['password'];
1974
	$vip_password = escapeshellarg(addslashes(str_replace(" ", "", $vip_password)));
1975
	if ($vip['password'] != "")
1976
		$password = " pass {$vip_password}";
1977

    
1978
	// set the vip interface to the vhid
1979
	$vipif = "vip{$vip['vhid']}";
1980

    
1981
	/*
1982
	 * ensure the interface containing the VIP really exists
1983
 	 * prevents a panic if the interface is missing or invalid
1984
	 */
1985
	$realif = get_real_interface($vip['interface']);
1986
	if (!does_interface_exist($realif)) {
1987
		file_notice("CARP", sprintf(gettext("Interface specified for the virtual IP address %s does not exist. Skipping this VIP."), $vip['subnet']), "Firewall: Virtual IP", "");
1988
		return;
1989
	}
1990

    
1991
	if(is_ipaddrv4($vip['subnet'])) {
1992
		/* Ensure CARP IP really exists prior to loading up. */
1993
		$ww_subnet_ip = find_interface_ip($realif);
1994
		$ww_subnet_bits = find_interface_subnet($realif);
1995
		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'])) {
1996
			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", "");
1997
			return;
1998
		}
1999
	}
2000
	if(is_ipaddrv6($vip['subnet'])) {
2001
		/* Ensure CARP IP really exists prior to loading up. */
2002
		$ww_subnet_ip = find_interface_ipv6($realif);
2003
		$ww_subnet_bits = find_interface_subnetv6($realif);
2004
		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'])) {
2005
			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", "");
2006
			return;
2007
		}
2008
	}
2009

    
2010
	/* create the carp interface and setup */
2011
	if (does_interface_exist($vipif)) {
2012
		pfSense_interface_flags($vipif, -IFF_UP);
2013
	} else {
2014
		$carpif = pfSense_interface_create("carp");
2015
		pfSense_interface_rename($carpif, $vipif);
2016
		pfSense_ngctl_name("{$carpif}:", $vipif);
2017
	}
2018

    
2019
	/* invalidate interface cache */
2020
	get_interface_arr(true);
2021

    
2022

    
2023
	$advbase = "";
2024
	if (!empty($vip['advbase']))
2025
		$advbase = "advbase {$vip['advbase']}";
2026

    
2027
	if(is_ipaddrv4($vip['subnet'])) {
2028
		$broadcast_address = gen_subnet_max($vip['subnet'], $vip['subnet_bits']);
2029
		mwexec("/sbin/ifconfig {$vipif} {$vip['subnet']}/{$vip['subnet_bits']} vhid {$vip['vhid']} advskew {$vip['advskew']} {$advbase} {$password}");
2030
	}
2031
	if(is_ipaddrv6($vip['subnet'])) {
2032
		$broadcast_address = gen_subnet_max($vip['subnet'], $vip['subnet_bits']);
2033
		mwexec("/sbin/ifconfig {$vipif} inet6 {$vip['subnet']} prefixlen {$vip['subnet_bits']} vhid {$vip['vhid']} advskew {$vip['advskew']} {$advbase} {$password}");
2034
		/* make sure to add a link local address too */
2035
		mwexec("/sbin/ifconfig {$vipif} inet6 fe80::5:{$vip['vhid']} vhid {$vip['vhid']} advskew {$vip['advskew']} {$advbase} {$password}");
2036
	}
2037

    
2038
	interfaces_bring_up($vipif);
2039
	
2040
	return $vipif;
2041
}
2042

    
2043
function interface_carpdev_configure(&$vip) {
2044
	global $g;
2045

    
2046
	if ($vip['mode'] != "carpdev-dhcp")
2047
		return;
2048

    
2049
	$vip_password = $vip['password'];
2050
	$vip_password = str_replace(" ", "", $vip_password);
2051
	if($vip['password'] != "")
2052
		$password = " pass \"" . $vip_password . "\"";
2053

    
2054
	if (empty($vip['interface']))
2055
		return;
2056

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

    
2069
	if (does_interface_exist($vipif)) {
2070
		interface_bring_down($vipif);
2071
	} else {
2072
		$carpdevif = exec("/sbin/ifconfig carp create");
2073
		mwexec("/sbin/ifconfig {$carpdevif} name {$vipif}");
2074
		pfSense_ngctl_name("{$carpdevif}:", $vipif);
2075
	}
2076

    
2077
	mwexec("/sbin/ifconfig {$vipif} carpdev {$realif} vhid {$vip['vhid']} advskew {$vip['advskew']} advbase {$vip['advbase']} {$password}");
2078
	interfaces_bring_up($vipif);
2079

    
2080
	/*
2081
	 * XXX: BIG HACK but carpdev needs ip services active
2082
	 *      before even starting something as dhclient.
2083
	 *      I do not know if this is a feature or a bug
2084
	 *      but better than track it make it work ;) .
2085
	 */
2086
	//$fakeiptouse = "10.254.254." . ($carp_instances_counter+1);
2087
	//$cmdchain->add("CarpDEV hack", "/sbin/ifconfig {$carpint} inet {$fakeiptouse}", false);
2088

    
2089
	/* generate dhclient_wan.conf */
2090
	$fd = fopen("{$g['varetc_path']}/dhclient_{$vipif}.conf", "w");
2091
	if ($fd) {
2092
		$dhclientconf = "";
2093

    
2094
		$dhclientconf .= <<<EOD
2095
interface "{$vipif}" {
2096
timeout 60;
2097
retry 1;
2098
select-timeout 0;
2099
initial-interval 1;
2100
script "/sbin/dhclient-script";
2101
}
2102

    
2103
EOD;
2104

    
2105
		fwrite($fd, $dhclientconf);
2106
		fclose($fd);
2107

    
2108
		/* fire up dhclient */
2109
		mwexec("/sbin/dhclient -c {$g['varetc_path']}/dhclient_{$vipif}.conf {$vipif} >{$g['tmp_path']}/{$vipif}_output 2>{$g['tmp_path']}/{$vipif}_error_output", false);
2110
	} else {
2111
		log_error(sprintf(gettext("Error: cannot open dhclient_%s.conf in interfaces_carpdev_configure() for writing.%s"), $vipif, "\n"));
2112
		mwexec("/sbin/dhclient -b {$vipif}");
2113
	}
2114

    
2115
	return $vipif;
2116
}
2117

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

    
2159
	if($needs_clone == true) {
2160
		/* remove previous instance if it exists */
2161
		if(does_interface_exist($realif))
2162
			pfSense_interface_destroy($realif);
2163

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

    
2182
function interface_sync_wireless_clones(&$ifcfg, $sync_changes = false) {
2183
	global $config, $g;
2184

    
2185
	$shared_settings = array('standard', 'turbo', 'protmode', 'txpower', 'channel',
2186
	                         'diversity', 'txantenna', 'rxantenna', 'distance',
2187
	                         'regdomain', 'regcountry', 'reglocation');
2188

    
2189
	if(!is_interface_wireless($ifcfg['if']))
2190
		return;
2191

    
2192
	$baseif = interface_get_wireless_base($ifcfg['if']);
2193

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

    
2218
	// Read or write settings at shared area
2219
	if (isset($config['wireless']['interfaces'][$baseif])) {
2220
		foreach ($shared_settings as $setting) {
2221
			if ($sync_changes) {
2222
				if (isset($ifcfg['wireless'][$setting]))
2223
					$config['wireless']['interfaces'][$baseif][$setting] = $ifcfg['wireless'][$setting];
2224
				else if (isset($config['wireless']['interfaces'][$baseif][$setting]))
2225
					unset($config['wireless']['interfaces'][$baseif][$setting]);
2226
			} else if (isset($config['wireless']['interfaces'][$baseif][$setting])) {
2227
				if (isset($config['wireless']['interfaces'][$baseif][$setting]))
2228
					$ifcfg['wireless'][$setting] = $config['wireless']['interfaces'][$baseif][$setting];
2229
				else if (isset($ifcfg['wireless'][$setting]))
2230
					unset($ifcfg['wireless'][$setting]);
2231
			}
2232
		}
2233
	}
2234

    
2235
	// Sync the mode on the clone creation page with the configured mode on the interface
2236
	if (interface_is_wireless_clone($ifcfg['if'])) {
2237
		foreach ($config['wireless']['clone'] as &$clone) {
2238
			if ($clone['cloneif'] == $ifcfg['if']) {
2239
				if ($sync_changes) {
2240
					$clone['mode'] = $ifcfg['wireless']['mode'];
2241
				} else {
2242
					$ifcfg['wireless']['mode'] = $clone['mode'];
2243
				}
2244
				break;
2245
			}
2246
		}
2247
		unset($clone);
2248
	}
2249
}
2250

    
2251
function interface_wireless_configure($if, &$wl, &$wlcfg) {
2252
	global $config, $g;
2253

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

    
2261
	// Remove script file
2262
	unlink_if_exists("{$g['tmp_path']}/{$if}_setup.sh");
2263

    
2264
	// Clone wireless nic if needed.
2265
	interface_wireless_clone($if, $wl);
2266

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

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

    
2274
	/* set values for /path/program */
2275
	$hostapd = "/usr/sbin/hostapd";
2276
	$wpa_supplicant = "/usr/sbin/wpa_supplicant";
2277
	$ifconfig = "/sbin/ifconfig";
2278
	$sysctl = "/sbin/sysctl";
2279
	$killall = "/usr/bin/killall";
2280

    
2281
	/* Set all wireless ifconfig variables (splitt up to get rid of needed checking) */
2282

    
2283
	$wlcmd = array();
2284
	$wl_sysctl = array();
2285
	/* Make sure it's up */
2286
	$wlcmd[] = "up";
2287
	/* Set a/b/g standard */
2288
	$standard = str_replace(" Turbo", "", $wlcfg['standard']);
2289
	$wlcmd[] = "mode " . escapeshellarg($standard);
2290

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

    
2296
	/* Set ssid */
2297
	if($wlcfg['ssid'])
2298
		$wlcmd[] = "ssid " .escapeshellarg($wlcfg['ssid']);
2299

    
2300
	/* Set 802.11g protection mode */
2301
	$wlcmd[] = "protmode " . escapeshellarg($wlcfg['protmode']);
2302

    
2303
	/* set wireless channel value */
2304
	if(isset($wlcfg['channel'])) {
2305
		if($wlcfg['channel'] == "0") {
2306
			$wlcmd[] = "channel any";
2307
		} else {
2308
			$wlcmd[] = "channel " . escapeshellarg($wlcfg['channel']);
2309
		}
2310
	}
2311

    
2312
	/* Set antenna diversity value */
2313
	if(isset($wlcfg['diversity']))
2314
		$wl_sysctl[] = "diversity=" . escapeshellarg($wlcfg['diversity']);
2315

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

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

    
2324
	/* set Distance value */
2325
	if($wlcfg['distance'])
2326
		$distance = escapeshellarg($wlcfg['distance']);
2327

    
2328
	/* Set wireless hostap mode */
2329
	if ($wlcfg['mode'] == "hostap") {
2330
		$wlcmd[] = "mediaopt hostap";
2331
	} else {
2332
		$wlcmd[] = "-mediaopt hostap";
2333
	}
2334

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

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

    
2344
	/* handle hide ssid option */
2345
	if(isset($wlcfg['hidessid']['enable'])) {
2346
		$wlcmd[] = "hidessid";
2347
	} else {
2348
		$wlcmd[] = "-hidessid";
2349
	}
2350

    
2351
	/* handle pureg (802.11g) only option */
2352
	if(isset($wlcfg['pureg']['enable'])) {
2353
		$wlcmd[] = "mode 11g pureg";
2354
	} else {
2355
		$wlcmd[] = "-pureg";
2356
	}
2357

    
2358
	/* handle puren (802.11n) only option */
2359
	if(isset($wlcfg['puren']['enable'])) {
2360
		$wlcmd[] = "puren";
2361
	} else {
2362
		$wlcmd[] = "-puren";
2363
	}
2364

    
2365
	/* enable apbridge option */
2366
	if(isset($wlcfg['apbridge']['enable'])) {
2367
		$wlcmd[] = "apbridge";
2368
	} else {
2369
		$wlcmd[] = "-apbridge";
2370
	}
2371

    
2372
	/* handle turbo option */
2373
	if(isset($wlcfg['turbo']['enable'])) {
2374
		$wlcmd[] = "mediaopt turbo";
2375
	} else {
2376
		$wlcmd[] = "-mediaopt turbo";
2377
	}
2378

    
2379
	/* handle txpower setting */
2380
	/* if($wlcfg['txpower'] <> "")
2381
		$wlcmd[] = "txpower " . escapeshellarg($wlcfg['txpower']);
2382
	*/
2383
	/* handle wme option */
2384
	if(isset($wlcfg['wme']['enable'])) {
2385
		$wlcmd[] = "wme";
2386
	} else {
2387
		$wlcmd[] = "-wme";
2388
	}
2389

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

    
2416
	mwexec(kill_hostapd("{$if}"));
2417
	mwexec(kill_wpasupplicant("{$if}"));
2418

    
2419
	/* generate wpa_supplicant/hostap config if wpa is enabled */
2420
	conf_mount_rw();
2421

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

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

    
2476
EOD;
2477

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

    
2484
EOD;
2485

    
2486
}
2487
				if($wlcfg['auth_server_addr'] && $wlcfg['auth_server_shared_secret']) {
2488
					$auth_server_port = "1812";
2489
					if($wlcfg['auth_server_port']) 
2490
						$auth_server_port = $wlcfg['auth_server_port'];
2491
					$auth_server_port2 = "1812";
2492
					if($wlcfg['auth_server_port2']) 
2493
						$auth_server_port2 = $wlcfg['auth_server_port2'];
2494
					$wpa .= <<<EOD
2495

    
2496
ieee8021x=1
2497
auth_server_addr={$wlcfg['auth_server_addr']}
2498
auth_server_port={$auth_server_port}
2499
auth_server_shared_secret={$wlcfg['auth_server_shared_secret']}
2500
auth_server_addr={$wlcfg['auth_server_addr2']}
2501
auth_server_port={$auth_server_port2}
2502
auth_server_shared_secret={$wlcfg['auth_server_shared_secret2']}
2503

    
2504
EOD;
2505
				} else {
2506
					$wpa .= "ieee8021x={$wlcfg['wpa']['ieee8021x']}\n";
2507
				}
2508

    
2509
				$fd = fopen("{$g['varetc_path']}/hostapd_{$if}.conf", "w");
2510
				fwrite($fd, "{$wpa}");
2511
				fclose($fd);
2512

    
2513
			}
2514
			break;
2515
	}
2516

    
2517
	/*
2518
	 *    all variables are set, lets start up everything
2519
	 */
2520

    
2521
	$baseif = interface_get_wireless_base($if);
2522
	preg_match("/^(.*?)([0-9]*)$/", $baseif, $baseif_split);
2523
	$wl_sysctl_prefix = 'dev.' . $baseif_split[1] . '.' . $baseif_split[2];
2524

    
2525
	/* set sysctls for the wireless interface */
2526
	if (!empty($wl_sysctl)) {
2527
		fwrite($fd_set, "# sysctls for {$baseif}\n");
2528
		foreach ($wl_sysctl as $wl_sysctl_line) {
2529
			fwrite($fd_set, "{$sysctl} {$wl_sysctl_prefix}.{$wl_sysctl_line}\n");
2530
		}
2531
	}
2532

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

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

    
2552
			fwrite($fd_set, "{$hostapd} -B {$g['varetc_path']}/hostapd_{$if}.conf\n");
2553

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

    
2567
	fclose($fd_set);
2568
	conf_mount_ro();
2569

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

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

    
2590
	if ($reg_changing) {
2591
		/* set regulatory domain */
2592
		if($wlcfg['regdomain'])
2593
			$wlregcmd[] = "regdomain " . escapeshellarg($wlcfg['regdomain']);
2594

    
2595
		/* set country */
2596
		if($wlcfg['regcountry'])
2597
			$wlregcmd[] = "country " . escapeshellarg($wlcfg['regcountry']);
2598

    
2599
		/* set location */
2600
		if($wlcfg['reglocation'])
2601
			$wlregcmd[] = escapeshellarg($wlcfg['reglocation']);
2602

    
2603
		$wlregcmd_args = implode(" ", $wlregcmd);
2604

    
2605
		/* build a complete list of the wireless clones for this interface */
2606
		$clone_list = array();
2607
		if (does_interface_exist(interface_get_wireless_clone($baseif)))
2608
			$clone_list[] = interface_get_wireless_clone($baseif);
2609
		if (is_array($config['wireless']['clone'])) {
2610
			foreach ($config['wireless']['clone'] as $clone) {
2611
				if ($clone['if'] == $baseif)
2612
					$clone_list[] = $clone['cloneif'];
2613
			}
2614
		}
2615

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

    
2626
		/* apply the regulatory settings */
2627
		mwexec("{$ifconfig} " . escapeshellarg($if) . " {$wlregcmd_args}");
2628

    
2629
		/* bring the clones back up that were previously up */
2630
		foreach ($clones_up as $clone_if) {
2631
			mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " up");
2632

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

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

    
2653
	/* configure wireless */
2654
	$wlcmd_args = implode(" ", $wlcmd);
2655
	mwexec("/sbin/ifconfig {$if} $wlcmd_args", false);
2656

    
2657
	
2658
	sleep(1);
2659
	/* execute hostapd and wpa_supplicant if required in shell */
2660
	mwexec("/bin/sh {$g['tmp_path']}/{$if}_setup.sh");
2661

    
2662
	return 0;
2663

    
2664
}
2665

    
2666
function kill_hostapd($interface) {
2667
	return "/bin/pkill -f \"hostapd .*{$interface}\"\n";
2668
}
2669

    
2670
function kill_wpasupplicant($interface) {
2671
	return "/bin/pkill -f \"wpa_supplicant .*{$interface}\"\n";
2672
}
2673

    
2674
function find_dhclient_process($interface) {
2675
	if ($interface)
2676
		$pid = `/bin/pgrep -axf "dhclient: {$interface}"`;
2677
	else
2678
		$pid = 0;
2679

    
2680
	return intval($pid);
2681
}
2682

    
2683
function find_dhcp6c_process($interface) {
2684
	if ($interface)
2685
		$pid = `/bin/ps auxw|grep "[d]hcp6c" |grep "{$interface}"|awk '{print $2}'`;
2686
	else
2687
		return(false);
2688

    
2689
	return intval($pid);
2690
}
2691

    
2692
function interface_configure($interface = "wan", $reloadall = false, $linkupevent = false) {
2693
	global $config, $g;
2694
	global $interface_sn_arr_cache, $interface_ip_arr_cache;
2695
	global $interface_snv6_arr_cache, $interface_ipv6_arr_cache;
2696

    
2697
	$wancfg = $config['interfaces'][$interface];
2698

    
2699
	$realif = get_real_interface($interface);
2700
	$realhwif_array = get_parent_interface($interface);
2701
	// Need code to handle MLPPP if we ever use $realhwif for MLPPP handling
2702
	$realhwif = $realhwif_array[0];
2703

    
2704
	/* Disable Accepting router advertisements unless specifically requested */
2705
	log_error("Deny router advertisements for interface {$interface}");
2706
	mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 -accept_rtadv");
2707
			
2708
	if (!$g['booting'] && !substr($realif, 0, 4) == "ovpn") {
2709
		/* remove all IPv4 and IPv6 addresses */
2710
		while (mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " -alias", true) == 0);
2711
		while (mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 -alias", true) == 0);
2712

    
2713
		/* only bring down the interface when both v4 and v6 are set to NONE */
2714
		if(($wancfg['ipaddr'] <> "none") && ($wancfg['ipaddrv6'] <> "none")) {
2715

    
2716

    
2717

    
2718

    
2719

    
2720

    
2721

    
2722

    
2723
			interface_bring_down($interface);
2724

    
2725
		}
2726
	}
2727

    
2728
	/* wireless configuration? */
2729
	if (is_array($wancfg['wireless']))
2730
		interface_wireless_configure($realif, $wancfg, $wancfg['wireless']);
2731

    
2732
	$mac = get_interface_mac($realhwif);
2733
	/*	Don't try to reapply the spoofed MAC if it's already applied.
2734
		When ifconfig link is used, it cycles the interface down/up, which triggers 
2735
		the interface config again, which attempts to spoof the MAC again, 
2736
		which cycles the link again... */
2737
	if ($wancfg['spoofmac'] && ($wancfg['spoofmac'] != $mac)) {
2738
		mwexec("/sbin/ifconfig " . escapeshellarg($realhwif) .
2739
			" link " . escapeshellarg($wancfg['spoofmac']));
2740

    
2741
                /*
2742
                 * All vlans need to spoof their parent mac address, too.  see
2743
                 * ticket #1514: http://cvstrac.pfsense.com/tktview?tn=1514,33
2744
                 */
2745
                if (is_array($config['vlans']['vlan'])) {
2746
                        foreach ($config['vlans']['vlan'] as $vlan) {
2747
                                if ($vlan['if'] == $realhwif)
2748
                                        mwexec("/sbin/ifconfig " . escapeshellarg($vlan['vlanif']) .
2749
                                                " link " . escapeshellarg($wancfg['spoofmac']));
2750
                        }
2751
                }
2752
	}  else {
2753

    
2754
		if ($mac == "ff:ff:ff:ff:ff:ff") {
2755
			/*   this is not a valid mac address.  generate a
2756
			 *   temporary mac address so the machine can get online.
2757
			 */
2758
			echo gettext("Generating new MAC address.");
2759
			$random_mac = generate_random_mac_address();
2760
			mwexec("/sbin/ifconfig " . escapeshellarg($realhwif) .
2761
				" link " . escapeshellarg($random_mac));
2762
			$wancfg['spoofmac'] = $random_mac;
2763
			write_config();
2764
			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");
2765
		}
2766
	}
2767

    
2768
	/* media */
2769
	if ($wancfg['media'] || $wancfg['mediaopt']) {
2770
		$cmd = "/sbin/ifconfig " . escapeshellarg($realhwif);
2771
		if ($wancfg['media'])
2772
			$cmd .= " media " . escapeshellarg($wancfg['media']);
2773
		if ($wancfg['mediaopt'])
2774
			$cmd .= " mediaopt " . escapeshellarg($wancfg['mediaopt']);
2775
		mwexec($cmd);
2776
	}
2777
	if (!empty($wancfg['mtu']))
2778
		pfSense_interface_mtu($realhwif, $wancfg['mtu']);
2779
	else {
2780
		$mtu = get_interface_default_mtu(remove_numbers($realhwif));
2781
		if ($mtu != get_interface_mtu($realhwif))
2782
			pfSense_interface_mtu($realhwif, $mtu);
2783
	}
2784

    
2785
	$options = pfSense_get_interface_addresses($realhwif);
2786
	if (is_array($options) && isset($options['caps']['polling'])) {
2787
		if (isset($config['system']['polling']))
2788
			pfSense_interface_capabilities($realif, IFCAP_POLLING);
2789
		else
2790
			pfSense_interface_capabilities($realif, -IFCAP_POLLING);
2791
	}
2792

    
2793
	/* skip vlans for checksumming and polling */
2794
        if (!stristr($realhwif, "vlan") && is_array($options)) {
2795
		$flags = 0;
2796
		if(isset($config['system']['disablechecksumoffloading'])) {
2797
			if (isset($options['encaps']['txcsum']))
2798
				$flags |= IFCAP_TXCSUM;
2799
			if (isset($options['encaps']['rxcsum']))
2800
				$flags |= IFCAP_RXCSUM;
2801
        	} else {
2802
 			if (!isset($options['caps']['txcsum']))
2803
				$flags |= IFCAP_TXCSUM;
2804
			if (!isset($options['caps']['rxcsum']))
2805
				$flags |= IFCAP_RXCSUM;
2806
        	}
2807

    
2808
        	if(isset($config['system']['disablesegmentationoffloading'])) {
2809
                	if (isset($options['encaps']['tso4']))
2810
				$flags |= IFCAP_TSO;
2811
                	if (isset($options['encaps']['tso6']))
2812
				$flags |= IFCAP_TSO;
2813
        	} else {
2814
                	if (!isset($options['caps']['tso4']))
2815
				$flags |= IFCAP_TSO;
2816
                	if (!isset($options['caps']['tso6']))
2817
				$flags |= IFCAP_TSO;
2818
        	}
2819

    
2820
        	if(isset($config['system']['disablelargereceiveoffloading'])) {
2821
                	if (isset($options['encaps']['lro']))
2822
				$flags |= IFCAP_LRO;
2823
        	} else {
2824
                	if (!isset($options['caps']['lro']))
2825
				$flags |= IFCAP_LRO;
2826
        	}
2827

    
2828
        	/* if the NIC supports polling *AND* it is enabled in the GUI */
2829
        	if (!isset($config['system']['polling']) || !isset($options['caps']['polling'])) {
2830
			$flags |= IFCAP_POLLING;
2831
		}
2832
               	pfSense_interface_capabilities($realhwif, -$flags);
2833
	}
2834

    
2835
	/* invalidate interface/ip/sn cache */
2836
	get_interface_arr(true);
2837
	unset($interface_ip_arr_cache[$realif]);
2838
	unset($interface_sn_arr_cache[$realif]);
2839
	unset($interface_ipv6_arr_cache[$realif]);
2840
	unset($interface_snv6_arr_cache[$realif]);
2841

    
2842
	switch ($wancfg['ipaddr']) {
2843
		case 'carpdev-dhcp':
2844
			interface_carpdev_dhcp_configure($interface);
2845
			break;
2846
		case 'dhcp':
2847
			interface_dhcp_configure($interface);
2848
			break;
2849
		case 'pppoe':
2850
		case 'l2tp':
2851
		case 'pptp':
2852
		case 'ppp':
2853
			interface_ppps_configure($interface);
2854
			break;
2855
		default:
2856
			if (is_ipaddr($wancfg['ipaddr']) && $wancfg['subnet'] <> "") {
2857
				pfSense_interface_setaddress($realif, "{$wancfg['ipaddr']}/{$wancfg['subnet']}");
2858
			} else if (substr($realif, 0, 3) == "gre") {
2859
				if (is_array($config['gres']['gre'])) {
2860
					foreach ($config['gres']['gre'] as $gre)
2861
						if ($gre['greif'] == $realif)
2862
							interface_gre_configure($gre);
2863
				}
2864
			} else if (substr($realif, 0, 3) == "gif") {
2865
				 if (is_array($config['gifs']['gif'])) {
2866
					foreach ($config['gifs']['gif'] as $gif)
2867
						if($gif['gifif'] == $realif)
2868
							interface_gif_configure($gif);
2869
				}
2870
			} else if (substr($realif, 0, 4) == "ovpn") {
2871
				/* XXX: Should be done anything?! */
2872
			}
2873
			break;
2874
	}
2875

    
2876
	switch ($wancfg['ipaddrv6']) {
2877
		case 'dhcp6':
2878
			interface_dhcpv6_configure($interface);
2879
			break;
2880
		case '6rd':
2881
			interface_6rd_configure($interface);
2882
			break;
2883
		case '6to4':
2884
			interface_6to4_configure($interface);
2885
			break;
2886
		case 'track6':
2887
			interface_track6_configure($interface);
2888
			break;
2889
		default:
2890
			if (is_ipaddr($wancfg['ipaddrv6']) && $wancfg['subnetv6'] <> "") {
2891
				pfSense_interface_setaddress($realif, "{$wancfg['ipaddrv6']}/{$wancfg['subnetv6']}");
2892
				// FIXME: Add IPv6 Support to the pfSense module
2893
				mwexec("/sbin/ifconfig {$realif} inet6 {$wancfg['ipaddrv6']} prefixlen {$wancfg['subnetv6']} ");
2894
			}
2895
			break;
2896
	}
2897

    
2898
	if(does_interface_exist($wancfg['if']))
2899
		interfaces_bring_up($wancfg['if']);
2900

    
2901
	interface_netgraph_needed($interface);
2902
 	
2903
	if (!$g['booting']) {
2904
		link_interface_to_vips($interface, "update");
2905

    
2906
		unset($gre);
2907
		$gre = link_interface_to_gre($interface);
2908
		if (!empty($gre))
2909
			array_walk($gre, 'interface_gre_configure');
2910

    
2911
		unset($gif);
2912
		$gif = link_interface_to_gif($interface);
2913
		if (!empty($gif))
2914
			array_walk($gif, 'interface_gif_configure');
2915

    
2916
		if ($linkupevent == false || substr($realif, 0, 4) == "ovpn") {
2917
			unset($bridgetmp);
2918
			$bridgetmp = link_interface_to_bridge($interface);
2919
			if (!empty($bridgetmp))
2920
				interface_bridge_add_member($bridgetmp, $realif);
2921
		}
2922

    
2923
		$grouptmp = link_interface_to_group($interface);
2924
		if (!empty($grouptmp))
2925
			array_walk($grouptmp, 'interface_group_add_member');
2926

    
2927
		if ($interface == "lan")
2928
			/* make new hosts file */
2929
			system_hosts_generate();
2930

    
2931
		if ($reloadall == true) {
2932

    
2933
			/* reconfigure static routes (kernel may have deleted them) */
2934
			system_routing_configure($interface);
2935

    
2936
			/* reload ipsec tunnels */
2937
			vpn_ipsec_configure();
2938

    
2939
			/* restart dnsmasq */
2940
			services_dnsmasq_configure();
2941

    
2942
			/* update dyndns */
2943
			send_event("service reload dyndns {$interface}");
2944

    
2945
			/* reload captive portal */
2946
			captiveportal_init_rules();
2947
		}
2948
	}
2949

    
2950
	return 0;
2951
}
2952

    
2953
function interface_carpdev_dhcp_configure($interface = "wan") {
2954
	global $config, $g;
2955

    
2956
	$wancfg = $config['interfaces'][$interface];
2957
	$wanif = $wancfg['if'];
2958
	/* bring wan interface up before starting dhclient */
2959
	if($wanif)
2960
		interfaces_bring_up($wanif);
2961
	else 
2962
		log_error(gettext("Could not bring wanif up in terface_carpdev_dhcp_configure()"));
2963

    
2964
	return 0;
2965
}
2966

    
2967
function interface_track6_configure($interface = "lan") {
2968
	global $config, $g;
2969
	$iflist = get_configured_interface_with_descr(false, true);
2970

    
2971
	$wancfg = $config['interfaces'][$interface];
2972
	$wanif = $wancfg['if'];
2973
	if (empty($wancfg))
2974
		$wancfg = array();
2975

    
2976
	$wanif = get_real_interface($interface);
2977
	
2978
	/* If the interface is not configured via another, exit */
2979
	if(!$wancfg['track6-interface'] <> "") {
2980
		return(false);
2981
	}
2982

    
2983
	$type = $config['interfaces'][$wancfg['track6-interface']]['ipaddrv6'];
2984
	switch($type) {
2985
		case "6to4":
2986
			log_error("Interface {$interface} configured via {$wancfg['track6-interface']}  type {$type}");
2987
			interface_track6_6to4_configure($interface);
2988
			break;
2989
		case "6rd":
2990
			log_error("Interface {$interface} configured via {$wancfg['track6-interface']}  type {$type}");
2991
			interface_track6_6rd_configure($interface);
2992
			break;
2993
		case "dhcp6":
2994
			log_error("Interface {$interface} configured via {$wancfg['track6-interface']}  type {$type}");
2995
			interface_track6_dhcp6_configure($interface);
2996
			break;
2997
		default:
2998
			log_error("Interface {$interface} configured via {$wancfg['track6-interface']} but unknown type {$type}");
2999
			break;
3000
	}
3001
	return 0;
3002
}
3003

    
3004

    
3005
function interface_track6_6rd_configure($interface = "lan") {
3006
	global $config, $g;
3007
	$iflist = get_configured_interface_with_descr(false, true);
3008

    
3009
	$lancfg = $config['interfaces'][$interface];
3010
	$lanif = $lancfg['if'];
3011
	if (empty($lancfg))
3012
		$lancfg = array();
3013

    
3014
	$lanif = get_real_interface($interface);
3015
	
3016
	/* If the interface is not configured via another, exit */
3017
	if(!$lancfg['track6-interface'] <> "") {
3018
		return(false);
3019
	}
3020
	if(!is_numeric($lancfg['track6-prefix-id']))
3021
		$lancfg['track6-prefix-id'] = 0;
3022
	
3023
	$wancfg = $config['interfaces'][$lancfg['track6-interface']];
3024
	$wanif = $wancfg['if'];
3025
	if (empty($wancfg))
3026
		$wancfg = array();
3027
	
3028
	$ip4address = find_interface_ip($wanif);
3029
	if((!is_ipaddrv4($ip4address)) || (is_private_ip($ip4address))) {
3030
		log_error("The interface IPv4 '{$ip4address}' address on interface '{$wanif}' is not public, not configuring 6RD tunnel");
3031
		return false;
3032
	}
3033
	$hexwanv4 = return_hex_ipv4($ip4address);
3034
	
3035
	/* create the long prefix notation for math, save the prefix length */
3036
	$rd6prefix = explode("/", $wancfg['prefix-6rd']);
3037
	$rd6prefixlen = $rd6prefix[1];
3038
	$rd6prefix = Net_IPv6::uncompress($rd6prefix[0]);
3039

    
3040
	/* binary presentation of the prefix for all 128 bits. */
3041
	$rd6lanbin = convert_ipv6_to_128bit($rd6prefix);
3042
	
3043
	/* just save the left prefix length bits */
3044
	$rd6lanbin = substr($rd6lanbin, 0, $rd6prefixlen);
3045
	/* add the v4 address, offset n bits from the left */
3046
	$rd6lanbin .= substr(sprintf("%032b", hexdec($hexwanv4)), (0 + $wancfg['prefix-6rd-v4plen']), 32);
3047

    
3048
	/* add the custom prefix id, max 32bits long? (64 bits - (prefixlen + (32 - v4plen)) */
3049
	/* 64 - (37 + (32 - 17)) = 8 == /52 */
3050
	$restbits = 64 - ($rd6prefixlen + (32 - $wancfg['prefix-6rd-v4plen']));
3051
	// echo "64 - (prefixlen {$rd6prefixlen} + v4len (32 - {$wancfg['prefix-6rd-v4plen']})) = {$restbits} \n";
3052
	$rd6lanbin .= substr(sprintf("%032b", str_pad($lancfg['track6-prefix-id'], 32, "0", STR_PAD_LEFT)), (32 - $restbits), 32);
3053
	/* fill the rest out with zeros */
3054
	$rd6lanbin = str_pad($rd6lanbin, 128, "0", STR_PAD_RIGHT);;
3055

    
3056
	/* convert the 128 bits for the lan address back into a valid IPv6 address */ 
3057
	$rd6lan = convert_128bit_to_ipv6($rd6lanbin) ."1";
3058
	
3059
	log_error("rd6 {$interface} with ipv6 address {$rd6lan} based on {$lancfg['track6-interface']} ipv4 {$ip4address}");
3060
	mwexec("/sbin/ifconfig {$lanif} inet6 {$rd6lan} prefixlen 64");
3061
	return 0;
3062
}
3063

    
3064
function interface_track6_6to4_configure($interface = "lan") {
3065
	global $config, $g;
3066
	$iflist = get_configured_interface_with_descr(false, true);
3067

    
3068
	$lancfg = $config['interfaces'][$interface];
3069
	$lanif = $lancfg['if'];
3070
	if (empty($lancfg))
3071
		$lancfg = array();
3072

    
3073
	$lanif = get_real_interface($interface);
3074
	
3075
	/* If the interface is not configured via another, exit */
3076
	if(!$lancfg['track6-interface'] <> "") {
3077
		return(false);
3078
	}
3079
	if(!is_numeric($lancfg['track6-prefix-id']))
3080
		$lancfg['track6-prefix-id'] = 0;
3081
	
3082
	$wancfg = $config['interfaces'][$lancfg['track6-interface']];
3083
	$wanif = $wancfg['if'];
3084
	if (empty($wancfg))
3085
		$wancfg = array();
3086
	
3087
	$ip4address = find_interface_ip($wanif);
3088
	if((!is_ipaddrv4($ip4address)) || (is_private_ip($ip4address))) {
3089
		log_error("The interface IPv4 '{$ip4address}' address on interface '{$wanif}' is not public, not configuring 6RD tunnel");
3090
		return false;
3091
	}
3092
	$hexwanv4 = return_hex_ipv4($ip4address);
3093
	
3094
	/* create the long prefix notation for math, save the prefix length */
3095
	$sixto4prefix = "2002::";
3096
	$sixto4prefixlen = 16;
3097
	$sixto4prefix = Net_IPv6::uncompress($sixto4prefix);
3098

    
3099
	/* binary presentation of the prefix for all 128 bits. */
3100
	$sixto4lanbin = convert_ipv6_to_128bit($sixto4prefix);
3101
	
3102
	/* just save the left prefix length bits */
3103
	$sixto4lanbin = substr($sixto4lanbin, 0, $sixto4prefixlen);
3104
	/* add the v4 address */
3105
	$sixto4lanbin .= sprintf("%032b", hexdec($hexwanv4));
3106
	/* add the custom prefix id */
3107
	$sixto4lanbin .= sprintf("%016b", $lancfg['track6-prefix-id']);
3108
	/* fill the rest out with zeros */
3109
	$sixto4lanbin = str_pad($sixto4lanbin, 128, "0", STR_PAD_RIGHT);;
3110
	
3111
	/* convert the 128 bits for the lan address back into a valid IPv6 address */ 
3112
	$sixto4lan = convert_128bit_to_ipv6($sixto4lanbin) ."1";
3113
	
3114
	log_error("sixto4 {$interface} with ipv6 address {$sixto4lan} based on {$lancfg['track6-interface']} ipv4 {$ip4address}");
3115
	mwexec("/sbin/ifconfig {$lanif} inet6 {$sixto4lan} prefixlen 64");
3116
	return 0;
3117
}
3118

    
3119
function interface_track6_dhcp6_configure($interface = "lan") {
3120
	global $config, $g;
3121
	$iflist = get_configured_interface_with_descr(false, true);
3122

    
3123
	$lancfg = $config['interfaces'][$interface];
3124
	$lanif = $lancfg['if'];
3125
	if (empty($lancfg))
3126
		$lancfg = array();
3127

    
3128
	$lanif = get_real_interface($interface);
3129
	
3130
	/* If the interface is not configured via another, exit */
3131
	if(!$lancfg['track6-interface'] <> "") {
3132
		return(false);
3133
	}
3134
	if(!is_numeric($lancfg['track6-prefix-id']))
3135
		$lancfg['track6-prefix-id'] = 0;
3136
	
3137
	$wancfg = $config['interfaces'][$lancfg['track6-interface']];
3138
	$wanif = $wancfg['if'];
3139
	if (empty($wancfg))
3140
		$wancfg = array();
3141
	
3142
	
3143
	$ifcfgipv6 = find_interface_ipv6($lanif);
3144
	if(is_ipaddrv6($ifcfgipv6)) {
3145
		$dhcp6lanarr = explode(":", Net_IPv6::uncompress($ifcfgipv6));
3146
		$dhcp6lanarr[4] = 0;
3147
		$dhcp6lanarr[5] = 0;
3148
		$dhcp6lanarr[6] = 0;
3149
		$dhcp6lanarr[7] = 1;
3150
		$dhcp6lan =  Net_IPv6::compress(implode(":", $dhcp6lanarr));
3151
		log_error("dhcp6 {$interface} with ipv6 address {$dhcp6lan} based on {$lancfg['track6-interface']}");
3152
		mwexec("/sbin/ifconfig {$lanif} inet6 {$dhcp6lan} prefixlen 64");
3153
	}
3154
	return 0;
3155
}
3156

    
3157
function interface_6rd_configure($interface = "wan") {
3158
	global $config, $g;
3159
	$iflist = get_configured_interface_with_descr(false, true);
3160

    
3161
	/* because this is a tunnel interface we can only function 
3162
	 *	with a public IPv4 address on the interface */
3163

    
3164
	$wancfg = $config['interfaces'][$interface];
3165
	$wanif = $wancfg['if'];
3166
	if (empty($wancfg))
3167
		$wancfg = array();
3168

    
3169
	$wanif = get_real_interface($interface);
3170
	
3171
	$ip4address = find_interface_ip($wanif);
3172
	if((!is_ipaddrv4($ip4address)) || (is_private_ip($ip4address))) {
3173
		log_error("The interface IPv4 '{$ip4address}' address on interface '{$wanif}' is not public, not configuring 6RD tunnel");
3174
		return false;
3175
	}
3176
	$hexwanv4 = return_hex_ipv4($ip4address);
3177
	
3178
	if(!is_numeric($wancfg['prefix-6rd-v4plen']))
3179
		$wancfg['prefix-6rd-v4plen'] = 0;
3180

    
3181
	/* create the long prefix notation for math, save the prefix length */
3182
	$rd6prefix = explode("/", $wancfg['prefix-6rd']);
3183
	$rd6prefixlen = $rd6prefix[1];
3184
	$rd6prefix = Net_IPv6::uncompress($rd6prefix[0]);
3185

    
3186
	/* we need the hex form of the broker IPv4 address */
3187
	$hexbrv4 = return_hex_ipv4($wancfg['gateway-6rd']);
3188
	
3189
	/* binary presentation of the prefix for all 128 bits. */
3190
	$rd6prefixbin = convert_ipv6_to_128bit($rd6prefix);
3191
		
3192
	/* just save the left prefix length bits */
3193
	$rd6brprefixbin = substr($rd6prefixbin, 0, $rd6prefixlen);
3194
	/* if the prefix length is not 32 bits we need to shave bits off from the left of the v4 address. */
3195
	$rd6brprefixbin .= substr(sprintf("%032b", hexdec($hexbrv4)), $wancfg['prefix-6rd-v4plen'], 32);
3196
	/* fill out the rest with 0's */
3197
	$rd6brprefixbin = str_pad($rd6brprefixbin, 128, "0", STR_PAD_RIGHT);;
3198

    
3199
	/* convert the 128 bits for the broker address back into a valid IPv6 address */ 
3200
	$rd6brgw = convert_128bit_to_ipv6($rd6brprefixbin);
3201

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

    
3209
	/* convert the 128 bits for the broker address back into a valid IPv6 address */ 
3210
	$rd6prefix = convert_128bit_to_ipv6($rd6prefixbin);
3211

    
3212
	/* setup the stf interface */
3213
	/* use the srd device
3214
	mwexec("/sbin/ifconfig srd0 destroy");
3215
	mwexec("/sbin/ifconfig srd0 create");
3216
	mwexec("/sbin/ifconfig srd0 v4plen {$wancfg['prefix-6rd-v4plen']} pfix {$rd6prefix} plen {$rd6prefixlen} braddr {$wancfg['gateway-6rd']}");
3217
	log_error("Created 6rd interface srd0 v4plen {$wancfg['prefix-6rd-v4plen']} pfix {$rd6prefix} plen {$rd6prefixlen} braddr {$wancfg['gateway-6rd']}");
3218
	*/
3219
	/* stf approach only works when embedding the entire 32 bits of the v4 */
3220
	mwexec("/sbin/ifconfig stf0 destroy");
3221
	mwexec("/sbin/ifconfig stf0 create");
3222
	mwexec("/sbin/ifconfig stf0 inet6 {$rd6prefix}/{$rd6prefixlen}");
3223
	log_error("Created 6rd interface stf0 {$rd6prefix}/{$rd6prefixlen}");
3224

    
3225
	/* write out a default router file */
3226
	file_put_contents("{$g['tmp_path']}/{$wanif}_routerv6", "{$rd6brgw}\n");
3227
	file_put_contents("{$g['tmp_path']}/{$wanif}_defaultgwv6", "{$rd6brgw}\n");
3228

    
3229
	/* configure dependent interfaces */
3230
	foreach($iflist as $if => $ifname) {
3231
		if($config['interfaces'][$if]['track6-interface'] == $interface)
3232
			interface_track6_configure($if);
3233
	}
3234
	
3235
	return 0;
3236
}
3237

    
3238
function interface_6to4_configure($interface = "wan"){
3239
	global $config, $g;
3240
	$iflist = get_configured_interface_with_descr(false, true);
3241

    
3242
	/* because this is a tunnel interface we can only function 
3243
	 *	with a public IPv4 address on the interface */
3244

    
3245
	$wancfg = $config['interfaces'][$interface];
3246
	$wanif = $wancfg['if'];
3247
	if (empty($wancfg))
3248
		$wancfg = array();
3249

    
3250
	$wanif = get_real_interface($interface);
3251
	
3252
	$ip4address = find_interface_ip($wanif);
3253
	if((!is_ipaddrv4($ip4address)) || (is_private_ip($ip4address))) {
3254
		log_error("The interface IPv4 '{$ip4address}' address on interface '{$wanif}' is not public, not configuring 6RD tunnel");
3255
		return false;
3256
	}
3257
	
3258
	/* create the long prefix notation for math, save the prefix length */
3259
	$stfprefixlen = 16;
3260
	$stfprefix = Net_IPv6::uncompress("2002::");
3261
	$stfarr = explode(":", $stfprefix);
3262
	$v4prefixlen = "0";
3263
	
3264
	/* we need the hex form of the interface IPv4 address */
3265
	$ip4arr = explode(".", $ip4address);
3266
	$hexwanv4 = "";
3267
	foreach($ip4arr as $octet)
3268
		$hexwanv4 .= sprintf("%02x", $octet);
3269

    
3270
	/* we need the hex form of the broker IPv4 address */
3271
	$ip4arr = explode(".", "192.88.99.1");
3272
	$hexbrv4 = "";
3273
	foreach($ip4arr as $octet)
3274
		$hexbrv4 .= sprintf("%02x", $octet);
3275
	
3276
	/* binary presentation of the prefix for all 128 bits. */
3277
	$stfprefixbin = "";
3278
	foreach($stfarr as $element) {
3279
		$stfprefixbin .= sprintf("%016b", hexdec($element));
3280
	}
3281
	/* just save the left prefix length bits */
3282
	$stfprefixstartbin = substr($stfprefixbin, 0, $stfprefixlen);
3283

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

    
3288
	/* for the local subnet too. */
3289
	$stflanbin = substr(sprintf("%032b", hexdec($hexwanv4)), $v4prefixlen, 32);
3290
	$stflanbin = str_pad($stfprefixstartbin . $stflanbin, 128, "0", STR_PAD_RIGHT);;
3291

    
3292
	/* convert the 128 bits for the broker address back into a valid IPv6 address */ 
3293
	$stfbrarr = array();
3294
	$stfbrbinarr = array();
3295
	$stfbrbinarr = str_split($stfbrokerbin, 16);
3296
	foreach($stfbrbinarr as $bin)
3297
		$stfbrarr[] = dechex(bindec($bin));
3298
	$stfbrarr[7] = 1;
3299
	$stfbrgw = Net_IPv6::compress(implode(":", $stfbrarr));
3300

    
3301
	/* convert the 128 bits for the broker address back into a valid IPv6 address */ 
3302
	$stflanarr = array();
3303
	$stflanbinarr = array();
3304
	$stflanbinarr = str_split($stflanbin, 16);
3305
	foreach($stflanbinarr as $bin)
3306
		$stflanarr[] = dechex(bindec($bin));
3307
	$stflanpr = Net_IPv6::compress(implode(":", $stflanarr));
3308
	$stflanarr[7] = 1;
3309
	$stflan = Net_IPv6::compress(implode(":", $stflanarr));
3310

    
3311
	/* setup the stf interface */
3312
	mwexec("/sbin/ifconfig stf0 destroy");
3313
	mwexec("/sbin/ifconfig stf0 create");
3314
	mwexec("/sbin/ifconfig stf0 inet6 {$stflanpr} prefixlen 16");
3315

    
3316
	log_error("Set IPv6 address inet6 {$stflanpr} prefixlen 16 for stf0, route {$stfbrgw}");
3317
	
3318
	/* write out a default router file */
3319
	file_put_contents("{$g['tmp_path']}/{$wanif}_routerv6", "{$stfbrgw}");
3320
	file_put_contents("{$g['tmp_path']}/{$wanif}_defaultgwv6", "{$stfbrgw}");
3321

    
3322
	/* configure dependent interfaces */
3323
	foreach($iflist as $if => $ifname) {
3324
		if($config['interfaces'][$if]['track6-interface'] == $interface)
3325
			interface_track6_configure($if);
3326
	}
3327
	
3328
	return 0;
3329
}
3330

    
3331
function interface_dhcpv6_configure($interface = "wan") {
3332
	global $config, $g;
3333
	$iflist = get_configured_interface_with_descr(false, true);
3334

    
3335
	$wancfg = $config['interfaces'][$interface];
3336
	$wanif = $wancfg['if'];
3337
	if (empty($wancfg))
3338
		$wancfg = array();
3339

    
3340
	$wanif = get_real_interface($interface);
3341

    
3342
	/* Add ISC IPv6 dhclient here, only wide-dhcp6c works for now. */
3343
	$fd = fopen("{$g['varetc_path']}/dhcp6c_{$interface}.conf", "w");
3344
	if (!$fd) {
3345
		printf("Error: cannot open dhcp6c_{$interface}.conf in interfaces_wan_dhcpv6_configure() for writing.\n");
3346
		return 1;
3347
	}
3348

    
3349
	$dhcp6cconf = "";
3350
 	$dhcp6cconf .= "interface {$wanif} {\n";
3351
	$dhcp6cconf .= " 	send ia-na 0;	# request stateful address\n";
3352
	if(is_numeric($wancfg['dhcp6-ia-pd-len'])) {
3353
		$dhcp6cconf .= "	send ia-pd 0;	# request prefix delegation\n";
3354
	}
3355
	$dhcp6cconf .= "request domain-name-servers;\n";
3356
	$dhcp6cconf .= "request domain-name;\n";
3357
	$dhcp6cconf .= "script \"{$g['varetc_path']}/dhcp6c_{$interface}_script.sh\"; # we'd like some nameservers please\n";
3358

    
3359
	$dhcp6cconf .= "};\n";
3360
	$dhcp6cconf .= "id-assoc na 0 { };\n";
3361
	if(is_numeric($wancfg['dhcp6-ia-pd-len'])) {
3362
		/* Setup the prefix delegation */
3363
		$dhcp6cconf .= "id-assoc pd 0 {\n";
3364
		foreach($iflist as $friendly => $ifdescr) {
3365
			if($config['interfaces'][$friendly]['track6-interface'] != $interface)
3366
				continue;
3367
			if(is_numeric($config['interfaces'][$friendly]['track6-prefix-id'])) {
3368
				log_error("setting up $friendly - {$config['interfaces'][$friendly]['track6-prefix-id']}");
3369
				$realif = get_real_interface($friendly);
3370
				$dhcp6cconf .= "	prefix-interface {$realif} {\n";
3371
				$dhcp6cconf .= "		sla-id {$config['interfaces'][$friendly]['track6-prefix-id']};\n";
3372
				$dhcp6cconf .= "		sla-len {$wancfg['dhcp6-ia-pd-len']};\n";
3373
				$dhcp6cconf .= "	};\n";
3374
			}
3375
		}
3376
		$dhcp6cconf .= "};\n";
3377
	}
3378

    
3379
	fwrite($fd, $dhcp6cconf);
3380
	fclose($fd);
3381

    
3382
	/* Add wide-dhcp6c shell script here. Because we can not pass a argument to it. */
3383
	$fds = fopen("{$g['varetc_path']}/dhcp6c_{$interface}_script.sh", "w");
3384
	if (!$fds) {
3385
		printf("Error: cannot open dhcp6c_{$interface}_script.sh in interfaces_wan_dhcpv6_configure() for writing.\n");
3386
		return 1;
3387
	}
3388
	$dhcp6cscript = "#!/bin/sh\n";
3389
	$dhcp6cscript .= "# This shell script launches /etc/rc.newwanipv6 with a interface argument.\n";
3390
	$dhcp6cscript .= "/etc/rc.newwanipv6 $interface \n";
3391

    
3392
	fwrite($fds, $dhcp6cscript);
3393
	fclose($fds);
3394
	chmod("{$g['varetc_path']}/dhcp6c_{$interface}_script.sh", 0755);
3395

    
3396

    
3397
	/* accept router advertisements for this interface */
3398
	mwexec("/sbin/sysctl -w net.inet6.ip6.accept_rtadv=1");
3399
	log_error("Accept router advertisements on interface {$wanif} ");
3400
	mwexec("/sbin/ifconfig {$wanif} inet6 accept_rtadv");
3401
	mwexec("/sbin/ifconfig {$wanif} inet6 defroute_rtadv");
3402

    
3403
	/* fire up dhcp6c for IPv6 first, this backgrounds immediately */
3404
	mwexec("/usr/local/sbin/dhcp6c -d -c {$g['varetc_path']}/dhcp6c_{$interface}.conf {$wanif}");
3405
	exec("/sbin/rtsol -d {$wanif} 2>&1", $out, $ret);
3406
	if(!empty($out)) {
3407
		foreach($out as $line) {
3408
			if(stristr($line, "received")) {
3409
				$parts = explode(" ", $line);
3410
				if(is_ipaddrv6($parts[3])) {
3411
					log_error("Found IPv6 default gateway '{$parts[3]}' by RA.");
3412
					file_put_contents("{$g['tmp_path']}/{$wanif}_routerv6", "{$parts[3]}\n");
3413
					file_put_contents("{$g['tmp_path']}/{$wanif}_defaultgwv6", "{$parts[3]}\n");
3414
				}
3415
			}
3416
		}
3417
	}
3418
	/* sleep a few seconds before returning to give the client some time
3419
	 * to configure a lan interface with a prefix */
3420
	sleep(5);
3421

    
3422
	/* configure dependent interfaces */
3423
	foreach($iflist as $if => $ifname) {
3424
		if($config['interfaces'][$if]['track6-interface'] == $interface)
3425
			interface_track6_configure($if);
3426
	}
3427

    
3428
	return 0;
3429
}
3430

    
3431
function interface_dhcp_configure($interface = "wan") {
3432
	global $config, $g;
3433

    
3434
	$wancfg = $config['interfaces'][$interface];
3435
	$wanif = $wancfg['if'];
3436
	if (empty($wancfg))
3437
		$wancfg = array();
3438

    
3439
	/* generate dhclient_wan.conf */
3440
	$fd = fopen("{$g['varetc_path']}/dhclient_{$interface}.conf", "w");
3441
	if (!$fd) {
3442
		printf(printf(gettext("Error: cannot open dhclient_%s.conf in interfaces_wan_dhcp_configure() for writing.%s"), $interface, "\n"));
3443
		return 1;
3444
	}
3445

    
3446
	if ($wancfg['dhcphostname']) {
3447
		$dhclientconf_hostname = "send dhcp-client-identifier \"{$wancfg['dhcphostname']}\";\n";
3448
		$dhclientconf_hostname .= "\tsend host-name \"{$wancfg['dhcphostname']}\";\n";
3449
	} else {
3450
		$dhclientconf_hostname = "";
3451
	}
3452

    
3453
	$wanif = get_real_interface($interface);
3454
	if (empty($wanif)) {
3455
		log_error(sprintf(gettext("Invalid interface \"%s\" in interface_dhcp_configure()"), $interface));
3456
		return 0;
3457
	}
3458
 	$dhclientconf = "";
3459
	
3460
	$dhclientconf .= <<<EOD
3461
interface "{$wanif}" {
3462
timeout 60;
3463
retry 1;
3464
select-timeout 0;
3465
initial-interval 1;
3466
	{$dhclientconf_hostname}
3467
	script "/sbin/dhclient-script";
3468
}
3469

    
3470
EOD;
3471

    
3472
if(is_ipaddr($wancfg['alias-address'])) {
3473
	$subnetmask = gen_subnet_mask($wancfg['alias-subnet']);
3474
	$dhclientconf .= <<<EOD
3475
alias {
3476
	interface  "{$wanif}";
3477
	fixed-address {$wancfg['alias-address']};
3478
	option subnet-mask {$subnetmask};
3479
}
3480

    
3481
EOD;
3482
}
3483
	fwrite($fd, $dhclientconf);
3484
	fclose($fd);
3485

    
3486
	/* bring wan interface up before starting dhclient */
3487
	if($wanif)
3488
		interfaces_bring_up($wanif);
3489
	else 
3490
		log_error(printf(gettext("Could not bring up %s interface in interface_dhcp_configure()"), $wanif));
3491

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

    
3495
	return 0;
3496
}
3497

    
3498
function interfaces_group_setup() {
3499
	global $config;
3500

    
3501
	if (!is_array($config['ifgroups']['ifgroupentry']))
3502
		return;
3503

    
3504
	foreach ($config['ifgroups']['ifgroupentry'] as $groupar)
3505
		interface_group_setup($groupar);
3506

    
3507
	return;
3508
}
3509

    
3510
function interface_group_setup(&$groupname /* The parameter is an array */) {
3511
	global $config;
3512

    
3513
	if (!is_array($groupname))
3514
		return;
3515
	$members = explode(" ", $groupname['members']);
3516
	foreach($members as $ifs) {
3517
		$realif = get_real_interface($ifs);
3518
		if ($realif)
3519
			mwexec("/sbin/ifconfig {$realif} group {$groupname['ifname']}");
3520
	}
3521

    
3522
	return;
3523
}
3524

    
3525
function interface_group_add_member($interface, $groupname) {
3526
	$interface = get_real_interface($interface);
3527
	mwexec("/sbin/ifconfig {$interface} group {$groupname}", true);
3528
}
3529
 
3530
/* COMPAT Function */
3531
function convert_friendly_interface_to_real_interface_name($interface) {
3532
	return get_real_interface($interface);
3533
}
3534

    
3535
/* COMPAT Function */
3536
function get_real_wan_interface($interface = "wan") {
3537
	return get_real_interface($interface);
3538
}
3539

    
3540
/* COMPAT Function */
3541
function get_current_wan_address($interface = "wan") {
3542
	return get_interface_ip($interface);
3543
}
3544

    
3545
/*
3546
 * convert_real_interface_to_friendly_interface_name($interface): convert fxp0 -> wan, etc.
3547
 */
3548
function convert_real_interface_to_friendly_interface_name($interface = "wan") {
3549
        global $config;
3550

    
3551
	if (stristr($interface, "vip")) {
3552
                $index = intval(substr($interface, 3));
3553
                foreach ($config['virtualip']['vip'] as $counter => $vip) {
3554
                        if ($vip['mode'] == "carpdev-dhcp" || $vip['mode'] == "carp")  {
3555
                                if ($index == $vip['vhid'])
3556
                                        return $vip['interface'];
3557
                        }
3558
                }
3559
        }
3560

    
3561
        /* XXX: For speed reasons reference directly the interface array */
3562
	$ifdescrs = &$config['interfaces'];
3563
        //$ifdescrs = get_configured_interface_list(false, true);
3564

    
3565
        foreach ($ifdescrs as $if => $ifname) {
3566
                if ($config['interfaces'][$if]['if'] == $interface)
3567
                        return $if;
3568

    
3569
                if (stristr($interface, "_wlan0") && $config['interfaces'][$if]['if'] == interface_get_wireless_base($interface))
3570
                        return $if;
3571

    
3572
		// XXX: This case doesn't work anymore (segfaults - recursion?) - should be replaced with something else or just removed.
3573
		//      Not to be replaced with get_real_interface - causes slow interface listings here because of recursion!
3574
		/*
3575
                $int = get_parent_interface($if);
3576
                if ($int[0] == $interface)
3577
                        return $ifname;
3578
		*/
3579
        }
3580
        return NULL;
3581
}
3582

    
3583
/* attempt to resolve interface to friendly descr */
3584
function convert_friendly_interface_to_friendly_descr($interface) {
3585
        global $config;
3586

    
3587
        switch ($interface) {
3588
        case "l2tp":
3589
        	$ifdesc = "L2TP";
3590
                break;
3591
	case "pptp":
3592
		$ifdesc = "PPTP";
3593
		break;
3594
	case "pppoe":
3595
		$ifdesc = "PPPoE";
3596
		break;
3597
	case "openvpn":
3598
		$ifdesc = "OpenVPN";
3599
		break;
3600
	case "enc0":
3601
	case "ipsec":
3602
		$ifdesc = "IPsec";
3603
		break;
3604
        default:
3605
                if (isset($config['interfaces'][$interface])) {
3606
                        if (empty($config['interfaces'][$interface]['descr']))
3607
                                $ifdesc = strtoupper($interface);
3608
                        else
3609
                                $ifdesc = strtoupper($config['interfaces'][$interface]['descr']);
3610
			break;
3611
		} else if (substr($interface, 0, 3) == "vip") {
3612
			if (is_array($config['virtualip']['vip'])) {
3613
				foreach ($config['virtualip']['vip'] as $counter => $vip) {
3614
					if ($vip['mode'] == "carpdev-dhcp" || $vip['mode'] == "carp")  {
3615
						if ($interface == "vip{$vip['vhid']}")
3616
							return "{$vip['subnet']} - {$vip['descr']}";
3617
					}
3618
				}
3619
                        }
3620
                } else {
3621
			/* if list */
3622
			$ifdescrs = get_configured_interface_with_descr(false, true);
3623
			foreach ($ifdescrs as $if => $ifname) {
3624
					if ($if == $interface || $ifname == $interface)
3625
						return $ifname;
3626
			}
3627
		}
3628
                break;
3629
        }
3630

    
3631
        return $ifdesc;
3632
}
3633

    
3634
function convert_real_interface_to_friendly_descr($interface) {
3635
        global $config;
3636

    
3637
        $ifdesc = convert_real_interface_to_friendly_interface_name("{$interface}");
3638

    
3639
        if ($ifdesc) {
3640
                $iflist = get_configured_interface_with_descr(false, true);
3641
                return $iflist[$ifdesc];
3642
        }
3643

    
3644
        return $interface;
3645
}
3646

    
3647
/*
3648
 *  get_parent_interface($interface):
3649
 *			--returns the (real or virtual) parent interface(s) array for a given interface friendly name (i.e. wan)
3650
 *				or virtual interface (i.e. vlan)
3651
 *				(We need array because MLPPP and bridge interfaces have more than one parent.)
3652
 *			-- returns $interface passed in if $interface parent is not found
3653
 *			-- returns empty array if an invalid interface is passed
3654
 *	(Only handles ppps and vlans now.)
3655
 */
3656
function get_parent_interface($interface) {
3657
	global $config;
3658

    
3659
	$parents = array();
3660
	//Check that we got a valid interface passed
3661
	$realif = get_real_interface($interface);
3662
	if ($realif == NULL)
3663
		return $parents;
3664

    
3665
	// If we got a real interface, find it's friendly assigned name
3666
	$interface = convert_real_interface_to_friendly_interface_name($interface);
3667
		
3668
	if (!empty($interface) && isset($config['interfaces'][$interface])) {
3669
		$ifcfg = $config['interfaces'][$interface];
3670
		switch ($ifcfg['ipaddr']) {
3671
			case "ppp":
3672
			case "pppoe":
3673
			case "pptp":
3674
			case "l2tp":
3675
				if (empty($parents))
3676
					if (is_array($config['ppps']['ppp']))
3677
						foreach ($config['ppps']['ppp'] as $pppidx => $ppp) {
3678
							if ($ppp_if == $ppp['if']) {
3679
								$ports = explode(',', $ppp['ports']);
3680
								foreach ($ports as $pid => $parent_if) 
3681
									$parents[$pid] = get_real_interface($parent_if);
3682
								break;
3683
							}
3684
						}
3685
				break;
3686
			case "dhcp":
3687
			case "static":
3688
			default:
3689
				// Handle _vlans
3690
				if (strstr($realif,"_vlan"))
3691
					if (is_array($config['vlans']['vlan'])) 
3692
						foreach ($config['vlans']['vlan'] as $vlanidx => $vlan)
3693
							if ($ifcfg['if'] == $vlan['vlanif']){
3694
								$parents[0] = $vlan['if'];
3695
								break;
3696
							}
3697
				break;
3698
		}
3699
	}
3700
	
3701
	if (empty($parents))
3702
		$parents[0] = $realif;
3703
	
3704
	return $parents;
3705
}
3706

    
3707
function interface_is_wireless_clone($wlif) {
3708
	if(!stristr($wlif, "_wlan")) {
3709
		return false;
3710
	} else {
3711
		return true;
3712
	}
3713
}
3714

    
3715
function interface_get_wireless_base($wlif) {
3716
	if(!stristr($wlif, "_wlan")) {
3717
		return $wlif;
3718
	} else {
3719
		return substr($wlif, 0, stripos($wlif, "_wlan"));
3720
	}
3721
}
3722

    
3723
function interface_get_wireless_clone($wlif) {
3724
	if(!stristr($wlif, "_wlan")) {
3725
		return $wlif . "_wlan0";
3726
	} else {
3727
		return $wlif;
3728
	}
3729
}
3730

    
3731
function get_real_interface($interface = "wan") {
3732
    global $config;
3733

    
3734
	$wanif = NULL;
3735

    
3736
	switch ($interface) {
3737
	case "l2tp":
3738
		$wanif = "l2tp";
3739
		break;
3740
	case "pptp":
3741
		$wanif = "pptp";
3742
		break;
3743
	case "pppoe":
3744
		$wanif = "pppoe";
3745
		break;
3746
	case "openvpn":
3747
		$wanif = "openvpn";
3748
		break;
3749
	case "ipsec":
3750
	case "enc0":
3751
		$wanif = "enc0";
3752
		break;
3753
	case "ppp":
3754
		$wanif = "ppp";
3755
		break;
3756
	default:
3757
		// If a real interface was alread passed simply
3758
		// pass the real interface back.  This encourages
3759
		// the usage of this function in more cases so that
3760
		// we can combine logic for more flexibility.
3761
		if(does_interface_exist($interface)) {
3762
			$wanif = $interface;
3763
			break;
3764
		}
3765
		if (empty($config['interfaces'][$interface]))
3766
			break;
3767

    
3768
		$cfg = &$config['interfaces'][$interface];
3769

    
3770
		// Wireless cloned NIC support (FreeBSD 8+)
3771
		// interface name format: $parentnic_wlanparentnic#
3772
		// example: ath0_wlan0
3773
		if (is_interface_wireless($cfg['if'])) {
3774
			$wanif = interface_get_wireless_clone($cfg['if']);
3775
			break;
3776
		}
3777
		/*
3778
		if (empty($cfg['if'])) {
3779
			$wancfg = $cfg['if'];
3780
			break;
3781
		}
3782
		*/
3783

    
3784
		switch ($cfg['ipaddr']) {
3785
			case "carpdev-dhcp":
3786
				$viparr = &$config['virtualip']['vip'];
3787
				if(is_array($viparr))
3788
				foreach ($viparr as $counter => $vip) {
3789
					if ($vip['mode'] == "carpdev-dhcp") {
3790
						if($vip['interface'] == $interface) {
3791
							$wanif = "carp{$counter}";
3792
							break;
3793
						}
3794
					}
3795
				}
3796
				break;
3797
			case "pppoe": 
3798
			case "pptp": 
3799
			case "l2tp": 
3800
			case "ppp":
3801
				$wanif = $cfg['if'];
3802
				break;
3803
			default:
3804
				$wanif = $cfg['if'];
3805
				break;
3806
		}
3807
		break;
3808
	}
3809

    
3810
    return $wanif;
3811
}
3812

    
3813
/* Guess the physical interface by providing a IP address */
3814
function guess_interface_from_ip($ipaddress) {
3815
	if(! is_ipaddr($ipaddress)) {
3816
		return false;
3817
	}
3818
	if(is_ipaddrv4($ipaddress)) {
3819
		/* create a route table we can search */
3820
		exec("netstat -rnWf inet", $output, $ret);
3821
		foreach($output as $line) {
3822
			if(preg_match("/^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\/[0-9]+[ ]+link[#]/", $line)) {
3823
				$fields = preg_split("/[ ]+/", $line);
3824
				if(ip_in_subnet($ipaddress, $fields[0])) {
3825
					return $fields[6];
3826
				}
3827
			}
3828
		}
3829
	}
3830
	/* FIXME: This works from cursory testing, regexp might need fine tuning */
3831
	if(is_ipaddrv6($ipaddress)) {
3832
		/* create a route table we can search */
3833
		exec("netstat -rnWf inet6", $output, $ret);
3834
		foreach($output as $line) {
3835
			if(preg_match("/[0-9a-f]+[:]+[0-9a-f]+[:]+[\/][0-9]+/", $line)) {
3836
				$fields = preg_split("/[ ]+/", $line);
3837
				if(ip_in_subnet($ipaddress, $fields[0])) {
3838
					return $fields[6];
3839
				}
3840
			}
3841
		}
3842
	}
3843
	$ret = exec_command("/sbin/route -n get {$ipaddress} | /usr/bin/awk '/interface/ { print \$2; };'");
3844
	if(empty($ret)) {
3845
        	return false;
3846
	}
3847
	return $ret;
3848
}
3849

    
3850
/*
3851
 * find_ip_interface($ip): return the interface where an ip is defined
3852
 */
3853
function find_ip_interface($ip)
3854
{
3855
        /* if list */
3856
        $ifdescrs = get_configured_interface_list();
3857

    
3858
        foreach ($ifdescrs as $ifdescr => $ifname) {
3859
		if ($ip == get_interface_ip($ifname)) {
3860
                	$int = get_real_interface($ifname);
3861
			return $int;
3862
		}
3863
        }
3864
        return false;
3865
}
3866

    
3867
/*
3868
 *   find_number_of_created_carp_interfaces: return the number of carp interfaces
3869
 */
3870
function find_number_of_created_carp_interfaces() {
3871
	return `/sbin/ifconfig | grep "carp:" | wc -l`;
3872
}
3873

    
3874
function get_all_carp_interfaces() {
3875
	$ints = str_replace("\n", " ", `ifconfig | grep "carp:" -B2 | grep ": flag" | cut -d: -f1`);
3876
	$ints = explode(" ", $ints);
3877
	return $ints;
3878
}
3879

    
3880
/*
3881
 * find_carp_interface($ip): return the carp interface where an ip is defined
3882
 */
3883
function find_carp_interface($ip) {
3884
	global $config;
3885
	if (is_array($config['virtualip']['vip'])) {
3886
		foreach ($config['virtualip']['vip'] as $vip) {
3887
			if ($vip['mode'] == "carp" || $vip['mode'] == "carpdev") {
3888
				if(is_ipaddrv4($ip)) {
3889
					$carp_ip = get_interface_ip($vip['interface']);
3890
				}
3891
				if(is_ipaddrv6($ip)) {
3892
					$carp_ip = get_interface_ipv6($vip['interface']);
3893
				}
3894
				exec("/sbin/ifconfig", $output, $return);
3895
				foreach($output as $line) {
3896
					$elements = preg_split("/[ ]+/i", $line);
3897
					if(strstr($elements[0], "vip"))
3898
						$curif = str_replace(":", "", $elements[0]);
3899
					if(stristr($line, $ip)) {
3900
						$if = $curif;
3901
						continue;
3902
					}
3903
				}
3904

    
3905
				if ($if)
3906
					return $if;
3907
			}
3908
		}
3909
	}
3910
}
3911

    
3912
function link_carp_interface_to_parent($interface) {
3913
        global $config;
3914

    
3915
        if ($interface == "")
3916
                return;
3917

    
3918
        $carp_ip = get_interface_ip($interface);
3919
        if (!is_ipaddr($carp_ip))
3920
                return;
3921

    
3922
        /* if list */
3923
        $ifdescrs = get_configured_interface_list();
3924
        foreach ($ifdescrs as $ifdescr => $ifname) {
3925
                $interfaceip = get_interface_ip($ifname);
3926
                $subnet_bits = get_interface_subnet($ifname);
3927
                $subnet_ip = gen_subnet("{$interfaceip}", "{$subnet_bits}");
3928
                if(ip_in_subnet($carp_ip, "{$subnet_ip}/{$subnet_bits}"))
3929
                        return $ifname;
3930
        }
3931

    
3932
        return "";
3933
}
3934

    
3935
/****f* interfaces/link_ip_to_carp_interface
3936
 * NAME
3937
 *   link_ip_to_carp_interface - Find where a CARP interface links to.
3938
 * INPUTS
3939
 *   $ip
3940
 * RESULT
3941
 *   $carp_ints
3942
 ******/
3943
function link_ip_to_carp_interface($ip) {
3944
        global $config;
3945

    
3946
        if (!is_ipaddr($ip))
3947
                return;
3948

    
3949
        $carp_ints = "";
3950
        if (is_array($config['virtualip']['vip'])) {
3951
		$first = 0;
3952
		$carp_int = array();
3953
                foreach ($config['virtualip']['vip'] as $vip) {
3954
                        if ($vip['mode'] == "carp" || $vip['mode'] == "carpdev") {
3955
                                $carp_ip = $vip['subnet'];
3956
                                $carp_sn = $vip['subnet_bits'];
3957
                                $carp_nw = gen_subnet($carp_ip, $carp_sn);
3958
                                if (ip_in_subnet($ip, "{$carp_nw}/{$carp_sn}"))
3959
					$carp_int[] = "vip{$vip['vhid']}";
3960
                        }
3961
                }
3962
		if (!empty($carp_int))
3963
			$carp_ints = implode(" ", array_unique($carp_int));
3964
        }
3965

    
3966
        return $carp_ints;
3967
}
3968

    
3969
function link_interface_to_vlans($int, $action = "") {
3970
	global $config;
3971

    
3972
	if (empty($int))
3973
		return;
3974

    
3975
	if (is_array($config['vlans']['vlan'])) {
3976
                foreach ($config['vlans']['vlan'] as $vlan) {
3977
			if ($int == $vlan['if']) {
3978
				if ($action == "update") {
3979
					interfaces_bring_up($int);
3980
				} else if ($action == "")
3981
					return $vlan;
3982
			}
3983
		}
3984
	}
3985
}
3986

    
3987
function link_interface_to_vips($int, $action = "") {
3988
        global $config;
3989

    
3990
        if (is_array($config['virtualip']['vip'])) {
3991
		foreach ($config['virtualip']['vip'] as $vip) {
3992
			if ($int == $vip['interface']) {
3993
				if ($action == "update") {
3994
					if ($vip['mode'] == "carp" && !does_interface_exist("vip{$vip['vhid']}"))
3995
						interfaces_vips_configure($int);
3996
					else {
3997
						interface_vip_bring_down($vip);
3998
						interfaces_vips_configure($int);
3999
					}
4000
				} else
4001
					return $vip;
4002
			}
4003
		}
4004
	}
4005
}
4006

    
4007
/****f* interfaces/link_interface_to_bridge
4008
 * NAME
4009
 *   link_interface_to_bridge - Finds out a bridge group for an interface
4010
 * INPUTS
4011
 *   $ip
4012
 * RESULT
4013
 *   bridge[0-99]
4014
 ******/
4015
function link_interface_to_bridge($int) {
4016
        global $config;
4017

    
4018
        if (is_array($config['bridges']['bridged'])) {
4019
                foreach ($config['bridges']['bridged'] as $bridge) {
4020
			if (in_array($int, explode(',', $bridge['members'])))
4021
                                return "{$bridge['bridgeif']}";
4022
		}
4023
	}
4024
}
4025

    
4026
function link_interface_to_group($int) {
4027
        global $config;
4028

    
4029
	$result = array();
4030

    
4031
        if (is_array($config['ifgroups']['ifgroupentry'])) {
4032
                foreach ($config['ifgroups']['ifgroupentry'] as $group) {
4033
			if (in_array($int, explode(" ", $group['members'])))
4034
				$result[$group['ifname']] = $int;
4035
		}
4036
	}
4037

    
4038
	return $result;
4039
}
4040

    
4041
function link_interface_to_gre($interface) {
4042
        global $config;
4043

    
4044
	$result = array();
4045

    
4046
        if (is_array($config['gres']['gre'])) {
4047
                foreach ($config['gres']['gre'] as $gre)
4048
                        if($gre['if'] == $interface)
4049
				$result[] = $gre;
4050
	}
4051

    
4052
	return $result;
4053
}
4054

    
4055
function link_interface_to_gif($interface) {
4056
        global $config;
4057

    
4058
	$result = array();
4059

    
4060
        if (is_array($config['gifs']['gif'])) {
4061
                foreach ($config['gifs']['gif'] as $gif)
4062
                        if($gif['if'] == $interface)
4063
                                $result[] = $gif;
4064
	}
4065

    
4066
	return $result;
4067
}
4068

    
4069
/*
4070
 * find_interface_ip($interface): return the interface ip (first found)
4071
 */
4072
function find_interface_ip($interface, $flush = false)
4073
{
4074
	global $interface_ip_arr_cache;
4075
	global $interface_sn_arr_cache;
4076

    
4077
	$interface = str_replace("\n", "", $interface);
4078
	
4079
	if (!does_interface_exist($interface))
4080
		return;
4081

    
4082
	/* Setup IP cache */
4083
	if (!isset($interface_ip_arr_cache[$interface]) or $flush) {
4084
		$ifinfo = pfSense_get_interface_addresses($interface);
4085
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
4086
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
4087
	}
4088

    
4089
	return $interface_ip_arr_cache[$interface];
4090
}
4091

    
4092
/*
4093
 * find_interface_ipv6($interface): return the interface ip (first found)
4094
 */
4095
function find_interface_ipv6($interface, $flush = false)
4096
{
4097
	global $interface_ipv6_arr_cache;
4098
	global $interface_snv6_arr_cache;
4099
	global $config;
4100
	
4101
	$interface = str_replace("\n", "", $interface);
4102
	
4103
	if (!does_interface_exist($interface))
4104
		return;
4105

    
4106
	/* Setup IP cache */
4107
	if (!isset($interface_ipv6_arr_cache[$interface]) or $flush) {
4108
		$ifinfo = pfSense_get_interface_addresses($interface);
4109
		// FIXME: Add IPv6 support to the pfSense module
4110
		exec("/sbin/ifconfig {$interface} inet6", $output);
4111
		foreach($output as $line) {
4112
			if(preg_match("/inet6/", $line)) {
4113
				$parts = explode(" ", $line);
4114
				if(! preg_match("/fe80::/", $parts[1])) {
4115
					$ifinfo['ipaddrv6'] = $parts[1];
4116
					if($parts[2] == "-->") {
4117
						$parts[5] = "126";
4118
						$ifinfo['subnetbitsv6'] = $parts[5];
4119
					} else {
4120
						$ifinfo['subnetbitsv6'] = $parts[3];
4121
					}
4122
				}
4123
			}
4124
		}
4125
		$interface_ipv6_arr_cache[$interface] = $ifinfo['ipaddrv6'];
4126
		$interface_snv6_arr_cache[$interface] = $ifinfo['subnetbitsv6'];
4127
	}
4128

    
4129
	return $interface_ipv6_arr_cache[$interface];
4130
}
4131

    
4132
/*
4133
 * find_interface_ipv6_ll($interface): return the interface ipv6 link local (first found)
4134
 */
4135
function find_interface_ipv6_ll($interface, $flush = false)
4136
{
4137
	global $interface_llv6_arr_cache;
4138
	global $config;
4139
	
4140
	$interface = str_replace("\n", "", $interface);
4141
	
4142
	if (!does_interface_exist($interface))
4143
		return;
4144

    
4145
	/* Setup IP cache */
4146
	if (!isset($interface_llv6_arr_cache[$interface]) or $flush) {
4147
		$ifinfo = pfSense_get_interface_addresses($interface);
4148
		// FIXME: Add IPv6 support to the pfSense module
4149
		exec("/sbin/ifconfig {$interface} inet6", $output);
4150
		foreach($output as $line) {
4151
			if(preg_match("/inet6/", $line)) {
4152
				$parts = explode(" ", $line);
4153
				if(preg_match("/fe80::/", $parts[1])) {
4154
					$partsaddress = explode("%", $parts[1]);
4155
					$ifinfo['linklocal'] = $partsaddress[0];
4156
				}
4157
			}
4158
		}
4159
		$interface_llv6_arr_cache[$interface] = $ifinfo['linklocal'];
4160
	}
4161
	return $interface_llv6_arr_cache[$interface];
4162
}
4163

    
4164
function find_interface_subnet($interface, $flush = false)
4165
{
4166
	global $interface_sn_arr_cache;
4167
	global $interface_ip_arr_cache;
4168

    
4169
	$interface = str_replace("\n", "", $interface);
4170
	if (does_interface_exist($interface) == false)
4171
		return;
4172

    
4173
	if (!isset($interface_sn_arr_cache[$interface]) or $flush) {
4174
		$ifinfo = pfSense_get_interface_addresses($interface);
4175
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
4176
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
4177
        }
4178

    
4179
	return $interface_sn_arr_cache[$interface];
4180
}
4181

    
4182
function find_interface_subnetv6($interface, $flush = false)
4183
{
4184
	global $interface_snv6_arr_cache;
4185
	global $interface_ipv6_arr_cache;
4186

    
4187
	$interface = str_replace("\n", "", $interface);
4188
	if (does_interface_exist($interface) == false)
4189
		return;
4190

    
4191
	if (!isset($interface_snv6_arr_cache[$interface]) or $flush) {
4192
		$ifinfo = pfSense_get_interface_addresses($interface);
4193
		// FIXME: Add IPv6 support to the pfSense module
4194
		exec("/sbin/ifconfig {$interface} inet6", $output);
4195
		foreach($output as $line) {
4196
			if(preg_match("/inet6/", $line)) {
4197
				$parts = explode(" ", $line);
4198
				if(! preg_match("/fe80::/", $parts[1])) {
4199
					$ifinfo['ipaddrv6'] = $parts[1];
4200
					if($parts[2] == "-->") {
4201
						$parts[5] = "126";
4202
						$ifinfo['subnetbitsv6'] = $parts[5];
4203
					} else {
4204
						$ifinfo['subnetbitsv6'] = $parts[3];
4205
					}
4206
				}
4207
			}
4208
		}
4209
		$interface_ipv6_arr_cache[$interface] = $ifinfo['ipaddrv6'];
4210
		$interface_snv6_arr_cache[$interface] = $ifinfo['subnetbitsv6'];
4211
        }
4212

    
4213
	return $interface_snv6_arr_cache[$interface];
4214
}
4215

    
4216
function ip_in_interface_alias_subnet($interface, $ipalias) {
4217
	global $config;
4218

    
4219
	if (empty($interface) || !is_ipaddr($ipalias))
4220
		return false;
4221
	if (is_array($config['virtualip']['vip'])) {
4222
                foreach ($config['virtualip']['vip'] as $vip) {
4223
                        switch ($vip['mode']) {
4224
                        case "ipalias":
4225
                                if ($vip['interface'] <> $interface)
4226
                                        break;
4227
				if (ip_in_subnet($ipalias, gen_subnet($vip['subnet'], $vip['subnet_bits']) . "/" . $vip['subnet_bits']))
4228
					return true;
4229
                                break;
4230
                        }
4231
                }
4232
	}
4233

    
4234
	return false;
4235
}
4236

    
4237
function get_interface_ip($interface = "wan")
4238
{
4239
	$realif = get_real_interface($interface);
4240
	if (!$realif) {
4241
		if (preg_match("/^carp/i", $interface))
4242
			$realif = $interface;
4243
		else if (preg_match("/^vip/i", $interface))
4244
			$realif = $interface;
4245
		else
4246
			return null;
4247
	}
4248

    
4249
	$curip = find_interface_ip($realif);
4250
	if ($curip && is_ipaddr($curip) && ($curip != "0.0.0.0"))
4251
		return $curip;
4252
	else
4253
		return null;
4254
}
4255

    
4256
function get_interface_ipv6($interface = "wan")
4257
{
4258
	$realif = get_real_interface($interface);
4259
	if (!$realif) {
4260
		if (preg_match("/^carp/i", $interface))
4261
			$realif = $interface;
4262
		else if (preg_match("/^vip/i", $interface))
4263
			$realif = $interface;
4264
		else
4265
			return null;
4266
	}
4267

    
4268
	$curip = find_interface_ipv6($realif);
4269
	if ($curip && is_ipaddrv6($curip) && ($curip != "::"))
4270
		return $curip;
4271
	else
4272
		return null;
4273
}
4274

    
4275
function get_interface_linklocal($interface = "wan")
4276
{
4277
	$realif = get_real_interface($interface);
4278
	if (!$realif) {
4279
		if (preg_match("/^carp/i", $interface))
4280
			$realif = $interface;
4281
		else if (preg_match("/^vip/i", $interface))
4282
			$realif = $interface;
4283
		else
4284
			return null;
4285
	}
4286

    
4287
	$curip = find_interface_ipv6_ll($realif);
4288
	if ($curip && is_ipaddrv6($curip) && ($curip != "::"))
4289
		return $curip;
4290
	else
4291
		return null;
4292
}
4293

    
4294
function get_interface_subnet($interface = "wan")
4295
{
4296
	$realif = get_real_interface($interface);
4297
	if (!$realif) {
4298
                if (preg_match("/^carp/i", $interface))
4299
                        $realif = $interface;
4300
                else if (preg_match("/^vip/i", $interface))
4301
                        $realif = $interface;
4302
                else
4303
                        return null;
4304
        }
4305

    
4306
	$cursn = find_interface_subnet($realif);
4307
	if (!empty($cursn))
4308
		return $cursn;
4309

    
4310
	return null;
4311
}
4312

    
4313
function get_interface_subnetv6($interface = "wan")
4314
{
4315
	$realif = get_real_interface($interface);
4316
	if (!$realif) {
4317
                if (preg_match("/^carp/i", $interface))
4318
                        $realif = $interface;
4319
                else if (preg_match("/^vip/i", $interface))
4320
                        $realif = $interface;
4321
                else
4322
                        return null;
4323
        }
4324

    
4325
	$cursn = find_interface_subnetv6($realif);
4326
	if (!empty($cursn))
4327
		return $cursn;
4328

    
4329
	return null;
4330
}
4331

    
4332
/* return outside interfaces with a gateway */
4333
function get_interfaces_with_gateway() {
4334
	global $config;
4335

    
4336
	$ints = array();
4337

    
4338
	/* loop interfaces, check config for outbound */
4339
	foreach($config['interfaces'] as $ifdescr => $ifname) {
4340
		switch ($ifname['ipaddr']) {
4341
			case "dhcp":
4342
			case "carpdev-dhcp":
4343
			case "ppp";
4344
			case "pppoe":
4345
			case "pptp":
4346
			case "l2tp":
4347
			case "ppp";
4348
				$ints[$ifdescr] = $ifdescr;
4349
			break;
4350
			default:
4351
				if (substr($ifname['if'], 0, 5) ==  "ovpnc" ||
4352
				    !empty($ifname['gateway']))
4353
					$ints[$ifdescr] = $ifdescr;
4354
			break;
4355
		}
4356
	}
4357
	return $ints;
4358
}
4359

    
4360
/* return true if interface has a gateway */
4361
function interface_has_gateway($friendly) {
4362
	global $config;
4363

    
4364
	if (!empty($config['interfaces'][$friendly])) {
4365
		$ifname = &$config['interfaces'][$friendly];
4366
		switch ($ifname['ipaddr']) {
4367
			case "dhcp":
4368
			case "carpdev-dhcp":
4369
			case "pppoe":
4370
			case "pptp":
4371
			case "l2tp":
4372
			case "ppp";
4373
				return true;
4374
			break;
4375
			default:
4376
				if (substr($ifname['if'], 0, 5) ==  "ovpnc")
4377
					return true;
4378
				if (!empty($ifname['gateway']))
4379
					return true;
4380
			break;
4381
		}
4382
	}
4383

    
4384
	return false;
4385
}
4386

    
4387
/* return true if interface has a gateway */
4388
function interface_has_gatewayv6($friendly) {
4389
	global $config;
4390

    
4391
	if (!empty($config['interfaces'][$friendly])) {
4392
		$ifname = &$config['interfaces'][$friendly];
4393
		switch ($ifname['ipaddrv6']) {
4394
			case "dhcp6":
4395
				return true;
4396
				break;
4397
			case "6to4":
4398
				return true;
4399
				break;
4400
			case "6rd":
4401
				return true;
4402
				break;
4403
			default:
4404
				if (substr($ifname['if'], 0, 5) ==  "ovpnc")
4405
					return true;
4406
				if (!empty($ifname['gatewayv6']))
4407
					return true;
4408
				break;
4409
		}
4410
	}
4411

    
4412
	return false;
4413
}
4414

    
4415
/****f* interfaces/is_altq_capable
4416
 * NAME
4417
 *   is_altq_capable - Test if interface is capable of using ALTQ
4418
 * INPUTS
4419
 *   $int            - string containing interface name
4420
 * RESULT
4421
 *   boolean         - true or false
4422
 ******/
4423

    
4424
function is_altq_capable($int) {
4425
        /* Per:
4426
         * http://www.freebsd.org/cgi/man.cgi?query=altq&manpath=FreeBSD+7.2-current&format=html
4427
         * Only the following drivers have ALTQ support
4428
         */
4429
	$capable = array("age", "alc", "ale", "an", "ath", "aue", "awi", "bce",
4430
			"bfe", "bge", "bridge", "cas", "dc", "de", "ed", "em", "ep", "fxp", "gem",
4431
			"hme", "igb", "ipw", "iwi", "jme", "le", "lem", "msk", "mxge", "my", "nfe",
4432
			"npe", "nve", "ral", "re", "rl", "rum", "run", "bwn", "sf", "sis", "sk",
4433
			"ste", "stge", "txp", "udav", "ural", "vge", "vr", "wi", "xl",
4434
			"ndis", "tun", "ovpns", "ovpnc", "vlan", "pppoe", "pptp", "ng",
4435
			"l2tp", "ppp");
4436

    
4437
        $int_family = preg_split("/[0-9]+/", $int);
4438

    
4439
        if (in_array($int_family[0], $capable))
4440
                return true;
4441
	else if (stristr($int, "l2tp")) /* VLANs are name $parent_$vlan now */
4442
		return true;
4443
	else if (stristr($int, "vlan")) /* VLANs are name $parent_$vlan now */
4444
		return true;
4445
	else if (stristr($int, "_wlan")) /* WLANs are name $parent_$wlan now */
4446
		return true;
4447
        else
4448
                return false;
4449
}
4450

    
4451
/****f* interfaces/is_interface_wireless
4452
 * NAME
4453
 *   is_interface_wireless - Returns if an interface is wireless
4454
 * RESULT
4455
 *   $tmp       - Returns if an interface is wireless
4456
 ******/
4457
function is_interface_wireless($interface) {
4458
        global $config, $g;
4459

    
4460
        $friendly = convert_real_interface_to_friendly_interface_name($interface);
4461
        if(!isset($config['interfaces'][$friendly]['wireless'])) {
4462
                if (preg_match($g['wireless_regex'], $interface)) {
4463
                        if (isset($config['interfaces'][$friendly]))
4464
                                $config['interfaces'][$friendly]['wireless'] = array();
4465
                        return true;
4466
                }
4467
                return false;
4468
        } else
4469
                return true;
4470
}
4471

    
4472
function get_wireless_modes($interface) {
4473
	/* return wireless modes and channels */
4474
	$wireless_modes = array();
4475

    
4476
	$cloned_interface = get_real_interface($interface);
4477

    
4478
	if($cloned_interface && is_interface_wireless($cloned_interface)) {
4479
		$chan_list = "/sbin/ifconfig {$cloned_interface} list chan";
4480
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
4481
		$format_list = "/usr/bin/awk '{print \$5 \" \" \$6 \",\" \$1}'";
4482

    
4483
		$interface_channels = "";
4484
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
4485
		$interface_channel_count = count($interface_channels);
4486

    
4487
		$c = 0;
4488
		while ($c < $interface_channel_count)
4489
		{
4490
			$channel_line = explode(",", $interface_channels["$c"]);
4491
			$wireless_mode = trim($channel_line[0]);
4492
			$wireless_channel = trim($channel_line[1]);
4493
			if(trim($wireless_mode) != "") {
4494
				/* if we only have 11g also set 11b channels */
4495
				if($wireless_mode == "11g") {
4496
					if(!isset($wireless_modes["11b"]))
4497
						$wireless_modes["11b"] = array();
4498
				} else if($wireless_mode == "11g ht") {
4499
					if(!isset($wireless_modes["11b"]))
4500
						$wireless_modes["11b"] = array();
4501
					if(!isset($wireless_modes["11g"]))
4502
						$wireless_modes["11g"] = array();
4503
					$wireless_mode = "11ng";
4504
				} else if($wireless_mode == "11a ht") {
4505
					if(!isset($wireless_modes["11a"]))
4506
						$wireless_modes["11a"] = array();
4507
					$wireless_mode = "11na";
4508
				}
4509
				$wireless_modes["$wireless_mode"]["$c"] = $wireless_channel;
4510
			}
4511
			$c++;
4512
		}
4513
	}
4514
	return($wireless_modes);
4515
}
4516

    
4517
/* return channel numbers, frequency, max txpower, and max regulation txpower */
4518
function get_wireless_channel_info($interface) {
4519
	$wireless_channels = array();
4520

    
4521
	$cloned_interface = get_real_interface($interface);
4522

    
4523
	if($cloned_interface && is_interface_wireless($cloned_interface)) {
4524
		$chan_list = "/sbin/ifconfig {$cloned_interface} list txpower";
4525
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
4526
		$format_list = "/usr/bin/awk '{print \$1 \",\" \$3 \" \" \$4 \",\" \$5 \",\" \$7}'";
4527

    
4528
		$interface_channels = "";
4529
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
4530

    
4531
		foreach ($interface_channels as $channel_line) {
4532
			$channel_line = explode(",", $channel_line);
4533
			if(!isset($wireless_channels[$channel_line[0]]))
4534
				$wireless_channels[$channel_line[0]] = $channel_line;
4535
		}
4536
	}
4537
	return($wireless_channels);
4538
}
4539

    
4540
/****f* interfaces/get_interface_mtu
4541
 * NAME
4542
 *   get_interface_mtu - Return the mtu of an interface
4543
 * RESULT
4544
 *   $tmp       - Returns the mtu of an interface
4545
 ******/
4546
function get_interface_mtu($interface) {
4547
        $mtu = pfSense_get_interface_addresses($interface);
4548
        return $mtu['mtu'];
4549
}
4550

    
4551
function get_interface_mac($interface) {
4552

    
4553
	$macinfo = pfSense_get_interface_addresses($interface);
4554
	return $macinfo["macaddr"];
4555
}
4556

    
4557
/****f* pfsense-utils/generate_random_mac_address
4558
 * NAME
4559
 *   generate_random_mac - generates a random mac address
4560
 * INPUTS
4561
 *   none
4562
 * RESULT
4563
 *   $mac - a random mac address
4564
 ******/
4565
function generate_random_mac_address() {
4566
        $mac = "02";
4567
        for($x=0; $x<5; $x++)
4568
                $mac .= ":" . dechex(rand(16, 255));
4569
        return $mac;
4570
}
4571

    
4572
/****f* interfaces/is_jumbo_capable
4573
 * NAME
4574
 *   is_jumbo_capable - Test if interface is jumbo frame capable.  Useful for determining VLAN capability.
4575
 * INPUTS
4576
 *   $int             - string containing interface name
4577
 * RESULT
4578
 *   boolean          - true or false
4579
 ******/
4580
function is_jumbo_capable($iface) {
4581

    
4582

    
4583
	$iface = trim($iface);
4584
	$capable = pfSense_get_interface_addresses($iface);
4585
	if (isset($capable['caps']['vlanmtu']))
4586
                return true;
4587

    
4588

    
4589

    
4590

    
4591

    
4592
	return false;
4593
}
4594

    
4595
function setup_pppoe_reset_file($pppif, $iface="") {
4596
	global $g;
4597
	$cron_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
4598

    
4599
	if(!empty($iface) && !empty($pppif)){
4600
		$cron_cmd = <<<EOD
4601
#!/bin/sh
4602
/usr/local/sbin/pfSctl -c 'interface reload {$iface}'
4603
/usr/bin/logger -t pppoe{$iface} "PPPoE periodic reset executed on {$iface}"
4604

    
4605
EOD;
4606

    
4607
		file_put_contents($cron_file, $cron_cmd);
4608
		chmod($cron_file, 0700);
4609
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
4610
	} else
4611
		unlink_if_exists($cron_file);
4612
}
4613

    
4614
function get_interface_default_mtu($type = "ethernet") {
4615
	switch ($type) {
4616
	case "gre":
4617
		return 1476;
4618
		break;
4619
	case "gif":
4620
		return 1280;
4621
		break;
4622
	case "tun":
4623
	case "vlan":
4624
	case "tap":
4625
	case "ethernet":
4626
	default:
4627
		return 1500;
4628
		break;
4629
	}
4630

    
4631
	/* Never reached */
4632
	return 1500;
4633
}
4634

    
4635
function get_vip_descr($ipaddress) {
4636
	global $config;
4637

    
4638
	foreach ($config['virtualip']['vip'] as $vip) {
4639
		if ($vip['subnet'] == $ipaddress) {
4640
			return ($vip['descr']);
4641
		}
4642
	}
4643
	return "";
4644
}
4645

    
4646
function interfaces_staticarp_configure($if) {
4647
	global $config, $g;
4648
	if(isset($config['system']['developerspew'])) {
4649
		$mt = microtime();
4650
		echo "interfaces_staticarp_configure($if) being called $mt\n";
4651
	}
4652

    
4653
	$ifcfg = $config['interfaces'][$if];
4654

    
4655
	if (empty($if) || empty($ifcfg['if']))
4656
		return 0;
4657

    
4658
	/* Enable staticarp, if enabled */
4659
	if(isset($config['dhcpd'][$if]['staticarp'])) {
4660
		mwexec("/sbin/ifconfig " . escapeshellarg($ifcfg['if']) . " staticarp " );
4661
		mwexec("/usr/sbin/arp -d -i " . escapeshellarg($ifcfg['if']) . " -a > /dev/null 2>&1 ");
4662
		if (is_array($config['dhcpd'][$if]['staticmap'])) {
4663

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

    
4667
			}
4668

    
4669
		}
4670
	} else {
4671
		mwexec("/sbin/ifconfig " . escapeshellarg($ifcfg['if']) . " -staticarp " );
4672
		mwexec("/usr/sbin/arp -d -i " . escapeshellarg($ifcfg['if']) . " -a > /dev/null 2>&1 ");
4673
	}
4674

    
4675
	return 0;
4676
}
4677

    
4678
?>
(26-26/64)