Project

General

Profile

Download (98.9 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:	/usr/sbin/pppd	/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_MODULE:	interfaces
41

    
42
*/
43

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

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

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

    
63
        /* If the cache doesn't exist, build it */
64
        if (!isset($interface_arr_cache) or $flush)
65
                $interface_arr_cache = explode(" ", trim(`/sbin/ifconfig -l`));
66

    
67
        return $interface_arr_cache;
68
}
69

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

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

    
87
function interfaces_loopback_configure() {
88
	if($g['booting'])
89
		echo "Configuring loopback interface...";
90
	pfSense_interface_setaddress("lo0", "127.0.0.1");
91
	interfaces_bring_up("lo0");
92
	exec("/sbin/route add 127.0.0.2 127.0.0.1");
93
	if($g['booting'])
94
		echo "done.\n";
95
	return 0;
96
}
97

    
98
function interfaces_vlan_configure() {
99
	global $config, $g;
100
	if($g['booting'])
101
		echo "Configuring VLAN interfaces...";
102
	if (is_array($config['vlans']['vlan']) && count($config['vlans']['vlan'])) {
103
		foreach ($config['vlans']['vlan'] as $vlan) {
104
			if(empty($vlan['vlanif']))
105
				$vlan['vlanif'] = "{$vlan['if']}_vlan{$vlan['tag']}";
106
			/* XXX: Maybe we should report any errors?! */
107
			interface_vlan_configure($vlan);
108
		}
109
	}
110
	if($g['booting'])
111
		echo "done.\n";
112
}
113

    
114
function interface_vlan_configure(&$vlan) {
115
        global $config, $g;
116

    
117
	if (!is_array($vlan)) {
118
		log_error("VLAN: called with wrong options. Problems with config!");
119
		return;
120
	}
121
	$if = $vlan['if'];
122
	$vlanif  = empty($vlan['vlanif']) ? "{$if}_vlan{$vlan['tag']}" : $vlan['vlanif'];
123
	$tag = $vlan['tag'];
124

    
125
	if (empty($if)) {
126
		log_error("interface_vlan_confgure called with if undefined.");
127
		return;
128
	}
129

    
130
	/* make sure the parent interface is up */
131
	interfaces_bring_up($if);
132
	/* Since we are going to add vlan(4) try to enable all that hardware supports. */
133
	pfSense_interface_capabilities($if, IFCAP_VLAN_HWTAGGING|IFCAP_VLAN_MTU|IFCAP_VLAN_HWFILTER);
134

    
135
	if (!empty($vlanif) && does_interface_exist($vlanif)) {
136
		interface_bring_down($vlanif);
137
	} else {
138
		$tmpvlanif = pfSense_interface_create("vlan");
139
		pfSense_interface_rename($tmpvlanif, $vlanif);
140
		pfSense_ngctl_name("{$tmpvlanif}:", $vlanif);
141
	}
142

    
143
	pfSense_vlan_create($vlanif, $if, $tag);
144

    
145
	interfaces_bring_up($vlanif);
146

    
147
	/* invalidate interface cache */
148
	get_interface_arr(true);
149

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

    
153
	return $vlanif;
154
}
155

    
156
function interface_qinq_configure(&$vlan, $fd = NULL) {
157
        global $config, $g;
158

    
159
        if (!is_array($vlan)) {
160
                log_error("QinQ compat VLAN: called with wrong options. Problems with config!\n");
161
                return;
162
        }
163

    
164
        $qinqif = $vlan['if'];
165
        $tag = $vlan['tag'];
166
        if(empty($qinqif)) {
167
                log_error("interface_qinq_confgure called with if undefined.\n");
168
                return;
169
        }
170
	$vlanif = interface_vlan_configure($vlan);
171

    
172
        if ($fd == NULL) {
173
                $exec = true;
174
                $fd = fopen("{$g['tmp_path']}/netgraphcmd", "w");
175
        } else
176
                $exec = false;
177
        /* make sure the parent is converted to ng_vlan(4) and is up */
178
        interfaces_bring_up($qinqif);
179

    
180
        if (!empty($vlanif) && does_interface_exist($vlanif)) {
181
                fwrite($fd, "shutdown {$qinqif}qinq:\n");
182
                exec("/usr/sbin/ngctl msg {$qinqif}qinq: gettable", $result);
183
                if (empty($result)) {
184
                        fwrite($fd, "mkpeer {$qinqif}: vlan lower downstream\n");
185
                        fwrite($fd, "name {$qinqif}:lower {$vlanif}qinq\n");
186
                        fwrite($fd, "connect {$qinqif}: {$vlanif}qinq: upper nomatch\n");
187
                }
188
        } else {
189
                fwrite($fd, "mkpeer {$qinqif}: vlan lower downstream\n");
190
                fwrite($fd, "name {$qinqif}:lower {$vlanif}qinq\n");
191
                fwrite($fd, "connect {$qinqif}: {$vlanif}qinq: upper nomatch\n");
192
        }
193

    
194
        /* invalidate interface cache */
195
        get_interface_arr(true);
196

    
197
        if (!stristr($qinqif, "vlan"))
198
                mwexec("/sbin/ifconfig {$qinqif} promisc\n");
199

    
200
        $macaddr = get_interface_mac($qinqif);
201
        if (!empty($vlan['members'])) {
202
                $members = explode(" ", $vlan['members']);
203
                foreach ($members as $qtag) {
204
                        $qinq = array();
205
                        $qinq['tag'] = $qtag;
206
                        $qinq['if'] = $vlanif;
207
                        interface_qinq2_configure($qinq, $fd, $macaddr);
208
                }
209
        }
210
        if ($exec == true) {
211
                fclose($fd);
212
                mwexec("/usr/sbin/ngctl -f {$g['tmp_path']}/netgraphcmd");
213
        }
214

    
215
        interfaces_bring_up($qinqif);
216
        if (!empty($vlan['members'])) {
217
                $members = explode(" ", $vlan['members']);
218
                foreach ($members as $qif)
219
                        interfaces_bring_up("{$vlanif}_{$qif}");
220
        }
221

    
222
        return $vlanif;
223
}
224

    
225
function interfaces_qinq_configure() {
226
	global $config, $g;
227
	if($g['booting'])
228
		echo "Configuring QinQ interfaces...";
229
	if (is_array($config['qinqs']['qinqentry']) && count($config['qinqs']['qinqentry'])) {
230
		foreach ($config['qinqs']['qinqentry'] as $qinq) {
231
			/* XXX: Maybe we should report any errors?! */
232
			interface_qinq_configure($qinq);
233
		}
234
	}
235
	if($g['booting'])
236
		echo "done.\n";
237
}
238

    
239
function interface_qinq2_configure(&$qinq, $fd, $macaddr) {
240
        global $config, $g;
241

    
242
        if (!is_array($qinq)) {
243
                log_error("QinQ compat VLAN: called with wrong options. Problems with config!\n");
244
                return;
245
        }
246

    
247
        $if = $qinq['if'];
248
        $tag = $qinq['tag'];
249
        $vlanif = "{$if}_{$tag}";
250
        if(empty($if)) {
251
                log_error("interface_qinq_confgure called with if undefined.\n");
252
                return;
253
        }
254

    
255
        fwrite($fd, "shutdown {$if}h{$tag}:\n");
256
        fwrite($fd, "mkpeer {$if}qinq: eiface {$if}{$tag} ether\n");
257
        fwrite($fd, "name {$if}qinq:{$if}{$tag} {$if}h{$tag}\n");
258
        fwrite($fd, "msg {$if}qinq: addfilter { vlan={$tag} hook=\"{$if}{$tag}\" }\n");
259
        fwrite($fd, "msg {$if}h{$tag}: setifname \"{$vlanif}\"\n");
260
        fwrite($fd, "msg {$if}h{$tag}: set {$macaddr}\n");
261

    
262
        /* invalidate interface cache */
263
        get_interface_arr(true);
264

    
265
        return $vlanif;
266
}
267

    
268
function interfaces_create_wireless_clones() {
269
	global $config;
270

    
271
	if($g['booting'])
272
		echo "Creating other wireless clone interfaces...";
273
	if (is_array($config['wireless']['clone']) && count($config['wireless']['clone'])) {
274
		foreach ($config['wireless']['clone'] as $clone) {
275
			if(empty($clone['cloneif']))
276
				continue;
277
			if(does_interface_exist($clone['cloneif']))
278
				continue;
279
			/* XXX: Maybe we should report any errors?! */
280
			if(interface_wireless_clone($clone['cloneif'], $clone))
281
				if($g['booting'])
282
					echo " " . $clone['cloneif'];
283
		}
284
	}
285
	if($g['booting'])
286
		echo " done.\n";
287
}
288

    
289
function interfaces_bridge_configure() {
290
        global $config;
291

    
292
        $i = 0;
293
        if (is_array($config['bridges']['bridged']) && count($config['bridges']['bridged'])) {
294
                foreach ($config['bridges']['bridged'] as $bridge) {
295
                        if(empty($bridge['bridgeif']))
296
                                $bridge['bridgeif'] = "bridge{$i}";
297
                        /* XXX: Maybe we should report any errors?! */
298
                        interface_bridge_configure($bridge);
299
                        $i++;
300
                }
301
        }
302
}
303

    
304
function interface_bridge_configure(&$bridge) {
305
	global $config, $g;
306

    
307
	if (!is_array($bridge))
308
	        return -1;
309

    
310
	if (empty($bridge['members'])) {
311
		log_error("No members found on {$bridge['bridgeif']}");
312
		return -1;
313
	}
314

    
315
	$members = explode(',', $bridge['members']);
316
	if (!count($members))
317
		return -1;
318

    
319
	$checklist = get_configured_interface_list();
320

    
321
	if ($g['booting'] || !empty($bridge['bridgeif'])) {
322
		pfSense_interface_destroy($bridge['bridgeif']);
323
		pfSense_interface_create($bridge['bridgeif']);
324
		$bridgeif = $bridge['bridgeif'];
325
	} else
326
		$bridgeif = pfSense_interface_create("bridge");
327

    
328
	/* Calculate smaller mtu and enforce it */
329
	$smallermtu = 0;
330
	$commonrx = true;
331
	$commontx = true;
332
	foreach ($members as $member) {
333
		$realif = get_real_interface($member);
334
		$opts = pfSense_get_interface_addresses($realif);
335
		$mtu = $opts['mtu'];
336
		if (!isset($opts['encaps']['txcsum']))
337
			$commontx = false;
338
		if (!isset($opts['encaps']['rxcsum']))
339
			$commonrx = false;
340
		if ($smallermtu == 0 && !empty($mtu))
341
			$smallermtu = $mtu;
342
		else if (!empty($mtu) && $mtu < $smallermtu)
343
			$smallermtu = $mtu;
344
	}
345
	 
346
	/* Just in case anything is not working well */
347
	if ($smallermtu == 0)
348
		$smallermtu = 1500; 
349

    
350
	$flags = 0;
351
	if ($commonrx == false)
352
		$flags |= IFCAP_RXCSUM;
353
	if ($commontx == false)
354
		$flags |= IFCAP_TXCSUM;
355
		
356
	/* Add interfaces to bridge */
357
	foreach ($members as $member) {
358
		if (!array_key_exists($member, $checklist))
359
			continue;
360
		$realif1 = get_real_interface($member);
361
		$realif =  escapeshellarg($realif1);
362
		if (!$realif) {
363
			log_error("realif not defined in interfaces bridge - up");
364
			continue;
365
		}
366
		/* make sure the parent interface is up */
367
		pfSense_interface_mtu($realif1, $smallermtu);
368
		pfSense_interface_capabilities($realif1, -$flags);
369
		interfaces_bring_up($realif1);
370
		mwexec("/sbin/ifconfig {$bridgeif} addm {$realif}");	
371
	}
372

    
373
	if (isset($bridge['enablestp'])) {
374
		/* Choose spanning tree proto */
375
		mwexec("/sbin/ifconfig {$bridgeif} proto {$bridge['proto']}");	
376
		
377
		if (!empty($bridge['stp'])) {
378
			$stpifs = explode(',', $bridge['stp']);
379
			foreach ($stpifs as $stpif) {
380
				$realif = get_real_interface($stpif);
381
				mwexec("/sbin/ifconfig {$bridgeif} stp {$realif}");
382
			}
383
		}
384
		if (!empty($bridge['maxage']))
385
			mwexec("/sbin/ifconfig {$bridgeif} maxage {$bridge['maxage']}");
386
		if (!empty($brige['fwdelay']))
387
			mwexec("/sbin/ifconfig {$bridgeif} fwddelay {$bridge['fwdelay']}");
388
		if (!empty($brige['hellotime']))
389
                        mwexec("/sbin/ifconfig {$bridgeif} hellotime {$bridge['hellotime']}");
390
		if (!empty($brige['priority']))
391
                        mwexec("/sbin/ifconfig {$bridgeif} priority {$bridge['priority']}");
392
		if (!empty($brige['holdcount']))
393
                        mwexec("/sbin/ifconfig {$bridgeif} holdcnt {$bridge['holdcnt']}");
394
		if (!empty($bridge['ifpriority'])) {
395
			$pconfig = explode(",", $bridge['ifpriority']);
396
			$ifpriority = array();
397
			foreach ($pconfig as $cfg) {
398
				$embcfg = explode(":", $cfg);
399
				foreach ($embcfg as $key => $value)
400
					$ifpriority[$key] = $value;
401
			}
402
			foreach ($ifpriority as $key => $value) {
403
				$realif = get_real_interface($key);
404
				mwexec("/sbin/ifconfig ${bridgeif} ifpriority {$realif} {$value}"); 
405
			}
406
		}
407
		if (!empty($bridge['ifpathcost'])) {
408
			$pconfig = explode(",", $bridges['ifpathcost']);
409
			$ifpathcost = array();
410
			foreach ($pconfig as $cfg) {
411
				$embcfg = explode(":", $cfg);
412
				foreach ($embcfg as $key => $value)
413
					$ifpathcost[$key] = $value;
414
			}
415
			foreach ($ifpathcost as $key => $value) {
416
                        	$realif = get_real_interface($key);
417
                        	mwexec("/sbin/ifconfig ${bridgeif} ifpathcost {$realif} {$value}");
418
                	}
419
		}
420
	}
421

    
422
	if ($bridge['maxaddr'] <> "")
423
		mwexec("/sbin/ifconfig {$bridgeif} maxaddr {$bridge['maxaddr']}");
424
        if ($bridge['timeout'] <> "")
425
                mwexec("/sbin/ifconfig {$bridgeif} timeout {$bridge['timeout']}");
426
        if ($bridge['span'] <> "") {
427
		$realif = get_real_interface($bridge['span']);
428
                mwexec("/sbin/ifconfig {$bridgeif} span {$realif}");
429
	}
430
	if (!empty($bridge['edge'])) {
431
        	$edgeifs = explode(',', $bridge['edge']);
432
        	foreach ($edgeifs as $edgeif) {
433
			$realif = get_real_interface($edgeif);
434
                	mwexec("/sbin/ifconfig {$bridgeif} edge {$realif}");
435
        	}
436
	}
437
	if (!empty($bridge['autoedge'])) {
438
        	$edgeifs = explode(',', $bridge['autoedge']);
439
        	foreach ($edgeifs as $edgeif) {
440
                	$realif = get_real_interface($edgeif);
441
                	mwexec("/sbin/ifconfig {$bridgeif} -autoedge {$realif}");
442
        	}
443
	}
444
	if (!empty($bridge['ptp'])) {
445
        	$ptpifs = explode(',', $bridge['ptp']);
446
        	foreach ($ptpifs as $ptpif) {
447
                	$realif = get_real_interface($ptpif);
448
                	mwexec("/sbin/ifconfig {$bridgeif} ptp {$realif}");
449
        	}
450
	}
451
	if (!empty($bridge['autoptp'])) {
452
        	$ptpifs = explode(',', $bridge['autoptp']);
453
        	foreach ($ptpifs as $ptpif) {
454
                	$realif = get_real_interface($ptpif);
455
                	mwexec("/sbin/ifconfig {$bridgeif} -autoptp {$realif}");
456
        	}
457
	}
458
	if (!empty($bridge['static'])) {
459
        	$stickyifs = explode(',', $bridge['static']);
460
        	foreach ($stickyifs as $stickyif) {
461
                	$realif = get_real_interface($stickyif);
462
                	mwexec("/sbin/ifconfig {$bridgeif} sticky {$realif}");
463
        	}
464
	}
465
	if (!empty($bridge['private'])) {
466
        	$privateifs = explode(',', $bridge['private']);
467
        	foreach ($privateifs as $privateif) {
468
                	$realif = get_real_interface($privateif);
469
               	 	mwexec("/sbin/ifconfig {$bridgeif} private {$realif}");
470
        	}
471
	}
472

    
473
	if($bridgeif)
474
		interfaces_bring_up($bridgeif);	
475
	else 
476
		log_error("bridgeif not defined -- could not bring interface up");
477

    
478
	return $bridgeif;
479
}
480

    
481
function interface_bridge_add_member($bridgeif, $interface) {
482

    
483
	if (!does_interface_exist($bridgeif) || !does_interface_exist($interface))
484
		return;
485

    
486
	$mtu = get_interface_mtu($brigeif);
487
	$mtum = get_interface_mtu($interface);
488
	
489
	if ($mtu != $mtum)
490
		pfSense_interface_mtu($interface, $mtu);
491

    
492
	$options = pfSense_get_interface_addresses($bridgeif);
493
	$flags = 0;
494
	if (!isset($options['encaps']['txcsum']))
495
		$flags |= IFCAP_TXCSUM;
496

    
497
	if (!isset($options['encaps']['rxcsum']))
498
		$flags |= IFCAP_RXCSUM;
499

    
500
	pfSense_interface_capabilities($interface, -$flags);
501

    
502
	interfaces_bring_up($interface);
503
	mwexec("/sbin/ifconfig {$bridgeif} addm {$interface}");
504
}
505

    
506
function interfaces_lagg_configure() 
507
{
508
        global $config, $g;
509
		if($g['booting']) 
510
			echo "Configuring LAGG interfaces...";
511
        $i = 0;
512
		if (is_array($config['laggs']['lagg']) && count($config['laggs']['lagg'])) {
513
			foreach ($config['laggs']['lagg'] as $lagg) {
514
				if(empty($lagg['laggif']))
515
					$lagg['laggif'] = "lagg{$i}";
516
				/* XXX: Maybe we should report any errors?! */
517
				interface_lagg_configure($lagg);
518
				$i++;
519
			}
520
		}
521
		if($g['booting']) 
522
			echo "done.\n";
523
}
524

    
525
function interface_lagg_configure(&$lagg) {
526
        global $config, $g;
527

    
528
        if (!is_array($lagg))
529
		return -1;
530

    
531
	$members = explode(',', $lagg['members']);
532
	if (!count($members))
533
		return -1;
534
	
535
	$checklist = get_interface_list();
536

    
537
	if ($g['booting'] || !(empty($lagg['laggif']))) {
538
		pfSense_interface_destroy($lagg['laggif']);
539
		pfSense_interface_create($lagg['laggif']);
540
                $laggif = $lagg['laggif'];
541
        } else
542
		$laggif = pfSense_interface_create("lagg");
543

    
544
	/* Calculate smaller mtu and enforce it */
545
        $smallermtu = 0;
546
        foreach ($members as $member) {
547
                $mtu = get_interface_mtu($member);
548
		if ($smallermtu == 0 && !empty($mtu))
549
			$smallermtu = $mtu;
550
                else if (!empty($mtu) && $mtu < $smallermtu)
551
                        $smallermtu = $mtu;
552
        }
553

    
554
	/* Just in case anything is not working well */
555
        if ($smallermtu == 0)
556
                $smallermtu = 1500;
557

    
558
	foreach ($members as $member) {
559
		if (!array_key_exists($member, $checklist))
560
			continue;
561
		/* make sure the parent interface is up */
562
		pfSense_interface_mtu($member, $smallermtu);
563
		interfaces_bring_up($member);
564
		mwexec("/sbin/ifconfig {$laggif} laggport {$member}");
565
	}
566
	
567
	mwexec("/sbin/ifconfig {$laggif} laggproto {$lagg['proto']}");
568

    
569
	interfaces_bring_up($laggif);
570

    
571
	return $laggif;
572
}
573

    
574
function interfaces_gre_configure() {
575
        global $config;
576

    
577
        $i = 0;
578
        if (is_array($config['gres']['gre']) && count($config['gres']['gre'])) {
579
                foreach ($config['gres']['gre'] as $gre) {
580
                        if(empty($gre['greif']))
581
                                $gre['greif'] = "gre{$i}";
582
                        /* XXX: Maybe we should report any errors?! */
583
                        interface_gre_configure($gre);
584
                        $i++;
585
                }
586
        }
587
}
588

    
589
function interface_gre_configure(&$gre) {
590
        global $config, $g;
591

    
592
	if (!is_array($gre))
593
		return -1;
594

    
595
	$realif = get_real_interface($gre['if']);
596
	$realifip = get_interface_ip($gre['if']);
597

    
598
	/* make sure the parent interface is up */
599
	interfaces_bring_up($realif);
600

    
601
	if ($g['booting'] || !(empty($gre['greif']))) {
602
		pfSense_interface_destroy($gre['greif']);
603
		pfSense_interface_create($gre['greif']);
604
		$greif = $gre['greif'];
605
	} else
606
		$greif = pfSense_interface_create("gre");
607

    
608
	/* Do not change the order here for more see gre(4) NOTES section. */
609
	mwexec("/sbin/ifconfig {$greif} tunnel {$realifip} {$gre['remote-addr']}");
610
	mwexec("/sbin/ifconfig {$greif} {$gre['tunnel-local-addr']} {$gre['tunnel-remote-addr']} netmask " . gen_subnet_mask($gre['tunnel-remote-net']));
611
	if (isset($gre['link0']) && $gre['link0'])
612
		pfSense_interface_flags($greif, IFF_LINK0);
613
	if (isset($gre['link1']) && $gre['link1'])
614
		pfSense_interface_flags($greif, IFF_LINK1);
615
	if (isset($gre['link2']) && $gre['link2'])
616
		pfSense_interface_flags($greif, IFF_LINK2);
617

    
618
	if($greif)
619
		interfaces_bring_up($greif);
620
	else 
621
		log_error("Could not bring greif up -- variable not defined.");
622

    
623
	if (isset($gre['link1']) && $gre['link1'])
624
		mwexec("/sbin/route add {$gre['tunnel-remote-addr']}/{$gre['tunnel-remote-net']} {$gre['tunnel-local-addr']}");
625
	file_put_contents("{$g['tmp_path']}/{$greif}_router", $gre['tunnel-remote-addr']);
626

    
627
	return $greif;
628
}
629

    
630
function interfaces_gif_configure() {
631
	global $config;
632
	$i = 0;
633
	if (is_array($config['gifs']['gif']) && count($config['gifs']['gif'])) {
634
		foreach ($config['gifs']['gif'] as $gif) {
635
			if(empty($gif['gifif']))
636
				$gre['gifif'] = "gif{$i}";
637
			/* XXX: Maybe we should report any errors?! */
638
			interface_gif_configure($gif);
639
			$i++;
640
		}
641
	}
642
}
643

    
644
function interface_gif_configure(&$gif) {
645
	global $config, $g;
646

    
647
	if (!is_array($gif))
648
		return -1;
649

    
650
	$realif = get_real_interface($gif['if']);
651
	$realifip = get_interface_ip($gif['if']);
652

    
653
	/* make sure the parent interface is up */
654
	if($realif)
655
		interfaces_bring_up($realif);
656
	else 
657
		log_error("could not bring realif up -- variable not defined -- interface_gif_configure()");
658

    
659
	if ($g['booting'] || !(empty($gif['gifif']))) {
660
		pfSense_interface_destroy($gif['gifif']);
661
		pfSense_interface_create($gif['gifif']);
662
		$gifif = $gif['gifif'];
663
	} else
664
		$gifif = pfSense_interface_create("gif");
665

    
666
	/* Do not change the order here for more see gif(4) NOTES section. */
667
	mwexec("/sbin/ifconfig {$gifif} tunnel {$realifip} {$gif['remote-addr']}");
668
	mwexec("/sbin/ifconfig {$gifif} {$gif['tunnel-local-addr']} {$gif['tunnel-remote-addr']} netmask " . gen_subnet_mask($gif['tunnel-remote-net']));
669
	if (isset($gif['link0']) && $gif['link0'])
670
		pfSense_interface_flags($gifif, IFF_LINK0);
671
	if (isset($gif['link1']) && $gif['link1'])
672
		pfSense_interface_flags($gifif, IFF_LINK1);
673
	if($gifif)
674
		interfaces_bring_up($gifif);
675
	else
676
		log_error("could not bring gifif up -- variable not defined");
677

    
678
	/* XXX: Needed?! */
679
	//mwexec("/sbin/route add {$gif['tunnel-remote-addr']}/{$gif['tunnel-remote-net']} -iface {$gifif}");
680
	file_put_contents("{$g['tmp_path']}/{$gifif}_router", $gif['tunnel-remote-addr']);
681

    
682
	return $gifif;
683
}
684

    
685
function interfaces_configure() {
686
	global $config, $g;
687

    
688
	/* Set up our loopback interface */
689
	interfaces_loopback_configure();
690

    
691
	/* set up LAGG virtual interfaces */
692
	interfaces_lagg_configure();
693

    
694
	/* set up VLAN virtual interfaces */
695
	interfaces_vlan_configure();
696

    
697
	interfaces_qinq_configure();
698

    
699
	$iflist = get_configured_interface_with_descr();
700
	$delayed_list = array();
701
	$bridge_list = array();
702
	
703
	/* This is needed to speedup interfaces on bootup. */
704
	$reload = false;
705
	if ($g['booting'])
706
		$reload = true;
707

    
708
	foreach($iflist as $if => $ifname) {
709
		$realif = $config['interfaces'][$if]['if'];
710
		if (strstr($realif, "bridge")) 
711
			$bridge_list[$if] = $ifname;
712
		else if (strstr($realif, "gre"))
713
			$delayed_list[$if] = $ifname;
714
		else if (strstr($realif, "gif"))
715
			$delayed_list[$if] = $ifname;
716
		else if (strstr($realif, "ovpn")) {
717
			//echo "Delaying OpenVPN interface configuration...done.\n";
718
			continue;
719
		} else {
720
			if ($g['booting'])
721
				echo "Configuring {$ifname} interface...";
722
			if($g['debug'])
723
				log_error("Configuring {$ifname}");
724
			interface_configure($if, $reload);
725
			if ($g['booting']) 
726
				echo "done.\n";
727
		}
728
	}
729

    
730
	/* create the unconfigured wireless clones */
731
	interfaces_create_wireless_clones();
732

    
733
	/* set up GRE virtual interfaces */
734
	interfaces_gre_configure();
735

    
736
	/* set up GIF virtual interfaces */
737
	interfaces_gif_configure();
738
	
739
	foreach ($delayed_list as $if => $ifname) {
740
		if ($g['booting'])
741
			echo "Configuring {$ifname} interface...";
742
        	if ($g['debug'])
743
        		log_error("Configuring {$ifname}");
744

    
745
		interface_configure($if, $reload);
746

    
747
		if ($g['booting'])
748
			echo "done.\n";
749
	}
750

    
751
	/* set up BRIDGe virtual interfaces */
752
	interfaces_bridge_configure();
753

    
754
	foreach ($bridge_list as $if => $ifname) {
755
		if ($g['booting'])
756
			echo "Configuring {$ifname} interface...";
757
		if($g['debug'])
758
			log_error("Configuring {$ifname}");
759

    
760
		interface_configure($if, $reload);
761

    
762
		if ($g['booting'])
763
			echo "done.\n";
764
	}
765

    
766
	/* bring up vip interfaces */
767
	interfaces_vips_configure();
768

    
769
	/* configure interface groups */
770
	interfaces_group_setup();
771

    
772
	if (!$g['booting']) {
773
		/* reconfigure static routes (kernel may have deleted them) */
774
		system_routing_configure();
775

    
776
		/* reload IPsec tunnels */
777
		vpn_ipsec_configure();
778

    
779
		/* reload dhcpd (interface enabled/disabled status may have changed) */
780
		services_dhcpd_configure();
781

    
782
		/* restart dnsmasq */
783
		services_dnsmasq_configure();
784

    
785
		/* reload captive portal */
786
		captiveportal_init_rules();
787

    
788
		/* set the reload filter dity flag */
789
		filter_configure();
790
	}
791

    
792
	return 0;
793
}
794

    
795
function interface_reconfigure($interface = "wan") {
796
	interface_bring_down($interface);
797
	interface_configure($interface, true);
798
}
799

    
800
function interface_vip_bring_down($vip) {
801
	global $g;
802

    
803
	switch ($vip['mode']) {
804
	case "proxyarp":
805
		$vipif = get_real_interface($vip['interface']);
806
		if (file_exists("{$g['varrun_path']}/choparp_{$vipif}.pid"))
807
			killbypid("{$g['varrun_path']}/choparp_{$vipif}.pid");
808
		break;
809
	case "ipalias":
810
		$vipif = get_real_interface($vip['interface']);
811
		if(does_interface_exist($vipif))
812
			pfSense_interface_deladdress($vipif, $vip['subnet']);
813
		break;
814
	case "carp":
815
		$vipif = "vip" . $vip['vhid'];
816
		if(does_interface_exist($vipif)) 
817
			pfSense_interface_destroy($vipif);
818
		break;
819
	case "carpdev-dhcp":
820
		$vipif = "vip" . $vip['vhid'];
821
		if(does_interface_exist($vipif)) 
822
			pfSense_interface_destroy($vipif);
823
		break;
824
	}
825
}
826

    
827
function interface_bring_down($interface = "wan", $destroy = false) {
828
	global $config, $g;
829

    
830
	if (!isset($config['interfaces'][$interface]))
831
		return; 
832

    
833
	$ifcfg = $config['interfaces'][$interface];
834

    
835
	$realif = get_real_interface($interface);
836

    
837
	switch ($ifcfg['ipaddr']) {
838
	case "ppp":
839
	case "pppoe":
840
	case "pptp":
841
	case "l2tp":
842
		if (is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) {
843
			foreach ($config['ppps']['ppp'] as $pppid => $ppp) {
844
				if ($realif == $ppp['if']) {
845
					if (file_exists("{$g['varrun_path']}/{$ifcfg['ipaddr']}_{$interface}.pid")) {
846
						killbypid("{$g['varrun_path']}/{$ifcfg['ipaddr']}_{$interface}.pid");
847
						sleep(2);
848
					}
849
					unlink_if_exists("{$g['varetc_path']}/mpd_{$interface}.conf");
850
					if (isset($ppp['ondemand']) && !$destroy)
851
						file_put_contents("{$g['tmp_path']}/interface_configure", $interface);
852
					break;
853
				}
854
			}
855
		}
856
		break;
857
	case "carpdev-dhcp":
858
		/* 
859
		 * NB: When carpdev gets enabled it would be better to be handled as all
860
		 *	   other interfaces! 
861
		 */
862
	case "dhcp":
863
		$pid = find_dhclient_process($realif);
864
		if($pid)
865
			mwexec("kill {$pid}");
866
		sleep(1);
867
		unlink_if_exists("{$g['varetc_path']}/dhclient_{$interface}.conf");
868
		if(does_interface_exist("$realif")) {
869
			mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete", true);
870
			if ($destroy == true)
871
				pfSense_interface_flags($realif, -IFF_UP);
872
			mwexec("/usr/sbin/arp -d -i {$realif} -a");
873
		}
874
		break;
875
	default:
876
		if(does_interface_exist("$realif")) {
877
			mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete", true);
878
			if ($destroy == true)
879
				pfSense_interface_flags($realif, -IFF_UP);
880
			mwexec("/usr/sbin/arp -d -i {$realif} -a");
881
		}
882
		break;
883
	}
884

    
885
	/* remove interface up file if it exists */
886
	unlink_if_exists("{$g['tmp_path']}/{$realif}up");
887
	unlink_if_exists("{$g['vardb_path']}/{$interface}ip");
888
	unlink_if_exists("{$g['tmp_path']}/{$realif}_router");
889
	
890
	/* hostapd and wpa_supplicant do not need to be running when the interface is down.
891
	 * They will also use 100% CPU if running after the wireless clone gets deleted. */
892
	if (is_array($ifcfg['wireless'])) {
893
		mwexec(kill_hostapd($realif));
894
		mwexec(kill_wpasupplicant($realif));
895
	}
896

    
897
	if ($destroy == true) {
898
		if (preg_match("/^vip|^tun|^ovpn|^gif|^gre|^lagg|^bridge|vlan/i", $realif))
899
			pfSense_interface_destroy($realif);
900
	}	
901

    
902
	return;
903
}
904

    
905
function interfaces_ptpid_used($ptpid) {
906
	global $config;
907

    
908
	if (is_array($config['ppps']['ppp']))
909
		foreach ($config['ppps']['ppp'] as & $settings)
910
			if ($ptpid == $settings['ptpid'])
911
				return true;
912

    
913
	return false;
914
}
915

    
916
function interfaces_ptpid_next() {
917

    
918
	$ptpid = 0;
919
	while(interfaces_ptpid_used($ptpid))
920
		$ptpid++;
921

    
922
	return $ptpid;
923
}
924

    
925
function getMPDCRONSettings($pppif_) {
926
	global $config;
927
	$cron_cmd_file = "{$g['varetc_path']}/pppoe_restart_";
928
	if (is_array($config['cron']['item'])) {
929
		for ($i = 0; $i < count($config['cron']['item']); $i++) {
930
			$item = $config['cron']['item'][$i];
931
			if (strpos($item['command'], $cron_cmd_file.$pppif_) !== false) {
932
				return array("ID" => $i, "ITEM" => $item);
933
			}
934
		}
935
	}
936
	return NULL;
937
}
938

    
939
function handle_pppoe_reset($post_array) {
940
	global $config, $g;
941

    
942
	$cron_cmd_file = "{$g['varetc_path']}/pppoe_restart_";
943

    
944
	$pppif = $post_array['type'].$post_array['ptpid'];
945
	if (!is_array($config['cron']['item'])) 
946
		$config['cron']['item'] = array(); 
947
	$itemhash = getMPDCRONSettings($pppif);
948
	$item = $itemhash['ITEM'];
949
	
950
	// reset cron items if necessary and return
951
	if (empty($post_array['pppoe-reset-type'])) {
952
		if (isset($item))
953
			unset($config['cron']['item'][$itemhash['ID']]);
954
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
955
		return;
956
	}
957

    
958
	if (empty($item)) 
959
		$item = array();
960
	if (isset($post_array['pppoe-reset-type']) && $post_array['pppoe-reset-type'] == "custom") {
961
		$item['minute'] = $post_array['pppoe_resetminute'];
962
		$item['hour'] = $post_array['pppoe_resethour'];
963
		if (isset($post_array['pppoe_resetdate']) && $post_array['pppoe_resetdate'] <> "") {
964
			$date = explode("/", $post_array['pppoe_resetdate']);
965
			$item['mday'] = $date[1];
966
			$item['month'] = $date[0];
967
		} else {
968
			$item['mday'] = "*";
969
			$item['month'] = "*";
970
		}
971
		$item['wday'] = "*";
972
		$item['who'] = "root";
973
		$item['command'] = $cron_cmd_file.$pppif;
974
	} else if (isset($post_array['pppoe-reset-type']) && $post_array['pppoe-reset-type'] == "preset") {
975
		switch ($post_array['pppoe_pr_preset_val']) {
976
			case "monthly":
977
				$item['minute'] = "0";
978
				$item['hour'] = "0";
979
				$item['mday'] = "1";
980
				$item['month'] = "*";
981
				$item['wday'] = "*";
982
				$item['who'] = "root";
983
				$item['command'] = $cron_cmd_file.$pppif;
984
				break;
985
	        case "weekly":
986
				$item['minute'] = "0";
987
				$item['hour'] = "0";
988
				$item['mday'] = "*";
989
				$item['month'] = "*";
990
				$item['wday'] = "0";
991
				$item['who'] = "root";
992
				$item['command'] = $cron_cmd_file.$pppif;
993
				break;
994
			case "daily":
995
				$item['minute'] = "0";
996
				$item['hour'] = "0";
997
				$item['mday'] = "*";
998
				$item['month'] = "*";
999
				$item['wday'] = "*";
1000
				$item['who'] = "root";
1001
				$item['command'] = $cron_cmd_file.$pppif;
1002
				break;
1003
			case "hourly":
1004
				$item['minute'] = "0";
1005
				$item['hour'] = "*";
1006
				$item['mday'] = "*";
1007
				$item['month'] = "*";
1008
				$item['wday'] = "*";
1009
				$item['who'] = "root";
1010
				$item['command'] = $cron_cmd_file.$pppif;
1011
				break;
1012
		} // end switch
1013
	} else {
1014
		/* test whether a cron item exists and unset() it if necessary */
1015
		$itemhash = getMPDCRONSettings($pppif);
1016
		$item = $itemhash['ITEM'];
1017
		if (isset($item))
1018
			unset($config['cron']['item'][$itemhash['ID']]); 
1019
	}// end if
1020
	if (isset($itemhash['ID'])) 
1021
		$config['cron']['item'][$itemhash['ID']] = $item;
1022
	else 
1023
		$config['cron']['item'][] = $item;
1024
}
1025

    
1026
/*	This function can configure PPPoE, MLPPP (PPPoE), PPTP.
1027
*	It writes the mpd config file to /var/etc every time the link is opened.
1028
*/
1029

    
1030
function interface_ppps_configure($interface) {
1031
	global $config, $g;
1032
	
1033
	// mpd5 requires a /var/spool/lock directory for PPP modem links.
1034
	if(!is_dir("/var/spool/lock")) {
1035
		exec("/bin/mkdir -p /var/spool/lock");
1036
		exec("/bin/chmod a+rw /var/spool/lock/.");
1037
	}
1038
	// mpd5 modem chat script expected in the same directory as the mpd_xxx.conf files	
1039
	if (!file_exists("{$g['varetc_path']}/mpd.script"))
1040
		mwexec("/bin/ln -s /usr/local/sbin/mpd.script {$g['varetc_path']}/.");
1041
		
1042
	$ifcfg = &$config['interfaces'][$interface];
1043
	if (!isset($ifcfg['enable']))
1044
		return 0;
1045
	if (is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) {
1046
		foreach ($config['ppps']['ppp'] as $pppid => $ppp) {
1047
			if ($ifcfg['if'] == $ppp['if'])
1048
				break;
1049
		}
1050
	}
1051
	if (!$ppp || $ifcfg['if'] != $ppp['if']){
1052
		log_error("Can't find PPP config for {$ifcfg['if']} in interface_ppps_configure().");
1053
		return 0;
1054
	}
1055
	$pppif = $ifcfg['if'];
1056
	if ($ppp['type'] == "ppp")
1057
		$type = "modem";
1058
	else
1059
		$type = $ppp['type'];
1060
	$upper_type = strtoupper($ppp['type']);	
1061
	
1062
	if($g['booting']) {
1063
		$descr = isset($ifcfg['descr']) ? $ifcfg['descr'] : strtoupper($interface);
1064
		echo "starting {$pppif} link...";
1065
		// Do not re-configure the interface if we are booting and it's already been started
1066
		if(file_exists("{$g['varrun_path']}/{$ppp['type']}_{$interface}.pid"))
1067
			return 0;
1068
	}
1069
	
1070
	$ports = explode(',',$ppp['ports']);
1071
	if ($type != "modem") {
1072
		foreach ($ports as $pid => $port)
1073
			$ports[$pid] = get_real_interface($port);
1074
	}
1075
	$localips = explode(',',$ppp['localip']);
1076
	$gateways = explode(',',$ppp['gateway']);
1077
	$subnets = explode(',',$ppp['subnet']);
1078
	
1079
	/* We bring up the parent interface first because if DHCP is configured on the parent we need
1080
	to obtain an address first so we can write it in the mpd .conf file for PPTP and L2TP configs
1081
	*/
1082
	foreach($ports as $pid => $port){
1083
		switch ($ppp['type']) {
1084
			case "pppoe": 
1085
				/* Bring the parent interface up */
1086
				interfaces_bring_up($port);
1087
				break;
1088
			case "pptp":
1089
			case "l2tp":
1090
				/* configure interface */
1091
				if(is_ipaddr($localips[$pid])){
1092
					// Manually configure interface IP/subnet
1093
					pfSense_interface_setaddress($port, "{$localips[$pid]}/{$subnets[$pid]}");
1094
					interfaces_bring_up($port);
1095
				} else if (empty($localips[$pid]))
1096
					$localips[$pid] = get_interface_ip($port); // try to get the interface IP from the port
1097
				
1098
				if(!is_ipaddr($localips[$pid])){
1099
					log_error("Could not get a Local IP address for PPTP/L2TP link on {$port} in interfaces_ppps_configure.");
1100
					return 0;
1101
				}
1102
				/* XXX: This needs to go away soon! [It's commented out!] */
1103
				/* Configure the gateway (remote IP ) */
1104
				if (!$g['booting'] && !is_ipaddr($gateways[$pid]) && is_hostname($gateways[$pid])) {
1105
					/* XXX: Fix later 
1106
					$gateways[$pid] = gethostbyname($gateways[$pid]);
1107
					if(!is_ipaddr($gateways[$pid])) {
1108
						log_error("Could not get a valid Gateway IP from {$port} via DNS in interfaces_ppps_configure.");
1109
						return 0;
1110
					}
1111
					*/
1112
				}
1113
				if(!is_ipaddr($gateways[$pid])){
1114
					log_error("Could not get a PPTP/L2TP Remote IP address from {$dhcp_gateway} for {$gway} in interfaces_ppps_configure.");
1115
					return 0;
1116
				}
1117
				break;
1118
			case "ppp":
1119
				if (!file_exists("{$port}")) {
1120
					log_error("Device {$port} does not exist. PPP link cannot start without the modem device.");
1121
					return 0;
1122
				}
1123
				break;
1124
			default:
1125
				log_error("Unkown {$type} configured as ppp interface.");
1126
				break;
1127
		}
1128
	}
1129
	
1130
	if (is_array($ports) && count($ports) > 1)
1131
		$multilink = "enable";
1132
	else
1133
		$multilink = "disable";
1134
	
1135
	if ($type == "modem"){
1136
		if (is_ipaddr($ppp['localip']))
1137
			$localip = $ppp['localip'];
1138
		else
1139
			$localip = '0.0.0.0';
1140

    
1141
		if (is_ipaddr($ppp['gateway']))
1142
			$gateway = $ppp['gateway'];
1143
		else
1144
			$gateway = "10.64.64.{$pppid}";
1145
		$ranges = "{$localip}/0 {$gateway}/0";
1146
		
1147
		if (empty($ppp['apnum']))	
1148
			$ppp['apnum'] = 1;
1149
	} else
1150
		$ranges = "0.0.0.0/0 0.0.0.0/0";
1151

    
1152
	if (isset($ppp['ondemand'])) 
1153
		$ondemand = "enable";
1154
	else
1155
		$ondemand = "disable";
1156
	if (!isset($ppp['idletimeout']))
1157
		$ppp['idletimeout'] = 0;
1158

    
1159
	if (empty($ppp['username']) && $type == "modem"){
1160
		$ppp['username'] = "user";
1161
		$ppp['password'] = "none";
1162
	}
1163
	if (empty($ppp['password']) && $type == "modem")
1164
		$passwd = "none";
1165
	else
1166
		$passwd = base64_decode($ppp['password']);
1167

    
1168
	$bandwidths = explode(',',$ppp['bandwidth']);
1169
	$mtus = explode(',',$ppp['mtu']);
1170
	$mrus = explode(',',$ppp['mru']);
1171

    
1172
	if (isset($ppp['mrru']))
1173
		$mrrus = explode(',',$ppp['mrru']);
1174

    
1175
	// Construct the mpd.conf file
1176
	$mpdconf = <<<EOD
1177
startup:
1178
	# configure the console
1179
	set console close
1180
	# configure the web server
1181
	set web close
1182

    
1183
default:
1184
{$ppp['type']}client:
1185
	create bundle static {$interface}
1186
	set iface name {$pppif}
1187

    
1188
EOD;
1189
	$setdefaultgw = false;
1190
	$founddefaultgw = false;
1191
	if (is_array($config['gateways']['gateway_item'])) {
1192
		foreach($config['gateways']['gateway_item'] as $gateway) {
1193
			if($interface == $gateway['interface'] && isset($gateway['defaultgw'])) {
1194
				$setdefaultgw = true;
1195
				break;
1196
			} else if (isset($gateway['defaultgw']) && !empty($gateway['interface'])) {
1197
				$founddefaultgw = true;
1198
				break;
1199
			}
1200
		}
1201
	}
1202
	
1203
	if (($interface == "wan" && $founddefaultgw == false) || $setdefaultgw == true){
1204
		$setdefaultgw = true;
1205
		$mpdconf .= <<<EOD
1206
	set iface route default
1207

    
1208
EOD;
1209
	}
1210
	$mpdconf .= <<<EOD
1211
	set iface {$ondemand} on-demand
1212
	set iface idle {$ppp['idletimeout']}
1213

    
1214
EOD;
1215

    
1216
	if (isset($ppp['ondemand']))
1217
		$mpdconf .= <<<EOD
1218
	set iface addrs 10.10.1.1 10.10.1.2
1219

    
1220
EOD;
1221
	
1222
	if (isset($ppp['tcpmssfix']))
1223
		$tcpmss = "disable";
1224
	else
1225
		$tcpmss = "enable";
1226
		$mpdconf .= <<<EOD
1227
	set iface {$tcpmss} tcpmssfix
1228

    
1229
EOD;
1230

    
1231
	$mpdconf .= <<<EOD
1232
	set iface up-script /usr/local/sbin/ppp-linkup
1233
	set iface down-script /usr/local/sbin/ppp-linkdown
1234
	set ipcp ranges {$ranges}
1235

    
1236
EOD;
1237
	if (isset($ppp['vjcomp']))
1238
		$mpdconf .= <<<EOD
1239
	set ipcp no vjcomp
1240

    
1241
EOD;
1242

    
1243
	if (isset($config['system']['dnsallowoverride']))
1244
		$mpdconf .= <<<EOD
1245
	set ipcp enable req-pri-dns
1246
	set ipcp enable req-sec-dns
1247

    
1248
EOD;
1249
	if (!isset($ppp['verbose_log']))
1250
		$mpdconf .= <<<EOD
1251
	#log -bund -ccp -chat -iface -ipcp -lcp -link
1252

    
1253
EOD;
1254
	foreach($ports as $pid => $port){
1255
		$port = get_real_interface($port);
1256
		$mpdconf .= <<<EOD
1257

    
1258
	create link static {$interface}_link{$pid} {$type}
1259
	set link action bundle {$interface}
1260
	set link {$multilink} multilink
1261
	set link keep-alive 10 60
1262
	set link max-redial 0
1263

    
1264
EOD;
1265
		if (isset($ppp['shortseq']))
1266
			$mpdconf .= <<<EOD
1267
	set link no shortseq
1268

    
1269
EOD;
1270

    
1271
		if (isset($ppp['acfcomp']))
1272
			$mpdconf .= <<<EOD
1273
	set link no acfcomp
1274

    
1275
EOD;
1276

    
1277
		if (isset($ppp['protocomp']))
1278
			$mpdconf .= <<<EOD
1279
	set link no protocomp
1280

    
1281
EOD;
1282

    
1283
		$mpdconf .= <<<EOD
1284
	set link disable chap pap
1285
	set link accept chap pap eap
1286
	set link disable incoming
1287

    
1288
EOD;
1289

    
1290

    
1291
		if (!empty($bandwidths[$pid]))
1292
			$mpdconf .= <<<EOD
1293
	set link bandwidth {$bandwidths[$pid]}
1294

    
1295
EOD;
1296

    
1297
		if (empty($mtus[$pid]))
1298
			$mtus[$pid] = "1492";
1299
			$mpdconf .= <<<EOD
1300
	set link mtu {$mtus[$pid]}
1301

    
1302
EOD;
1303

    
1304
		if (!empty($mrus[$pid]))
1305
			$mpdconf .= <<<EOD
1306
	set link mru {$mrus[$pid]}
1307

    
1308
EOD;
1309

    
1310
		if (!empty($mrrus[$pid]))
1311
			$mpdconf .= <<<EOD
1312
	set link mrru {$mrrus[$pid]}
1313

    
1314
EOD;
1315

    
1316
		$mpdconf .= <<<EOD
1317
	set auth authname "{$ppp['username']}"
1318
	set auth password {$passwd}
1319

    
1320
EOD;
1321
		if ($type == "modem") {
1322
			$mpdconf .= <<<EOD
1323
	set modem device {$ppp['ports']}
1324
	set modem script DialPeer
1325
	set modem idle-script Ringback
1326
	set modem watch -cd
1327
	set modem var \$DialPrefix "DT"
1328
	set modem var \$Telephone "{$ppp['phone']}"
1329

    
1330
EOD;
1331
		}
1332
		if (isset($ppp['connect-timeout']) && $type == "modem") {
1333
			$mpdconf .= <<<EOD
1334
	set modem var \$ConnectTimeout "{$ppp['connect-timeout']}"
1335

    
1336
EOD;
1337
		}
1338
		if (isset($ppp['initstr']) && $type == "modem") {
1339
			$initstr = base64_decode($ppp['initstr']);
1340
			$mpdconf .= <<<EOD
1341
	set modem var \$InitString "{$initstr}"
1342

    
1343
EOD;
1344
		}
1345
		if (isset($ppp['simpin']) && $type == "modem") {
1346
			$mpdconf .= <<<EOD
1347
	set modem var \$SimPin "{$ppp['simpin']}"
1348
	set modem var \$PinWait "{$ppp['pin-wait']}"
1349

    
1350
EOD;
1351
		}
1352
		if (isset($ppp['apn']) && $type == "modem") {
1353
			$mpdconf .= <<<EOD
1354
	set modem var \$APN "{$ppp['apn']}"
1355
	set modem var \$APNum "{$ppp['apnum']}"
1356

    
1357
EOD;
1358
		}
1359
		if (isset($ppp['provider']) && $type == "pppoe") {
1360
			$mpdconf .= <<<EOD
1361
	set pppoe service "{$ppp['provider']}"
1362

    
1363
EOD;
1364
		}
1365
		if ($type == "pppoe")
1366
			$mpdconf .= <<<EOD
1367
	set pppoe iface {$port}
1368

    
1369
EOD;
1370

    
1371
		if ($type == "pptp" || $type == "l2tp") {
1372
			$mpdconf .= <<<EOD
1373
	set {$type} self {$localips[$pid]}
1374
	set {$type} peer {$gateways[$pid]}
1375
	set {$type} disable windowing
1376

    
1377
EOD;
1378
		}
1379
		
1380
		$mpdconf .= "\topen\r\n";
1381
	} //end foreach($port)
1382

    
1383

    
1384
	/* Generate mpd.conf. If mpd_[interface].conf exists in the conf path, then link to it instead of generating a fresh conf file. */
1385
	if (file_exists("{$g['conf_path']}/mpd_{$interface}.conf"))
1386
		mwexec("/bin/ln -s {$g['conf_path']}/mpd_{$interface}.conf {$g['varetc_path']}/.");
1387
	else {
1388
		$fd = fopen("{$g['varetc_path']}/mpd_{$interface}.conf", "w");
1389
		if (!$fd) {
1390
			log_error("Error: cannot open mpd_{$interface}.conf in interface_ppps_configure().\n");
1391
			return 0;
1392
		}
1393
		// Write out mpd_ppp.conf
1394
		fwrite($fd, $mpdconf);
1395
		fclose($fd);
1396
	}
1397

    
1398
	// Create the uptime log if requested and if it doesn't exist already, or delete it if it is no longer requested.
1399
	if (isset($ppp['uptime'])) {
1400
		if (!file_exists("/conf/{$pppif}.log")) {
1401
			conf_mount_rw();
1402
			mwexec("echo /dev/null > /conf/{$pppif}.log");
1403
			conf_mount_ro();
1404
		}
1405
	} else {
1406
		if (file_exists("/conf/{$pppif}.log")) {
1407
			conf_mount_rw();
1408
			mwexec("rm -f /conf/{$pppif}.log");
1409
			conf_mount_ro();
1410
		}
1411
	}
1412
		
1413
	/* fire up mpd */
1414
	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");
1415

    
1416
	// Check for PPPoE periodic reset request 
1417
	if ($type == "pppoe") {
1418
		if (isset($ppp['pppoe-reset-type']))
1419
			setup_pppoe_reset_file($ppp['if'], $interface);
1420
		else
1421
			setup_pppoe_reset_file($ppp['if']);
1422
	}
1423

    
1424
	return 1;
1425
}
1426

    
1427
function interfaces_carp_setup() {
1428
	global $g, $config;
1429

    
1430
	$balanacing = "";
1431
	$pfsyncinterface = "";
1432
	$pfsyncenabled = "";
1433
	if(isset($config['system']['developerspew'])) {
1434
		$mt = microtime();
1435
		echo "interfaces_carp_setup() being called $mt\n";
1436
	}
1437

    
1438
	// Prepare CmdCHAIN that will be used to execute commands.
1439
	$cmdchain = new CmdCHAIN();	
1440

    
1441
	if ($g['booting']) {
1442
		echo "Configuring CARP settings...";
1443
		mute_kernel_msgs();
1444
	}
1445

    
1446
	/* suck in configuration items */
1447
	if($config['installedpackages']['carpsettings']) {
1448
		if($config['installedpackages']['carpsettings']['config']) {
1449
			foreach($config['installedpackages']['carpsettings']['config'] as $carp) {
1450
				$pfsyncenabled = $carp['pfsyncenabled'];
1451
				$balanacing = $carp['balancing'];
1452
				$pfsyncinterface = $carp['pfsyncinterface'];
1453
				$pfsyncpeerip = $carp['pfsyncpeerip'];
1454
			}
1455
		}
1456
	} else {
1457
		unset($pfsyncinterface);
1458
		unset($balanacing);
1459
		unset($pfsyncenabled);
1460
	}
1461

    
1462
	$cmdchain->add("Allow CARP", "/sbin/sysctl net.inet.carp.allow=1", true);			
1463
	if($balanacing) {
1464
		$cmdchain->add("Enable CARP ARP-balancing", "/sbin/sysctl net.inet.carp.arpbalance=1", true);
1465
		$cmdchain->add("Disallow CARP preemption", "/sbin/sysctl net.inet.carp.preempt=0", true);
1466
	} else
1467
		$cmdchain->add("Enable CARP preemption", "/sbin/sysctl net.inet.carp.preempt=1", true);		
1468

    
1469
	$cmdchain->add("Enable CARP logging", "/sbin/sysctl net.inet.carp.log=2", true);
1470
	if (!empty($pfsyncinterface))
1471
		$carp_sync_int = get_real_interface($pfsyncinterface);
1472

    
1473
	if($g['booting']) {
1474
		/*    install rules to alllow pfsync to sync up during boot
1475
		 *    carp interfaces will remain down until the bootup sequence finishes
1476
		 */
1477
		$fd = fopen("{$g['tmp_path']}/rules.boot", "w");
1478
		if ($fd) {
1479
			fwrite($fd, "pass quick proto carp all keep state\n");
1480
			fwrite($fd, "pass quick proto pfsync all\n");
1481
			fwrite($fd, "pass out quick from any to any keep state\n");
1482
			fclose($fd);
1483
			mwexec("/sbin/pfctl -f {$g['tmp_path']}/rules.boot");
1484
		} else
1485
			log_error("Could not create rules.boot file!");
1486
	}
1487

    
1488
	/* setup pfsync interface */
1489
	if($carp_sync_int and $pfsyncenabled) {
1490
		if (is_ipaddr($pfsyncpeerip))
1491
			$cmdchain->add("Bring up pfsync0 syncpeer", "/sbin/ifconfig pfsync0 syncdev {$carp_sync_int} syncpeer {$pfsyncpeerip} up", false);						
1492
		else
1493
			$cmdchain->add("Bring up pfsync0 syncdev", "/sbin/ifconfig pfsync0 syncdev {$carp_sync_int} up", false);			
1494
	} else
1495
		$cmdchain->add("Bring up pfsync0", "/sbin/ifconfig pfsync0 syncdev lo0 up", false);						
1496

    
1497
	if($config['virtualip']['vip'])
1498
		$cmdchain->add("Allow CARP.", "/sbin/sysctl net.inet.carp.allow=1", true);				
1499
	else
1500
		$cmdchain->add("Disallow CARP.", "/sbin/sysctl net.inet.carp.allow=0", true);		
1501
	
1502
	if($g['debug'])
1503
		$cmdchain->setdebug(); // optional for verbose logging
1504

    
1505
	$cmdchain->execute();
1506
	$cmdchain->clear();
1507

    
1508
	if ($g['booting']) {
1509
		unmute_kernel_msgs();
1510
		echo "done.\n";
1511
	}
1512
}
1513

    
1514
function interface_proxyarp_configure($interface = "") {
1515
	global $config, $g;
1516
	if(isset($config['system']['developerspew'])) {
1517
		$mt = microtime();
1518
		echo "interface_proxyarp_configure() being called $mt\n";
1519
	}
1520

    
1521
	/* kill any running choparp */
1522
	if (empty($interface))
1523
		killbyname("choparp");
1524
	else {
1525
		$vipif = get_real_interface($interface);
1526
		if (file_exists("{$g['varrun_path']}/choparp_{$vipif}.pid"))
1527
			killbypid("{$g['varrun_path']}/choparp_{$vipif}.pid");
1528
	}
1529

    
1530
	$paa = array();
1531
	if (!empty($config['virtualip']) && is_array($config['virtualip']['vip'])) {
1532

    
1533
		/* group by interface */
1534
		foreach ($config['virtualip']['vip'] as $vipent) {
1535
			if ($vipent['mode'] === "proxyarp") {
1536
				if ($vipent['interface'])
1537
					$proxyif = $vipent['interface'];
1538
				else
1539
					$proxyif = "wan";
1540
				
1541
				if (!empty($interface) && $interface != $proxyif)
1542
					continue;
1543

    
1544
				if (!is_array($paa[$proxyif]))
1545
					$paa[$proxyif] = array();
1546

    
1547
				$paa[$proxyif][] = $vipent;
1548
			}
1549
		}
1550
	}
1551

    
1552
	if (!empty($interface)) {
1553
		if (is_array($paa[$interface])) {
1554
			$paaifip = get_interface_ip($interface);
1555
                        if (!is_ipaddr($paaifip))
1556
                                return;
1557
                        $args = get_real_interface($interface) . " auto";
1558
                        foreach ($paa[$interface] as $paent) {
1559
                                if (isset($paent['subnet']))
1560
                                        $args .= " " . escapeshellarg("{$paent['subnet']}/{$paent['subnet_bits']}");
1561
                                else if (isset($paent['range']))
1562
                                        $args .= " " . escapeshellarg($paent['range']['from'] . "-" . $paent['range']['to']);
1563
                        }
1564
                        mwexec_bg("/usr/local/sbin/choparp " . $args);	
1565
		}
1566
	} else if (count($paa) > 0) {
1567
		foreach ($paa as $paif => $paents)  {
1568
			$paaifip = get_interface_ip($paif);
1569
			if (!is_ipaddr($paaifip))
1570
				continue;
1571
			$args = get_real_interface($paif) . " auto";
1572
			foreach ($paents as $paent) {
1573
				if (isset($paent['subnet']))
1574
					$args .= " " . escapeshellarg("{$paent['subnet']}/{$paent['subnet_bits']}");
1575
				else if (isset($paent['range']))
1576
					$args .= " " . escapeshellarg($paent['range']['from'] . "-" . $paent['range']['to']);
1577
			}
1578
			mwexec_bg("/usr/local/sbin/choparp " . $args);
1579
		}
1580
	}
1581
}
1582

    
1583
function interfaces_vips_configure($interface = "") {
1584
	global $g, $config;
1585
	if(isset($config['system']['developerspew'])) {
1586
		$mt = microtime();
1587
		echo "interfaces_vips_configure() being called $mt\n";
1588
	}
1589
	$paa = array();
1590
	if(is_array($config['virtualip']['vip'])) {
1591
		$carp_setuped = false;
1592
		$anyproxyarp = false;
1593
		foreach ($config['virtualip']['vip'] as $vip) {
1594
			switch ($vip['mode']) {
1595
			case "proxyarp":
1596
				/* nothing it is handled on interface_proxyarp_configure() */
1597
				if ($interface <> "" && $vip['interface'] <> $interface)
1598
					continue;
1599
				$anyproxyarp = true;
1600
				break;
1601
			case "ipalias":
1602
				if ($interface <> "" && $vip['interface'] <> $interface)
1603
					continue;
1604
				interface_ipalias_configure(&$vip);
1605
				break;
1606
			case "carp":
1607
				if ($interface <> "" && $vip['interface'] <> $interface)
1608
					continue;
1609
				if ($carp_setuped == false) {
1610
					interfaces_carp_setup();
1611
					$carp_setuped = true;
1612
				}
1613
				interface_carp_configure($vip);
1614
				break;
1615
			case "carpdev-dhcp":
1616
				if ($interface <> "" && $vip['interface'] <> $interface)
1617
					continue;
1618
				interface_carpdev_configure($vip);
1619
				break;
1620
			}
1621
		}
1622
		
1623
		if ($anyproxyarp == true)
1624
			interface_proxyarp_configure();
1625
	}
1626
}
1627

    
1628
function interface_ipalias_configure(&$vip) {
1629

    
1630
	if ($vip['mode'] == "ipalias") {
1631
		$if = get_real_interface($vip['interface']);
1632
		mwexec("/sbin/ifconfig " . escapeshellarg($if) . " " . $vip['subnet'] . "/" . escapeshellarg($vip['subnet_bits']) . " alias");
1633
	}
1634
}
1635

    
1636
function interface_reload_carps($cif) {
1637
	global $config;
1638

    
1639
	$carpifs = link_ip_to_carp_interface(find_interface_ip($cif));
1640
	if (empty($carpifs))
1641
		return;
1642

    
1643
	$carps = explode(" ", $carpifs);
1644
	if(is_array($config['virtualip']['vip'])) {
1645
		$viparr = &$config['virtualip']['vip'];
1646
		foreach ($viparr as $vip) {
1647
			if (in_array($vip['carpif'], $carps)) {
1648
				switch ($vip['mode']) {
1649
				case "carp":
1650
					interface_vip_bring_down($vip);
1651
					sleep(1);
1652
					interface_carp_configure($vip);
1653
					break;
1654
				case "carpdev-dhcp":
1655
					interface_vip_bring_down($vip);
1656
					sleep(1);
1657
					interface_carpdev_configure($vip);
1658
					break;
1659
				case "ipalias":
1660
					interface_vip_bring_down($vip);
1661
					sleep(1);
1662
					interface_ipalias_configure($vip);
1663
					break;
1664
				}
1665
			}
1666
		}
1667
	}
1668
}
1669

    
1670
function interface_carp_configure(&$vip) {
1671
	global $config, $g;
1672
	if(isset($config['system']['developerspew'])) {
1673
		$mt = microtime();
1674
		echo "interface_carp_configure() being called $mt\n";
1675
	}
1676

    
1677
	if ($vip['mode'] != "carp")
1678
		return;
1679

    
1680
	$vip_password = $vip['password'];
1681
	$vip_password = escapeshellarg(addslashes(str_replace(" ", "", $vip_password)));
1682
	if ($vip['password'] != "")
1683
		$password = " pass {$vip_password}";
1684

    
1685
	// set the vip interface to the vhid
1686
	$vipif = "vip{$vip['vhid']}";
1687

    
1688
	$interface = interface_translate_type_to_real($vip['interface']);
1689
	/*
1690
	 * ensure the interface containing the VIP really exists
1691
 	 * prevents a panic if the interface is missing or invalid
1692
	 */
1693
	$realif = get_real_interface($vip['interface']);
1694
	if (!does_interface_exist($realif)) {
1695
		file_notice("CARP", "Interface specified for the virtual IP address {$vip['subnet']} does not exist. Skipping this VIP.", "Firewall: Virtual IP", "");
1696
		return;
1697
	}
1698

    
1699
	/* Ensure CARP IP really exists prior to loading up. */
1700
	$ww_subnet_ip = find_interface_ip($realif);
1701
	$ww_subnet_bits = find_interface_subnet($realif);
1702
	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'])) {
1703
		file_notice("CARP", "Sorry but we could not find a matching real interface subnet for the virtual IP address {$vip['subnet']}.", "Firewall: Virtual IP", "");
1704
		return;
1705
	}
1706

    
1707
	/* create the carp interface and setup */
1708
	if (does_interface_exist($vipif)) {
1709
		pfSense_interface_flags($vipif, -IFF_UP);
1710
	} else {
1711
		$carpif = pfSense_interface_create("carp");
1712
		pfSense_interface_rename($carpif, $vipif);
1713
		pfSense_ngctl_name("{$carpif}:", $vipif);
1714
	}
1715

    
1716
	/* invalidate interface cache */
1717
	get_interface_arr(true);
1718

    
1719
	$broadcast_address = gen_subnet_max($vip['subnet'], $vip['subnet_bits']);
1720
	mwexec("/sbin/ifconfig {$vipif} {$vip['subnet']}/{$vip['subnet_bits']} vhid {$vip['vhid']} advskew {$vip['advskew']} {$password}");
1721

    
1722
	interfaces_bring_up($vipif);
1723
	
1724
	return $vipif;
1725
}
1726

    
1727
function interface_carpdev_configure(&$vip) {
1728
	global $g;
1729

    
1730
	if ($vip['mode'] != "carpdev-dhcp")
1731
		return;
1732

    
1733
	$vip_password = $vip['password'];
1734
	$vip_password = str_replace(" ", "", $vip_password);
1735
	if($vip['password'] != "")
1736
		$password = " pass \"" . $vip_password . "\"";
1737

    
1738
	log_error("Found carpdev interface {$vip['interface']} on top of interface {$interface}");
1739
	if (empty($vip['interface']))
1740
		return;
1741

    
1742
	$vipif = "vip" . $vip['vhid'];
1743
	$realif = interface_translate_type_to_real($vip['interface']);
1744
	interfaces_bring_up($realif);
1745
	/*
1746
	 * ensure the interface containing the VIP really exists
1747
	 * prevents a panic if the interface is missing or invalid
1748
	 */
1749
	if (!does_interface_exist($realif)) {
1750
		file_notice("CARP", "Interface specified for the virtual IP address {$vip['subnet']} does not exist. Skipping this VIP.", "Firewall: Virtual IP", "");
1751
		return;
1752
	}
1753

    
1754
	if (does_interface_exist($vipif)) {
1755
		interface_bring_down($vipif);
1756
	} else {
1757
		$carpdevif = exec("/sbin/ifconfig carp create");
1758
		mwexec("/sbin/ifconfig {$carpdevif} name {$vipif}");
1759
		pfSense_ngctl_name("{$carpdevif}:", $vipif);
1760
	}
1761

    
1762
	mwexec("/sbin/ifconfig {$vipif} carpdev {$realif} vhid {$vip['vhid']} advskew {$vip['advskew']} {$password}");
1763
	interfaces_bring_up($vipif);
1764

    
1765
	/*
1766
	 * XXX: BIG HACK but carpdev needs ip services active
1767
	 *      before even starting something as dhclient.
1768
	 *      I do not know if this is a feature or a bug
1769
	 *      but better than track it make it work ;) .
1770
	 */
1771
	//$fakeiptouse = "10.254.254." . ($carp_instances_counter+1);
1772
	//$cmdchain->add("CarpDEV hack", "/sbin/ifconfig {$carpint} inet {$fakeiptouse}", false);
1773

    
1774
	/* generate dhclient_wan.conf */
1775
	$fd = fopen("{$g['varetc_path']}/dhclient_{$vipif}.conf", "w");
1776
	if ($fd) {
1777
		$dhclientconf = "";
1778

    
1779
		$dhclientconf .= <<<EOD
1780
interface "{$vipif}" {
1781
timeout 60;
1782
retry 1;
1783
select-timeout 0;
1784
initial-interval 1;
1785
script "/sbin/dhclient-script";
1786
}
1787

    
1788
EOD;
1789

    
1790
		fwrite($fd, $dhclientconf);
1791
		fclose($fd);
1792

    
1793
		/* fire up dhclient */
1794
		mwexec("/sbin/dhclient -c {$g['varetc_path']}/dhclient_{$vipif}.conf {$vipif} > {$g['tmp_path']}/{$vipif}_output > {$g['tmp_path']}/{$vipif}_error_output", false);
1795
	} else {
1796
		log_error("Error: cannot open dhclient_{$vipif}.conf in interfaces_carpdev_configure() for writing.\n");
1797
		mwexec("/sbin/dhclient -b {$vipif}");
1798
	}
1799

    
1800
	return $vipif;
1801
}
1802

    
1803
function interface_wireless_clone($realif, $wlcfg) {
1804
	global $config, $g;
1805
	/*   Check to see if interface has been cloned as of yet.  
1806
	 *   If it has not been cloned then go ahead and clone it.
1807
	 */
1808
	$needs_clone = false;
1809
	if(is_array($wlcfg['wireless']))
1810
		$wlcfg_mode = $wlcfg['wireless']['mode'];
1811
	else
1812
		$wlcfg_mode = $wlcfg['mode'];
1813
	switch($wlcfg_mode) {
1814
		 case "hostap":
1815
			$mode = "wlanmode hostap";
1816
			break;
1817
		 case "adhoc":
1818
			$mode = "wlanmode adhoc";
1819
			break;
1820
		 default:
1821
			$mode = "";
1822
			break;
1823
	}
1824
	$baseif = interface_get_wireless_base($wlcfg['if']);
1825
	if(does_interface_exist($realif)) {
1826
		exec("/sbin/ifconfig {$realif}", $output, $ret);
1827
		$ifconfig_str = implode($output);
1828
		if(($wlcfg_mode == "hostap") && (! preg_match("/hostap/si", $ifconfig_str))) {
1829
			log_error("Interface {$realif} changed to hostap mode");
1830
			$needs_clone = true;
1831
		}
1832
		if(($wlcfg_mode == "adhoc") && (! preg_match("/adhoc/si", $ifconfig_str))) {
1833
			log_error("Interface {$realif} changed to adhoc mode");
1834
			$needs_clone = true;
1835
		}
1836
		if(($wlcfg_mode == "bss") && (preg_match("/hostap|adhoc/si", $ifconfig_str))) {
1837
			log_error("Interface {$realif} changed to infrastructure mode");
1838
			$needs_clone = true;
1839
		}
1840
	} else {
1841
		$needs_clone = true;
1842
	}
1843

    
1844
	if($needs_clone == true) {
1845
		/* remove previous instance if it exists */
1846
		if(does_interface_exist($realif))
1847
			pfSense_interface_destroy($realif);
1848

    
1849
		log_error("Cloning new wireless interface {$realif}");
1850
		// Create the new wlan interface. FreeBSD returns the new interface name.
1851
		// example:  wlan2
1852
		exec("/sbin/ifconfig wlan create wlandev {$baseif} {$mode} bssid 2>&1", $out, $ret);
1853
		if($ret <> 0) {
1854
			log_error("Failed to clone interface {$baseif} with error code {$ret}, output {$out[0]}");
1855
			return false;
1856
		}
1857
		$newif = trim($out[0]);
1858
		// Rename the interface to {$parentnic}_wlan{$number}#: EX: ath0_wlan0
1859
		pfSense_interface_rename($newif, $realif);
1860
		// FIXME: not sure what ngctl is for. Doesn't work.
1861
		// mwexec("/usr/sbin/ngctl name {$newif}: {$realif}", false);
1862
	}
1863
	return true;
1864
}
1865

    
1866
function interface_sync_wireless_clones(&$ifcfg, $sync_changes = false) {
1867
	global $config, $g;
1868

    
1869
	$shared_settings = array('standard', 'turbo', 'protmode', 'txpower', 'channel',
1870
	                         'diversity', 'txantenna', 'rxantenna', 'distance',
1871
	                         'regdomain', 'regcountry', 'reglocation');
1872

    
1873
	if(!is_interface_wireless($ifcfg['if']))
1874
		return;
1875

    
1876
	$baseif = interface_get_wireless_base($ifcfg['if']);
1877

    
1878
	// Sync shared settings for assigned clones
1879
	$iflist = get_configured_interface_list(false, true);
1880
	foreach ($iflist as $if) {
1881
		if ($baseif == interface_get_wireless_base($config['interfaces'][$if]['if']) && $ifcfg['if'] != $config['interfaces'][$if]['if']) {
1882
			if (isset($config['interfaces'][$if]['wireless']['standard']) || $sync_changes) {
1883
				foreach ($shared_settings as $setting) {
1884
					if ($sync_changes) {
1885
						if (isset($ifcfg['wireless'][$setting]))
1886
							$config['interfaces'][$if]['wireless'][$setting] = $ifcfg['wireless'][$setting];
1887
						else if (isset($config['interfaces'][$if]['wireless'][$setting]))
1888
							unset($config['interfaces'][$if]['wireless'][$setting]);
1889
					} else {
1890
						if (isset($config['interfaces'][$if]['wireless'][$setting]))
1891
							$ifcfg['wireless'][$setting] = $config['interfaces'][$if]['wireless'][$setting];
1892
						else if (isset($ifcfg['wireless'][$setting]))
1893
							unset($ifcfg['wireless'][$setting]);
1894
					}
1895
				}
1896
				if (!$sync_changes)
1897
					break;
1898
			}
1899
		}
1900
	}
1901

    
1902
	// Read or write settings at shared area
1903
	if (isset($config['wireless']['interfaces'][$baseif])) {
1904
		foreach ($shared_settings as $setting) {
1905
			if ($sync_changes) {
1906
				if (isset($ifcfg['wireless'][$setting]))
1907
					$config['wireless']['interfaces'][$baseif][$setting] = $ifcfg['wireless'][$setting];
1908
				else if (isset($config['wireless']['interfaces'][$baseif][$setting]))
1909
					unset($config['wireless']['interfaces'][$baseif][$setting]);
1910
			} else if (isset($config['wireless']['interfaces'][$baseif][$setting])) {
1911
				if (isset($config['wireless']['interfaces'][$baseif][$setting]))
1912
					$ifcfg['wireless'][$setting] = $config['wireless']['interfaces'][$baseif][$setting];
1913
				else if (isset($ifcfg['wireless'][$setting]))
1914
					unset($ifcfg['wireless'][$setting]);
1915
			}
1916
		}
1917
	}
1918

    
1919
	// Sync the mode on the clone creation page with the configured mode on the interface
1920
	if (interface_is_wireless_clone($ifcfg['if'])) {
1921
		foreach ($config['wireless']['clone'] as &$clone) {
1922
			if ($clone['cloneif'] == $ifcfg['if']) {
1923
				if ($sync_changes) {
1924
					$clone['mode'] = $ifcfg['wireless']['mode'];
1925
				} else {
1926
					$ifcfg['wireless']['mode'] = $clone['mode'];
1927
				}
1928
				break;
1929
			}
1930
		}
1931
		unset($clone);
1932
	}
1933
}
1934

    
1935
function interface_wireless_configure($if, &$wl, &$wlcfg) {
1936
	global $config, $g;
1937

    
1938
	/*    open up a shell script that will be used to output the commands.
1939
	 *    since wireless is changing a lot, these series of commands are fragile
1940
     *    and will sometimes need to be verified by a operator by executing the command
1941
     *    and returning the output of the command to the developers for inspection.  please
1942
     *    do not change this routine from a shell script to individul exec commands.  -sullrich
1943
	 */
1944

    
1945
	// Remove script file
1946
	unlink_if_exists("{$g['tmp_path']}/{$if}_setup.sh");
1947

    
1948
	// Clone wireless nic if needed.
1949
	interface_wireless_clone($if, $wl);
1950

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

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

    
1958
	/* set values for /path/program */
1959
	$hostapd = "/usr/sbin/hostapd";
1960
	$wpa_supplicant = "/usr/sbin/wpa_supplicant";
1961
	$ifconfig = "/sbin/ifconfig";
1962
	$sysctl = "/sbin/sysctl";
1963
	$killall = "/usr/bin/killall";
1964

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

    
1967
	$wlcmd = array();
1968
	$wl_sysctl = array();
1969
	/* Make sure it's up */
1970
	$wlcmd[] = "up";
1971
	/* Set a/b/g standard */
1972
	$standard = str_replace(" Turbo", "", $wlcfg['standard']);
1973
	$wlcmd[] = "mode " . escapeshellarg($standard);
1974

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

    
1980
	/* Set ssid */
1981
	if($wlcfg['ssid'])
1982
		$wlcmd[] = "ssid " .escapeshellarg($wlcfg['ssid']);
1983

    
1984
	/* Set 802.11g protection mode */
1985
	$wlcmd[] = "protmode " . escapeshellarg($wlcfg['protmode']);
1986

    
1987
	/* set wireless channel value */
1988
	if(isset($wlcfg['channel'])) {
1989
		if($wlcfg['channel'] == "0") {
1990
			$wlcmd[] = "channel any";
1991
		} else {
1992
			$wlcmd[] = "channel " . escapeshellarg($wlcfg['channel']);
1993
		}
1994
	}
1995

    
1996
	/* Set antenna diversity value */
1997
	if(isset($wlcfg['diversity']))
1998
		$wl_sysctl[] = "diversity=" . escapeshellarg($wlcfg['diversity']);
1999

    
2000
	/* Set txantenna value */
2001
	if(isset($wlcfg['txantenna']))
2002
		$wl_sysctl[] = "txantenna=" . escapeshellarg($wlcfg['txantenna']);
2003

    
2004
	/* Set rxantenna value */
2005
	if(isset($wlcfg['rxantenna']))
2006
		$wl_sysctl[] = "rxantenna=" . escapeshellarg($wlcfg['rxantenna']);
2007

    
2008
	/* set Distance value */
2009
	if($wlcfg['distance'])
2010
		$distance = escapeshellarg($wlcfg['distance']);
2011

    
2012
	/* Set wireless hostap mode */
2013
	if ($wlcfg['mode'] == "hostap") {
2014
		$wlcmd[] = "mediaopt hostap";
2015
	} else {
2016
		$wlcmd[] = "-mediaopt hostap";
2017
	}
2018

    
2019
	/* Set wireless adhoc mode */
2020
	if ($wlcfg['mode'] == "adhoc") {
2021
		$wlcmd[] = "mediaopt adhoc";
2022
	} else {
2023
		$wlcmd[] = "-mediaopt adhoc";
2024
	}
2025

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

    
2028
	/* handle hide ssid option */
2029
	if(isset($wlcfg['hidessid']['enable'])) {
2030
		$wlcmd[] = "hidessid";
2031
	} else {
2032
		$wlcmd[] = "-hidessid";
2033
	}
2034

    
2035
	/* handle pureg (802.11g) only option */
2036
	if(isset($wlcfg['pureg']['enable'])) {
2037
		$wlcmd[] = "mode 11g pureg";
2038
	} else {
2039
		$wlcmd[] = "-pureg";
2040
	}
2041

    
2042
	/* handle puren (802.11n) only option */
2043
	if(isset($wlcfg['puren']['enable'])) {
2044
		$wlcmd[] = "puren";
2045
	} else {
2046
		$wlcmd[] = "-puren";
2047
	}
2048

    
2049
	/* enable apbridge option */
2050
	if(isset($wlcfg['apbridge']['enable'])) {
2051
		$wlcmd[] = "apbridge";
2052
	} else {
2053
		$wlcmd[] = "-apbridge";
2054
	}
2055

    
2056
	/* handle turbo option */
2057
	if(isset($wlcfg['turbo']['enable'])) {
2058
		$wlcmd[] = "mediaopt turbo";
2059
	} else {
2060
		$wlcmd[] = "-mediaopt turbo";
2061
	}
2062

    
2063
	/* handle txpower setting */
2064
	/* if($wlcfg['txpower'] <> "")
2065
		$wlcmd[] = "txpower " . escapeshellarg($wlcfg['txpower']);
2066
	*/
2067
	/* handle wme option */
2068
	if(isset($wlcfg['wme']['enable'])) {
2069
		$wlcmd[] = "wme";
2070
	} else {
2071
		$wlcmd[] = "-wme";
2072
	}
2073

    
2074
	/* set up wep if enabled */
2075
	$wepset = "";
2076
	if (isset($wlcfg['wep']['enable']) && is_array($wlcfg['wep']['key'])) {
2077
		switch($wlcfg['wpa']['auth_algs']) {
2078
			case "1":
2079
				$wepset .= "authmode open wepmode on ";
2080
				break;
2081
			case "2":
2082
				$wepset .= "authmode shared wepmode on ";
2083
				break;
2084
			case "3":
2085
				$wepset .= "authmode mixed wepmode on ";
2086
		}
2087
		$i = 1;
2088
		foreach ($wlcfg['wep']['key'] as $wepkey) {
2089
			$wepset .= "wepkey " . escapeshellarg("{$i}:{$wepkey['value']}") . " ";
2090
			if (isset($wepkey['txkey'])) {
2091
				$wlcmd[] = "weptxkey {$i} ";
2092
			}
2093
			$i++;
2094
		}
2095
		$wlcmd[] = $wepset;
2096
	} else {
2097
		$wlcmd[] = "authmode open wepmode off ";
2098
	}
2099

    
2100
	mwexec(kill_hostapd("{$if}"));
2101
	mwexec(kill_wpasupplicant("{$if}"));
2102

    
2103
	/* generate wpa_supplicant/hostap config if wpa is enabled */
2104
	conf_mount_rw();
2105

    
2106
	switch ($wlcfg['mode']) {
2107
		case 'bss':
2108
			if (isset($wlcfg['wpa']['enable'])) {
2109
				$wpa .= <<<EOD
2110
ctrl_interface={$g['varrun_path']}/wpa_supplicant
2111
ctrl_interface_group=0
2112
ap_scan=1
2113
#fast_reauth=1
2114
network={
2115
ssid="{$wlcfg['ssid']}"
2116
scan_ssid=1
2117
priority=5
2118
key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
2119
psk="{$wlcfg['wpa']['passphrase']}"
2120
pairwise={$wlcfg['wpa']['wpa_pairwise']}
2121
group={$wlcfg['wpa']['wpa_pairwise']}
2122
}
2123
EOD;
2124

    
2125
				$fd = fopen("{$g['varetc_path']}/wpa_supplicant_{$if}.conf", "w");
2126
				fwrite($fd, "{$wpa}");
2127
				fclose($fd);
2128
			}
2129
			break;
2130
		case 'hostap':
2131
			if($wlcfg['wpa']['passphrase']) 
2132
				$wpa_passphrase = "wpa_passphrase={$wlcfg['wpa']['passphrase']}\n";
2133
			else 
2134
				$wpa_passphrase = "";
2135
			if (isset($wlcfg['wpa']['enable'])) {
2136
				$wpa .= <<<EOD
2137
interface={$if}
2138
driver=bsd
2139
logger_syslog=-1
2140
logger_syslog_level=0
2141
logger_stdout=-1
2142
logger_stdout_level=0
2143
dump_file={$g['tmp_path']}/hostapd_{$if}.dump
2144
ctrl_interface={$g['varrun_path']}/hostapd
2145
ctrl_interface_group=wheel
2146
#accept_mac_file={$g['tmp_path']}/hostapd_{$if}.accept
2147
#deny_mac_file={$g['tmp_path']}/hostapd_{$if}.deny
2148
#macaddr_acl={$wlcfg['wpa']['macaddr_acl']}
2149
ssid={$wlcfg['ssid']}
2150
debug={$wlcfg['wpa']['debug_mode']}
2151
auth_algs={$wlcfg['wpa']['auth_algs']}
2152
wpa={$wlcfg['wpa']['wpa_mode']}
2153
wpa_key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
2154
wpa_pairwise={$wlcfg['wpa']['wpa_pairwise']}
2155
wpa_group_rekey={$wlcfg['wpa']['wpa_group_rekey']}
2156
wpa_gmk_rekey={$wlcfg['wpa']['wpa_gmk_rekey']}
2157
wpa_strict_rekey={$wlcfg['wpa']['wpa_strict_rekey']}
2158
{$wpa_passphrase}
2159

    
2160
EOD;
2161

    
2162
if (isset($wlcfg['wpa']['rsn_preauth'])) {
2163
	$wpa .= <<<EOD
2164
# Enable the next lines for preauth when roaming. Interface = wired or wireless interface talking to the AP you want to roam from/to
2165
rsn_preauth=1
2166
rsn_preauth_interfaces={$if}
2167

    
2168
EOD;
2169

    
2170
}
2171
				if($wlcfg['auth_server_addr'] && $wlcfg['auth_server_shared_secret']) {
2172
					$auth_server_port = "1812";
2173
					if($wlcfg['auth_server_port']) 
2174
						$auth_server_port = $wlcfg['auth_server_port'];
2175
					$wpa .= <<<EOD
2176

    
2177
ieee8021x=1
2178
auth_server_addr={$wlcfg['auth_server_addr']}
2179
auth_server_port={$auth_server_port}
2180
auth_server_shared_secret={$wlcfg['auth_server_shared_secret']}
2181

    
2182
EOD;
2183
				} else {
2184
					$wpa .= "ieee8021x={$wlcfg['wpa']['ieee8021x']}\n";
2185
				}
2186

    
2187
				$fd = fopen("{$g['varetc_path']}/hostapd_{$if}.conf", "w");
2188
				fwrite($fd, "{$wpa}");
2189
				fclose($fd);
2190

    
2191
			}
2192
			break;
2193
	}
2194

    
2195
	/*
2196
	 *    all variables are set, lets start up everything
2197
	 */
2198

    
2199
	$baseif = interface_get_wireless_base($if);
2200
	preg_match("/^(.*?)([0-9]*)$/", $baseif, $baseif_split);
2201
	$wl_sysctl_prefix = 'dev.' . $baseif_split[1] . '.' . $baseif_split[2];
2202

    
2203
	/* set sysctls for the wireless interface */
2204
	if (!empty($wl_sysctl)) {
2205
		fwrite($fd_set, "# sysctls for {$baseif}\n");
2206
		foreach ($wl_sysctl as $wl_sysctl_line) {
2207
			fwrite($fd_set, "{$sysctl} {$wl_sysctl_prefix}.{$wl_sysctl_line}\n");
2208
		}
2209
	}
2210

    
2211
	/* set ack timers according to users preference (if he/she has any) */
2212
	if($distance) {
2213
		fwrite($fd_set, "# Enable ATH distance settings\n");
2214
		fwrite($fd_set, "/sbin/athctrl.sh -i {$baseif} -d {$distance}\n");
2215
	}
2216

    
2217
	if (isset($wlcfg['wpa']['enable'])) {
2218
		if ($wlcfg['mode'] == "bss") {
2219
			fwrite($fd_set, "{$wpa_supplicant} -B -i {$if} -c {$g['varetc_path']}/wpa_supplicant_{$if}.conf\n");
2220
		}
2221
		if ($wlcfg['mode'] == "hostap") {
2222
			fwrite($fd_set, "{$hostapd} -B {$g['varetc_path']}/hostapd_{$if}.conf\n");
2223
		}
2224
	}
2225

    
2226
	fclose($fd_set);
2227
	conf_mount_ro();
2228

    
2229
	/* Making sure regulatory settings have actually changed
2230
	 * before applying, because changing them requires bringing
2231
	 * down all wireless networks on the interface. */
2232
	exec("{$ifconfig} " . escapeshellarg($if), $output);
2233
	$ifconfig_str = implode($output);
2234
	unset($output);
2235
	$reg_changing = false;
2236

    
2237
	/* special case for the debug country code */
2238
	if ($wlcfg['regcountry'] == 'DEBUG' && !preg_match("/\sregdomain\s+DEBUG\s/si", $ifconfig_str))
2239
		$reg_changing = true;
2240
	else if ($wlcfg['regdomain'] && !preg_match("/\sregdomain\s+{$wlcfg['regdomain']}\s/si", $ifconfig_str))
2241
		$reg_changing = true;
2242
	else if ($wlcfg['regcountry'] && !preg_match("/\scountry\s+{$wlcfg['regcountry']}\s/si", $ifconfig_str))
2243
		$reg_changing = true;
2244
	else if ($wlcfg['reglocation'] == 'anywhere' && preg_match("/\s(indoor|outdoor)\s/si", $ifconfig_str))
2245
		$reg_changing = true;
2246
	else if ($wlcfg['reglocation'] && $wlcfg['reglocation'] != 'anywhere' && !preg_match("/\s{$wlcfg['reglocation']}\s/si", $ifconfig_str))
2247
		$reg_changing = true;
2248

    
2249
	if ($reg_changing) {
2250
		/* set regulatory domain */
2251
		if($wlcfg['regdomain'])
2252
			$wlregcmd[] = "regdomain " . escapeshellarg($wlcfg['regdomain']);
2253

    
2254
		/* set country */
2255
		if($wlcfg['regcountry'])
2256
			$wlregcmd[] = "country " . escapeshellarg($wlcfg['regcountry']);
2257

    
2258
		/* set location */
2259
		if($wlcfg['reglocation'])
2260
			$wlregcmd[] = escapeshellarg($wlcfg['reglocation']);
2261

    
2262
		$wlregcmd_args = implode(" ", $wlregcmd);
2263

    
2264
		/* build a complete list of the wireless clones for this interface */
2265
		$clone_list = array();
2266
		if (does_interface_exist(interface_get_wireless_clone($baseif)))
2267
			$clone_list[] = interface_get_wireless_clone($baseif);
2268
		if (is_array($config['wireless']['clone'])) {
2269
			foreach ($config['wireless']['clone'] as $clone) {
2270
				if ($clone['if'] == $baseif)
2271
					$clone_list[] = $clone['cloneif'];
2272
			}
2273
		}
2274

    
2275
		/* find which clones are up and bring them down */
2276
		$clones_up = array();
2277
		foreach ($clone_list as $clone_if) {
2278
			$clone_status = pfSense_get_interface_addresses($clone_if);
2279
			if ($clone_status['status'] == 'up') {
2280
				$clones_up[] = $clone_if;
2281
				mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " down");
2282
			}
2283
		}
2284

    
2285
		/* apply the regulatory settings */
2286
		mwexec("{$ifconfig} " . escapeshellarg($if) . " {$wlregcmd_args}");
2287

    
2288
		/* bring the clones back up that were previously up */
2289
		foreach ($clones_up as $clone_if) {
2290
			mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " up");
2291

    
2292
			/*
2293
			 * Rerun the setup script for the interface if it isn't this interface, the interface
2294
			 * is in infrastructure mode, and WPA is enabled.
2295
			 * This can be removed if wpa_supplicant stops dying when you bring the interface down.
2296
			 */
2297
			if ($clone_if != $if) {
2298
				$friendly_if = convert_real_interface_to_friendly_interface_name($clone_if);
2299
				if ( !empty($friendly_if)
2300
				    && $config['interfaces'][$friendly_if]['wireless']['mode'] == "bss"
2301
				    && isset($config['interfaces'][$friendly_if]['wireless']['wpa']['enable']) ) {
2302
					mwexec("/bin/sh {$g['tmp_path']}/{$clone_if}_setup.sh");
2303
				}
2304
			}
2305
		}
2306
	}
2307

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

    
2312
	/* configure wireless */
2313
	$wlcmd_args = implode(" ", $wlcmd);
2314
	mwexec("/sbin/ifconfig {$if} $wlcmd_args", false);
2315

    
2316
	
2317
	sleep(1);
2318
	/* execute hostapd and wpa_supplicant if required in shell */
2319
	mwexec("/bin/sh {$g['tmp_path']}/{$if}_setup.sh");
2320

    
2321
	return 0;
2322

    
2323
}
2324

    
2325
function kill_hostapd($interface) {
2326
	return "/bin/pkill -f \"hostapd .*{$interface}\"\n";
2327
}
2328

    
2329
function kill_wpasupplicant($interface) {
2330
	return "/bin/pkill -f \"wpa_supplicant .*{$interface}\"\n";
2331
}
2332

    
2333
function find_dhclient_process($interface) {
2334
	if ($interface)
2335
		$pid = `/bin/pgrep -xf "dhclient: {$interface}"`;
2336
	else
2337
		$pid = 0;
2338

    
2339
	return $pid;
2340
}
2341

    
2342
function interface_configure($interface = "wan", $reloadall = false, $linkupevent = false) {
2343
	global $config, $g;
2344
	global $interface_sn_arr_cache, $interface_ip_arr_cache;
2345

    
2346
	$wancfg = $config['interfaces'][$interface];
2347

    
2348
	$realif = get_real_interface($interface);
2349

    
2350
	if (!$g['booting']) {
2351
		/* remove all IPv4 addresses */
2352
		while (mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " -alias", true) == 0);
2353

    
2354
		switch ($wancfg['ipaddr']) {
2355
			case 'pppoe':
2356
			case 'l2tp':
2357
			case 'pptp':
2358
			case 'ppp':
2359
				interface_bring_down($interface, true);
2360
				break;
2361
			default:
2362
				interface_bring_down($interface);
2363
				break;
2364
		}
2365
	}
2366

    
2367
	/* wireless configuration? */
2368
	if (is_array($wancfg['wireless']))
2369
		interface_wireless_configure($realif, $wancfg, $wancfg['wireless']);
2370

    
2371
	if ($wancfg['spoofmac']) {
2372
		mwexec("/sbin/ifconfig " . escapeshellarg($realif) .
2373
			" link " . escapeshellarg($wancfg['spoofmac']));
2374

    
2375
                /*
2376
                 * All vlans need to spoof their parent mac address, too.  see
2377
                 * ticket #1514: http://cvstrac.pfsense.com/tktview?tn=1514,33
2378
                 */
2379
                if (is_array($config['vlans']['vlan'])) {
2380
                        foreach ($config['vlans']['vlan'] as $vlan) {
2381
                                if ($vlan['if'] == $realif)
2382
                                        mwexec("/sbin/ifconfig " . escapeshellarg($vlan['vlanif']) .
2383
                                                " link " . escapeshellarg($wancfg['spoofmac']));
2384
                        }
2385
                }
2386
	}  else {
2387
		$mac = get_interface_mac(get_real_interface($wancfg['if']));
2388
		if($mac == "ff:ff:ff:ff:ff:ff") {
2389
			/*   this is not a valid mac address.  generate a
2390
			 *   temporary mac address so the machine can get online.
2391
			 */
2392
			echo "Generating new MAC address.";
2393
			$random_mac = generate_random_mac_address();
2394
			mwexec("/sbin/ifconfig " . escapeshellarg(get_real_interface($wancfg['if'])) .
2395
				" link " . escapeshellarg($random_mac));
2396
			$wancfg['spoofmac'] = $random_mac;
2397
			write_config();
2398
			file_notice("MAC Address altered", "The INVALID MAC address (ff:ff:ff:ff:ff:ff) on interface {$realif} has been automatically replaced with {$random_mac}", "Interfaces");
2399
		}
2400
	}
2401

    
2402
	/* media */
2403
	if ($wancfg['media'] || $wancfg['mediaopt']) {
2404
		$cmd = "/sbin/ifconfig " . escapeshellarg(get_real_interface($wancfg['if']));
2405
		if ($wancfg['media'])
2406
			$cmd .= " media " . escapeshellarg($wancfg['media']);
2407
		if ($wancfg['mediaopt'])
2408
			$cmd .= " mediaopt " . escapeshellarg($wancfg['mediaopt']);
2409
		mwexec($cmd);
2410
	}
2411
	if (!empty($wancfg['mtu']))
2412
		pfSense_interface_mtu($realif, $wancfg['mtu']);
2413

    
2414
	$options = pfSense_get_interface_addresses($realif);
2415
	if (is_array($options) && isset($options['caps']['polling'])) {
2416
		if (isset($config['system']['polling']))
2417
			pfSense_interface_capabilities($realif, IFCAP_POLLING);
2418
		else
2419
			pfSense_interface_capabilities($realif, -IFCAP_POLLING);
2420
	}
2421

    
2422
	/* skip vlans for checksumming and polling */
2423
        if (!stristr($realif, "vlan") && is_array($options)) {
2424
		$flags = 0;
2425
		if(isset($config['system']['disablechecksumoffloading'])) {
2426
			if (isset($options['encaps']['txcsum']))
2427
				$flags |= IFCAP_TXCSUM;
2428
			if (isset($options['encaps']['rxcsum']))
2429
				$flags |= IFCAP_RXCSUM;
2430
        	} else {
2431
 			if (!isset($options['caps']['txcsum']))
2432
				$flags |= IFCAP_TXCSUM;
2433
			if (!isset($options['caps']['rxcsum']))
2434
				$flags |= IFCAP_RXCSUM;
2435
        	}
2436

    
2437
        	if(isset($config['system']['disablesegmentationoffloading'])) {
2438
                	if (isset($options['encaps']['tso4']))
2439
				$flags |= IFCAP_TSO;
2440
                	if (isset($options['encaps']['tso6']))
2441
				$flags |= IFCAP_TSO;
2442
        	} else {
2443
                	if (!isset($options['caps']['tso4']))
2444
				$flags |= IFCAP_TSO;
2445
                	if (!isset($options['caps']['tso6']))
2446
				$flags |= IFCAP_TSO;
2447
        	}
2448

    
2449
        	if(isset($config['system']['disablelargereceiveoffloading'])) {
2450
                	if (isset($options['encaps']['lro']))
2451
				$flags |= IFCAP_LRO;
2452
        	} else {
2453
                	if (!isset($options['caps']['lro']))
2454
				$flags |= IFCAP_LRO;
2455
        	}
2456

    
2457
        	/* if the NIC supports polling *AND* it is enabled in the GUI */
2458
        	if (!isset($config['system']['polling']) || !isset($options['caps']['polling'])) {
2459
			$flags |= IFCAP_POLLING;
2460
		}
2461
               	pfSense_interface_capabilities($realif, -$flags);
2462
	}
2463

    
2464
	/* invalidate interface/ip/sn cache */
2465
	get_interface_arr(true);
2466
	unset($interface_ip_arr_cache[$realif]);
2467
	unset($interface_sn_arr_cache[$realif]);
2468

    
2469
	switch ($wancfg['ipaddr']) {
2470
		case 'carpdev-dhcp':
2471
			interface_carpdev_dhcp_configure($interface);
2472
			break;
2473
		case 'dhcp':
2474
			interface_dhcp_configure($interface);
2475
			break;
2476
		case 'pppoe':
2477
		case 'l2tp':
2478
		case 'pptp':
2479
		case 'ppp':
2480
			interface_ppps_configure($interface);
2481
			break;
2482
		default:
2483
			if ($wancfg['ipaddr'] <> "" && $wancfg['subnet'] <> "") {
2484
				pfSense_interface_setaddress($realif, "{$wancfg['ipaddr']}/{$wancfg['subnet']}");
2485
			} else if (substr($realif, 0, 3) == "gre") {
2486
				if (is_array($config['gres']['gre'])) {
2487
					foreach ($config['gres']['gre'] as $gre)
2488
						if ($gre['greif'] == $realif)
2489
							interface_gre_configure($gre);
2490
				}
2491
			} else if (substr($realif, 0, 3) == "gif") {
2492
				 if (is_array($config['gifs']['gif'])) {
2493
					foreach ($config['gifs']['gif'] as $gif)
2494
						if($gif['gifif'] == $interface)
2495
							interface_gif_configure($gif);
2496
				}
2497
			} else if (substr($realif, 0, 4) == "ovpn") {
2498
				/* XXX: Should be done anything?! */
2499
			}
2500

    
2501
			if (is_ipaddr($wancfg['gateway']))
2502
				file_put_contents("{$g['tmp_path']}/{$realif}_router", $wancfg['gateway']);
2503
			break;
2504
	}
2505

    
2506
	if(does_interface_exist($wancfg['if']))
2507
		interfaces_bring_up($wancfg['if']);
2508
 	
2509
	if (!$g['booting']) {
2510
		interface_reload_carps($realif);
2511

    
2512
		unset($gre);
2513
		$gre = link_interface_to_gre($interface);
2514
		if (!empty($gre))
2515
			interface_gre_configure($gre);
2516

    
2517
		unset($gif);
2518
		$gif = link_interface_to_gif($interface);
2519
		if (!empty($gif))
2520
                       	interface_gif_configure($gif);
2521

    
2522
		if ($linkupevent == false) {
2523
			unset($bridgetmp);
2524
			$bridgetmp = link_interface_to_bridge($interface);
2525
			if (!empty($bridgetmp))
2526
				interface_bridge_add_member($bridgetmp, $realif);
2527
		}
2528

    
2529
		link_interface_to_vips($interface, "update");
2530

    
2531
		$grouptmp = link_interface_to_group($interface);
2532
		if (!empty($grouptmp))
2533
			interface_group_add_member($realif, $grouptmp);
2534

    
2535
		if ($interface == "lan")
2536
			/* make new hosts file */
2537
			system_hosts_generate();
2538

    
2539
		if ($reloadall == true) {
2540

    
2541
			/* reconfigure static routes (kernel may have deleted them) */
2542
			system_routing_configure($interface);
2543

    
2544
			/* reload ipsec tunnels */
2545
			vpn_ipsec_configure();
2546

    
2547
			/* update dyndns */
2548
			services_dyndns_configure($interface);
2549

    
2550
			/* force DNS update */
2551
			services_dnsupdate_process($interface);
2552

    
2553
			/* restart dnsmasq */
2554
			services_dnsmasq_configure();
2555

    
2556
			/* reload captive portal */
2557
			captiveportal_init_rules();
2558

    
2559
			/* set the reload filter dity flag */
2560
			filter_configure();
2561
		}
2562
	}
2563

    
2564
	return 0;
2565
}
2566

    
2567
function interface_carpdev_dhcp_configure($interface = "wan") {
2568
	global $config, $g;
2569

    
2570
	$wancfg = $config['interfaces'][$interface];
2571
	$wanif = $wancfg['if'];
2572
	/* bring wan interface up before starting dhclient */
2573
	if($wanif)
2574
		interfaces_bring_up($wanif);
2575
	else 
2576
		log_error("Could not bring wanif up in terface_carpdev_dhcp_configure()");
2577

    
2578
	return 0;
2579
}
2580

    
2581
function interface_dhcp_configure($interface = "wan") {
2582
	global $config, $g;
2583

    
2584
	$wancfg = $config['interfaces'][$interface];
2585
	if (empty($wancfg))
2586
		$wancfg = array();
2587

    
2588
	/* generate dhclient_wan.conf */
2589
	$fd = fopen("{$g['varetc_path']}/dhclient_{$interface}.conf", "w");
2590
	if (!$fd) {
2591
		printf("Error: cannot open dhclient_{$interface}.conf in interfaces_wan_dhcp_configure() for writing.\n");
2592
		return 1;
2593
	}
2594

    
2595
	if ($wancfg['dhcphostname']) {
2596
		$dhclientconf_hostname = "send dhcp-client-identifier \"{$wancfg['dhcphostname']}\";\n";
2597
		$dhclientconf_hostname .= "\tsend host-name \"{$wancfg['dhcphostname']}\";\n";
2598
	} else {
2599
		$dhclientconf_hostname = "";
2600
	}
2601

    
2602
	$wanif = get_real_interface($interface);
2603
	if (empty($wanif)) {
2604
		log_error("Invalid interface \"{$interface}\" in interface_dhcp_configure()");
2605
		return 0;
2606
	}
2607
 	$dhclientconf = "";
2608
	
2609
	$dhclientconf .= <<<EOD
2610
interface "{$wanif}" {
2611
timeout 60;
2612
retry 1;
2613
select-timeout 0;
2614
initial-interval 1;
2615
	{$dhclientconf_hostname}
2616
	script "/sbin/dhclient-script";
2617
}
2618

    
2619
EOD;
2620

    
2621
if(is_ipaddr($wancfg['alias-address'])) {
2622
	$subnetmask = gen_subnet_mask($wancfg['alias-subnet']);
2623
	$dhclientconf .= <<<EOD
2624
alias {
2625
	interface  "{$wanif}";
2626
	fixed-address {$wancfg['alias-address']};
2627
	option subnet-mask {$subnetmask};
2628
}
2629

    
2630
EOD;
2631
}
2632
	fwrite($fd, $dhclientconf);
2633
	fclose($fd);
2634

    
2635
	/* bring wan interface up before starting dhclient */
2636
	if($wanif)
2637
		interfaces_bring_up($wanif);
2638
	else 
2639
		log_error("Could not bring up {$wanif} interface in interface_dhcp_configure()");
2640

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

    
2644
	return 0;
2645
}
2646

    
2647
function interfaces_group_setup() {
2648
	global $config;
2649

    
2650
	if (!is_array($config['ifgroups']['ifgroupentry']))
2651
		return;
2652

    
2653
	foreach ($config['ifgroups']['ifgroupentry'] as $groupar)
2654
		interface_group_setup($groupar);
2655

    
2656
	return;
2657
}
2658

    
2659
function interface_group_setup(&$groupname /* The parameter is an array */) {
2660
	global $config;
2661

    
2662
	if (!is_array($groupname))
2663
		return;
2664
	$members = explode(" ", $groupname['members']);
2665
	foreach($members as $ifs) {
2666
		$realif = get_real_interface($ifs);
2667
		if ($realif)
2668
			mwexec("/sbin/ifconfig {$realif} group {$groupname['ifname']}");
2669
	}
2670

    
2671
	return;
2672
}
2673

    
2674
function interface_group_add_member($interface, $groupname) {
2675
	mwexec("/sbin/ifconfig {$interface} group {$groupname}", true);
2676
}
2677
 
2678
/* COMPAT Function */
2679
function convert_friendly_interface_to_real_interface_name($interface) {
2680
	return get_real_interface($interface);
2681
}
2682

    
2683
/* COMPAT Function */
2684
function get_real_wan_interface($interface = "wan") {
2685
	return get_real_interface($interface);
2686
}
2687

    
2688
/* COMPAT Function */
2689
function get_current_wan_address($interface = "wan") {
2690
	return get_interface_ip($interface);
2691
}
2692

    
2693
/*
2694
 * convert_real_interface_to_friendly_interface_name($interface): convert fxp0 -> wan, etc.
2695
 */
2696
function convert_real_interface_to_friendly_interface_name($interface = "wan") {
2697
        global $config;
2698

    
2699
	if (stristr($interface, "vip")) {
2700
                $index = intval(substr($interface, 3));
2701
                foreach ($config['virtualip']['vip'] as $counter => $vip) {
2702
                        if ($vip['mode'] == "carpdev-dhcp" || $vip['mode'] == "carp")  {
2703
                                if ($index == $counter)
2704
                                        return $vip['interface'];
2705
                        }
2706
                }
2707
        }
2708

    
2709
        /* XXX: For speed reasons reference directly the interface array */
2710
	$ifdescrs =& $config['interfaces'];
2711
        //$ifdescrs = get_configured_interface_list(false, true);
2712

    
2713
        foreach ($ifdescrs as $if => $ifname) {
2714
                if ($config['interfaces'][$if]['if'] == $interface)
2715
                        return $if;
2716

    
2717
                if (stristr($interface, "_wlan0") && $config['interfaces'][$if]['if'] == interface_get_wireless_base($interface))
2718
                        return $if;
2719

    
2720
                $int = interface_translate_type_to_real($if);
2721
                if ($int == $interface)
2722
                        return $ifname;
2723
        }
2724
        return NULL;
2725
}
2726

    
2727
/* attempt to resolve interface to friendly descr */
2728
function convert_friendly_interface_to_friendly_descr($interface) {
2729
        global $config;
2730

    
2731
        switch ($interface) {
2732
                case "l2tp":
2733
                                $ifdesc = "L2TP";
2734
                                break;
2735
                case "pptp":
2736
                                $ifdesc = "PPTP";
2737
                                break;
2738
                case "pppoe":
2739
                                $ifdesc = "PPPoE";
2740
                                break;
2741
                case "openvpn":
2742
                                $ifdesc = "OpenVPN";
2743
                                break;
2744
                case "enc0":
2745
                        case "ipsec":
2746
                                $ifdesc = "IPsec";
2747
                                break;
2748
        default:
2749
                if (isset($config['interfaces'][$interface])) {
2750
                        if (empty($config['interfaces'][$interface]['descr']))
2751
                                $ifdesc = strtoupper($interface);
2752
                        else
2753
                                $ifdesc = strtoupper($config['interfaces'][$interface]['descr']);
2754
			break;
2755
		}
2756
                /* if list */
2757
                $ifdescrs = get_configured_interface_with_descr(false, true);
2758
                foreach ($ifdescrs as $if => $ifname) {
2759
                                if ($if == $interface || $ifname == $interface)
2760
                                        return $ifname;
2761
                }
2762
                break;
2763
        }
2764

    
2765
        return $ifdesc;
2766
}
2767

    
2768
function convert_real_interface_to_friendly_descr($interface) {
2769
        global $config;
2770

    
2771
        $ifdesc = convert_real_interface_to_friendly_interface_name("{$interface}");
2772

    
2773
        if ($ifdesc) {
2774
                $iflist = get_configured_interface_with_descr(false, true);
2775
                return $iflist[$ifdesc];
2776
        }
2777

    
2778
        return $interface;
2779
}
2780

    
2781
/*
2782
 *  interface_translate_type_to_real($interface):
2783
 *              returns the real hardware interface name for a friendly interface.  ie: wan
2784
 */
2785
function interface_translate_type_to_real($interface) {
2786
        global $config;
2787

    
2788
        if ($config['interfaces'][$interface]['if'] <> "")
2789
                return $config['interfaces'][$interface]['if'];
2790
        else
2791
		return $interface;
2792
}
2793

    
2794
function interface_is_wireless_clone($wlif) {
2795
	if(!stristr($wlif, "_wlan")) {
2796
		return false;
2797
	} else {
2798
		return true;
2799
	}
2800
}
2801

    
2802
function interface_get_wireless_base($wlif) {
2803
	if(!stristr($wlif, "_wlan")) {
2804
		return $wlif;
2805
	} else {
2806
		return substr($wlif, 0, stripos($wlif, "_wlan"));
2807
	}
2808
}
2809

    
2810
function interface_get_wireless_clone($wlif) {
2811
	if(!stristr($wlif, "_wlan")) {
2812
		return $wlif . "_wlan0";
2813
	} else {
2814
		return $wlif;
2815
	}
2816
}
2817

    
2818
function get_real_interface($interface = "wan") {
2819
    global $config;
2820

    
2821
	$wanif = NULL;
2822

    
2823
	switch ($interface) {
2824
	case "l2tp":
2825
		$wanif = "l2tp";
2826
		break;
2827
	case "pptp":
2828
		$wanif = "pptp";
2829
		break;
2830
	case "pppoe":
2831
		$wanif = "pppoe";
2832
		break;
2833
	case "openvpn":
2834
		$wanif = "openvpn";
2835
		break;
2836
	case "ipsec":
2837
	case "enc0":
2838
		$wanif = "enc0";
2839
		break;
2840
	case "ppp":
2841
		$wanif = "ppp";
2842
		break;
2843
	default:
2844
		// If a real interface was alread passed simply
2845
		// pass the real interface back.  This encourages
2846
		// the usage of this function in more cases so that
2847
		// we can combine logic for more flexibility.
2848
		if(does_interface_exist($interface)) {
2849
			$wanif = $interface;
2850
			break;
2851
		}
2852
		if (empty($config['interfaces'][$interface]))
2853
			break;
2854

    
2855
		$cfg =& $config['interfaces'][$interface];
2856

    
2857
		// Wireless cloned NIC support (FreeBSD 8+)
2858
		// interface name format: $parentnic_wlanparentnic#
2859
		// example: ath0_wlan0
2860
		if (is_interface_wireless($cfg['if'])) {
2861
			$wanif = interface_get_wireless_clone($cfg['if']);
2862
			break;
2863
		}
2864
		/*
2865
		if (empty($cfg['if'])) {
2866
			$wancfg = $cfg['if'];
2867
			break;
2868
		}
2869
		*/
2870

    
2871
		switch ($cfg['ipaddr']) {
2872
			case "carpdev-dhcp":
2873
				$viparr = &$config['virtualip']['vip'];
2874
				if(is_array($viparr))
2875
				foreach ($viparr as $counter => $vip) {
2876
					if ($vip['mode'] == "carpdev-dhcp") {
2877
						if($vip['interface'] == $interface) {
2878
							$wanif = "carp{$counter}";
2879
							break;
2880
						}
2881
					}
2882
				}
2883
				break;
2884
			case "pppoe": 
2885
			case "pptp": 
2886
			case "l2tp": 
2887
			case "ppp":
2888
				$wanif = $cfg['if'];
2889
				break;
2890
			default:
2891
				$wanif = $cfg['if'];
2892
				break;
2893
		}
2894
		break;
2895
	}
2896

    
2897
    return $wanif;
2898
}
2899

    
2900
/* Guess the physical interface by providing a IP address */
2901
function guess_interface_from_ip($ipaddress) {
2902
	if(! is_ipaddr($ipaddress)) {
2903
		return false;
2904
	}
2905
	/* create a route table we can search */
2906
	exec("netstat -rnWf inet", $output, $ret);
2907
	foreach($output as $line) {
2908
		if(preg_match("/^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\/[0-9]+[ ]+link[#]/", $line)) {
2909
			$fields = preg_split("/[ ]+/", $line);
2910
			if(ip_in_subnet($ipaddress, $fields[0])) {
2911
				return $fields[6];
2912
			}
2913
		}
2914
	}
2915
	$ret = exec_command("/sbin/route -n get {$ipaddress} | /usr/bin/awk '/interface/ { print \$2; };'");
2916
	if(empty($ret)) {
2917
        	return false;
2918
	}
2919
	return $ret;
2920
}
2921

    
2922
/*
2923
 * find_ip_interface($ip): return the interface where an ip is defined
2924
 */
2925
function find_ip_interface($ip)
2926
{
2927
        /* if list */
2928
        $ifdescrs = get_configured_interface_list();
2929

    
2930
        foreach ($ifdescrs as $ifdescr => $ifname) {
2931
		if ($ip == get_interface_ip($ifname)) {
2932
                	$int = get_real_interface($ifname);
2933
			return $int;
2934
		}
2935
        }
2936
        return false;
2937
}
2938

    
2939
/*
2940
 *   find_number_of_created_carp_interfaces: return the number of carp interfaces
2941
 */
2942
function find_number_of_created_carp_interfaces() {
2943
	return `/sbin/ifconfig | grep "carp:" | wc -l`;
2944
}
2945

    
2946
function get_all_carp_interfaces() {
2947
	$ints = str_replace("\n", " ", `ifconfig | grep "carp:" -B2 | grep ": flag" | cut -d: -f1`);
2948
	$ints = explode(" ", $ints);
2949
	return $ints;
2950
}
2951

    
2952
/*
2953
 * find_carp_interface($ip): return the carp interface where an ip is defined
2954
 */
2955
function find_carp_interface($ip) {
2956
	global $config;
2957
	if (is_array($config['virtualip']['vip'])) {
2958
		foreach ($config['virtualip']['vip'] as $vip) {
2959
			if ($vip['mode'] == "carp" || $vip['mode'] == "carpdev") {
2960
				$carp_ip = get_interface_ip($vip['interface']);
2961
				$if = `ifconfig | grep '$ip ' -B1 | head -n1 | cut -d: -f1`;
2962
				if ($if)
2963
					return $if;
2964
			}
2965
		}
2966
	}
2967
}
2968

    
2969
function link_carp_interface_to_parent($interface) {
2970
        global $config;
2971

    
2972
        if ($interface == "")
2973
                return;
2974

    
2975
        $carp_ip = get_interface_ip($interface);
2976
        if (!is_ipaddr($carp_ip))
2977
                return;
2978

    
2979
        /* if list */
2980
        $ifdescrs = get_configured_interface_list();
2981
        foreach ($ifdescrs as $ifdescr => $ifname) {
2982
                $interfaceip = get_interface_ip($ifname);
2983
                $subnet_bits = get_interface_subnet($ifname);
2984
                $subnet_ip = gen_subnet("{$interfaceip}", "{$subnet_bits}");
2985
                if(ip_in_subnet($carp_ip, "{$subnet_ip}/{$subnet_bits}"))
2986
                        return $ifname;
2987
        }
2988

    
2989
        return "";
2990
}
2991

    
2992
/****f* interfaces/link_ip_to_carp_interface
2993
 * NAME
2994
 *   link_ip_to_carp_interface - Find where a CARP interface links to.
2995
 * INPUTS
2996
 *   $ip
2997
 * RESULT
2998
 *   $carp_ints
2999
 ******/
3000
function link_ip_to_carp_interface($ip) {
3001
        global $config;
3002

    
3003
        if (!is_ipaddr($ip))
3004
                return;
3005

    
3006
        $carp_ints = "";
3007
        if (is_array($config['virtualip']['vip'])) {
3008
		$first = 0;
3009
		$carp_int = array();
3010
                foreach ($config['virtualip']['vip'] as $vip) {
3011
                        if ($vip['mode'] == "carp" || $vip['mode'] == "carpdev") {
3012
                                $carp_ip = $vip['subnet'];
3013
                                $carp_sn = $vip['subnet_bits'];
3014
                                $carp_nw = gen_subnet($carp_ip, $carp_sn);
3015
                                if (ip_in_subnet($ip, "{$carp_nw}/{$carp_sn}"))
3016
					$carp_int[] = "vip{$vip['vhid']}";
3017
                        }
3018
                }
3019
		if (!empty($carp_int))
3020
			$carp_ints = implode(" ", array_unique($carp_int));
3021
        }
3022

    
3023
        return $carp_ints;
3024
}
3025

    
3026
function link_interface_to_vlans($int, $action = "") {
3027
	global $config;
3028

    
3029
	if (empty($int))
3030
		return;
3031

    
3032
	if (is_array($config['vlans']['vlan'])) {
3033
                foreach ($config['vlans']['vlan'] as $vlan) {
3034
			if ($int == $vlan['if']) {
3035
				if ($action == "update") {
3036
					interfaces_bring_up($int);
3037
				} else if ($action == "")
3038
					return $vlan;
3039
			}
3040
		}
3041
	}
3042
}
3043

    
3044
function link_interface_to_vips($int, $action = "") {
3045
        global $config;
3046

    
3047
        if (is_array($config['virtualip']['vip']))
3048
                foreach ($config['virtualip']['vip'] as $vip)
3049
                        if ($int == $vip['interface']) {
3050
				if ($action == "update")
3051
					interfaces_vips_configure($int);
3052
				else
3053
                                	return $vip;
3054
			}
3055
}
3056

    
3057
/****f* interfaces/link_interface_to_bridge
3058
 * NAME
3059
 *   link_interface_to_bridge - Finds out a bridge group for an interface
3060
 * INPUTS
3061
 *   $ip
3062
 * RESULT
3063
 *   bridge[0-99]
3064
 ******/
3065
function link_interface_to_bridge($int) {
3066
        global $config;
3067

    
3068
        if (is_array($config['bridges']['bridged'])) {
3069
                foreach ($config['bridges']['bridged'] as $bridge) {
3070
			if (in_array($int, explode(',', $bridge['members'])))
3071
                                return "{$bridge['bridgeif']}";
3072
		}
3073
	}
3074
}
3075

    
3076
function link_interface_to_group($int) {
3077
        global $config;
3078

    
3079
        if (is_array($config['ifgroups']['ifgroupentry'])) {
3080
                foreach ($config['ifgroups']['ifgroupentry'] as $group) {
3081
			if (in_array($int, explode(" ", $groupname['members'])))
3082
                                return "{$group['ifname']}";
3083
		}
3084
	}
3085
}
3086

    
3087
function link_interface_to_gre($interface) {
3088
        global $config;
3089

    
3090
        if (is_array($config['gres']['gre']))
3091
                foreach ($config['gres']['gre'] as $gre)
3092
                        if($gre['if'] == $interface)
3093
                                return $gre;
3094
}
3095

    
3096
function link_interface_to_gif($interface) {
3097
        global $config;
3098

    
3099
        if (is_array($config['gifs']['gif']))
3100
                foreach ($config['gifs']['gif'] as $gif)
3101
                        if($gif['if'] == $interface)
3102
                                return $gif;
3103
}
3104

    
3105
/*
3106
 * find_interface_ip($interface): return the interface ip (first found)
3107
 */
3108
function find_interface_ip($interface, $flush = false)
3109
{
3110
	global $interface_ip_arr_cache;
3111

    
3112
	$interface = str_replace("\n", "", $interface);
3113
	
3114
	if (!does_interface_exist($interface))
3115
		return;
3116

    
3117
	/* Setup IP cache */
3118
	if (!isset($interface_ip_arr_cache[$interface]) or $flush) {
3119
		$ifinfo = pfSense_get_interface_addresses($interface);
3120
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
3121
	}
3122

    
3123
	return $interface_ip_arr_cache[$interface];
3124
}
3125

    
3126
function find_interface_subnet($interface, $flush = false)
3127
{
3128
	global $interface_sn_arr_cache;
3129

    
3130
	$interface = str_replace("\n", "", $interface);
3131
	if (does_interface_exist($interface) == false)
3132
		return;
3133

    
3134
	if (!isset($interface_sn_arr_cache[$interface]) or $flush) {
3135
		$ifinfo = pfSense_get_interface_addresses($interface);
3136
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
3137
        }
3138

    
3139
	return $interface_sn_arr_cache[$interface];
3140
}
3141

    
3142
function ip_in_interface_alias_subnet($interface, $ipalias) {
3143
	global $config;
3144

    
3145
	if (empty($interface) || !is_ipaddr($ipalias))
3146
		return false;
3147
	if (is_array($config['virtualip']['vip'])) {
3148
                foreach ($config['virtualip']['vip'] as $vip) {
3149
                        switch ($vip['mode']) {
3150
                        case "ipalias":
3151
                                if ($vip['interface'] <> $interface)
3152
                                        break;
3153
				if (ip_in_subnet($ipalias, gen_subnet($vip['subnet'], $vip['subnet_bits']) . "/" . $vip['subnet_bits']))
3154
					return true;
3155
                                break;
3156
                        }
3157
                }
3158
	}
3159

    
3160
	return false;
3161
}
3162

    
3163
function get_interface_ip($interface = "wan")
3164
{
3165
	$realif = get_real_interface($interface);
3166
	if (!$realif) {
3167
		if (preg_match("/^carp/i", $interface))
3168
			$realif = $interface;
3169
		else if (preg_match("/^vip/i", $interface))
3170
			$realif = $interface;
3171
		else
3172
			return null;
3173
	}
3174

    
3175
	$curip = find_interface_ip($realif);
3176
	if ($curip && is_ipaddr($curip) && ($curip != "0.0.0.0"))
3177
		return $curip;
3178
	else
3179
		return null;
3180
}
3181

    
3182
function get_interface_subnet($interface = "wan")
3183
{
3184
	$realif = get_real_interface($interface);
3185
	if (!$realif) {
3186
                if (preg_match("/^carp/i", $interface))
3187
                        $realif = $interface;
3188
                else if (preg_match("/^vip/i", $interface))
3189
                        $realif = $interface;
3190
                else
3191
                        return null;
3192
        }
3193

    
3194
	$cursn = find_interface_subnet($realif);
3195
	if (!empty($cursn))
3196
		return $cursn;
3197

    
3198
	return null;
3199
}
3200

    
3201
/* return outside interfaces with a gateway */
3202
function get_interfaces_with_gateway() {
3203
	global $config;
3204

    
3205
	$ints = array();
3206

    
3207
	/* loop interfaces, check config for outbound */
3208
	foreach($config['interfaces'] as $ifdescr => $ifname) {
3209
		if (substr($ifdescr, 0, 5) ==  "ovpnc")
3210
			return true;
3211

    
3212
		switch ($ifname['ipaddr']) {
3213
			case "dhcp":
3214
			case "carpdev-dhcp":
3215
			case "ppp";
3216
			case "pppoe":
3217
			case "pptp":
3218
			case "l2tp":
3219
			case "ppp";
3220
				$ints[$ifdescr] = $ifdescr;
3221
			break;
3222
			default:
3223
				if (!empty($ifname['gateway']))
3224
					$ints[$ifdescr] = $ifdescr;
3225
			break;
3226
		}
3227
	}
3228
	return $ints;
3229
}
3230

    
3231
/* return true if interface has a gateway */
3232
function interface_has_gateway($friendly) {
3233
	global $config;
3234

    
3235
	if (!empty($config['interfaces'][$friendly])) {
3236
		if (substr($friendly, 0, 5) ==  "ovpnc")
3237
			return true;
3238
		$ifname =& $config['interfaces'][$friendly];
3239
		switch ($ifname['ipaddr']) {
3240
			case "dhcp":
3241
			case "carpdev-dhcp":
3242
			case "pppoe":
3243
			case "pptp":
3244
			case "l2tp":
3245
			case "ppp";
3246
				return true;
3247
			break;
3248
			default:
3249
				if (!empty($ifname['gateway']))
3250
					return true;
3251
			break;
3252
		}
3253
	}
3254

    
3255
	return false;
3256
}
3257

    
3258
/****f* interfaces/is_altq_capable
3259
 * NAME
3260
 *   is_altq_capable - Test if interface is capable of using ALTQ
3261
 * INPUTS
3262
 *   $int            - string containing interface name
3263
 * RESULT
3264
 *   boolean         - true or false
3265
 ******/
3266

    
3267
function is_altq_capable($int) {
3268
        /* Per:
3269
         * http://www.freebsd.org/cgi/man.cgi?query=altq&manpath=FreeBSD+7.2-current&format=html
3270
         * Only the following drivers have ALTQ support
3271
         */
3272
	$capable = array("age", "ale", "an", "ath", "aue", "awi", "bce",
3273
			"bfe", "bge", "dc", "de", "ed", "em", "ep", "fxp", "gem",
3274
			"hme", "igb", "ipw", "iwi", "jme", "le", "msk", "mxge", "my", "nfe",
3275
			"npe", "nve", "ral", "re", "rl", "rum", "run", "bwn", "sf", "sis", "sk",
3276
			"ste", "stge", "txp", "udav", "ural", "vge", "vr", "wi", "xl",
3277
			"ndis", "tun", "ovpns", "ovpnc", "vlan", "pppoe", "pptp", "ng",
3278
			"l2tp", "ppp");
3279

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

    
3282
        if (in_array($int_family[0], $capable))
3283
                return true;
3284
	else if (stristr($int_family, "vlan")) /* VLANs are name $parent_$vlan now */
3285
		return true;
3286
	else if (stristr($int_family, "_wlan")) /* WLANs are name $parent_$wlan now */
3287
		return true;
3288
        else
3289
                return false;
3290
}
3291

    
3292
/****f* interfaces/is_interface_wireless
3293
 * NAME
3294
 *   is_interface_wireless - Returns if an interface is wireless
3295
 * RESULT
3296
 *   $tmp       - Returns if an interface is wireless
3297
 ******/
3298
function is_interface_wireless($interface) {
3299
        global $config, $g;
3300

    
3301
        $friendly = convert_real_interface_to_friendly_interface_name($interface);
3302
        if(!isset($config['interfaces'][$friendly]['wireless'])) {
3303
                if (preg_match($g['wireless_regex'], $interface)) {
3304
                        if (isset($config['interfaces'][$friendly]))
3305
                                $config['interfaces'][$friendly]['wireless'] = array();
3306
                        return true;
3307
                }
3308
                return false;
3309
        } else
3310
                return true;
3311
}
3312

    
3313
function get_wireless_modes($interface) {
3314
	/* return wireless modes and channels */
3315
	$wireless_modes = array();
3316

    
3317
	$wlif = interface_translate_type_to_real($interface);
3318

    
3319
	if(is_interface_wireless($wlif)) {
3320
		$cloned_interface = get_real_interface($interface);
3321
		$chan_list = "/sbin/ifconfig {$cloned_interface} list chan";
3322
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
3323
		$format_list = "/usr/bin/awk '{print \$5 \" \" \$6 \",\" \$1}'";
3324

    
3325
		$interface_channels = "";
3326
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
3327
		$interface_channel_count = count($interface_channels);
3328

    
3329
		$c = 0;
3330
		while ($c < $interface_channel_count)
3331
		{
3332
			$channel_line = explode(",", $interface_channels["$c"]);
3333
			$wireless_mode = trim($channel_line[0]);
3334
			$wireless_channel = trim($channel_line[1]);
3335
			if(trim($wireless_mode) != "") {
3336
				/* if we only have 11g also set 11b channels */
3337
				if($wireless_mode == "11g") {
3338
					if(!isset($wireless_modes["11b"]))
3339
						$wireless_modes["11b"] = array();
3340
				} else if($wireless_mode == "11g ht") {
3341
					if(!isset($wireless_modes["11b"]))
3342
						$wireless_modes["11b"] = array();
3343
					if(!isset($wireless_modes["11g"]))
3344
						$wireless_modes["11g"] = array();
3345
					$wireless_mode = "11ng";
3346
				} else if($wireless_mode == "11a ht") {
3347
					if(!isset($wireless_modes["11a"]))
3348
						$wireless_modes["11a"] = array();
3349
					$wireless_mode = "11na";
3350
				}
3351
				$wireless_modes["$wireless_mode"]["$c"] = $wireless_channel;
3352
			}
3353
			$c++;
3354
		}
3355
	}
3356
	return($wireless_modes);
3357
}
3358

    
3359
/* return channel numbers, frequency, max txpower, and max regulation txpower */
3360
function get_wireless_channel_info($interface) {
3361
	$wireless_channels = array();
3362

    
3363
	$wlif = interface_translate_type_to_real($interface);
3364

    
3365
	if(is_interface_wireless($wlif)) {
3366
		$cloned_interface = get_real_interface($interface);
3367
		$chan_list = "/sbin/ifconfig {$cloned_interface} list txpower";
3368
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
3369
		$format_list = "/usr/bin/awk '{print \$1 \",\" \$3 \" \" \$4 \",\" \$5 \",\" \$7}'";
3370

    
3371
		$interface_channels = "";
3372
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
3373

    
3374
		foreach ($interface_channels as $channel_line) {
3375
			$channel_line = explode(",", $channel_line);
3376
			if(!isset($wireless_channels[$channel_line[0]]))
3377
				$wireless_channels[$channel_line[0]] = $channel_line;
3378
		}
3379
	}
3380
	return($wireless_channels);
3381
}
3382

    
3383
/****f* interfaces/get_interface_mtu
3384
 * NAME
3385
 *   get_interface_mtu - Return the mtu of an interface
3386
 * RESULT
3387
 *   $tmp       - Returns the mtu of an interface
3388
 ******/
3389
function get_interface_mtu($interface) {
3390
        $mtu = pfSense_get_interface_addresses($interface);
3391
        return $mtu['mtu'];
3392
}
3393

    
3394
function get_interface_mac($interface) {
3395

    
3396
	$macinfo = pfSense_get_interface_addresses($interface);
3397
	return $macinfo["macaddr"];
3398
}
3399

    
3400
/****f* pfsense-utils/generate_random_mac_address
3401
 * NAME
3402
 *   generate_random_mac - generates a random mac address
3403
 * INPUTS
3404
 *   none
3405
 * RESULT
3406
 *   $mac - a random mac address
3407
 ******/
3408
function generate_random_mac_address() {
3409
        $mac = "02";
3410
        for($x=0; $x<5; $x++)
3411
                $mac .= ":" . dechex(rand(16, 255));
3412
        return $mac;
3413
}
3414

    
3415
/****f* interfaces/is_jumbo_capable
3416
 * NAME
3417
 *   is_jumbo_capable - Test if interface is jumbo frame capable.  Useful for determining VLAN capability.
3418
 * INPUTS
3419
 *   $int             - string containing interface name
3420
 * RESULT
3421
 *   boolean          - true or false
3422
 ******/
3423
function is_jumbo_capable($int) {
3424
        global $g;
3425

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

    
3428
        if (in_array($int_family[0], $g['vlan_long_frame']))
3429
                return true;
3430
        else
3431
                return false;
3432
}
3433

    
3434
function setup_pppoe_reset_file($pppif, $iface="") {
3435
	global $g;
3436
	$cron_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
3437

    
3438
	if(!empty($iface) && !empty($pppif)){
3439
		$cron_cmd = "#!/bin/sh\necho '<?php require(\"config.inc\"); require(\"interfaces.inc\"); interface_reconfigure({$iface}); log_error(\"PPPoE periodic reset executed on {$iface}\"); ?>' | /usr/local/bin/php -q";
3440
		file_put_contents($cron_file, $cron_cmd);
3441
		chmod($cron_file, 0700);
3442
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
3443
	} else
3444
		unlink_if_exists($cron_file);
3445
}
3446

    
3447
?>
(22-22/54)