Project

General

Profile

Download (97.8 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
			pfSense_interface_flags($realif, -IFF_UP);
871
			mwexec("/usr/sbin/arp -d -i {$realif} -a");
872
		}
873
		break;
874
	default:
875
		if(does_interface_exist("$realif")) {
876
			mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete", true);
877
			pfSense_interface_flags($realif, -IFF_UP);
878
			mwexec("/usr/sbin/arp -d -i {$realif} -a");
879
		}
880
		break;
881
	}
882

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

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

    
900
	return;
901
}
902

    
903
function interfaces_ptpid_used($ptpid) {
904
	global $config;
905

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

    
911
	return false;
912
}
913

    
914
function interfaces_ptpid_next() {
915

    
916
	$ptpid = 0;
917
	while(interfaces_ptpid_used($ptpid))
918
		$ptpid++;
919

    
920
	return $ptpid;
921
}
922

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

    
937
function handle_pppoe_reset($post_array) {
938
	global $config, $g;
939

    
940
	$cron_cmd_file = "{$g['varetc_path']}/pppoe_restart_";
941

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1212
EOD;
1213

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

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

    
1227
EOD;
1228

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

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

    
1239
EOD;
1240

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

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

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

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

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

    
1267
EOD;
1268

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

    
1273
EOD;
1274

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

    
1279
EOD;
1280

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

    
1286
EOD;
1287

    
1288

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

    
1293
EOD;
1294

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

    
1300
EOD;
1301

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

    
1306
EOD;
1307

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

    
1312
EOD;
1313

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

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

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

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

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

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

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

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

    
1367
EOD;
1368

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

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

    
1381

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

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

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

    
1422
	return 1;
1423
}
1424

    
1425
function interfaces_carp_setup() {
1426
	global $g, $config;
1427

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

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

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

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

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

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

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

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

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

    
1503
	$cmdchain->execute();
1504
	$cmdchain->clear();
1505

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

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

    
1519
	/* kill any running choparp */
1520
	if (empty($interface))
1521
		killbyname("choparp");
1522

    
1523
	if (isset($config['virtualip']) && is_array($config['virtualip']['vip'])) {
1524
		$paa = array();
1525

    
1526
		/* group by interface */
1527
		foreach ($config['virtualip']['vip'] as $vipent) {
1528
			if ($vipent['mode'] === "proxyarp") {
1529
				if ($vipent['interface'])
1530
					$proxyif = $vipent['interface'];
1531
				else
1532
					$proxyif = "wan";
1533

    
1534
				if (!is_array($paa[$if]))
1535
					$paa[$proxyif] = array();
1536

    
1537
				$paa[$proxyif][] = $vipent;
1538
			}
1539
		}
1540
	}
1541

    
1542
	if (!empty($interface)) {
1543
		if (is_array($paa[$interface])) {
1544
			$paaifip = get_interface_ip($interface);
1545
                        if (!is_ipaddr($paaifip))
1546
                                return;
1547
                        $args = get_real_interface($interface) . " auto";
1548
                        foreach ($paa[$interface] as $paent) {
1549
                                if (isset($paent['subnet']))
1550
                                        $args .= " " . escapeshellarg("{$paent['subnet']}/{$paent['subnet_bits']}");
1551
                                else if (isset($paent['range']))
1552
                                        $args .= " " . escapeshellarg($paent['range']['from'] . "-" . $paent['range']['to']);
1553
                        }
1554
                        mwexec_bg("/usr/local/sbin/choparp " . $args);	
1555
		}
1556
	} else if (count($paa)) {
1557
		foreach ($paa as $paif => $paents) {
1558
			$paaifip = get_interface_ip($paif);
1559
			if (!(is_ipaddr($paaifip)))
1560
				continue;
1561
			$args = get_real_interface($paif) . " auto";
1562
			foreach ($paents as $paent) {
1563
				if (isset($paent['subnet']))
1564
					$args .= " " . escapeshellarg("{$paent['subnet']}/{$paent['subnet_bits']}");
1565
				else if (isset($paent['range']))
1566
					$args .= " " . escapeshellarg($paent['range']['from'] . "-" . $paent['range']['to']);
1567
			}
1568
			mwexec_bg("/usr/local/sbin/choparp " . $args);
1569
		}
1570
	}
1571
}
1572

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

    
1618
function interface_ipalias_configure(&$vip) {
1619

    
1620
	if ($vip['mode'] == "ipalias") {
1621
		$if = get_real_interface($vip['interface']);
1622
		mwexec("/sbin/ifconfig " . escapeshellarg($if) . " " . $vip['subnet'] . "/" . escapeshellarg($vip['subnet_bits']) . " alias");
1623
	}
1624
}
1625

    
1626
function interface_reload_carps($cif) {
1627
	global $config;
1628

    
1629
	$carpifs = link_ip_to_carp_interface(find_interface_ip($cif));
1630
	if (empty($carpifs))
1631
		return;
1632

    
1633
	$carps = explode(" ", $carpifs);
1634
	if(is_array($config['virtualip']['vip'])) {
1635
		$viparr = &$config['virtualip']['vip'];
1636
		foreach ($viparr as $vip) {
1637
			if (in_array($vip['carpif'], $carps)) {
1638
				switch ($vip['mode']) {
1639
				case "carp":
1640
					interface_vip_bring_down($vip);
1641
					sleep(1);
1642
					interface_carp_configure($vip);
1643
					break;
1644
				case "carpdev-dhcp":
1645
					interface_vip_bring_down($vip);
1646
					sleep(1);
1647
					interface_carpdev_configure($vip);
1648
					break;
1649
				case "ipalias":
1650
					interface_vip_bring_down($vip);
1651
					sleep(1);
1652
					interface_ipalias_configure($vip);
1653
					break;
1654
				}
1655
			}
1656
		}
1657
	}
1658
}
1659

    
1660
function interface_carp_configure(&$vip) {
1661
	global $config, $g;
1662
	if(isset($config['system']['developerspew'])) {
1663
		$mt = microtime();
1664
		echo "interface_carp_configure() being called $mt\n";
1665
	}
1666

    
1667
	if ($vip['mode'] != "carp")
1668
		return;
1669

    
1670
	$vip_password = $vip['password'];
1671
	$vip_password = escapeshellarg(addslashes(str_replace(" ", "", $vip_password)));
1672
	if ($vip['password'] != "")
1673
		$password = " pass {$vip_password}";
1674

    
1675
	// set the vip interface to the vhid
1676
	$vipif = "vip{$vip['vhid']}";
1677

    
1678
	$interface = interface_translate_type_to_real($vip['interface']);
1679
	/*
1680
	 * ensure the interface containing the VIP really exists
1681
 	 * prevents a panic if the interface is missing or invalid
1682
	 */
1683
	$realif = get_real_interface($vip['interface']);
1684
	if (!does_interface_exist($realif)) {
1685
		file_notice("CARP", "Interface specified for the virtual IP address {$vip['subnet']} does not exist. Skipping this VIP.", "Firewall: Virtual IP", "");
1686
		return;
1687
	}
1688

    
1689
	/* Ensure CARP IP really exists prior to loading up. */
1690
	$ww_subnet_ip = find_interface_ip($realif);
1691
	$ww_subnet_bits = find_interface_subnet($realif);
1692
	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'])) {
1693
		file_notice("CARP", "Sorry but we could not find a matching real interface subnet for the virtual IP address {$vip['subnet']}.", "Firewall: Virtual IP", "");
1694
		return;
1695
	}
1696

    
1697
	/* create the carp interface and setup */
1698
	if (does_interface_exist($vipif)) {
1699
		pfSense_interface_flags($vipif, -IFF_UP);
1700
	} else {
1701
		$carpif = pfSense_interface_create("carp");
1702
		pfSense_interface_rename($carpif, $vipif);
1703
		pfSense_ngctl_name("{$carpif}:", $vipif);
1704
	}
1705

    
1706
	/* invalidate interface cache */
1707
	get_interface_arr(true);
1708

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

    
1712
	interfaces_bring_up($vipif);
1713
	
1714
	return $vipif;
1715
}
1716

    
1717
function interface_carpdev_configure(&$vip) {
1718
	global $g;
1719

    
1720
	if ($vip['mode'] != "carpdev-dhcp")
1721
		return;
1722

    
1723
	$vip_password = $vip['password'];
1724
	$vip_password = str_replace(" ", "", $vip_password);
1725
	if($vip['password'] != "")
1726
		$password = " pass \"" . $vip_password . "\"";
1727

    
1728
	log_error("Found carpdev interface {$vip['interface']} on top of interface {$interface}");
1729
	if (empty($vip['interface']))
1730
		return;
1731

    
1732
	$vipif = "vip" . $vip['vhid'];
1733
	$realif = interface_translate_type_to_real($vip['interface']);
1734
	interfaces_bring_up($realif);
1735
	/*
1736
	 * ensure the interface containing the VIP really exists
1737
	 * prevents a panic if the interface is missing or invalid
1738
	 */
1739
	if (!does_interface_exist($realif)) {
1740
		file_notice("CARP", "Interface specified for the virtual IP address {$vip['subnet']} does not exist. Skipping this VIP.", "Firewall: Virtual IP", "");
1741
		return;
1742
	}
1743

    
1744
	if (does_interface_exist($vipif)) {
1745
		interface_bring_down($vipif);
1746
	} else {
1747
		$carpdevif = exec("/sbin/ifconfig carp create");
1748
		mwexec("/sbin/ifconfig {$carpdevif} name {$vipif}");
1749
		pfSense_ngctl_name("{$carpdevif}:", $vipif);
1750
	}
1751

    
1752
	mwexec("/sbin/ifconfig {$vipif} carpdev {$realif} vhid {$vip['vhid']} advskew {$vip['advskew']} {$password}");
1753
	interfaces_bring_up($vipif);
1754

    
1755
	/*
1756
	 * XXX: BIG HACK but carpdev needs ip services active
1757
	 *      before even starting something as dhclient.
1758
	 *      I do not know if this is a feature or a bug
1759
	 *      but better than track it make it work ;) .
1760
	 */
1761
	//$fakeiptouse = "10.254.254." . ($carp_instances_counter+1);
1762
	//$cmdchain->add("CarpDEV hack", "/sbin/ifconfig {$carpint} inet {$fakeiptouse}", false);
1763

    
1764
	/* generate dhclient_wan.conf */
1765
	$fd = fopen("{$g['varetc_path']}/dhclient_{$vipif}.conf", "w");
1766
	if ($fd) {
1767
		$dhclientconf = "";
1768

    
1769
		$dhclientconf .= <<<EOD
1770
interface "{$vipif}" {
1771
timeout 60;
1772
retry 1;
1773
select-timeout 0;
1774
initial-interval 1;
1775
script "/sbin/dhclient-script";
1776
}
1777

    
1778
EOD;
1779

    
1780
		fwrite($fd, $dhclientconf);
1781
		fclose($fd);
1782

    
1783
		/* fire up dhclient */
1784
		mwexec("/sbin/dhclient -c {$g['varetc_path']}/dhclient_{$vipif}.conf {$vipif} > {$g['tmp_path']}/{$vipif}_output > {$g['tmp_path']}/{$vipif}_error_output", false);
1785
	} else {
1786
		log_error("Error: cannot open dhclient_{$vipif}.conf in interfaces_carpdev_configure() for writing.\n");
1787
		mwexec("/sbin/dhclient -b {$vipif}");
1788
	}
1789

    
1790
	return $vipif;
1791
}
1792

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

    
1834
	if($needs_clone == true) {
1835
		/* remove previous instance if it exists */
1836
		if(does_interface_exist($realif))
1837
			pfSense_interface_destroy($realif);
1838

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

    
1856
function interface_sync_wireless_clones(&$ifcfg, $sync_changes = false) {
1857
	global $config, $g;
1858

    
1859
	$shared_settings = array('standard', 'turbo', 'protmode', 'txpower', 'channel',
1860
	                         'diversity', 'txantenna', 'rxantenna', 'distance',
1861
	                         'regdomain', 'regcountry', 'reglocation');
1862

    
1863
	if(!is_interface_wireless($ifcfg['if']))
1864
		return;
1865

    
1866
	$baseif = interface_get_wireless_base($ifcfg['if']);
1867

    
1868
	// Sync shared settings for assigned clones
1869
	$iflist = get_configured_interface_list(false, true);
1870
	foreach ($iflist as $if) {
1871
		if ($baseif == interface_get_wireless_base($config['interfaces'][$if]['if']) && $ifcfg['if'] != $config['interfaces'][$if]['if']) {
1872
			if (isset($config['interfaces'][$if]['wireless']['standard']) || $sync_changes) {
1873
				foreach ($shared_settings as $setting) {
1874
					if ($sync_changes) {
1875
						if (isset($ifcfg['wireless'][$setting]))
1876
							$config['interfaces'][$if]['wireless'][$setting] = $ifcfg['wireless'][$setting];
1877
						else if (isset($config['interfaces'][$if]['wireless'][$setting]))
1878
							unset($config['interfaces'][$if]['wireless'][$setting]);
1879
					} else {
1880
						if (isset($config['interfaces'][$if]['wireless'][$setting]))
1881
							$ifcfg['wireless'][$setting] = $config['interfaces'][$if]['wireless'][$setting];
1882
						else if (isset($ifcfg['wireless'][$setting]))
1883
							unset($ifcfg['wireless'][$setting]);
1884
					}
1885
				}
1886
				if (!$sync_changes)
1887
					break;
1888
			}
1889
		}
1890
	}
1891

    
1892
	// Read or write settings at shared area
1893
	if (isset($config['wireless']['interfaces'][$baseif])) {
1894
		foreach ($shared_settings as $setting) {
1895
			if ($sync_changes) {
1896
				if (isset($ifcfg['wireless'][$setting]))
1897
					$config['wireless']['interfaces'][$baseif][$setting] = $ifcfg['wireless'][$setting];
1898
				else if (isset($config['wireless']['interfaces'][$baseif][$setting]))
1899
					unset($config['wireless']['interfaces'][$baseif][$setting]);
1900
			} else if (isset($config['wireless']['interfaces'][$baseif][$setting])) {
1901
				if (isset($config['wireless']['interfaces'][$baseif][$setting]))
1902
					$ifcfg['wireless'][$setting] = $config['wireless']['interfaces'][$baseif][$setting];
1903
				else if (isset($ifcfg['wireless'][$setting]))
1904
					unset($ifcfg['wireless'][$setting]);
1905
			}
1906
		}
1907
	}
1908

    
1909
	// Sync the mode on the clone creation page with the configured mode on the interface
1910
	if (interface_is_wireless_clone($ifcfg['if'])) {
1911
		foreach ($config['wireless']['clone'] as &$clone) {
1912
			if ($clone['cloneif'] == $ifcfg['if']) {
1913
				if ($sync_changes) {
1914
					$clone['mode'] = $ifcfg['wireless']['mode'];
1915
				} else {
1916
					$ifcfg['wireless']['mode'] = $clone['mode'];
1917
				}
1918
				break;
1919
			}
1920
		}
1921
		unset($clone);
1922
	}
1923
}
1924

    
1925
function interface_wireless_configure($if, &$wl, &$wlcfg) {
1926
	global $config, $g;
1927

    
1928
	/*    open up a shell script that will be used to output the commands.
1929
	 *    since wireless is changing a lot, these series of commands are fragile
1930
     *    and will sometimes need to be verified by a operator by executing the command
1931
     *    and returning the output of the command to the developers for inspection.  please
1932
     *    do not change this routine from a shell script to individul exec commands.  -sullrich
1933
	 */
1934

    
1935
	// Remove script file
1936
	unlink_if_exists("{$g['tmp_path']}/{$if}_setup.sh");
1937

    
1938
	// Clone wireless nic if needed.
1939
	interface_wireless_clone($if, $wl);
1940

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

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

    
1948
	/* set values for /path/program */
1949
	$hostapd = "/usr/sbin/hostapd";
1950
	$wpa_supplicant = "/usr/sbin/wpa_supplicant";
1951
	$ifconfig = "/sbin/ifconfig";
1952
	$sysctl = "/sbin/sysctl";
1953
	$killall = "/usr/bin/killall";
1954

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

    
1957
	$wlcmd = array();
1958
	$wl_sysctl = array();
1959
	/* Make sure it's up */
1960
	$wlcmd[] = "up";
1961
	/* Set a/b/g standard */
1962
	$standard = str_replace(" Turbo", "", $wlcfg['standard']);
1963
	$wlcmd[] = "mode " . escapeshellarg($standard);
1964

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

    
1970
	/* Set ssid */
1971
	if($wlcfg['ssid'])
1972
		$wlcmd[] = "ssid " .escapeshellarg($wlcfg['ssid']);
1973

    
1974
	/* Set 802.11g protection mode */
1975
	$wlcmd[] = "protmode " . escapeshellarg($wlcfg['protmode']);
1976

    
1977
	/* set wireless channel value */
1978
	if(isset($wlcfg['channel'])) {
1979
		if($wlcfg['channel'] == "0") {
1980
			$wlcmd[] = "channel any";
1981
		} else {
1982
			$wlcmd[] = "channel " . escapeshellarg($wlcfg['channel']);
1983
		}
1984
	}
1985

    
1986
	/* Set antenna diversity value */
1987
	if(isset($wlcfg['diversity']))
1988
		$wl_sysctl[] = "diversity=" . escapeshellarg($wlcfg['diversity']);
1989

    
1990
	/* Set txantenna value */
1991
	if(isset($wlcfg['txantenna']))
1992
		$wl_sysctl[] = "txantenna=" . escapeshellarg($wlcfg['txantenna']);
1993

    
1994
	/* Set rxantenna value */
1995
	if(isset($wlcfg['rxantenna']))
1996
		$wl_sysctl[] = "rxantenna=" . escapeshellarg($wlcfg['rxantenna']);
1997

    
1998
	/* set Distance value */
1999
	if($wlcfg['distance'])
2000
		$distance = escapeshellarg($wlcfg['distance']);
2001

    
2002
	/* Set wireless hostap mode */
2003
	if ($wlcfg['mode'] == "hostap") {
2004
		$wlcmd[] = "mediaopt hostap";
2005
	} else {
2006
		$wlcmd[] = "-mediaopt hostap";
2007
	}
2008

    
2009
	/* Set wireless adhoc mode */
2010
	if ($wlcfg['mode'] == "adhoc") {
2011
		$wlcmd[] = "mediaopt adhoc";
2012
	} else {
2013
		$wlcmd[] = "-mediaopt adhoc";
2014
	}
2015

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

    
2018
	/* handle hide ssid option */
2019
	if(isset($wlcfg['hidessid']['enable'])) {
2020
		$wlcmd[] = "hidessid";
2021
	} else {
2022
		$wlcmd[] = "-hidessid";
2023
	}
2024

    
2025
	/* handle pureg (802.11g) only option */
2026
	if(isset($wlcfg['pureg']['enable'])) {
2027
		$wlcmd[] = "mode 11g pureg";
2028
	} else {
2029
		$wlcmd[] = "-pureg";
2030
	}
2031

    
2032
	/* handle puren (802.11n) only option */
2033
	if(isset($wlcfg['puren']['enable'])) {
2034
		$wlcmd[] = "puren";
2035
	} else {
2036
		$wlcmd[] = "-puren";
2037
	}
2038

    
2039
	/* enable apbridge option */
2040
	if(isset($wlcfg['apbridge']['enable'])) {
2041
		$wlcmd[] = "apbridge";
2042
	} else {
2043
		$wlcmd[] = "-apbridge";
2044
	}
2045

    
2046
	/* handle turbo option */
2047
	if(isset($wlcfg['turbo']['enable'])) {
2048
		$wlcmd[] = "mediaopt turbo";
2049
	} else {
2050
		$wlcmd[] = "-mediaopt turbo";
2051
	}
2052

    
2053
	/* handle txpower setting */
2054
	/* if($wlcfg['txpower'] <> "")
2055
		$wlcmd[] = "txpower " . escapeshellarg($wlcfg['txpower']);
2056
	*/
2057
	/* handle wme option */
2058
	if(isset($wlcfg['wme']['enable'])) {
2059
		$wlcmd[] = "wme";
2060
	} else {
2061
		$wlcmd[] = "-wme";
2062
	}
2063

    
2064
	/* set up wep if enabled */
2065
	$wepset = "";
2066
	if (isset($wlcfg['wep']['enable']) && is_array($wlcfg['wep']['key'])) {
2067
		switch($wlcfg['wpa']['auth_algs']) {
2068
			case "1":
2069
				$wepset .= "authmode open wepmode on ";
2070
				break;
2071
			case "2":
2072
				$wepset .= "authmode shared wepmode on ";
2073
				break;
2074
			case "3":
2075
				$wepset .= "authmode mixed wepmode on ";
2076
		}
2077
		$i = 1;
2078
		foreach ($wlcfg['wep']['key'] as $wepkey) {
2079
			$wepset .= "wepkey " . escapeshellarg("{$i}:{$wepkey['value']}") . " ";
2080
			if (isset($wepkey['txkey'])) {
2081
				$wlcmd[] = "weptxkey {$i} ";
2082
			}
2083
			$i++;
2084
		}
2085
		$wlcmd[] = $wepset;
2086
	} else {
2087
		$wlcmd[] = "authmode open wepmode off ";
2088
	}
2089

    
2090
	mwexec(kill_hostapd("{$if}"));
2091
	mwexec(kill_wpasupplicant("{$if}"));
2092

    
2093
	/* generate wpa_supplicant/hostap config if wpa is enabled */
2094
	conf_mount_rw();
2095

    
2096
	switch ($wlcfg['mode']) {
2097
		case 'bss':
2098
			if (isset($wlcfg['wpa']['enable'])) {
2099
				$wpa .= <<<EOD
2100
ctrl_interface={$g['varrun_path']}/wpa_supplicant
2101
ctrl_interface_group=0
2102
ap_scan=1
2103
#fast_reauth=1
2104
network={
2105
ssid="{$wlcfg['ssid']}"
2106
scan_ssid=1
2107
priority=5
2108
key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
2109
psk="{$wlcfg['wpa']['passphrase']}"
2110
pairwise={$wlcfg['wpa']['wpa_pairwise']}
2111
group={$wlcfg['wpa']['wpa_pairwise']}
2112
}
2113
EOD;
2114

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

    
2150
EOD;
2151

    
2152
if (isset($wlcfg['wpa']['rsn_preauth'])) {
2153
	$wpa .= <<<EOD
2154
# Enable the next lines for preauth when roaming. Interface = wired or wireless interface talking to the AP you want to roam from/to
2155
rsn_preauth=1
2156
rsn_preauth_interfaces={$if}
2157

    
2158
EOD;
2159

    
2160
}
2161
				if($wlcfg['auth_server_addr'] && $wlcfg['auth_server_shared_secret']) {
2162
					$auth_server_port = "1812";
2163
					if($wlcfg['auth_server_port']) 
2164
						$auth_server_port = $wlcfg['auth_server_port'];
2165
					$wpa .= <<<EOD
2166

    
2167
ieee8021x=1
2168
auth_server_addr={$wlcfg['auth_server_addr']}
2169
auth_server_port={$auth_server_port}
2170
auth_server_shared_secret={$wlcfg['auth_server_shared_secret']}
2171

    
2172
EOD;
2173
				} else {
2174
					$wpa .= "ieee8021x={$wlcfg['wpa']['ieee8021x']}\n";
2175
				}
2176

    
2177
				$fd = fopen("{$g['varetc_path']}/hostapd_{$if}.conf", "w");
2178
				fwrite($fd, "{$wpa}");
2179
				fclose($fd);
2180

    
2181
			}
2182
			break;
2183
	}
2184

    
2185
	/*
2186
	 *    all variables are set, lets start up everything
2187
	 */
2188

    
2189
	$baseif = interface_get_wireless_base($if);
2190
	preg_match("/^(.*?)([0-9]*)$/", $baseif, $baseif_split);
2191
	$wl_sysctl_prefix = 'dev.' . $baseif_split[1] . '.' . $baseif_split[2];
2192

    
2193
	/* set sysctls for the wireless interface */
2194
	if (!empty($wl_sysctl)) {
2195
		fwrite($fd_set, "# sysctls for {$baseif}\n");
2196
		foreach ($wl_sysctl as $wl_sysctl_line) {
2197
			fwrite($fd_set, "{$sysctl} {$wl_sysctl_prefix}.{$wl_sysctl_line}\n");
2198
		}
2199
	}
2200

    
2201
	/* set ack timers according to users preference (if he/she has any) */
2202
	if($distance) {
2203
		fwrite($fd_set, "# Enable ATH distance settings\n");
2204
		fwrite($fd_set, "/sbin/athctrl.sh -i {$baseif} -d {$distance}\n");
2205
	}
2206

    
2207
	if (isset($wlcfg['wpa']['enable'])) {
2208
		if ($wlcfg['mode'] == "bss") {
2209
			fwrite($fd_set, "{$wpa_supplicant} -B -i {$if} -c {$g['varetc_path']}/wpa_supplicant_{$if}.conf\n");
2210
		}
2211
		if ($wlcfg['mode'] == "hostap") {
2212
			fwrite($fd_set, "{$hostapd} -B {$g['varetc_path']}/hostapd_{$if}.conf\n");
2213
		}
2214
	}
2215

    
2216
	fclose($fd_set);
2217
	conf_mount_ro();
2218

    
2219
	/* Making sure regulatory settings have actually changed
2220
	 * before applying, because changing them requires bringing
2221
	 * down all wireless networks on the interface. */
2222
	exec("{$ifconfig} " . escapeshellarg($if), $output);
2223
	$ifconfig_str = implode($output);
2224
	unset($output);
2225
	$reg_changing = false;
2226

    
2227
	/* special case for the debug country code */
2228
	if ($wlcfg['regcountry'] == 'DEBUG' && !preg_match("/\sregdomain\s+DEBUG\s/si", $ifconfig_str))
2229
		$reg_changing = true;
2230
	else if ($wlcfg['regdomain'] && !preg_match("/\sregdomain\s+{$wlcfg['regdomain']}\s/si", $ifconfig_str))
2231
		$reg_changing = true;
2232
	else if ($wlcfg['regcountry'] && !preg_match("/\scountry\s+{$wlcfg['regcountry']}\s/si", $ifconfig_str))
2233
		$reg_changing = true;
2234
	else if ($wlcfg['reglocation'] == 'anywhere' && preg_match("/\s(indoor|outdoor)\s/si", $ifconfig_str))
2235
		$reg_changing = true;
2236
	else if ($wlcfg['reglocation'] && $wlcfg['reglocation'] != 'anywhere' && !preg_match("/\s{$wlcfg['reglocation']}\s/si", $ifconfig_str))
2237
		$reg_changing = true;
2238

    
2239
	if ($reg_changing) {
2240
		/* set regulatory domain */
2241
		if($wlcfg['regdomain'])
2242
			$wlregcmd[] = "regdomain " . escapeshellarg($wlcfg['regdomain']);
2243

    
2244
		/* set country */
2245
		if($wlcfg['regcountry'])
2246
			$wlregcmd[] = "country " . escapeshellarg($wlcfg['regcountry']);
2247

    
2248
		/* set location */
2249
		if($wlcfg['reglocation'])
2250
			$wlregcmd[] = escapeshellarg($wlcfg['reglocation']);
2251

    
2252
		$wlregcmd_args = implode(" ", $wlregcmd);
2253

    
2254
		/* build a complete list of the wireless clones for this interface */
2255
		$clone_list = array();
2256
		if (does_interface_exist(interface_get_wireless_clone($baseif)))
2257
			$clone_list[] = interface_get_wireless_clone($baseif);
2258
		if (is_array($config['wireless']['clone'])) {
2259
			foreach ($config['wireless']['clone'] as $clone) {
2260
				if ($clone['if'] == $baseif)
2261
					$clone_list[] = $clone['cloneif'];
2262
			}
2263
		}
2264

    
2265
		/* find which clones are up and bring them down */
2266
		$clones_up = array();
2267
		foreach ($clone_list as $clone_if) {
2268
			$clone_status = pfSense_get_interface_addresses($clone_if);
2269
			if ($clone_status['status'] == 'up') {
2270
				$clones_up[] = $clone_if;
2271
				mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " down");
2272
			}
2273
		}
2274

    
2275
		/* apply the regulatory settings */
2276
		mwexec("{$ifconfig} " . escapeshellarg($if) . " {$wlregcmd_args}");
2277

    
2278
		/* bring the clones back up that were previously up */
2279
		foreach ($clones_up as $clone_if) {
2280
			mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " up");
2281
		}
2282
	}
2283

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

    
2288
	/* configure wireless */
2289
	$wlcmd_args = implode(" ", $wlcmd);
2290
	mwexec("/sbin/ifconfig {$if} $wlcmd_args", false);
2291

    
2292
	
2293
	sleep(1);
2294
	/* execute hostapd and wpa_supplicant if required in shell */
2295
	mwexec("/bin/sh {$g['tmp_path']}/{$if}_setup.sh");
2296

    
2297
	return 0;
2298

    
2299
}
2300

    
2301
function kill_hostapd($interface) {
2302
	return "/bin/pkill -f \"hostapd .*{$interface}\"\n";
2303
}
2304

    
2305
function kill_wpasupplicant($interface) {
2306
	return "/bin/pkill -f \"wpa_supplicant .*{$interface}\"\n";
2307
}
2308

    
2309
function find_dhclient_process($interface) {
2310
	if($interface) {
2311
		$pid = `/bin/pgrep -xf "dhclient: {$interface}"`;
2312
	}
2313
	return $pid;
2314
}
2315

    
2316
function interface_configure($interface = "wan", $reloadall = false, $linkupevent = false) {
2317
	global $config, $g;
2318
	global $interface_sn_arr_cache, $interface_ip_arr_cache;
2319

    
2320
	$wancfg = $config['interfaces'][$interface];
2321

    
2322
	$realif = get_real_interface($interface);
2323

    
2324
	if (!$g['booting']) {
2325
		/* remove all IPv4 addresses */
2326
		while (mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " -alias", true) == 0);
2327
			interface_bring_down($interface, true);
2328
	}
2329

    
2330
	/* wireless configuration? */
2331
	if (is_array($wancfg['wireless']))
2332
		interface_wireless_configure($realif, $wancfg, $wancfg['wireless']);
2333

    
2334
	if ($wancfg['spoofmac']) {
2335
		mwexec("/sbin/ifconfig " . escapeshellarg($realif) .
2336
			" link " . escapeshellarg($wancfg['spoofmac']));
2337

    
2338
                /*
2339
                 * All vlans need to spoof their parent mac address, too.  see
2340
                 * ticket #1514: http://cvstrac.pfsense.com/tktview?tn=1514,33
2341
                 */
2342
                if (is_array($config['vlans']['vlan'])) {
2343
                        foreach ($config['vlans']['vlan'] as $vlan) {
2344
                                if ($vlan['if'] == $realif)
2345
                                        mwexec("/sbin/ifconfig " . escapeshellarg($vlan['vlanif']) .
2346
                                                " link " . escapeshellarg($wancfg['spoofmac']));
2347
                        }
2348
                }
2349
	}  else {
2350
		$mac = get_interface_mac(get_real_interface($wancfg['if']));
2351
		if($mac == "ff:ff:ff:ff:ff:ff") {
2352
			/*   this is not a valid mac address.  generate a
2353
			 *   temporary mac address so the machine can get online.
2354
			 */
2355
			echo "Generating new MAC address.";
2356
			$random_mac = generate_random_mac_address();
2357
			mwexec("/sbin/ifconfig " . escapeshellarg(get_real_interface($wancfg['if'])) .
2358
				" link " . escapeshellarg($random_mac));
2359
			$wancfg['spoofmac'] = $random_mac;
2360
			write_config();
2361
			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");
2362
		}
2363
	}
2364

    
2365
	/* media */
2366
	if ($wancfg['media'] || $wancfg['mediaopt']) {
2367
		$cmd = "/sbin/ifconfig " . escapeshellarg(get_real_interface($wancfg['if']));
2368
		if ($wancfg['media'])
2369
			$cmd .= " media " . escapeshellarg($wancfg['media']);
2370
		if ($wancfg['mediaopt'])
2371
			$cmd .= " mediaopt " . escapeshellarg($wancfg['mediaopt']);
2372
		mwexec($cmd);
2373
	}
2374
	if (!empty($wancfg['mtu']))
2375
		pfSense_interface_mtu($realif, $wancfg['mtu']);
2376

    
2377
	$options = pfSense_get_interface_addresses($realif);
2378
	if (is_array($options) && isset($options['caps']['polling'])) {
2379
		if (isset($config['system']['polling']))
2380
			pfSense_interface_capabilities($realif, IFCAP_POLLING);
2381
		else
2382
			pfSense_interface_capabilities($realif, -IFCAP_POLLING);
2383
	}
2384

    
2385
	/* skip vlans for checksumming and polling */
2386
        if (!stristr($realif, "vlan") && is_array($options)) {
2387
		$flags = 0;
2388
		if(isset($config['system']['disablechecksumoffloading'])) {
2389
			if (isset($options['encaps']['txcsum']))
2390
				$flags |= IFCAP_TXCSUM;
2391
			if (isset($options['encaps']['rxcsum']))
2392
				$flags |= IFCAP_RXCSUM;
2393
        	} else {
2394
 			if (!isset($options['caps']['txcsum']))
2395
				$flags |= IFCAP_TXCSUM;
2396
			if (!isset($options['caps']['rxcsum']))
2397
				$flags |= IFCAP_RXCSUM;
2398
        	}
2399

    
2400
        	if(isset($config['system']['disablesegmentationoffloading'])) {
2401
                	if (isset($options['encaps']['tso4']))
2402
				$flags |= IFCAP_TSO;
2403
                	if (isset($options['encaps']['tso6']))
2404
				$flags |= IFCAP_TSO;
2405
        	} else {
2406
                	if (!isset($options['caps']['tso4']))
2407
				$flags |= IFCAP_TSO;
2408
                	if (!isset($options['caps']['tso6']))
2409
				$flags |= IFCAP_TSO;
2410
        	}
2411

    
2412
        	if(isset($config['system']['disablelargereceiveoffloading'])) {
2413
                	if (isset($options['encaps']['lro']))
2414
				$flags |= IFCAP_LRO;
2415
        	} else {
2416
                	if (!isset($options['caps']['lro']))
2417
				$flags |= IFCAP_LRO;
2418
        	}
2419

    
2420
        	/* if the NIC supports polling *AND* it is enabled in the GUI */
2421
        	if (!isset($config['system']['polling']) || !isset($options['caps']['polling'])) {
2422
			$flags |= IFCAP_POLLING;
2423
		}
2424
               	pfSense_interface_capabilities($realif, -$flags);
2425
	}
2426

    
2427
	/* invalidate interface/ip/sn cache */
2428
	get_interface_arr(true);
2429
	unset($interface_ip_arr_cache[$realif]);
2430
	unset($interface_sn_arr_cache[$realif]);
2431

    
2432
	switch ($wancfg['ipaddr']) {
2433
		case 'carpdev-dhcp':
2434
			interface_carpdev_dhcp_configure($interface);
2435
			break;
2436
		case 'dhcp':
2437
			interface_dhcp_configure($interface);
2438
			break;
2439
		case 'pppoe':
2440
		case 'l2tp':
2441
		case 'pptp':
2442
		case 'ppp':
2443
			interface_ppps_configure($interface);
2444
			break;
2445
		default:
2446
			if ($wancfg['ipaddr'] <> "" && $wancfg['subnet'] <> "") {
2447
				pfSense_interface_setaddress($realif, "{$wancfg['ipaddr']}/{$wancfg['subnet']}");
2448
			} else if (substr($realif, 0, 3) == "gre") {
2449
				if (is_array($config['gres']['gre'])) {
2450
					foreach ($config['gres']['gre'] as $gre)
2451
						if ($gre['greif'] == $realif)
2452
							interface_gre_configure($gre);
2453
				}
2454
			} else if (substr($realif, 0, 3) == "gif") {
2455
				 if (is_array($config['gifs']['gif'])) {
2456
					foreach ($config['gifs']['gif'] as $gif)
2457
						if($gif['gifif'] == $interface)
2458
							interface_gif_configure($gif);
2459
				}
2460
			} else if (substr($realif, 0, 4) == "ovpn") {
2461
				/* XXX: Should be done anything?! */
2462
			}
2463

    
2464
			if (is_ipaddr($wancfg['gateway']))
2465
				file_put_contents("{$g['tmp_path']}/{$realif}_router", $wancfg['gateway']);
2466
			break;
2467
	}
2468

    
2469
	if(does_interface_exist($wancfg['if']))
2470
		interfaces_bring_up($wancfg['if']);
2471
 	
2472
	if (!$g['booting']) {
2473
		interface_reload_carps($realif);
2474

    
2475
		unset($gre);
2476
		$gre = link_interface_to_gre($interface);
2477
		if (!empty($gre))
2478
			interface_gre_configure($gre);
2479

    
2480
		unset($gif);
2481
		$gif = link_interface_to_gif($interface);
2482
		if (!empty($gif))
2483
                       	interface_gif_configure($gif);
2484

    
2485
		if ($linkupevent == false) {
2486
			unset($bridgetmp);
2487
			$bridgetmp = link_interface_to_bridge($interface);
2488
			if (!empty($bridgetmp))
2489
				interface_bridge_add_member($bridgetmp, $realif);
2490
		}
2491

    
2492
		link_interface_to_vips($interface, "update");
2493

    
2494
		$grouptmp = link_interface_to_group($interface);
2495
		if (!empty($grouptmp))
2496
			interface_group_add_member($realif, $grouptmp);
2497

    
2498
		if ($interface == "lan")
2499
			/* make new hosts file */
2500
			system_hosts_generate();
2501

    
2502
		if ($reloadall == true) {
2503

    
2504
			/* reconfigure static routes (kernel may have deleted them) */
2505
			system_routing_configure($interface);
2506

    
2507
			/* reload ipsec tunnels */
2508
			vpn_ipsec_configure();
2509

    
2510
			/* update dyndns */
2511
			services_dyndns_configure($interface);
2512

    
2513
			/* force DNS update */
2514
			services_dnsupdate_process($interface);
2515

    
2516
			/* restart dnsmasq */
2517
			services_dnsmasq_configure();
2518

    
2519
			/* reload captive portal */
2520
			captiveportal_init_rules();
2521

    
2522
			/* set the reload filter dity flag */
2523
			filter_configure();
2524
		}
2525
	}
2526

    
2527
	return 0;
2528
}
2529

    
2530
function interface_carpdev_dhcp_configure($interface = "wan") {
2531
	global $config, $g;
2532

    
2533
	$wancfg = $config['interfaces'][$interface];
2534
	$wanif = $wancfg['if'];
2535
	/* bring wan interface up before starting dhclient */
2536
	if($wanif)
2537
		interfaces_bring_up($wanif);
2538
	else 
2539
		log_error("Could not bring wanif up in terface_carpdev_dhcp_configure()");
2540

    
2541
	return 0;
2542
}
2543

    
2544
function interface_dhcp_configure($interface = "wan") {
2545
	global $config, $g;
2546

    
2547
	$wancfg = $config['interfaces'][$interface];
2548
	if (empty($wancfg))
2549
		$wancfg = array();
2550

    
2551
	/* generate dhclient_wan.conf */
2552
	$fd = fopen("{$g['varetc_path']}/dhclient_{$interface}.conf", "w");
2553
	if (!$fd) {
2554
		printf("Error: cannot open dhclient_{$interface}.conf in interfaces_wan_dhcp_configure() for writing.\n");
2555
		return 1;
2556
	}
2557

    
2558
	if ($wancfg['dhcphostname']) {
2559
		$dhclientconf_hostname = "send dhcp-client-identifier \"{$wancfg['dhcphostname']}\";\n";
2560
		$dhclientconf_hostname .= "\tsend host-name \"{$wancfg['dhcphostname']}\";\n";
2561
	} else {
2562
		$dhclientconf_hostname = "";
2563
	}
2564

    
2565
	$wanif = get_real_interface($interface);
2566
	if (empty($wanif)) {
2567
		log_error("Invalid interface \"{$interface}\" in interface_dhcp_configure()");
2568
		return 0;
2569
	}
2570
 	$dhclientconf = "";
2571
	
2572
	$dhclientconf .= <<<EOD
2573
interface "{$wanif}" {
2574
timeout 60;
2575
retry 1;
2576
select-timeout 0;
2577
initial-interval 1;
2578
	{$dhclientconf_hostname}
2579
	script "/sbin/dhclient-script";
2580
}
2581

    
2582
EOD;
2583

    
2584
if(is_ipaddr($wancfg['alias-address'])) {
2585
	$subnetmask = gen_subnet_mask($wancfg['alias-subnet']);
2586
	$dhclientconf .= <<<EOD
2587
alias {
2588
	interface  "{$wanif}";
2589
	fixed-address {$wancfg['alias-address']};
2590
	option subnet-mask {$subnetmask};
2591
}
2592

    
2593
EOD;
2594
}
2595
	fwrite($fd, $dhclientconf);
2596
	fclose($fd);
2597

    
2598
	/* bring wan interface up before starting dhclient */
2599
	if($wanif)
2600
		interfaces_bring_up($wanif);
2601
	else 
2602
		log_error("Could not bring up {$wanif} interface in interface_dhcp_configure()");
2603

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

    
2607
	return 0;
2608
}
2609

    
2610
function interfaces_group_setup() {
2611
	global $config;
2612

    
2613
	if (!is_array($config['ifgroups']['ifgroupentry']))
2614
		return;
2615

    
2616
	foreach ($config['ifgroups']['ifgroupentry'] as $groupar)
2617
		interface_group_setup($groupar);
2618

    
2619
	return;
2620
}
2621

    
2622
function interface_group_setup(&$groupname /* The parameter is an array */) {
2623
	global $config;
2624

    
2625
	if (!is_array($groupname))
2626
		return;
2627
	$members = explode(" ", $groupname['members']);
2628
	foreach($members as $ifs) {
2629
		$realif = get_real_interface($ifs);
2630
		if ($realif)
2631
			mwexec("/sbin/ifconfig {$realif} group {$groupname['ifname']}");
2632
	}
2633

    
2634
	return;
2635
}
2636

    
2637
function interface_group_add_member($interface, $groupname) {
2638
	mwexec("/sbin/ifconfig {$interface} group {$groupname}", true);
2639
}
2640
 
2641
/* COMPAT Function */
2642
function convert_friendly_interface_to_real_interface_name($interface) {
2643
	return get_real_interface($interface);
2644
}
2645

    
2646
/* COMPAT Function */
2647
function get_real_wan_interface($interface = "wan") {
2648
	return get_real_interface($interface);
2649
}
2650

    
2651
/* COMPAT Function */
2652
function get_current_wan_address($interface = "wan") {
2653
	return get_interface_ip($interface);
2654
}
2655

    
2656
/*
2657
 * convert_real_interface_to_friendly_interface_name($interface): convert fxp0 -> wan, etc.
2658
 */
2659
function convert_real_interface_to_friendly_interface_name($interface = "wan") {
2660
        global $config;
2661

    
2662
	if (stristr($interface, "vip")) {
2663
                $index = intval(substr($interface, 3));
2664
                foreach ($config['virtualip']['vip'] as $counter => $vip) {
2665
                        if ($vip['mode'] == "carpdev-dhcp" || $vip['mode'] == "carp")  {
2666
                                if ($index == $counter)
2667
                                        return $vip['interface'];
2668
                        }
2669
                }
2670
        }
2671

    
2672
        /* XXX: For speed reasons reference directly the interface array */
2673
	$ifdescrs =& $config['interfaces'];
2674
        //$ifdescrs = get_configured_interface_list(false, true);
2675

    
2676
        foreach ($ifdescrs as $if => $ifname) {
2677
                if ($config['interfaces'][$if]['if'] == $interface)
2678
                        return $if;
2679

    
2680
                if (stristr($interface, "_wlan0") && $config['interfaces'][$if]['if'] == interface_get_wireless_base($interface))
2681
                        return $if;
2682

    
2683
                $int = interface_translate_type_to_real($if);
2684
                if ($int == $interface)
2685
                        return $ifname;
2686
        }
2687
        return NULL;
2688
}
2689

    
2690
/* attempt to resolve interface to friendly descr */
2691
function convert_friendly_interface_to_friendly_descr($interface) {
2692
        global $config;
2693

    
2694
        switch ($interface) {
2695
                case "l2tp":
2696
                                $ifdesc = "L2TP";
2697
                                break;
2698
                case "pptp":
2699
                                $ifdesc = "PPTP";
2700
                                break;
2701
                case "pppoe":
2702
                                $ifdesc = "PPPoE";
2703
                                break;
2704
                case "openvpn":
2705
                                $ifdesc = "OpenVPN";
2706
                                break;
2707
                case "enc0":
2708
                        case "ipsec":
2709
                                $ifdesc = "IPsec";
2710
                                break;
2711
        default:
2712
                if (isset($config['interfaces'][$interface])) {
2713
                        if (empty($config['interfaces'][$interface]['descr']))
2714
                                $ifdesc = strtoupper($interface);
2715
                        else
2716
                                $ifdesc = strtoupper($config['interfaces'][$interface]['descr']);
2717
			break;
2718
		}
2719
                /* if list */
2720
                $ifdescrs = get_configured_interface_with_descr(false, true);
2721
                foreach ($ifdescrs as $if => $ifname) {
2722
                                if ($if == $interface || $ifname == $interface)
2723
                                        return $ifname;
2724
                }
2725
                break;
2726
        }
2727

    
2728
        return $ifdesc;
2729
}
2730

    
2731
function convert_real_interface_to_friendly_descr($interface) {
2732
        global $config;
2733

    
2734
        $ifdesc = convert_real_interface_to_friendly_interface_name("{$interface}");
2735

    
2736
        if ($ifdesc) {
2737
                $iflist = get_configured_interface_with_descr(false, true);
2738
                return $iflist[$ifdesc];
2739
        }
2740

    
2741
        return $interface;
2742
}
2743

    
2744
/*
2745
 *  interface_translate_type_to_real($interface):
2746
 *              returns the real hardware interface name for a friendly interface.  ie: wan
2747
 */
2748
function interface_translate_type_to_real($interface) {
2749
        global $config;
2750

    
2751
        if ($config['interfaces'][$interface]['if'] <> "")
2752
                return $config['interfaces'][$interface]['if'];
2753
        else
2754
		return $interface;
2755
}
2756

    
2757
function interface_is_wireless_clone($wlif) {
2758
	if(!stristr($wlif, "_wlan")) {
2759
		return false;
2760
	} else {
2761
		return true;
2762
	}
2763
}
2764

    
2765
function interface_get_wireless_base($wlif) {
2766
	if(!stristr($wlif, "_wlan")) {
2767
		return $wlif;
2768
	} else {
2769
		return substr($wlif, 0, stripos($wlif, "_wlan"));
2770
	}
2771
}
2772

    
2773
function interface_get_wireless_clone($wlif) {
2774
	if(!stristr($wlif, "_wlan")) {
2775
		return $wlif . "_wlan0";
2776
	} else {
2777
		return $wlif;
2778
	}
2779
}
2780

    
2781
function get_real_interface($interface = "wan") {
2782
    global $config;
2783

    
2784
	$wanif = NULL;
2785

    
2786
	switch ($interface) {
2787
	case "l2tp":
2788
		$wanif = "l2tp";
2789
		break;
2790
	case "pptp":
2791
		$wanif = "pptp";
2792
		break;
2793
	case "pppoe":
2794
		$wanif = "pppoe";
2795
		break;
2796
	case "openvpn":
2797
		$wanif = "openvpn";
2798
		break;
2799
	case "ipsec":
2800
	case "enc0":
2801
		$wanif = "enc0";
2802
		break;
2803
	case "ppp":
2804
		$wanif = "ppp";
2805
		break;
2806
	default:
2807
		// If a real interface was alread passed simply
2808
		// pass the real interface back.  This encourages
2809
		// the usage of this function in more cases so that
2810
		// we can combine logic for more flexibility.
2811
		if(does_interface_exist($interface)) {
2812
			$wanif = $interface;
2813
			break;
2814
		}
2815
		if (empty($config['interfaces'][$interface]))
2816
			break;
2817

    
2818
		$cfg =& $config['interfaces'][$interface];
2819

    
2820
		// Wireless cloned NIC support (FreeBSD 8+)
2821
		// interface name format: $parentnic_wlanparentnic#
2822
		// example: ath0_wlan0
2823
		if (is_interface_wireless($cfg['if'])) {
2824
			$wanif = interface_get_wireless_clone($cfg['if']);
2825
			break;
2826
		}
2827
		/*
2828
		if (empty($cfg['if'])) {
2829
			$wancfg = $cfg['if'];
2830
			break;
2831
		}
2832
		*/
2833

    
2834
		switch ($cfg['ipaddr']) {
2835
			case "carpdev-dhcp":
2836
				$viparr = &$config['virtualip']['vip'];
2837
				if(is_array($viparr))
2838
				foreach ($viparr as $counter => $vip) {
2839
					if ($vip['mode'] == "carpdev-dhcp") {
2840
						if($vip['interface'] == $interface) {
2841
							$wanif = "carp{$counter}";
2842
							break;
2843
						}
2844
					}
2845
				}
2846
				break;
2847
			case "pppoe": 
2848
			case "pptp": 
2849
			case "l2tp": 
2850
			case "ppp":
2851
				$wanif = $cfg['if'];
2852
				break;
2853
			default:
2854
				$wanif = $cfg['if'];
2855
				break;
2856
		}
2857
		break;
2858
	}
2859

    
2860
    return $wanif;
2861
}
2862

    
2863
/* Guess the physical interface by providing a IP address */
2864
function guess_interface_from_ip($ipaddress) {
2865
	if(! is_ipaddr($ipaddress)) {
2866
		return false;
2867
	}
2868
	/* create a route table we can search */
2869
	exec("netstat -rnWf inet", $output, $ret);
2870
	foreach($output as $line) {
2871
		if(preg_match("/^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\/[0-9]+[ ]+link[#]/", $line)) {
2872
			$fields = preg_split("/[ ]+/", $line);
2873
			if(ip_in_subnet($ipaddress, $fields[0])) {
2874
				return $fields[6];
2875
			}
2876
		}
2877
	}
2878
	$ret = exec_command("/sbin/route -n get {$ipaddress} | /usr/bin/awk '/interface/ { print \$2; };'");
2879
	if(empty($ret)) {
2880
        	return false;
2881
	}
2882
	return $ret;
2883
}
2884

    
2885
/*
2886
 * find_ip_interface($ip): return the interface where an ip is defined
2887
 */
2888
function find_ip_interface($ip)
2889
{
2890
        /* if list */
2891
        $ifdescrs = get_configured_interface_list();
2892

    
2893
        foreach ($ifdescrs as $ifdescr => $ifname) {
2894
		if ($ip == get_interface_ip($ifname)) {
2895
                	$int = get_real_interface($ifname);
2896
			return $int;
2897
		}
2898
        }
2899
        return false;
2900
}
2901

    
2902
/*
2903
 *   find_number_of_created_carp_interfaces: return the number of carp interfaces
2904
 */
2905
function find_number_of_created_carp_interfaces() {
2906
	return `/sbin/ifconfig | grep "carp:" | wc -l`;
2907
}
2908

    
2909
function get_all_carp_interfaces() {
2910
	$ints = str_replace("\n", " ", `ifconfig | grep "carp:" -B2 | grep ": flag" | cut -d: -f1`);
2911
	$ints = explode(" ", $ints);
2912
	return $ints;
2913
}
2914

    
2915
/*
2916
 * find_carp_interface($ip): return the carp interface where an ip is defined
2917
 */
2918
function find_carp_interface($ip) {
2919
	global $config;
2920
	if (is_array($config['virtualip']['vip'])) {
2921
		foreach ($config['virtualip']['vip'] as $vip) {
2922
			if ($vip['mode'] == "carp" || $vip['mode'] == "carpdev") {
2923
				$carp_ip = get_interface_ip($vip['interface']);
2924
				$if = `ifconfig | grep '$ip ' -B1 | head -n1 | cut -d: -f1`;
2925
				if ($if)
2926
					return $if;
2927
			}
2928
		}
2929
	}
2930
}
2931

    
2932
function link_carp_interface_to_parent($interface) {
2933
        global $config;
2934

    
2935
        if ($interface == "")
2936
                return;
2937

    
2938
        $carp_ip = get_interface_ip($interface);
2939
        if (!is_ipaddr($carp_ip))
2940
                return;
2941

    
2942
        /* if list */
2943
        $ifdescrs = get_configured_interface_list();
2944
        foreach ($ifdescrs as $ifdescr => $ifname) {
2945
                $interfaceip = get_interface_ip($ifname);
2946
                $subnet_bits = get_interface_subnet($ifname);
2947
                $subnet_ip = gen_subnet("{$interfaceip}", "{$subnet_bits}");
2948
                if(ip_in_subnet($carp_ip, "{$subnet_ip}/{$subnet_bits}"))
2949
                        return $ifname;
2950
        }
2951

    
2952
        return "";
2953
}
2954

    
2955
/****f* interfaces/link_ip_to_carp_interface
2956
 * NAME
2957
 *   link_ip_to_carp_interface - Find where a CARP interface links to.
2958
 * INPUTS
2959
 *   $ip
2960
 * RESULT
2961
 *   $carp_ints
2962
 ******/
2963
function link_ip_to_carp_interface($ip) {
2964
        global $config;
2965

    
2966
        if (!is_ipaddr($ip))
2967
                return;
2968

    
2969
        $carp_ints = "";
2970
        if (is_array($config['virtualip']['vip'])) {
2971
		$first = 0;
2972
		$carp_int = array();
2973
                foreach ($config['virtualip']['vip'] as $vip) {
2974
                        if ($vip['mode'] == "carp" || $vip['mode'] == "carpdev") {
2975
                                $carp_ip = $vip['subnet'];
2976
                                $carp_sn = $vip['subnet_bits'];
2977
                                $carp_nw = gen_subnet($carp_ip, $carp_sn);
2978
                                if (ip_in_subnet($ip, "{$carp_nw}/{$carp_sn}"))
2979
					$carp_int[] = "vip{$vip['vhid']}";
2980
                        }
2981
                }
2982
		if (!empty($carp_int))
2983
			$carp_ints = implode(" ", array_unique($carp_int));
2984
        }
2985

    
2986
        return $carp_ints;
2987
}
2988

    
2989
function link_interface_to_vlans($int, $action = "") {
2990
	global $config;
2991

    
2992
	if (empty($int))
2993
		return;
2994

    
2995
	if (is_array($config['vlans']['vlan'])) {
2996
                foreach ($config['vlans']['vlan'] as $vlan) {
2997
			if ($int == $vlan['if']) {
2998
				if ($action == "update") {
2999
					interfaces_bring_up($int);
3000
				} else if ($action == "")
3001
					return $vlan;
3002
			}
3003
		}
3004
	}
3005
}
3006

    
3007
function link_interface_to_vips($int, $action = "") {
3008
        global $config;
3009

    
3010
        if (is_array($config['virtualip']['vip']))
3011
                foreach ($config['virtualip']['vip'] as $vip)
3012
                        if ($int == $vip['interface']) {
3013
				if ($action == "update")
3014
					interfaces_vips_configure($int);
3015
				else
3016
                                	return $vip;
3017
			}
3018
}
3019

    
3020
/****f* interfaces/link_interface_to_bridge
3021
 * NAME
3022
 *   link_interface_to_bridge - Finds out a bridge group for an interface
3023
 * INPUTS
3024
 *   $ip
3025
 * RESULT
3026
 *   bridge[0-99]
3027
 ******/
3028
function link_interface_to_bridge($int) {
3029
        global $config;
3030

    
3031
        if (is_array($config['bridges']['bridged'])) {
3032
                foreach ($config['bridges']['bridged'] as $bridge) {
3033
			if (in_array($int, explode(',', $bridge['members'])))
3034
                                return "{$bridge['bridgeif']}";
3035
		}
3036
	}
3037
}
3038

    
3039
function link_interface_to_group($int) {
3040
        global $config;
3041

    
3042
        if (is_array($config['ifgroups']['ifgroupentry'])) {
3043
                foreach ($config['ifgroups']['ifgroupentry'] as $group) {
3044
			if (in_array($int, explode(" ", $groupname['members'])))
3045
                                return "{$group['ifname']}";
3046
		}
3047
	}
3048
}
3049

    
3050
function link_interface_to_gre($interface) {
3051
        global $config;
3052

    
3053
        if (is_array($config['gres']['gre']))
3054
                foreach ($config['gres']['gre'] as $gre)
3055
                        if($gre['if'] == $interface)
3056
                                return $gre;
3057
}
3058

    
3059
function link_interface_to_gif($interface) {
3060
        global $config;
3061

    
3062
        if (is_array($config['gifs']['gif']))
3063
                foreach ($config['gifs']['gif'] as $gif)
3064
                        if($gif['if'] == $interface)
3065
                                return $gif;
3066
}
3067

    
3068
/*
3069
 * find_interface_ip($interface): return the interface ip (first found)
3070
 */
3071
function find_interface_ip($interface, $flush = false)
3072
{
3073
	global $interface_ip_arr_cache;
3074

    
3075
	$interface = str_replace("\n", "", $interface);
3076
	
3077
	if (!does_interface_exist($interface))
3078
		return;
3079

    
3080
	/* Setup IP cache */
3081
	if (!isset($interface_ip_arr_cache[$interface]) or $flush) {
3082
		$ifinfo = pfSense_get_interface_addresses($interface);
3083
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
3084
	}
3085

    
3086
	return $interface_ip_arr_cache[$interface];
3087
}
3088

    
3089
function find_interface_subnet($interface, $flush = false)
3090
{
3091
	global $interface_sn_arr_cache;
3092

    
3093
	$interface = str_replace("\n", "", $interface);
3094
	if (does_interface_exist($interface) == false)
3095
		return;
3096

    
3097
	if (!isset($interface_sn_arr_cache[$interface]) or $flush) {
3098
		$ifinfo = pfSense_get_interface_addresses($interface);
3099
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
3100
        }
3101

    
3102
	return $interface_sn_arr_cache[$interface];
3103
}
3104

    
3105
function ip_in_interface_alias_subnet($interface, $ipalias) {
3106
	global $config;
3107

    
3108
	if (empty($interface) || !is_ipaddr($ipalias))
3109
		return 0;
3110
	if (is_array($config['virtualip']['vip'])) {
3111
                foreach ($config['virtualip']['vip'] as $vip) {
3112
                        switch ($vip['mode']) {
3113
                        case "ipalias":
3114
                                if ($vip['interface'] <> $interface)
3115
                                        continue;
3116
				if (ip_in_subnet($ipalias, gen_subnet($vip['subnet'], $vip['subnet_bits']) . "/" . $vip['subnet_bits']))
3117
					return 1;
3118
                                break;
3119
                        }
3120
                }
3121
	}
3122
}
3123

    
3124
function get_interface_ip($interface = "wan")
3125
{
3126
	$realif = get_real_interface($interface);
3127
	if (!$realif) {
3128
		if (preg_match("/^carp/i", $interface))
3129
			$realif = $interface;
3130
		else if (preg_match("/^vip/i", $interface))
3131
			$realif = $interface;
3132
		else
3133
			return null;
3134
	}
3135

    
3136
	$curip = find_interface_ip($realif);
3137
	if ($curip && is_ipaddr($curip) && ($curip != "0.0.0.0"))
3138
		return $curip;
3139
	else
3140
		return null;
3141
}
3142

    
3143
function get_interface_subnet($interface = "wan")
3144
{
3145
	$realif = get_real_interface($interface);
3146
	if (!$realif) {
3147
                if (preg_match("/^carp/i", $interface))
3148
                        $realif = $interface;
3149
                else if (preg_match("/^vip/i", $interface))
3150
                        $realif = $interface;
3151
                else
3152
                        return null;
3153
        }
3154

    
3155
	$cursn = find_interface_subnet($realif);
3156
	if (!empty($cursn))
3157
		return $cursn;
3158

    
3159
	return null;
3160
}
3161

    
3162
/* return outside interfaces with a gateway */
3163
function get_interfaces_with_gateway() {
3164
	global $config;
3165

    
3166
	$ints = array();
3167

    
3168
	/* loop interfaces, check config for outbound */
3169
	foreach($config['interfaces'] as $ifdescr => $ifname) {
3170
		if (substr($ifdescr, 0, 5) ==  "ovpnc")
3171
			return true;
3172

    
3173
		switch ($ifname['ipaddr']) {
3174
			case "dhcp":
3175
			case "carpdev-dhcp":
3176
			case "ppp";
3177
			case "pppoe":
3178
			case "pptp":
3179
			case "l2tp":
3180
			case "ppp";
3181
				$ints[$ifdescr] = $ifdescr;
3182
			break;
3183
			default:
3184
				if (!empty($ifname['gateway']))
3185
					$ints[$ifdescr] = $ifdescr;
3186
			break;
3187
		}
3188
	}
3189
	return $ints;
3190
}
3191

    
3192
/* return true if interface has a gateway */
3193
function interface_has_gateway($friendly) {
3194
	global $config;
3195

    
3196
	if (!empty($config['interfaces'][$friendly])) {
3197
		if (substr($friendly, 0, 5) ==  "ovpnc")
3198
			return true;
3199
		$ifname =& $config['interfaces'][$friendly];
3200
		switch ($ifname['ipaddr']) {
3201
			case "dhcp":
3202
			case "carpdev-dhcp":
3203
			case "pppoe":
3204
			case "pptp":
3205
			case "l2tp":
3206
			case "ppp";
3207
				return true;
3208
			break;
3209
			default:
3210
				if (!empty($ifname['gateway']))
3211
					return true;
3212
			break;
3213
		}
3214
	}
3215

    
3216
	return false;
3217
}
3218

    
3219
/****f* interfaces/is_altq_capable
3220
 * NAME
3221
 *   is_altq_capable - Test if interface is capable of using ALTQ
3222
 * INPUTS
3223
 *   $int            - string containing interface name
3224
 * RESULT
3225
 *   boolean         - true or false
3226
 ******/
3227

    
3228
function is_altq_capable($int) {
3229
        /* Per:
3230
         * http://www.freebsd.org/cgi/man.cgi?query=altq&manpath=FreeBSD+7.2-current&format=html
3231
         * Only the following drivers have ALTQ support
3232
         */
3233
	$capable = array("age", "ale", "an", "ath", "aue", "awi", "bce",
3234
			"bfe", "bge", "dc", "de", "ed", "em", "ep", "fxp", "gem",
3235
			"hme", "igb", "ipw", "iwi", "jme", "le", "msk", "mxge", "my", "nfe",
3236
			"npe", "nve", "ral", "re", "rl", "rum", "run", "bwn", "sf", "sis", "sk",
3237
			"ste", "stge", "txp", "udav", "ural", "vge", "vr", "wi", "xl",
3238
			"ndis", "tun", "ovpns", "ovpnc", "vlan", "pppoe", "pptp", "ng",
3239
			"l2tp", "ppp");
3240

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

    
3243
        if (in_array($int_family[0], $capable))
3244
                return true;
3245
	else if (stristr($int_family, "vlan")) /* VLANs are name $parent_$vlan now */
3246
		return true;
3247
	else if (stristr($int_family, "_wlan")) /* WLANs are name $parent_$wlan now */
3248
		return true;
3249
        else
3250
                return false;
3251
}
3252

    
3253
/****f* interfaces/is_interface_wireless
3254
 * NAME
3255
 *   is_interface_wireless - Returns if an interface is wireless
3256
 * RESULT
3257
 *   $tmp       - Returns if an interface is wireless
3258
 ******/
3259
function is_interface_wireless($interface) {
3260
        global $config, $g;
3261

    
3262
        $friendly = convert_real_interface_to_friendly_interface_name($interface);
3263
        if(!isset($config['interfaces'][$friendly]['wireless'])) {
3264
                if (preg_match($g['wireless_regex'], $interface)) {
3265
                        if (isset($config['interfaces'][$friendly]))
3266
                                $config['interfaces'][$friendly]['wireless'] = array();
3267
                        return true;
3268
                }
3269
                return false;
3270
        } else
3271
                return true;
3272
}
3273

    
3274
function get_wireless_modes($interface) {
3275
	/* return wireless modes and channels */
3276
	$wireless_modes = array();
3277

    
3278
	$wlif = interface_translate_type_to_real($interface);
3279

    
3280
	if(is_interface_wireless($wlif)) {
3281
		$cloned_interface = get_real_interface($interface);
3282
		$chan_list = "/sbin/ifconfig {$cloned_interface} list chan";
3283
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
3284
		$format_list = "/usr/bin/awk '{print \$5 \" \" \$6 \",\" \$1}'";
3285

    
3286
		$interface_channels = "";
3287
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
3288
		$interface_channel_count = count($interface_channels);
3289

    
3290
		$c = 0;
3291
		while ($c < $interface_channel_count)
3292
		{
3293
			$channel_line = explode(",", $interface_channels["$c"]);
3294
			$wireless_mode = trim($channel_line[0]);
3295
			$wireless_channel = trim($channel_line[1]);
3296
			if(trim($wireless_mode) != "") {
3297
				/* if we only have 11g also set 11b channels */
3298
				if($wireless_mode == "11g") {
3299
					if(!isset($wireless_modes["11b"]))
3300
						$wireless_modes["11b"] = array();
3301
				} else if($wireless_mode == "11g ht") {
3302
					if(!isset($wireless_modes["11b"]))
3303
						$wireless_modes["11b"] = array();
3304
					if(!isset($wireless_modes["11g"]))
3305
						$wireless_modes["11g"] = array();
3306
					$wireless_mode = "11ng";
3307
				} else if($wireless_mode == "11a ht") {
3308
					if(!isset($wireless_modes["11a"]))
3309
						$wireless_modes["11a"] = array();
3310
					$wireless_mode = "11na";
3311
				}
3312
				$wireless_modes["$wireless_mode"]["$c"] = $wireless_channel;
3313
			}
3314
			$c++;
3315
		}
3316
	}
3317
	return($wireless_modes);
3318
}
3319

    
3320
/* return channel numbers, frequency, max txpower, and max regulation txpower */
3321
function get_wireless_channel_info($interface) {
3322
	$wireless_channels = array();
3323

    
3324
	$wlif = interface_translate_type_to_real($interface);
3325

    
3326
	if(is_interface_wireless($wlif)) {
3327
		$cloned_interface = get_real_interface($interface);
3328
		$chan_list = "/sbin/ifconfig {$cloned_interface} list txpower";
3329
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
3330
		$format_list = "/usr/bin/awk '{print \$1 \",\" \$3 \" \" \$4 \",\" \$5 \",\" \$7}'";
3331

    
3332
		$interface_channels = "";
3333
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
3334

    
3335
		foreach ($interface_channels as $channel_line) {
3336
			$channel_line = explode(",", $channel_line);
3337
			if(!isset($wireless_channels[$channel_line[0]]))
3338
				$wireless_channels[$channel_line[0]] = $channel_line;
3339
		}
3340
	}
3341
	return($wireless_channels);
3342
}
3343

    
3344
/****f* interfaces/get_interface_mtu
3345
 * NAME
3346
 *   get_interface_mtu - Return the mtu of an interface
3347
 * RESULT
3348
 *   $tmp       - Returns the mtu of an interface
3349
 ******/
3350
function get_interface_mtu($interface) {
3351
        $mtu = pfSense_get_interface_addresses($interface);
3352
        return $mtu['mtu'];
3353
}
3354

    
3355
function get_interface_mac($interface) {
3356

    
3357
	$macinfo = pfSense_get_interface_addresses($interface);
3358
	return $macinfo["macaddr"];
3359
}
3360

    
3361
/****f* pfsense-utils/generate_random_mac_address
3362
 * NAME
3363
 *   generate_random_mac - generates a random mac address
3364
 * INPUTS
3365
 *   none
3366
 * RESULT
3367
 *   $mac - a random mac address
3368
 ******/
3369
function generate_random_mac_address() {
3370
        $mac = "02";
3371
        for($x=0; $x<5; $x++)
3372
                $mac .= ":" . dechex(rand(16, 255));
3373
        return $mac;
3374
}
3375

    
3376
/****f* interfaces/is_jumbo_capable
3377
 * NAME
3378
 *   is_jumbo_capable - Test if interface is jumbo frame capable.  Useful for determining VLAN capability.
3379
 * INPUTS
3380
 *   $int             - string containing interface name
3381
 * RESULT
3382
 *   boolean          - true or false
3383
 ******/
3384
function is_jumbo_capable($int) {
3385
        global $g;
3386

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

    
3389
        if (in_array($int_family[0], $g['vlan_long_frame']))
3390
                return true;
3391
        else
3392
                return false;
3393
}
3394

    
3395
function setup_pppoe_reset_file($pppif, $iface="") {
3396
	global $g;
3397
	$cron_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
3398

    
3399
	if(!empty($iface) && !empty($pppif)){
3400
		$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";
3401
		file_put_contents($cron_file, $cron_cmd);
3402
		chmod($cron_file, 0700);
3403
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
3404
	} else
3405
		unlink_if_exists($cron_file);
3406
}
3407

    
3408
?>
(22-22/54)