Project

General

Profile

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

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

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

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

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

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

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

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

    
42
*/
43

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

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

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

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

    
67
        return $interface_arr_cache;
68
}
69

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

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

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

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

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

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

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

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

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

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

    
145
	interfaces_bring_up($vlanif);
146

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

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

    
153
	return $vlanif;
154
}
155

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

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

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

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

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

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

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

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

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

    
222
        return $vlanif;
223
}
224

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

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

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

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

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

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

    
265
        return $vlanif;
266
}
267

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

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

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

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

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

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

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

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

    
319
	$checklist = get_configured_interface_list();
320

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

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

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

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

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

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

    
478
	return $bridgeif;
479
}
480

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
569
	interfaces_bring_up($laggif);
570

    
571
	return $laggif;
572
}
573

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

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

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

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

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

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

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

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

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

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

    
627
	return $greif;
628
}
629

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

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

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

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

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

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

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

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

    
682
	return $gifif;
683
}
684

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

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

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

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

    
697
	interfaces_qinq_configure();
698

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

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

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

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

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

    
745
		interface_configure($if, $reload);
746

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

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

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

    
760
		interface_configure($if, $reload);
761

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

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

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

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

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

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

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

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

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

    
792
	return 0;
793
}
794

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

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

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

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

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

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

    
835
	$realif = get_real_interface($interface);
836

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

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

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

    
904
	return;
905
}
906

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

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

    
915
	return false;
916
}
917

    
918
function interfaces_ptpid_next() {
919

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

    
924
	return $ptpid;
925
}
926

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1216
EOD;
1217

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

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

    
1231
EOD;
1232

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

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

    
1243
EOD;
1244

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

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

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

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

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

    
1271
EOD;
1272

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

    
1277
EOD;
1278

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

    
1283
EOD;
1284

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

    
1290
EOD;
1291

    
1292

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

    
1297
EOD;
1298

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

    
1304
EOD;
1305

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

    
1310
EOD;
1311

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

    
1316
EOD;
1317

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

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

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

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

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

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

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

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

    
1371
EOD;
1372

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

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

    
1385

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

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

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

    
1426
	return 1;
1427
}
1428

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1630
function interface_ipalias_configure(&$vip) {
1631

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1790
EOD;
1791

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

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

    
1802
	return $vipif;
1803
}
1804

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2162
EOD;
2163

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

    
2170
EOD;
2171

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

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

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

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

    
2193
			}
2194
			break;
2195
	}
2196

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2323
	return 0;
2324

    
2325
}
2326

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

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

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

    
2341
	return $pid;
2342
}
2343

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

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

    
2350
	$realif = get_real_interface($interface);
2351

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2538
		if ($reloadall == true) {
2539

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

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

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

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

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

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

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

    
2563
	return 0;
2564
}
2565

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

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

    
2577
	return 0;
2578
}
2579

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

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

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

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

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

    
2618
EOD;
2619

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

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

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

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

    
2643
	return 0;
2644
}
2645

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

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

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

    
2655
	return;
2656
}
2657

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

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

    
2670
	return;
2671
}
2672

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

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

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

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

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

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

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

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

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

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

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

    
2764
        return $ifdesc;
2765
}
2766

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

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

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

    
2777
        return $interface;
2778
}
2779

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

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

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

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

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

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

    
2820
	$wanif = NULL;
2821

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

    
2854
		$cfg = $config['interfaces'][$interface];
2855

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

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

    
2896
    return $wanif;
2897
}
2898

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

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

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

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

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

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

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

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

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

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

    
2988
        return "";
2989
}
2990

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

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

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

    
3022
        return $carp_ints;
3023
}
3024

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
3163
	return false;
3164
}
3165

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

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

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

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

    
3201
	return null;
3202
}
3203

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

    
3208
	$ints = array();
3209

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

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

    
3234
/* return true if interface has a gateway */
3235
function interface_has_gateway($friendly) {
3236
	global $config;
3237

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

    
3258
	return false;
3259
}
3260

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

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

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

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

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

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

    
3316
function get_wireless_modes($interface) {
3317
	/* return wireless modes and channels */
3318
	$wireless_modes = array();
3319

    
3320
	$wlif = interface_translate_type_to_real($interface);
3321

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

    
3328
		$interface_channels = "";
3329
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
3330
		$interface_channel_count = count($interface_channels);
3331

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

    
3362
/* return channel numbers, frequency, max txpower, and max regulation txpower */
3363
function get_wireless_channel_info($interface) {
3364
	$wireless_channels = array();
3365

    
3366
	$wlif = interface_translate_type_to_real($interface);
3367

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

    
3374
		$interface_channels = "";
3375
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
3376

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

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

    
3397
function get_interface_mac($interface) {
3398

    
3399
	$macinfo = pfSense_get_interface_addresses($interface);
3400
	return $macinfo["macaddr"];
3401
}
3402

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

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

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

    
3431
        if (in_array($int_family[0], $g['vlan_long_frame']))
3432
                return true;
3433
        else
3434
                return false;
3435
}
3436

    
3437
function setup_pppoe_reset_file($pppif, $iface="") {
3438
	global $g;
3439
	$cron_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
3440

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

    
3450
?>
(22-22/54)