Project

General

Profile

Download (96.3 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 {
717
			if ($g['booting'])
718
				echo "Configuring {$ifname} interface...";
719
			if($g['debug'])
720
				log_error("Configuring {$ifname}");
721
			interface_configure($if, $reload);
722
			if ($g['booting']) 
723
				echo "done.\n";
724
		}
725
	}
726

    
727
	/* create the unconfigured wireless clones */
728
	interfaces_create_wireless_clones();
729

    
730
	/* set up GRE virtual interfaces */
731
	interfaces_gre_configure();
732

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

    
742
		interface_configure($if, $reload);
743

    
744
		if ($g['booting'])
745
			echo "done.\n";
746
	}
747

    
748
	/* set up BRIDGe virtual interfaces */
749
	interfaces_bridge_configure();
750

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

    
757
		interface_configure($if, $reload);
758

    
759
		if ($g['booting'])
760
			echo "done.\n";
761
	}
762

    
763
	/* bring up vip interfaces */
764
	interfaces_vips_configure();
765

    
766
	/* configure interface groups */
767
	interfaces_group_setup();
768

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

    
773
		/* reload IPsec tunnels */
774
		vpn_ipsec_configure();
775

    
776
		/* reload dhcpd (interface enabled/disabled status may have changed) */
777
		services_dhcpd_configure();
778

    
779
		/* restart dnsmasq */
780
		services_dnsmasq_configure();
781

    
782
		/* reload captive portal */
783
		captiveportal_init_rules();
784

    
785
		/* set the reload filter dity flag */
786
		filter_configure();
787
	}
788

    
789
	return 0;
790
}
791

    
792
function interface_reconfigure($interface = "wan") {
793
	interface_bring_down($interface);
794
	interface_configure($interface, true);
795
}
796

    
797
function interface_vip_bring_down($vip) {
798
	global $g;
799

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

    
824
function interface_bring_down($interface = "wan", $destroy = false) {
825
	global $config, $g;
826

    
827
	if (!isset($config['interfaces'][$interface]))
828
		return; 
829

    
830
	$ifcfg = $config['interfaces'][$interface];
831

    
832
	$realif = get_real_interface($interface);
833

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

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

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

    
898
	return;
899
}
900

    
901
function interfaces_ptpid_used($ptpid) {
902
	global $config;
903

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

    
909
	return false;
910
}
911

    
912
function interfaces_ptpid_next() {
913

    
914
	$ptpid = 0;
915
	while(interfaces_ptpid_used($ptpid))
916
		$ptpid++;
917

    
918
	return $ptpid;
919
}
920

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

    
935
function handle_pppoe_reset($post_array) {
936
	global $config, $g;
937

    
938
	$cron_cmd_file = "{$g['varetc_path']}/pppoe_restart_";
939

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1210
EOD;
1211

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

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

    
1225
EOD;
1226

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

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

    
1237
EOD;
1238

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

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

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

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

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

    
1265
EOD;
1266

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

    
1271
EOD;
1272

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

    
1277
EOD;
1278

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

    
1284
EOD;
1285

    
1286

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

    
1291
EOD;
1292

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

    
1298
EOD;
1299

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

    
1304
EOD;
1305

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

    
1310
EOD;
1311

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

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

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

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

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

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

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

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

    
1365
EOD;
1366

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

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

    
1379

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

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

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

    
1420
	return 1;
1421
}
1422

    
1423
function interfaces_carp_setup() {
1424
	global $g, $config;
1425

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

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

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

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

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

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

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

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

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

    
1501
	$cmdchain->execute();
1502
	$cmdchain->clear();
1503

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

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

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

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

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

    
1532
				if (!is_array($paa[$if]))
1533
					$paa[$proxyif] = array();
1534

    
1535
				$paa[$proxyif][] = $vipent;
1536
			}
1537
		}
1538
	}
1539

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

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

    
1616
function interface_ipalias_configure(&$vip) {
1617

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

    
1624
function interface_reload_carps($cif) {
1625
	global $config;
1626

    
1627
	$carpifs = link_ip_to_carp_interface(find_interface_ip($cif));
1628
	if (empty($carpifs))
1629
		return;
1630

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

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

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

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

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

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

    
1687
	/* Ensure CARP IP really exists prior to loading up. */
1688
	$ww_subnet_ip = find_interface_ip($realif);
1689
	$ww_subnet_bits = find_interface_subnet($realif);
1690
	if (!ip_in_subnet($vip['subnet'], gen_subnet($ww_subnet_ip, $ww_subnet_bits) . "/" . $ww_subnet_bits)) {
1691
		file_notice("CARP", "Sorry but we could not find a matching real interface subnet for the virtual IP address {$vip['subnet']}.", "Firewall: Virtual IP", "");
1692
		return;
1693
	}
1694

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

    
1704
	/* invalidate interface cache */
1705
	get_interface_arr(true);
1706

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

    
1710
	interfaces_bring_up($vipif);
1711
	
1712
	return $vipif;
1713
}
1714

    
1715
function interface_carpdev_configure(&$vip) {
1716
	global $g;
1717

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

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

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

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

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

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

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

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

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

    
1776
EOD;
1777

    
1778
		fwrite($fd, $dhclientconf);
1779
		fclose($fd);
1780

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

    
1788
	return $vipif;
1789
}
1790

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

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

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

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

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

    
1861
	if(!is_interface_wireless($ifcfg['if']))
1862
		return;
1863

    
1864
	$baseif = interface_get_wireless_base($ifcfg['if']);
1865

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

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

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

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

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

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

    
1936
	// Clone wireless nic if needed.
1937
	interface_wireless_clone($if, $wl);
1938

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2088
	mwexec(kill_hostapd("{$if}"));
2089
	mwexec(kill_wpasupplicant("{$if}"));
2090

    
2091
	/* generate wpa_supplicant/hostap config if wpa is enabled */
2092
	conf_mount_rw();
2093

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

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

    
2148
EOD;
2149

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

    
2156
EOD;
2157

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

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

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

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

    
2179
			}
2180
			break;
2181
	}
2182

    
2183
	/*
2184
	 *    all variables are set, lets start up everything
2185
	 */
2186

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

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

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

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

    
2214
	fclose($fd_set);
2215
	conf_mount_ro();
2216

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

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

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

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

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

    
2250
		$wlregcmd_args = implode(" ", $wlregcmd);
2251

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

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

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

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

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

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

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

    
2295
	return 0;
2296

    
2297
}
2298

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

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

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

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

    
2318
	$wancfg = $config['interfaces'][$interface];
2319

    
2320
	$realif = get_real_interface($interface);
2321

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2483
		unset($bridgetmp);
2484
		$bridgetmp = link_interface_to_bridge($interface);
2485
		if (!empty($bridgetmp))
2486
			interface_bridge_add_member($bridgetmp, $realif);
2487

    
2488
		link_interface_to_vips($interface, "update");
2489

    
2490
		if ($interface == "lan")
2491
			/* make new hosts file */
2492
			system_hosts_generate();
2493

    
2494
		if ($reloadall == true) {
2495

    
2496
			/* reconfigure static routes (kernel may have deleted them) */
2497
			system_routing_configure($interface);
2498

    
2499
			/* reload ipsec tunnels */
2500
			vpn_ipsec_configure();
2501

    
2502
			/* update dyndns */
2503
			services_dyndns_configure($interface);
2504

    
2505
			/* force DNS update */
2506
			services_dnsupdate_process($interface);
2507

    
2508
			/* restart dnsmasq */
2509
			services_dnsmasq_configure();
2510

    
2511
			/* reload captive portal */
2512
			captiveportal_init_rules();
2513

    
2514
			/* set the reload filter dity flag */
2515
			filter_configure();
2516
		}
2517
	}
2518

    
2519
	return 0;
2520
}
2521

    
2522
function interface_carpdev_dhcp_configure($interface = "wan") {
2523
	global $config, $g;
2524

    
2525
	$wancfg = $config['interfaces'][$interface];
2526
	$wanif = $wancfg['if'];
2527
	/* bring wan interface up before starting dhclient */
2528
	if($wanif)
2529
		interfaces_bring_up($wanif);
2530
	else 
2531
		log_error("Could not bring wanif up in terface_carpdev_dhcp_configure()");
2532

    
2533
	return 0;
2534
}
2535

    
2536
function interface_dhcp_configure($interface = "wan") {
2537
	global $config, $g;
2538

    
2539
	$wancfg = $config['interfaces'][$interface];
2540
	if (empty($wancfg))
2541
		$wancfg = array();
2542

    
2543
	/* generate dhclient_wan.conf */
2544
	$fd = fopen("{$g['varetc_path']}/dhclient_{$interface}.conf", "w");
2545
	if (!$fd) {
2546
		printf("Error: cannot open dhclient_{$interface}.conf in interfaces_wan_dhcp_configure() for writing.\n");
2547
		return 1;
2548
	}
2549

    
2550
	if ($wancfg['dhcphostname']) {
2551
		$dhclientconf_hostname = "send dhcp-client-identifier \"{$wancfg['dhcphostname']}\";\n";
2552
		$dhclientconf_hostname .= "\tsend host-name \"{$wancfg['dhcphostname']}\";\n";
2553
	} else {
2554
		$dhclientconf_hostname = "";
2555
	}
2556

    
2557
	$wanif = get_real_interface($interface);
2558
	if (empty($wanif)) {
2559
		log_error("Invalid interface \"{$interface}\" in interface_dhcp_configure()");
2560
		return 0;
2561
	}
2562
 	$dhclientconf = "";
2563
	
2564
	$dhclientconf .= <<<EOD
2565
interface "{$wanif}" {
2566
timeout 60;
2567
retry 1;
2568
select-timeout 0;
2569
initial-interval 1;
2570
	{$dhclientconf_hostname}
2571
	script "/sbin/dhclient-script";
2572
}
2573

    
2574
EOD;
2575

    
2576
if(is_ipaddr($wancfg['alias-address'])) {
2577
	$subnetmask = gen_subnet_mask($wancfg['alias-subnet']);
2578
	$dhclientconf .= <<<EOD
2579
alias {
2580
	interface  "{$wanif}";
2581
	fixed-address {$wancfg['alias-address']};
2582
	option subnet-mask {$subnetmask};
2583
}
2584

    
2585
EOD;
2586
}
2587
	fwrite($fd, $dhclientconf);
2588
	fclose($fd);
2589

    
2590
	/* bring wan interface up before starting dhclient */
2591
	if($wanif)
2592
		interfaces_bring_up($wanif);
2593
	else 
2594
		log_error("Could not bring up {$wanif} interface in interface_dhcp_configure()");
2595

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

    
2599
	return 0;
2600
}
2601

    
2602
function interfaces_group_setup() {
2603
	global $config;
2604

    
2605
	if (!is_array($config['ifgroups']['ifgroupentry']))
2606
		return;
2607

    
2608
	foreach ($config['ifgroups']['ifgroupentry'] as $groupar)
2609
		interface_group_setup($groupar);
2610

    
2611
	return;
2612
}
2613

    
2614
function interface_group_setup(&$groupname /* The parameter is an array */) {
2615
	global $config;
2616

    
2617
	if (!is_array($groupname))
2618
		return;
2619
	$members = explode(" ", $groupname['members']);
2620
	foreach($members as $ifs) {
2621
		$realif = get_real_interface($ifs);
2622
		if ($realif)
2623
			mwexec("/sbin/ifconfig {$realif} group {$groupname['ifname']}");
2624
	}
2625

    
2626
	return;
2627
}
2628
 
2629
/* COMPAT Function */
2630
function convert_friendly_interface_to_real_interface_name($interface) {
2631
	return get_real_interface($interface);
2632
}
2633

    
2634
/* COMPAT Function */
2635
function get_real_wan_interface($interface = "wan") {
2636
	return get_real_interface($interface);
2637
}
2638

    
2639
/* COMPAT Function */
2640
function get_current_wan_address($interface = "wan") {
2641
	return get_interface_ip($interface);
2642
}
2643

    
2644
/*
2645
 * convert_real_interface_to_friendly_interface_name($interface): convert fxp0 -> wan, etc.
2646
 */
2647
function convert_real_interface_to_friendly_interface_name($interface = "wan") {
2648
        global $config;
2649

    
2650
	if (stristr($interface, "vip")) {
2651
                $index = intval(substr($interface, 3));
2652
                foreach ($config['virtualip']['vip'] as $counter => $vip) {
2653
                        if ($vip['mode'] == "carpdev-dhcp" || $vip['mode'] == "carp")  {
2654
                                if ($index == $counter)
2655
                                        return $vip['interface'];
2656
                        }
2657
                }
2658
        }
2659

    
2660
        /* XXX: For speed reasons reference directly the interface array */
2661
	$ifdescrs =& $config['interfaces'];
2662
        //$ifdescrs = get_configured_interface_list(false, true);
2663

    
2664
        foreach ($ifdescrs as $if => $ifname) {
2665
                if ($config['interfaces'][$if]['if'] == $interface)
2666
                        return $if;
2667

    
2668
                if (get_real_interface($if) == $interface)
2669
                        return $if;
2670

    
2671
                $int = interface_translate_type_to_real($if);
2672
                if ($int == $interface)
2673
                        return $ifname;
2674
        }
2675
        return NULL;
2676
}
2677

    
2678
/* attempt to resolve interface to friendly descr */
2679
function convert_friendly_interface_to_friendly_descr($interface) {
2680
        global $config;
2681

    
2682
        switch ($interface) {
2683
                case "l2tp":
2684
                                $ifdesc = "L2TP";
2685
                                break;
2686
                case "pptp":
2687
                                $ifdesc = "PPTP";
2688
                                break;
2689
                case "pppoe":
2690
                                $ifdesc = "PPPoE";
2691
                                break;
2692
                case "openvpn":
2693
                                $ifdesc = "OpenVPN";
2694
                                break;
2695
                case "enc0":
2696
                        case "ipsec":
2697
                                $ifdesc = "IPsec";
2698
                                break;
2699
        default:
2700
                if (isset($config['interfaces'][$interface])) {
2701
                        if (empty($config['interfaces'][$interface]['descr']))
2702
                                $ifdesc = strtoupper($interface);
2703
                        else
2704
                                $ifdesc = strtoupper($config['interfaces'][$interface]['descr']);
2705
			break;
2706
		}
2707
                /* if list */
2708
                $ifdescrs = get_configured_interface_with_descr(false, true);
2709
                foreach ($ifdescrs as $if => $ifname) {
2710
                                if ($if == $interface || $ifname == $interface)
2711
                                        return $ifname;
2712
                }
2713
                break;
2714
        }
2715

    
2716
        return $ifdesc;
2717
}
2718

    
2719
function convert_real_interface_to_friendly_descr($interface) {
2720
        global $config;
2721

    
2722
        $ifdesc = convert_real_interface_to_friendly_interface_name("{$interface}");
2723

    
2724
        if ($ifdesc) {
2725
                $iflist = get_configured_interface_with_descr(false, true);
2726
                return $iflist[$ifdesc];
2727
        }
2728

    
2729
        return $interface;
2730
}
2731

    
2732
/*
2733
 *  interface_translate_type_to_real($interface):
2734
 *              returns the real hardware interface name for a friendly interface.  ie: wan
2735
 */
2736
function interface_translate_type_to_real($interface) {
2737
        global $config;
2738

    
2739
        if ($config['interfaces'][$interface]['if'] <> "")
2740
                return $config['interfaces'][$interface]['if'];
2741
        else
2742
		return $interface;
2743
}
2744

    
2745
function interface_is_wireless_clone($wlif) {
2746
	if(!stristr($wlif, "_wlan")) {
2747
		return false;
2748
	} else {
2749
		return true;
2750
	}
2751
}
2752

    
2753
function interface_get_wireless_base($wlif) {
2754
	if(!stristr($wlif, "_wlan")) {
2755
		return $wlif;
2756
	} else {
2757
		return substr($wlif, 0, stripos($wlif, "_wlan"));
2758
	}
2759
}
2760

    
2761
function interface_get_wireless_clone($wlif) {
2762
	if(!stristr($wlif, "_wlan")) {
2763
		return $wlif . "_wlan0";
2764
	} else {
2765
		return $wlif;
2766
	}
2767
}
2768

    
2769
function get_real_interface($interface = "wan") {
2770
    global $config;
2771

    
2772
	$wanif = NULL;
2773

    
2774
	switch ($interface) {
2775
	case "l2tp":
2776
		$wanif = "l2tp";
2777
		break;
2778
	case "pptp":
2779
		$wanif = "pptp";
2780
		break;
2781
	case "pppoe":
2782
		$wanif = "pppoe";
2783
		break;
2784
	case "openvpn":
2785
		$wanif = "openvpn";
2786
		break;
2787
	case "ipsec":
2788
	case "enc0":
2789
		$wanif = "enc0";
2790
		break;
2791
	case "ppp":
2792
		$wanif = "ppp";
2793
		break;
2794
	default:
2795
		// If a real interface was alread passed simply
2796
		// pass the real interface back.  This encourages
2797
		// the usage of this function in more cases so that
2798
		// we can combine logic for more flexibility.
2799
		if(does_interface_exist($interface)) {
2800
			$wanif = $interface;
2801
			break;
2802
		}
2803
		if (empty($config['interfaces'][$interface]))
2804
			break;
2805

    
2806
		$cfg =& $config['interfaces'][$interface];
2807

    
2808
		// Wireless cloned NIC support (FreeBSD 8+)
2809
		// interface name format: $parentnic_wlanparentnic#
2810
		// example: ath0_wlan0
2811
		if (is_interface_wireless($cfg['if'])) {
2812
			$wanif = interface_get_wireless_clone($cfg['if']);
2813
			break;
2814
		}
2815
		/*
2816
		if (empty($cfg['if'])) {
2817
			$wancfg = $cfg['if'];
2818
			break;
2819
		}
2820
		*/
2821

    
2822
		switch ($cfg['ipaddr']) {
2823
			case "carpdev-dhcp":
2824
				$viparr = &$config['virtualip']['vip'];
2825
				if(is_array($viparr))
2826
				foreach ($viparr as $counter => $vip) {
2827
					if ($vip['mode'] == "carpdev-dhcp") {
2828
						if($vip['interface'] == $interface) {
2829
							$wanif = "carp{$counter}";
2830
							break;
2831
						}
2832
					}
2833
				}
2834
				break;
2835
			case "pppoe": 
2836
			case "pptp": 
2837
			case "l2tp": 
2838
			case "ppp":
2839
				$wanif = $cfg['if'];
2840
				break;
2841
			default:
2842
				$wanif = $cfg['if'];
2843
				break;
2844
		}
2845
		break;
2846
	}
2847

    
2848
    return $wanif;
2849
}
2850

    
2851
/* Guess the physical interface by providing a IP address */
2852
function guess_interface_from_ip($ipaddress) {
2853
	if(! is_ipaddr($ipaddress)) {
2854
		return false;
2855
	}
2856
	/* create a route table we can search */
2857
	exec("netstat -rnWf inet", $output, $ret);
2858
	foreach($output as $line) {
2859
		if(preg_match("/^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\/[0-9]+[ ]+link[#]/", $line)) {
2860
			$fields = preg_split("/[ ]+/", $line);
2861
			if(ip_in_subnet($ipaddress, $fields[0])) {
2862
				return $fields[6];
2863
			}
2864
		}
2865
	}
2866
	$ret = exec_command("/sbin/route -n get {$ipaddress} | /usr/bin/awk '/interface/ { print \$2; };'");
2867
	if(empty($ret)) {
2868
        	return false;
2869
	}
2870
	return $ret;
2871
}
2872

    
2873
/*
2874
 * find_ip_interface($ip): return the interface where an ip is defined
2875
 */
2876
function find_ip_interface($ip)
2877
{
2878
        /* if list */
2879
        $ifdescrs = get_configured_interface_list();
2880

    
2881
        foreach ($ifdescrs as $ifdescr => $ifname) {
2882
		if ($ip == get_interface_ip($ifname)) {
2883
                	$int = get_real_interface($ifname);
2884
			return $int;
2885
		}
2886
        }
2887
        return false;
2888
}
2889

    
2890
/*
2891
 *   find_number_of_created_carp_interfaces: return the number of carp interfaces
2892
 */
2893
function find_number_of_created_carp_interfaces() {
2894
	return `/sbin/ifconfig | grep "carp:" | wc -l`;
2895
}
2896

    
2897
function get_all_carp_interfaces() {
2898
	$ints = str_replace("\n", " ", `ifconfig | grep "carp:" -B2 | grep ": flag" | cut -d: -f1`);
2899
	$ints = explode(" ", $ints);
2900
	return $ints;
2901
}
2902

    
2903
/*
2904
 * find_carp_interface($ip): return the carp interface where an ip is defined
2905
 */
2906
function find_carp_interface($ip) {
2907
	global $config;
2908
	if (is_array($config['virtualip']['vip'])) {
2909
		foreach ($config['virtualip']['vip'] as $vip) {
2910
			if ($vip['mode'] == "carp" || $vip['mode'] == "carpdev") {
2911
				$carp_ip = get_interface_ip($vip['interface']);
2912
				$if = `ifconfig | grep '$ip ' -B1 | head -n1 | cut -d: -f1`;
2913
				if ($if)
2914
					return $if;
2915
			}
2916
		}
2917
	}
2918
}
2919

    
2920
function link_carp_interface_to_parent($interface) {
2921
        global $config;
2922

    
2923
        if ($interface == "")
2924
                return;
2925

    
2926
        $carp_ip = get_interface_ip($interface);
2927
        if (!is_ipaddr($carp_ip))
2928
                return;
2929

    
2930
        /* if list */
2931
        $ifdescrs = get_configured_interface_list();
2932
        foreach ($ifdescrs as $ifdescr => $ifname) {
2933
                $interfaceip = get_interface_ip($ifname);
2934
                $subnet_bits = get_interface_subnet($ifname);
2935
                $subnet_ip = gen_subnet("{$interfaceip}", "{$subnet_bits}");
2936
                if(ip_in_subnet($carp_ip, "{$subnet_ip}/{$subnet_bits}"))
2937
                        return $ifname;
2938
        }
2939

    
2940
        return "";
2941
}
2942

    
2943
/****f* interfaces/link_ip_to_carp_interface
2944
 * NAME
2945
 *   link_ip_to_carp_interface - Find where a CARP interface links to.
2946
 * INPUTS
2947
 *   $ip
2948
 * RESULT
2949
 *   $carp_ints
2950
 ******/
2951
function link_ip_to_carp_interface($ip) {
2952
        global $config;
2953

    
2954
        if (!is_ipaddr($ip))
2955
                return;
2956

    
2957
        $carp_ints = "";
2958
        if (is_array($config['virtualip']['vip'])) {
2959
		$first = 0;
2960
		$carp_int = array();
2961
                foreach ($config['virtualip']['vip'] as $vip) {
2962
                        if ($vip['mode'] == "carp" || $vip['mode'] == "carpdev") {
2963
                                $carp_ip = $vip['subnet'];
2964
                                $carp_sn = $vip['subnet_bits'];
2965
                                $carp_nw = gen_subnet($carp_ip, $carp_sn);
2966
                                if (ip_in_subnet($ip, "{$carp_nw}/{$carp_sn}"))
2967
					$carp_int[] = "vip{$vip['vhid']}";
2968
                        }
2969
                }
2970
		if (!empty($carp_int))
2971
			$carp_ints = implode(" ", array_unique($carp_int));
2972
        }
2973

    
2974
        return $carp_ints;
2975
}
2976

    
2977
function link_interface_to_vlans($int, $action = "") {
2978
	global $config;
2979

    
2980
	if (empty($int))
2981
		return;
2982

    
2983
	if (is_array($config['vlans']['vlan'])) {
2984
                foreach ($config['vlans']['vlan'] as $vlan) {
2985
			if ($int == $vlan['if']) {
2986
				if ($action == "update") {
2987
					interfaces_bring_up($int);
2988
				} else if ($action == "")
2989
					return $vlan;
2990
			}
2991
		}
2992
	}
2993
}
2994

    
2995
function link_interface_to_vips($int, $action = "") {
2996
        global $config;
2997

    
2998
        if (is_array($config['virtualip']['vip']))
2999
                foreach ($config['virtualip']['vip'] as $vip)
3000
                        if ($int == $vip['interface']) {
3001
				if ($action == "update")
3002
					interfaces_vips_configure($int);
3003
				else
3004
                                	return $vip;
3005
			}
3006
}
3007

    
3008
/****f* interfaces/link_interface_to_bridge
3009
 * NAME
3010
 *   link_interface_to_bridge - Finds out a bridge group for an interface
3011
 * INPUTS
3012
 *   $ip
3013
 * RESULT
3014
 *   bridge[0-99]
3015
 ******/
3016
function link_interface_to_bridge($int) {
3017
        global $config;
3018

    
3019
        if (is_array($config['bridges']['bridged'])) {
3020
                foreach ($config['bridges']['bridged'] as $bridge) {
3021
			if (in_array($int, explode(',', $bridge['members'])))
3022
                                return "{$bridge['bridgeif']}";
3023
		}
3024
	}
3025
}
3026

    
3027
function link_interface_to_gre($interface) {
3028
        global $config;
3029

    
3030
        if (is_array($config['gres']['gre']))
3031
                foreach ($config['gres']['gre'] as $gre)
3032
                        if($gre['if'] == $interface)
3033
                                return $gre;
3034
}
3035

    
3036
function link_interface_to_gif($interface) {
3037
        global $config;
3038

    
3039
        if (is_array($config['gifs']['gif']))
3040
                foreach ($config['gifs']['gif'] as $gif)
3041
                        if($gif['if'] == $interface)
3042
                                return $gif;
3043
}
3044

    
3045
/*
3046
 * find_interface_ip($interface): return the interface ip (first found)
3047
 */
3048
function find_interface_ip($interface, $flush = false)
3049
{
3050
	global $interface_ip_arr_cache;
3051

    
3052
	$interface = str_replace("\n", "", $interface);
3053
	
3054
	if (!does_interface_exist($interface))
3055
		return;
3056

    
3057
	/* Setup IP cache */
3058
	if (!isset($interface_ip_arr_cache[$interface]) or $flush) {
3059
		$ifinfo = pfSense_get_interface_addresses($interface);
3060
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
3061
	}
3062

    
3063
	return $interface_ip_arr_cache[$interface];
3064
}
3065

    
3066
function find_interface_subnet($interface, $flush = false)
3067
{
3068
	global $interface_sn_arr_cache;
3069

    
3070
	$interface = str_replace("\n", "", $interface);
3071
	if (does_interface_exist($interface) == false)
3072
		return;
3073

    
3074
	if (!isset($interface_sn_arr_cache[$interface]) or $flush) {
3075
		$ifinfo = pfSense_get_interface_addresses($interface);
3076
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
3077
        }
3078

    
3079
	return $interface_sn_arr_cache[$interface];
3080
}
3081

    
3082
function get_interface_ip($interface = "wan")
3083
{
3084
	$realif = get_real_interface($interface);
3085
	if (!$realif) {
3086
		if (preg_match("/^carp/i", $interface))
3087
			$realif = $interface;
3088
		else if (preg_match("/^vip/i", $interface))
3089
			$realif = $interface;
3090
		else
3091
			return null;
3092
	}
3093

    
3094
	$curip = find_interface_ip($realif);
3095
	if ($curip && is_ipaddr($curip) && ($curip != "0.0.0.0"))
3096
		return $curip;
3097
	else
3098
		return null;
3099
}
3100

    
3101
function get_interface_subnet($interface = "wan")
3102
{
3103
	$realif = get_real_interface($interface);
3104
	if (!$realif) {
3105
                if (preg_match("/^carp/i", $interface))
3106
                        $realif = $interface;
3107
                else if (preg_match("/^vip/i", $interface))
3108
                        $realif = $interface;
3109
                else
3110
                        return null;
3111
        }
3112

    
3113
	$cursn = find_interface_subnet($realif);
3114
	if (!empty($cursn))
3115
		return $cursn;
3116

    
3117
	return null;
3118
}
3119

    
3120
/* return outside interfaces with a gateway */
3121
function get_interfaces_with_gateway() {
3122
	global $config;
3123

    
3124
	$ints = array();
3125

    
3126
	/* loop interfaces, check config for outbound */
3127
	foreach($config['interfaces'] as $ifdescr => $ifname) {
3128
		if (substr($ifdescr, 0, 5) ==  "ovpnc")
3129
			return true;
3130

    
3131
		switch ($ifname['ipaddr']) {
3132
			case "dhcp":
3133
			case "carpdev-dhcp":
3134
			case "ppp";
3135
			case "pppoe":
3136
			case "pptp":
3137
			case "l2tp":
3138
			case "ppp";
3139
				$ints[$ifdescr] = $ifdescr;
3140
			break;
3141
			default:
3142
				if (!empty($ifname['gateway']))
3143
					$ints[$ifdescr] = $ifdescr;
3144
			break;
3145
		}
3146
	}
3147
	return $ints;
3148
}
3149

    
3150
/* return true if interface has a gateway */
3151
function interface_has_gateway($friendly) {
3152
	global $config;
3153

    
3154
	if (!empty($config['interfaces'][$friendly])) {
3155
		if (substr($friendly, 0, 5) ==  "ovpnc")
3156
			return true;
3157
		$ifname =& $config['interfaces'][$friendly];
3158
		switch ($ifname['ipaddr']) {
3159
			case "dhcp":
3160
			case "carpdev-dhcp":
3161
			case "pppoe":
3162
			case "pptp":
3163
			case "l2tp":
3164
			case "ppp";
3165
				return true;
3166
			break;
3167
			default:
3168
				if (!empty($ifname['gateway']))
3169
					return true;
3170
			break;
3171
		}
3172
	}
3173

    
3174
	return false;
3175
}
3176

    
3177
/****f* interfaces/is_altq_capable
3178
 * NAME
3179
 *   is_altq_capable - Test if interface is capable of using ALTQ
3180
 * INPUTS
3181
 *   $int            - string containing interface name
3182
 * RESULT
3183
 *   boolean         - true or false
3184
 ******/
3185

    
3186
function is_altq_capable($int) {
3187
        /* Per:
3188
         * http://www.freebsd.org/cgi/man.cgi?query=altq&manpath=FreeBSD+7.2-current&format=html
3189
         * Only the following drivers have ALTQ support
3190
         */
3191
	$capable = array("age", "ale", "an", "ath", "aue", "awi", "bce",
3192
			"bfe", "bge", "dc", "de", "ed", "em", "ep", "fxp", "gem",
3193
			"hme", "igb", "ipw", "iwi", "jme", "le", "msk", "mxge", "my", "nfe",
3194
			"npe", "nve", "ral", "re", "rl", "rum", "sf", "sis", "sk",
3195
			"ste", "stge", "txp", "udav", "ural", "vge", "vr", "wi", "xl",
3196
			"ndis", "tun", "ovpns", "ovpnc", "vlan", "pppoe", "pptp", "ng",
3197
			"l2tp", "ppp");
3198

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

    
3201
        if (in_array($int_family[0], $capable))
3202
                return true;
3203
	else if (stristr($int_family, "vlan")) /* VLANs are name $parent_$vlan now */
3204
		return true;
3205
	else if (stristr($int_family, "_wlan")) /* WLANs are name $parent_$wlan now */
3206
		return true;
3207
        else
3208
                return false;
3209
}
3210

    
3211
/****f* interfaces/is_interface_wireless
3212
 * NAME
3213
 *   is_interface_wireless - Returns if an interface is wireless
3214
 * RESULT
3215
 *   $tmp       - Returns if an interface is wireless
3216
 ******/
3217
function is_interface_wireless($interface) {
3218
        global $config, $g;
3219

    
3220
        $friendly = convert_real_interface_to_friendly_interface_name($interface);
3221
        if(!isset($config['interfaces'][$friendly]['wireless'])) {
3222
                if (preg_match($g['wireless_regex'], $interface)) {
3223
                        if (isset($config['interfaces'][$friendly]))
3224
                                $config['interfaces'][$friendly]['wireless'] = array();
3225
                        return true;
3226
                }
3227
                return false;
3228
        } else
3229
                return true;
3230
}
3231

    
3232
function get_wireless_modes($interface) {
3233
	/* return wireless modes and channels */
3234
	$wireless_modes = array();
3235

    
3236
	$wlif = interface_translate_type_to_real($interface);
3237

    
3238
	if(is_interface_wireless($wlif)) {
3239
		$cloned_interface = get_real_interface($interface);
3240
		$chan_list = "/sbin/ifconfig {$cloned_interface} list chan";
3241
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
3242
		$format_list = "/usr/bin/awk '{print \$5 \" \" \$6 \",\" \$1}'";
3243

    
3244
		$interface_channels = "";
3245
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
3246
		$interface_channel_count = count($interface_channels);
3247

    
3248
		$c = 0;
3249
		while ($c < $interface_channel_count)
3250
		{
3251
			$channel_line = explode(",", $interface_channels["$c"]);
3252
			$wireless_mode = trim($channel_line[0]);
3253
			$wireless_channel = trim($channel_line[1]);
3254
			if(trim($wireless_mode) != "") {
3255
				/* if we only have 11g also set 11b channels */
3256
				if($wireless_mode == "11g") {
3257
					if(!isset($wireless_modes["11b"]))
3258
						$wireless_modes["11b"] = array();
3259
				} else if($wireless_mode == "11g ht") {
3260
					if(!isset($wireless_modes["11b"]))
3261
						$wireless_modes["11b"] = array();
3262
					if(!isset($wireless_modes["11g"]))
3263
						$wireless_modes["11g"] = array();
3264
					$wireless_mode = "11ng";
3265
				} else if($wireless_mode == "11a ht") {
3266
					if(!isset($wireless_modes["11a"]))
3267
						$wireless_modes["11a"] = array();
3268
					$wireless_mode = "11na";
3269
				}
3270
				$wireless_modes["$wireless_mode"]["$c"] = $wireless_channel;
3271
			}
3272
			$c++;
3273
		}
3274
	}
3275
	return($wireless_modes);
3276
}
3277

    
3278
/* return channel numbers, frequency, max txpower, and max regulation txpower */
3279
function get_wireless_channel_info($interface) {
3280
	$wireless_channels = array();
3281

    
3282
	$wlif = interface_translate_type_to_real($interface);
3283

    
3284
	if(is_interface_wireless($wlif)) {
3285
		$cloned_interface = get_real_interface($interface);
3286
		$chan_list = "/sbin/ifconfig {$cloned_interface} list txpower";
3287
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
3288
		$format_list = "/usr/bin/awk '{print \$1 \",\" \$3 \" \" \$4 \",\" \$5 \",\" \$7}'";
3289

    
3290
		$interface_channels = "";
3291
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
3292

    
3293
		foreach ($interface_channels as $channel_line) {
3294
			$channel_line = explode(",", $channel_line);
3295
			if(!isset($wireless_channels[$channel_line[0]]))
3296
				$wireless_channels[$channel_line[0]] = $channel_line;
3297
		}
3298
	}
3299
	return($wireless_channels);
3300
}
3301

    
3302
/****f* interfaces/get_interface_mtu
3303
 * NAME
3304
 *   get_interface_mtu - Return the mtu of an interface
3305
 * RESULT
3306
 *   $tmp       - Returns the mtu of an interface
3307
 ******/
3308
function get_interface_mtu($interface) {
3309
        $mtu = pfSense_get_interface_addresses($interface);
3310
        return $mtu['mtu'];
3311
}
3312

    
3313
function get_interface_mac($interface) {
3314

    
3315
	$macinfo = pfSense_get_interface_addresses($interface);
3316
	return $macinfo["macaddr"];
3317
}
3318

    
3319
/****f* pfsense-utils/generate_random_mac_address
3320
 * NAME
3321
 *   generate_random_mac - generates a random mac address
3322
 * INPUTS
3323
 *   none
3324
 * RESULT
3325
 *   $mac - a random mac address
3326
 ******/
3327
function generate_random_mac_address() {
3328
        $mac = "02";
3329
        for($x=0; $x<5; $x++)
3330
                $mac .= ":" . dechex(rand(16, 255));
3331
        return $mac;
3332
}
3333

    
3334
/****f* interfaces/is_jumbo_capable
3335
 * NAME
3336
 *   is_jumbo_capable - Test if interface is jumbo frame capable.  Useful for determining VLAN capability.
3337
 * INPUTS
3338
 *   $int             - string containing interface name
3339
 * RESULT
3340
 *   boolean          - true or false
3341
 ******/
3342
function is_jumbo_capable($int) {
3343
        global $g;
3344

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

    
3347
        if (in_array($int_family[0], $g['vlan_long_frame']))
3348
                return true;
3349
        else
3350
                return false;
3351
}
3352

    
3353
function setup_pppoe_reset_file($pppif, $iface="") {
3354
	global $g;
3355
	$cron_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
3356

    
3357
	if(!empty($iface) && !empty($pppif)){
3358
		$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";
3359
		file_put_contents($cron_file, $cron_cmd);
3360
		chmod($cron_file, 0700);
3361
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
3362
	} else
3363
		unlink_if_exists($cron_file);
3364
}
3365

    
3366
?>
(22-22/54)