Project

General

Profile

Download (99 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(true);
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
	if($g['booting'])
93
		echo "done.\n";
94
	return 0;
95
}
96

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

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

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

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

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

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

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

    
144
	interfaces_bring_up($vlanif);
145

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

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

    
152
	return $vlanif;
153
}
154

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

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

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

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

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

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

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

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

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

    
221
        return $vlanif;
222
}
223

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

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

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

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

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

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

    
264
        return $vlanif;
265
}
266

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

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

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

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

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

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

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

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

    
318
	$checklist = get_configured_interface_list();
319

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

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

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

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

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

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

    
477
	return $bridgeif;
478
}
479

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
568
	interfaces_bring_up($laggif);
569

    
570
	return $laggif;
571
}
572

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

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

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

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

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

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

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

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

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

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

    
626
	return $greif;
627
}
628

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

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

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

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

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

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

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

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

    
681
	return $gifif;
682
}
683

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

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

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

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

    
696
	interfaces_qinq_configure();
697

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

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

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

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

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

    
744
		interface_configure($if, $reload);
745

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

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

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

    
759
		interface_configure($if, $reload);
760

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

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

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

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

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

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

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

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

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

    
791
	return 0;
792
}
793

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

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

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

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

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

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

    
834
	$realif = get_real_interface($interface);
835

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

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

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

    
903
	return;
904
}
905

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

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

    
914
	return false;
915
}
916

    
917
function interfaces_ptpid_next() {
918

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

    
923
	return $ptpid;
924
}
925

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1215
EOD;
1216

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

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

    
1230
EOD;
1231

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

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

    
1242
EOD;
1243

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

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

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

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

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

    
1270
EOD;
1271

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

    
1276
EOD;
1277

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

    
1282
EOD;
1283

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

    
1289
EOD;
1290

    
1291

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

    
1296
EOD;
1297

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

    
1303
EOD;
1304

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

    
1309
EOD;
1310

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

    
1315
EOD;
1316

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

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

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

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

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

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

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

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

    
1370
EOD;
1371

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

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

    
1384

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

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

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

    
1425
	return 1;
1426
}
1427

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1629
function interface_ipalias_configure(&$vip) {
1630

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

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

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

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

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

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

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

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

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

    
1700
	/* Ensure CARP IP really exists prior to loading up. */
1701
	$ww_subnet_ip = find_interface_ip($realif);
1702
	$ww_subnet_bits = find_interface_subnet($realif);
1703
	if (!ip_in_subnet($vip['subnet'], gen_subnet($ww_subnet_ip, $ww_subnet_bits) . "/" . $ww_subnet_bits) && !ip_in_interface_alias_subnet($vip['interface'], $vip['subnet'])) {
1704
		file_notice("CARP", "Sorry but we could not find a matching real interface subnet for the virtual IP address {$vip['subnet']}.", "Firewall: Virtual IP", "");
1705
		return;
1706
	}
1707

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1789
EOD;
1790

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

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

    
1801
	return $vipif;
1802
}
1803

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2161
EOD;
2162

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

    
2169
EOD;
2170

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

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

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

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

    
2192
			}
2193
			break;
2194
	}
2195

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2322
	return 0;
2323

    
2324
}
2325

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

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

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

    
2340
	return $pid;
2341
}
2342

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

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

    
2349
	$realif = get_real_interface($interface);
2350

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2527
		link_interface_to_vips($interface, "update");
2528

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

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

    
2537
		if ($reloadall == true) {
2538

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

    
2542
			/* reload ipsec tunnels */
2543
			vpn_ipsec_configure();
2544

    
2545
			/* restart dnsmasq */
2546
			services_dnsmasq_configure();
2547

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

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

    
2554
			/* reload captive portal */
2555
			captiveportal_init_rules();
2556

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

    
2562
	return 0;
2563
}
2564

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

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

    
2576
	return 0;
2577
}
2578

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

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

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

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

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

    
2617
EOD;
2618

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

    
2628
EOD;
2629
}
2630
	fwrite($fd, $dhclientconf);
2631
	fclose($fd);
2632

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

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

    
2642
	return 0;
2643
}
2644

    
2645
function interfaces_group_setup() {
2646
	global $config;
2647

    
2648
	if (!is_array($config['ifgroups']['ifgroupentry']))
2649
		return;
2650

    
2651
	foreach ($config['ifgroups']['ifgroupentry'] as $groupar)
2652
		interface_group_setup($groupar);
2653

    
2654
	return;
2655
}
2656

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

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

    
2669
	return;
2670
}
2671

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

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

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

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

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

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

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

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

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

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

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

    
2763
        return $ifdesc;
2764
}
2765

    
2766
function convert_real_interface_to_friendly_descr($interface) {
2767
        global $config;
2768

    
2769
        $ifdesc = convert_real_interface_to_friendly_interface_name("{$interface}");
2770

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

    
2776
        return $interface;
2777
}
2778

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

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

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

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

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

    
2816
function get_real_interface($interface = "wan") {
2817
    global $config;
2818

    
2819
	$wanif = NULL;
2820

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

    
2853
		$cfg = &$config['interfaces'][$interface];
2854

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

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

    
2895
    return $wanif;
2896
}
2897

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

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

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

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

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

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

    
2967
function link_carp_interface_to_parent($interface) {
2968
        global $config;
2969

    
2970
        if ($interface == "")
2971
                return;
2972

    
2973
        $carp_ip = get_interface_ip($interface);
2974
        if (!is_ipaddr($carp_ip))
2975
                return;
2976

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

    
2987
        return "";
2988
}
2989

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

    
3001
        if (!is_ipaddr($ip))
3002
                return;
3003

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

    
3021
        return $carp_ints;
3022
}
3023

    
3024
function link_interface_to_vlans($int, $action = "") {
3025
	global $config;
3026

    
3027
	if (empty($int))
3028
		return;
3029

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

    
3042
function link_interface_to_vips($int, $action = "") {
3043
        global $config;
3044

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

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

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

    
3074
function link_interface_to_group($int) {
3075
        global $config;
3076

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

    
3085
function link_interface_to_gre($interface) {
3086
        global $config;
3087

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

    
3094
function link_interface_to_gif($interface) {
3095
        global $config;
3096

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

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

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

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

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

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

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

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

    
3141
	return $interface_sn_arr_cache[$interface];
3142
}
3143

    
3144
function ip_in_interface_alias_subnet($interface, $ipalias) {
3145
	global $config;
3146

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

    
3162
	return false;
3163
}
3164

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

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

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

    
3196
	$cursn = find_interface_subnet($realif);
3197
	if (!empty($cursn))
3198
		return $cursn;
3199

    
3200
	return null;
3201
}
3202

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

    
3207
	$ints = array();
3208

    
3209
	/* loop interfaces, check config for outbound */
3210
	foreach($config['interfaces'] as $ifdescr => $ifname) {
3211
		switch ($ifname['ipaddr']) {
3212
			case "dhcp":
3213
			case "carpdev-dhcp":
3214
			case "ppp";
3215
			case "pppoe":
3216
			case "pptp":
3217
			case "l2tp":
3218
			case "ppp";
3219
				$ints[$ifdescr] = $ifdescr;
3220
			break;
3221
			default:
3222
				if (substr($ifname['if'], 0, 5) ==  "ovpnc" ||
3223
				    !empty($ifname['gateway']))
3224
					$ints[$ifdescr] = $ifdescr;
3225
			break;
3226
		}
3227
	}
3228
	return $ints;
3229
}
3230

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

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

    
3255
	return false;
3256
}
3257

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

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

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

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

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

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

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

    
3317
	$wlif = interface_translate_type_to_real($interface);
3318

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

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

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

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

    
3363
	$wlif = interface_translate_type_to_real($interface);
3364

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

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

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

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

    
3394
function get_interface_mac($interface) {
3395

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

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

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

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

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

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

    
3438
	if(!empty($iface) && !empty($pppif)){
3439
		$cron_cmd = <<<EOD
3440
#!/bin/sh
3441
/usr/local/sbin/pfSctl -c 'interface reload {$iface}'
3442
/usr/bin/logger -t pppoe{$iface} "PPPoE periodic reset executed on {$iface}"
3443

    
3444
EOD;
3445

    
3446
		file_put_contents($cron_file, $cron_cmd);
3447
		chmod($cron_file, 0700);
3448
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
3449
	} else
3450
		unlink_if_exists($cron_file);
3451
}
3452

    
3453
?>
(22-22/54)