Project

General

Profile

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

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

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

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

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

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

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

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

    
42
*/
43

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

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

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

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

    
67
        return $interface_arr_cache;
68
}
69

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

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

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

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

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

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

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

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

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

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

    
145
	interfaces_bring_up($vlanif);
146

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

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

    
153
	return $vlanif;
154
}
155

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

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

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

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

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

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

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

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

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

    
222
        return $vlanif;
223
}
224

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

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

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

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

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

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

    
265
        return $vlanif;
266
}
267

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

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

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

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

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

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

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

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

    
319
	$checklist = get_configured_interface_list();
320

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

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

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

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

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

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

    
478
	return $bridgeif;
479
}
480

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
569
	interfaces_bring_up($laggif);
570

    
571
	return $laggif;
572
}
573

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

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

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

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

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

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

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

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

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

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

    
627
	return $greif;
628
}
629

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

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

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

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

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

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

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

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

    
682
	return $gifif;
683
}
684

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

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

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

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

    
697
	interfaces_qinq_configure();
698

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

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

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

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

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

    
745
		interface_configure($if, $reload);
746

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

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

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

    
760
		interface_configure($if, $reload);
761

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

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

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

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

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

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

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

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

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

    
792
	return 0;
793
}
794

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

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

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

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

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

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

    
835
	$realif = get_real_interface($interface);
836

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

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

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

    
900
	return;
901
}
902

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

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

    
911
	return false;
912
}
913

    
914
function interfaces_ptpid_next() {
915

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

    
920
	return $ptpid;
921
}
922

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1212
EOD;
1213

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

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

    
1227
EOD;
1228

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

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

    
1239
EOD;
1240

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

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

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

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

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

    
1267
EOD;
1268

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

    
1273
EOD;
1274

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

    
1279
EOD;
1280

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

    
1286
EOD;
1287

    
1288

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

    
1293
EOD;
1294

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

    
1300
EOD;
1301

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

    
1306
EOD;
1307

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

    
1312
EOD;
1313

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

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

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

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

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

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

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

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

    
1367
EOD;
1368

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

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

    
1381

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

    
1396
	// Create the uptime log if requested and if it doesn't exist already, or delete it if it is no longer requested.
1397
	if (isset($ppp['uptime'])) {
1398
		if (!file_exists("/conf/{$pppif}.log")) {
1399
			conf_mount_rw();
1400
			mwexec("echo /dev/null > /conf/{$pppif}.log");
1401
			conf_mount_ro();
1402
		}
1403
	} else {
1404
		if (file_exists("/conf/{$pppif}.log")) {
1405
			conf_mount_rw();
1406
			mwexec("rm -f /conf/{$pppif}.log");
1407
			conf_mount_ro();
1408
		}
1409
	}
1410
		
1411
	/* fire up mpd */
1412
	mwexec("/usr/local/sbin/mpd5 -b -k -d {$g['varetc_path']} -f mpd_{$interface}.conf -p {$g['varrun_path']}/{$ppp['type']}_{$interface}.pid -s ppp {$ppp['type']}client");
1413

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

    
1422
	return 1;
1423
}
1424

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1542
				if (!is_array($paa[$proxyif]))
1543
					$paa[$proxyif] = array();
1544

    
1545
				$paa[$proxyif][] = $vipent;
1546
			}
1547
		}
1548
	}
1549

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

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

    
1626
function interface_ipalias_configure(&$vip) {
1627

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

    
1634
function interface_reload_carps($cif) {
1635
	global $config;
1636

    
1637
	$carpifs = link_ip_to_carp_interface(find_interface_ip($cif));
1638
	if (empty($carpifs))
1639
		return;
1640

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

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

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

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

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

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

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

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

    
1714
	/* invalidate interface cache */
1715
	get_interface_arr(true);
1716

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

    
1720
	interfaces_bring_up($vipif);
1721
	
1722
	return $vipif;
1723
}
1724

    
1725
function interface_carpdev_configure(&$vip) {
1726
	global $g;
1727

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

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

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

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

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

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

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

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

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

    
1786
EOD;
1787

    
1788
		fwrite($fd, $dhclientconf);
1789
		fclose($fd);
1790

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

    
1798
	return $vipif;
1799
}
1800

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

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

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

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

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

    
1871
	if(!is_interface_wireless($ifcfg['if']))
1872
		return;
1873

    
1874
	$baseif = interface_get_wireless_base($ifcfg['if']);
1875

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

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

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

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

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

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

    
1946
	// Clone wireless nic if needed.
1947
	interface_wireless_clone($if, $wl);
1948

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2098
	mwexec(kill_hostapd("{$if}"));
2099
	mwexec(kill_wpasupplicant("{$if}"));
2100

    
2101
	/* generate wpa_supplicant/hostap config if wpa is enabled */
2102
	conf_mount_rw();
2103

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

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

    
2158
EOD;
2159

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

    
2166
EOD;
2167

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

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

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

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

    
2189
			}
2190
			break;
2191
	}
2192

    
2193
	/*
2194
	 *    all variables are set, lets start up everything
2195
	 */
2196

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

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

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

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

    
2224
	fclose($fd_set);
2225
	conf_mount_ro();
2226

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

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

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

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

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

    
2260
		$wlregcmd_args = implode(" ", $wlregcmd);
2261

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

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

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

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

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

    
2296
	/* configure wireless */
2297
	$wlcmd_args = implode(" ", $wlcmd);
2298
	mwexec("/sbin/ifconfig {$if} $wlcmd_args", false);
2299

    
2300
	
2301
	sleep(1);
2302
	/* execute hostapd and wpa_supplicant if required in shell */
2303
	mwexec("/bin/sh {$g['tmp_path']}/{$if}_setup.sh");
2304

    
2305
	return 0;
2306

    
2307
}
2308

    
2309
function kill_hostapd($interface) {
2310
	return "/bin/pkill -f \"hostapd .*{$interface}\"\n";
2311
}
2312

    
2313
function kill_wpasupplicant($interface) {
2314
	return "/bin/pkill -f \"wpa_supplicant .*{$interface}\"\n";
2315
}
2316

    
2317
function find_dhclient_process($interface) {
2318
	if ($interface)
2319
		$pid = `/bin/pgrep -xf "dhclient: {$interface}"`;
2320
	else
2321
		$pid = 0;
2322

    
2323
	return $pid;
2324
}
2325

    
2326
function interface_configure($interface = "wan", $reloadall = false, $linkupevent = false) {
2327
	global $config, $g;
2328
	global $interface_sn_arr_cache, $interface_ip_arr_cache;
2329

    
2330
	$wancfg = $config['interfaces'][$interface];
2331

    
2332
	$realif = get_real_interface($interface);
2333

    
2334
	if (!$g['booting']) {
2335
		/* remove all IPv4 addresses */
2336
		while (mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " -alias", true) == 0);
2337
	}
2338

    
2339
	/* wireless configuration? */
2340
	if (is_array($wancfg['wireless']))
2341
		interface_wireless_configure($realif, $wancfg, $wancfg['wireless']);
2342

    
2343
	if ($wancfg['spoofmac']) {
2344
		mwexec("/sbin/ifconfig " . escapeshellarg($realif) .
2345
			" link " . escapeshellarg($wancfg['spoofmac']));
2346

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

    
2374
	/* media */
2375
	if ($wancfg['media'] || $wancfg['mediaopt']) {
2376
		$cmd = "/sbin/ifconfig " . escapeshellarg(get_real_interface($wancfg['if']));
2377
		if ($wancfg['media'])
2378
			$cmd .= " media " . escapeshellarg($wancfg['media']);
2379
		if ($wancfg['mediaopt'])
2380
			$cmd .= " mediaopt " . escapeshellarg($wancfg['mediaopt']);
2381
		mwexec($cmd);
2382
	}
2383
	if (!empty($wancfg['mtu']))
2384
		pfSense_interface_mtu($realif, $wancfg['mtu']);
2385

    
2386
	$options = pfSense_get_interface_addresses($realif);
2387
	if (is_array($options) && isset($options['caps']['polling'])) {
2388
		if (isset($config['system']['polling']))
2389
			pfSense_interface_capabilities($realif, IFCAP_POLLING);
2390
		else
2391
			pfSense_interface_capabilities($realif, -IFCAP_POLLING);
2392
	}
2393

    
2394
	/* skip vlans for checksumming and polling */
2395
        if (!stristr($realif, "vlan") && is_array($options)) {
2396
		$flags = 0;
2397
		if(isset($config['system']['disablechecksumoffloading'])) {
2398
			if (isset($options['encaps']['txcsum']))
2399
				$flags |= IFCAP_TXCSUM;
2400
			if (isset($options['encaps']['rxcsum']))
2401
				$flags |= IFCAP_RXCSUM;
2402
        	} else {
2403
 			if (!isset($options['caps']['txcsum']))
2404
				$flags |= IFCAP_TXCSUM;
2405
			if (!isset($options['caps']['rxcsum']))
2406
				$flags |= IFCAP_RXCSUM;
2407
        	}
2408

    
2409
        	if(isset($config['system']['disablesegmentationoffloading'])) {
2410
                	if (isset($options['encaps']['tso4']))
2411
				$flags |= IFCAP_TSO;
2412
                	if (isset($options['encaps']['tso6']))
2413
				$flags |= IFCAP_TSO;
2414
        	} else {
2415
                	if (!isset($options['caps']['tso4']))
2416
				$flags |= IFCAP_TSO;
2417
                	if (!isset($options['caps']['tso6']))
2418
				$flags |= IFCAP_TSO;
2419
        	}
2420

    
2421
        	if(isset($config['system']['disablelargereceiveoffloading'])) {
2422
                	if (isset($options['encaps']['lro']))
2423
				$flags |= IFCAP_LRO;
2424
        	} else {
2425
                	if (!isset($options['caps']['lro']))
2426
				$flags |= IFCAP_LRO;
2427
        	}
2428

    
2429
        	/* if the NIC supports polling *AND* it is enabled in the GUI */
2430
        	if (!isset($config['system']['polling']) || !isset($options['caps']['polling'])) {
2431
			$flags |= IFCAP_POLLING;
2432
		}
2433
               	pfSense_interface_capabilities($realif, -$flags);
2434
	}
2435

    
2436
	/* invalidate interface/ip/sn cache */
2437
	get_interface_arr(true);
2438
	unset($interface_ip_arr_cache[$realif]);
2439
	unset($interface_sn_arr_cache[$realif]);
2440

    
2441
	switch ($wancfg['ipaddr']) {
2442
		case 'carpdev-dhcp':
2443
			interface_bring_down($interface);
2444
			interface_carpdev_dhcp_configure($interface);
2445
			break;
2446
		case 'dhcp':
2447
			interface_bring_down($interface);
2448
			interface_dhcp_configure($interface);
2449
			break;
2450
		case 'pppoe':
2451
		case 'l2tp':
2452
		case 'pptp':
2453
		case 'ppp':
2454
			interface_bring_down($interface, true);
2455
			interface_ppps_configure($interface);
2456
			break;
2457
		default:
2458
			interface_bring_down($interface);
2459

    
2460
			if ($wancfg['ipaddr'] <> "" && $wancfg['subnet'] <> "") {
2461
				pfSense_interface_setaddress($realif, "{$wancfg['ipaddr']}/{$wancfg['subnet']}");
2462
			} else if (substr($realif, 0, 3) == "gre") {
2463
				if (is_array($config['gres']['gre'])) {
2464
					foreach ($config['gres']['gre'] as $gre)
2465
						if ($gre['greif'] == $realif)
2466
							interface_gre_configure($gre);
2467
				}
2468
			} else if (substr($realif, 0, 3) == "gif") {
2469
				 if (is_array($config['gifs']['gif'])) {
2470
					foreach ($config['gifs']['gif'] as $gif)
2471
						if($gif['gifif'] == $interface)
2472
							interface_gif_configure($gif);
2473
				}
2474
			} else if (substr($realif, 0, 4) == "ovpn") {
2475
				/* XXX: Should be done anything?! */
2476
			}
2477

    
2478
			if (is_ipaddr($wancfg['gateway']))
2479
				file_put_contents("{$g['tmp_path']}/{$realif}_router", $wancfg['gateway']);
2480
			break;
2481
	}
2482

    
2483
	if(does_interface_exist($wancfg['if']))
2484
		interfaces_bring_up($wancfg['if']);
2485
 	
2486
	if (!$g['booting']) {
2487
		interface_reload_carps($realif);
2488

    
2489
		unset($gre);
2490
		$gre = link_interface_to_gre($interface);
2491
		if (!empty($gre))
2492
			interface_gre_configure($gre);
2493

    
2494
		unset($gif);
2495
		$gif = link_interface_to_gif($interface);
2496
		if (!empty($gif))
2497
                       	interface_gif_configure($gif);
2498

    
2499
		if ($linkupevent == false) {
2500
			unset($bridgetmp);
2501
			$bridgetmp = link_interface_to_bridge($interface);
2502
			if (!empty($bridgetmp))
2503
				interface_bridge_add_member($bridgetmp, $realif);
2504
		}
2505

    
2506
		link_interface_to_vips($interface, "update");
2507

    
2508
		$grouptmp = link_interface_to_group($interface);
2509
		if (!empty($grouptmp))
2510
			interface_group_add_member($realif, $grouptmp);
2511

    
2512
		if ($interface == "lan")
2513
			/* make new hosts file */
2514
			system_hosts_generate();
2515

    
2516
		if ($reloadall == true) {
2517

    
2518
			/* reconfigure static routes (kernel may have deleted them) */
2519
			system_routing_configure($interface);
2520

    
2521
			/* reload ipsec tunnels */
2522
			vpn_ipsec_configure();
2523

    
2524
			/* update dyndns */
2525
			services_dyndns_configure($interface);
2526

    
2527
			/* force DNS update */
2528
			services_dnsupdate_process($interface);
2529

    
2530
			/* restart dnsmasq */
2531
			services_dnsmasq_configure();
2532

    
2533
			/* reload captive portal */
2534
			captiveportal_init_rules();
2535

    
2536
			/* set the reload filter dity flag */
2537
			filter_configure();
2538
		}
2539
	}
2540

    
2541
	return 0;
2542
}
2543

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

    
2547
	$wancfg = $config['interfaces'][$interface];
2548
	$wanif = $wancfg['if'];
2549
	/* bring wan interface up before starting dhclient */
2550
	if($wanif)
2551
		interfaces_bring_up($wanif);
2552
	else 
2553
		log_error("Could not bring wanif up in terface_carpdev_dhcp_configure()");
2554

    
2555
	return 0;
2556
}
2557

    
2558
function interface_dhcp_configure($interface = "wan") {
2559
	global $config, $g;
2560

    
2561
	$wancfg = $config['interfaces'][$interface];
2562
	if (empty($wancfg))
2563
		$wancfg = array();
2564

    
2565
	/* generate dhclient_wan.conf */
2566
	$fd = fopen("{$g['varetc_path']}/dhclient_{$interface}.conf", "w");
2567
	if (!$fd) {
2568
		printf("Error: cannot open dhclient_{$interface}.conf in interfaces_wan_dhcp_configure() for writing.\n");
2569
		return 1;
2570
	}
2571

    
2572
	if ($wancfg['dhcphostname']) {
2573
		$dhclientconf_hostname = "send dhcp-client-identifier \"{$wancfg['dhcphostname']}\";\n";
2574
		$dhclientconf_hostname .= "\tsend host-name \"{$wancfg['dhcphostname']}\";\n";
2575
	} else {
2576
		$dhclientconf_hostname = "";
2577
	}
2578

    
2579
	$wanif = get_real_interface($interface);
2580
	if (empty($wanif)) {
2581
		log_error("Invalid interface \"{$interface}\" in interface_dhcp_configure()");
2582
		return 0;
2583
	}
2584
 	$dhclientconf = "";
2585
	
2586
	$dhclientconf .= <<<EOD
2587
interface "{$wanif}" {
2588
timeout 60;
2589
retry 1;
2590
select-timeout 0;
2591
initial-interval 1;
2592
	{$dhclientconf_hostname}
2593
	script "/sbin/dhclient-script";
2594
}
2595

    
2596
EOD;
2597

    
2598
if(is_ipaddr($wancfg['alias-address'])) {
2599
	$subnetmask = gen_subnet_mask($wancfg['alias-subnet']);
2600
	$dhclientconf .= <<<EOD
2601
alias {
2602
	interface  "{$wanif}";
2603
	fixed-address {$wancfg['alias-address']};
2604
	option subnet-mask {$subnetmask};
2605
}
2606

    
2607
EOD;
2608
}
2609
	fwrite($fd, $dhclientconf);
2610
	fclose($fd);
2611

    
2612
	/* bring wan interface up before starting dhclient */
2613
	if($wanif)
2614
		interfaces_bring_up($wanif);
2615
	else 
2616
		log_error("Could not bring up {$wanif} interface in interface_dhcp_configure()");
2617

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

    
2621
	return 0;
2622
}
2623

    
2624
function interfaces_group_setup() {
2625
	global $config;
2626

    
2627
	if (!is_array($config['ifgroups']['ifgroupentry']))
2628
		return;
2629

    
2630
	foreach ($config['ifgroups']['ifgroupentry'] as $groupar)
2631
		interface_group_setup($groupar);
2632

    
2633
	return;
2634
}
2635

    
2636
function interface_group_setup(&$groupname /* The parameter is an array */) {
2637
	global $config;
2638

    
2639
	if (!is_array($groupname))
2640
		return;
2641
	$members = explode(" ", $groupname['members']);
2642
	foreach($members as $ifs) {
2643
		$realif = get_real_interface($ifs);
2644
		if ($realif)
2645
			mwexec("/sbin/ifconfig {$realif} group {$groupname['ifname']}");
2646
	}
2647

    
2648
	return;
2649
}
2650

    
2651
function interface_group_add_member($interface, $groupname) {
2652
	mwexec("/sbin/ifconfig {$interface} group {$groupname}", true);
2653
}
2654
 
2655
/* COMPAT Function */
2656
function convert_friendly_interface_to_real_interface_name($interface) {
2657
	return get_real_interface($interface);
2658
}
2659

    
2660
/* COMPAT Function */
2661
function get_real_wan_interface($interface = "wan") {
2662
	return get_real_interface($interface);
2663
}
2664

    
2665
/* COMPAT Function */
2666
function get_current_wan_address($interface = "wan") {
2667
	return get_interface_ip($interface);
2668
}
2669

    
2670
/*
2671
 * convert_real_interface_to_friendly_interface_name($interface): convert fxp0 -> wan, etc.
2672
 */
2673
function convert_real_interface_to_friendly_interface_name($interface = "wan") {
2674
        global $config;
2675

    
2676
	if (stristr($interface, "vip")) {
2677
                $index = intval(substr($interface, 3));
2678
                foreach ($config['virtualip']['vip'] as $counter => $vip) {
2679
                        if ($vip['mode'] == "carpdev-dhcp" || $vip['mode'] == "carp")  {
2680
                                if ($index == $counter)
2681
                                        return $vip['interface'];
2682
                        }
2683
                }
2684
        }
2685

    
2686
        /* XXX: For speed reasons reference directly the interface array */
2687
	$ifdescrs =& $config['interfaces'];
2688
        //$ifdescrs = get_configured_interface_list(false, true);
2689

    
2690
        foreach ($ifdescrs as $if => $ifname) {
2691
                if ($config['interfaces'][$if]['if'] == $interface)
2692
                        return $if;
2693

    
2694
                if (stristr($interface, "_wlan0") && $config['interfaces'][$if]['if'] == interface_get_wireless_base($interface))
2695
                        return $if;
2696

    
2697
                $int = interface_translate_type_to_real($if);
2698
                if ($int == $interface)
2699
                        return $ifname;
2700
        }
2701
        return NULL;
2702
}
2703

    
2704
/* attempt to resolve interface to friendly descr */
2705
function convert_friendly_interface_to_friendly_descr($interface) {
2706
        global $config;
2707

    
2708
        switch ($interface) {
2709
                case "l2tp":
2710
                                $ifdesc = "L2TP";
2711
                                break;
2712
                case "pptp":
2713
                                $ifdesc = "PPTP";
2714
                                break;
2715
                case "pppoe":
2716
                                $ifdesc = "PPPoE";
2717
                                break;
2718
                case "openvpn":
2719
                                $ifdesc = "OpenVPN";
2720
                                break;
2721
                case "enc0":
2722
                        case "ipsec":
2723
                                $ifdesc = "IPsec";
2724
                                break;
2725
        default:
2726
                if (isset($config['interfaces'][$interface])) {
2727
                        if (empty($config['interfaces'][$interface]['descr']))
2728
                                $ifdesc = strtoupper($interface);
2729
                        else
2730
                                $ifdesc = strtoupper($config['interfaces'][$interface]['descr']);
2731
			break;
2732
		}
2733
                /* if list */
2734
                $ifdescrs = get_configured_interface_with_descr(false, true);
2735
                foreach ($ifdescrs as $if => $ifname) {
2736
                                if ($if == $interface || $ifname == $interface)
2737
                                        return $ifname;
2738
                }
2739
                break;
2740
        }
2741

    
2742
        return $ifdesc;
2743
}
2744

    
2745
function convert_real_interface_to_friendly_descr($interface) {
2746
        global $config;
2747

    
2748
        $ifdesc = convert_real_interface_to_friendly_interface_name("{$interface}");
2749

    
2750
        if ($ifdesc) {
2751
                $iflist = get_configured_interface_with_descr(false, true);
2752
                return $iflist[$ifdesc];
2753
        }
2754

    
2755
        return $interface;
2756
}
2757

    
2758
/*
2759
 *  interface_translate_type_to_real($interface):
2760
 *              returns the real hardware interface name for a friendly interface.  ie: wan
2761
 */
2762
function interface_translate_type_to_real($interface) {
2763
        global $config;
2764

    
2765
        if ($config['interfaces'][$interface]['if'] <> "")
2766
                return $config['interfaces'][$interface]['if'];
2767
        else
2768
		return $interface;
2769
}
2770

    
2771
function interface_is_wireless_clone($wlif) {
2772
	if(!stristr($wlif, "_wlan")) {
2773
		return false;
2774
	} else {
2775
		return true;
2776
	}
2777
}
2778

    
2779
function interface_get_wireless_base($wlif) {
2780
	if(!stristr($wlif, "_wlan")) {
2781
		return $wlif;
2782
	} else {
2783
		return substr($wlif, 0, stripos($wlif, "_wlan"));
2784
	}
2785
}
2786

    
2787
function interface_get_wireless_clone($wlif) {
2788
	if(!stristr($wlif, "_wlan")) {
2789
		return $wlif . "_wlan0";
2790
	} else {
2791
		return $wlif;
2792
	}
2793
}
2794

    
2795
function get_real_interface($interface = "wan") {
2796
    global $config;
2797

    
2798
	$wanif = NULL;
2799

    
2800
	switch ($interface) {
2801
	case "l2tp":
2802
		$wanif = "l2tp";
2803
		break;
2804
	case "pptp":
2805
		$wanif = "pptp";
2806
		break;
2807
	case "pppoe":
2808
		$wanif = "pppoe";
2809
		break;
2810
	case "openvpn":
2811
		$wanif = "openvpn";
2812
		break;
2813
	case "ipsec":
2814
	case "enc0":
2815
		$wanif = "enc0";
2816
		break;
2817
	case "ppp":
2818
		$wanif = "ppp";
2819
		break;
2820
	default:
2821
		// If a real interface was alread passed simply
2822
		// pass the real interface back.  This encourages
2823
		// the usage of this function in more cases so that
2824
		// we can combine logic for more flexibility.
2825
		if(does_interface_exist($interface)) {
2826
			$wanif = $interface;
2827
			break;
2828
		}
2829
		if (empty($config['interfaces'][$interface]))
2830
			break;
2831

    
2832
		$cfg =& $config['interfaces'][$interface];
2833

    
2834
		// Wireless cloned NIC support (FreeBSD 8+)
2835
		// interface name format: $parentnic_wlanparentnic#
2836
		// example: ath0_wlan0
2837
		if (is_interface_wireless($cfg['if'])) {
2838
			$wanif = interface_get_wireless_clone($cfg['if']);
2839
			break;
2840
		}
2841
		/*
2842
		if (empty($cfg['if'])) {
2843
			$wancfg = $cfg['if'];
2844
			break;
2845
		}
2846
		*/
2847

    
2848
		switch ($cfg['ipaddr']) {
2849
			case "carpdev-dhcp":
2850
				$viparr = &$config['virtualip']['vip'];
2851
				if(is_array($viparr))
2852
				foreach ($viparr as $counter => $vip) {
2853
					if ($vip['mode'] == "carpdev-dhcp") {
2854
						if($vip['interface'] == $interface) {
2855
							$wanif = "carp{$counter}";
2856
							break;
2857
						}
2858
					}
2859
				}
2860
				break;
2861
			case "pppoe": 
2862
			case "pptp": 
2863
			case "l2tp": 
2864
			case "ppp":
2865
				$wanif = $cfg['if'];
2866
				break;
2867
			default:
2868
				$wanif = $cfg['if'];
2869
				break;
2870
		}
2871
		break;
2872
	}
2873

    
2874
    return $wanif;
2875
}
2876

    
2877
/* Guess the physical interface by providing a IP address */
2878
function guess_interface_from_ip($ipaddress) {
2879
	if(! is_ipaddr($ipaddress)) {
2880
		return false;
2881
	}
2882
	/* create a route table we can search */
2883
	exec("netstat -rnWf inet", $output, $ret);
2884
	foreach($output as $line) {
2885
		if(preg_match("/^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\/[0-9]+[ ]+link[#]/", $line)) {
2886
			$fields = preg_split("/[ ]+/", $line);
2887
			if(ip_in_subnet($ipaddress, $fields[0])) {
2888
				return $fields[6];
2889
			}
2890
		}
2891
	}
2892
	$ret = exec_command("/sbin/route -n get {$ipaddress} | /usr/bin/awk '/interface/ { print \$2; };'");
2893
	if(empty($ret)) {
2894
        	return false;
2895
	}
2896
	return $ret;
2897
}
2898

    
2899
/*
2900
 * find_ip_interface($ip): return the interface where an ip is defined
2901
 */
2902
function find_ip_interface($ip)
2903
{
2904
        /* if list */
2905
        $ifdescrs = get_configured_interface_list();
2906

    
2907
        foreach ($ifdescrs as $ifdescr => $ifname) {
2908
		if ($ip == get_interface_ip($ifname)) {
2909
                	$int = get_real_interface($ifname);
2910
			return $int;
2911
		}
2912
        }
2913
        return false;
2914
}
2915

    
2916
/*
2917
 *   find_number_of_created_carp_interfaces: return the number of carp interfaces
2918
 */
2919
function find_number_of_created_carp_interfaces() {
2920
	return `/sbin/ifconfig | grep "carp:" | wc -l`;
2921
}
2922

    
2923
function get_all_carp_interfaces() {
2924
	$ints = str_replace("\n", " ", `ifconfig | grep "carp:" -B2 | grep ": flag" | cut -d: -f1`);
2925
	$ints = explode(" ", $ints);
2926
	return $ints;
2927
}
2928

    
2929
/*
2930
 * find_carp_interface($ip): return the carp interface where an ip is defined
2931
 */
2932
function find_carp_interface($ip) {
2933
	global $config;
2934
	if (is_array($config['virtualip']['vip'])) {
2935
		foreach ($config['virtualip']['vip'] as $vip) {
2936
			if ($vip['mode'] == "carp" || $vip['mode'] == "carpdev") {
2937
				$carp_ip = get_interface_ip($vip['interface']);
2938
				$if = `ifconfig | grep '$ip ' -B1 | head -n1 | cut -d: -f1`;
2939
				if ($if)
2940
					return $if;
2941
			}
2942
		}
2943
	}
2944
}
2945

    
2946
function link_carp_interface_to_parent($interface) {
2947
        global $config;
2948

    
2949
        if ($interface == "")
2950
                return;
2951

    
2952
        $carp_ip = get_interface_ip($interface);
2953
        if (!is_ipaddr($carp_ip))
2954
                return;
2955

    
2956
        /* if list */
2957
        $ifdescrs = get_configured_interface_list();
2958
        foreach ($ifdescrs as $ifdescr => $ifname) {
2959
                $interfaceip = get_interface_ip($ifname);
2960
                $subnet_bits = get_interface_subnet($ifname);
2961
                $subnet_ip = gen_subnet("{$interfaceip}", "{$subnet_bits}");
2962
                if(ip_in_subnet($carp_ip, "{$subnet_ip}/{$subnet_bits}"))
2963
                        return $ifname;
2964
        }
2965

    
2966
        return "";
2967
}
2968

    
2969
/****f* interfaces/link_ip_to_carp_interface
2970
 * NAME
2971
 *   link_ip_to_carp_interface - Find where a CARP interface links to.
2972
 * INPUTS
2973
 *   $ip
2974
 * RESULT
2975
 *   $carp_ints
2976
 ******/
2977
function link_ip_to_carp_interface($ip) {
2978
        global $config;
2979

    
2980
        if (!is_ipaddr($ip))
2981
                return;
2982

    
2983
        $carp_ints = "";
2984
        if (is_array($config['virtualip']['vip'])) {
2985
		$first = 0;
2986
		$carp_int = array();
2987
                foreach ($config['virtualip']['vip'] as $vip) {
2988
                        if ($vip['mode'] == "carp" || $vip['mode'] == "carpdev") {
2989
                                $carp_ip = $vip['subnet'];
2990
                                $carp_sn = $vip['subnet_bits'];
2991
                                $carp_nw = gen_subnet($carp_ip, $carp_sn);
2992
                                if (ip_in_subnet($ip, "{$carp_nw}/{$carp_sn}"))
2993
					$carp_int[] = "vip{$vip['vhid']}";
2994
                        }
2995
                }
2996
		if (!empty($carp_int))
2997
			$carp_ints = implode(" ", array_unique($carp_int));
2998
        }
2999

    
3000
        return $carp_ints;
3001
}
3002

    
3003
function link_interface_to_vlans($int, $action = "") {
3004
	global $config;
3005

    
3006
	if (empty($int))
3007
		return;
3008

    
3009
	if (is_array($config['vlans']['vlan'])) {
3010
                foreach ($config['vlans']['vlan'] as $vlan) {
3011
			if ($int == $vlan['if']) {
3012
				if ($action == "update") {
3013
					interfaces_bring_up($int);
3014
				} else if ($action == "")
3015
					return $vlan;
3016
			}
3017
		}
3018
	}
3019
}
3020

    
3021
function link_interface_to_vips($int, $action = "") {
3022
        global $config;
3023

    
3024
        if (is_array($config['virtualip']['vip']))
3025
                foreach ($config['virtualip']['vip'] as $vip)
3026
                        if ($int == $vip['interface']) {
3027
				if ($action == "update")
3028
					interfaces_vips_configure($int);
3029
				else
3030
                                	return $vip;
3031
			}
3032
}
3033

    
3034
/****f* interfaces/link_interface_to_bridge
3035
 * NAME
3036
 *   link_interface_to_bridge - Finds out a bridge group for an interface
3037
 * INPUTS
3038
 *   $ip
3039
 * RESULT
3040
 *   bridge[0-99]
3041
 ******/
3042
function link_interface_to_bridge($int) {
3043
        global $config;
3044

    
3045
        if (is_array($config['bridges']['bridged'])) {
3046
                foreach ($config['bridges']['bridged'] as $bridge) {
3047
			if (in_array($int, explode(',', $bridge['members'])))
3048
                                return "{$bridge['bridgeif']}";
3049
		}
3050
	}
3051
}
3052

    
3053
function link_interface_to_group($int) {
3054
        global $config;
3055

    
3056
        if (is_array($config['ifgroups']['ifgroupentry'])) {
3057
                foreach ($config['ifgroups']['ifgroupentry'] as $group) {
3058
			if (in_array($int, explode(" ", $groupname['members'])))
3059
                                return "{$group['ifname']}";
3060
		}
3061
	}
3062
}
3063

    
3064
function link_interface_to_gre($interface) {
3065
        global $config;
3066

    
3067
        if (is_array($config['gres']['gre']))
3068
                foreach ($config['gres']['gre'] as $gre)
3069
                        if($gre['if'] == $interface)
3070
                                return $gre;
3071
}
3072

    
3073
function link_interface_to_gif($interface) {
3074
        global $config;
3075

    
3076
        if (is_array($config['gifs']['gif']))
3077
                foreach ($config['gifs']['gif'] as $gif)
3078
                        if($gif['if'] == $interface)
3079
                                return $gif;
3080
}
3081

    
3082
/*
3083
 * find_interface_ip($interface): return the interface ip (first found)
3084
 */
3085
function find_interface_ip($interface, $flush = false)
3086
{
3087
	global $interface_ip_arr_cache;
3088

    
3089
	$interface = str_replace("\n", "", $interface);
3090
	
3091
	if (!does_interface_exist($interface))
3092
		return;
3093

    
3094
	/* Setup IP cache */
3095
	if (!isset($interface_ip_arr_cache[$interface]) or $flush) {
3096
		$ifinfo = pfSense_get_interface_addresses($interface);
3097
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
3098
	}
3099

    
3100
	return $interface_ip_arr_cache[$interface];
3101
}
3102

    
3103
function find_interface_subnet($interface, $flush = false)
3104
{
3105
	global $interface_sn_arr_cache;
3106

    
3107
	$interface = str_replace("\n", "", $interface);
3108
	if (does_interface_exist($interface) == false)
3109
		return;
3110

    
3111
	if (!isset($interface_sn_arr_cache[$interface]) or $flush) {
3112
		$ifinfo = pfSense_get_interface_addresses($interface);
3113
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
3114
        }
3115

    
3116
	return $interface_sn_arr_cache[$interface];
3117
}
3118

    
3119
function ip_in_interface_alias_subnet($interface, $ipalias) {
3120
	global $config;
3121

    
3122
	if (empty($interface) || !is_ipaddr($ipalias))
3123
		return false;
3124
	if (is_array($config['virtualip']['vip'])) {
3125
                foreach ($config['virtualip']['vip'] as $vip) {
3126
                        switch ($vip['mode']) {
3127
                        case "ipalias":
3128
                                if ($vip['interface'] <> $interface)
3129
                                        break;
3130
				if (ip_in_subnet($ipalias, gen_subnet($vip['subnet'], $vip['subnet_bits']) . "/" . $vip['subnet_bits']))
3131
					return true;
3132
                                break;
3133
                        }
3134
                }
3135
	}
3136

    
3137
	return false;
3138
}
3139

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

    
3152
	$curip = find_interface_ip($realif);
3153
	if ($curip && is_ipaddr($curip) && ($curip != "0.0.0.0"))
3154
		return $curip;
3155
	else
3156
		return null;
3157
}
3158

    
3159
function get_interface_subnet($interface = "wan")
3160
{
3161
	$realif = get_real_interface($interface);
3162
	if (!$realif) {
3163
                if (preg_match("/^carp/i", $interface))
3164
                        $realif = $interface;
3165
                else if (preg_match("/^vip/i", $interface))
3166
                        $realif = $interface;
3167
                else
3168
                        return null;
3169
        }
3170

    
3171
	$cursn = find_interface_subnet($realif);
3172
	if (!empty($cursn))
3173
		return $cursn;
3174

    
3175
	return null;
3176
}
3177

    
3178
/* return outside interfaces with a gateway */
3179
function get_interfaces_with_gateway() {
3180
	global $config;
3181

    
3182
	$ints = array();
3183

    
3184
	/* loop interfaces, check config for outbound */
3185
	foreach($config['interfaces'] as $ifdescr => $ifname) {
3186
		if (substr($ifdescr, 0, 5) ==  "ovpnc")
3187
			return true;
3188

    
3189
		switch ($ifname['ipaddr']) {
3190
			case "dhcp":
3191
			case "carpdev-dhcp":
3192
			case "ppp";
3193
			case "pppoe":
3194
			case "pptp":
3195
			case "l2tp":
3196
			case "ppp";
3197
				$ints[$ifdescr] = $ifdescr;
3198
			break;
3199
			default:
3200
				if (!empty($ifname['gateway']))
3201
					$ints[$ifdescr] = $ifdescr;
3202
			break;
3203
		}
3204
	}
3205
	return $ints;
3206
}
3207

    
3208
/* return true if interface has a gateway */
3209
function interface_has_gateway($friendly) {
3210
	global $config;
3211

    
3212
	if (!empty($config['interfaces'][$friendly])) {
3213
		if (substr($friendly, 0, 5) ==  "ovpnc")
3214
			return true;
3215
		$ifname =& $config['interfaces'][$friendly];
3216
		switch ($ifname['ipaddr']) {
3217
			case "dhcp":
3218
			case "carpdev-dhcp":
3219
			case "pppoe":
3220
			case "pptp":
3221
			case "l2tp":
3222
			case "ppp";
3223
				return true;
3224
			break;
3225
			default:
3226
				if (!empty($ifname['gateway']))
3227
					return true;
3228
			break;
3229
		}
3230
	}
3231

    
3232
	return false;
3233
}
3234

    
3235
/****f* interfaces/is_altq_capable
3236
 * NAME
3237
 *   is_altq_capable - Test if interface is capable of using ALTQ
3238
 * INPUTS
3239
 *   $int            - string containing interface name
3240
 * RESULT
3241
 *   boolean         - true or false
3242
 ******/
3243

    
3244
function is_altq_capable($int) {
3245
        /* Per:
3246
         * http://www.freebsd.org/cgi/man.cgi?query=altq&manpath=FreeBSD+7.2-current&format=html
3247
         * Only the following drivers have ALTQ support
3248
         */
3249
	$capable = array("age", "ale", "an", "ath", "aue", "awi", "bce",
3250
			"bfe", "bge", "dc", "de", "ed", "em", "ep", "fxp", "gem",
3251
			"hme", "igb", "ipw", "iwi", "jme", "le", "msk", "mxge", "my", "nfe",
3252
			"npe", "nve", "ral", "re", "rl", "rum", "run", "bwn", "sf", "sis", "sk",
3253
			"ste", "stge", "txp", "udav", "ural", "vge", "vr", "wi", "xl",
3254
			"ndis", "tun", "ovpns", "ovpnc", "vlan", "pppoe", "pptp", "ng",
3255
			"l2tp", "ppp");
3256

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

    
3259
        if (in_array($int_family[0], $capable))
3260
                return true;
3261
	else if (stristr($int_family, "vlan")) /* VLANs are name $parent_$vlan now */
3262
		return true;
3263
	else if (stristr($int_family, "_wlan")) /* WLANs are name $parent_$wlan now */
3264
		return true;
3265
        else
3266
                return false;
3267
}
3268

    
3269
/****f* interfaces/is_interface_wireless
3270
 * NAME
3271
 *   is_interface_wireless - Returns if an interface is wireless
3272
 * RESULT
3273
 *   $tmp       - Returns if an interface is wireless
3274
 ******/
3275
function is_interface_wireless($interface) {
3276
        global $config, $g;
3277

    
3278
        $friendly = convert_real_interface_to_friendly_interface_name($interface);
3279
        if(!isset($config['interfaces'][$friendly]['wireless'])) {
3280
                if (preg_match($g['wireless_regex'], $interface)) {
3281
                        if (isset($config['interfaces'][$friendly]))
3282
                                $config['interfaces'][$friendly]['wireless'] = array();
3283
                        return true;
3284
                }
3285
                return false;
3286
        } else
3287
                return true;
3288
}
3289

    
3290
function get_wireless_modes($interface) {
3291
	/* return wireless modes and channels */
3292
	$wireless_modes = array();
3293

    
3294
	$wlif = interface_translate_type_to_real($interface);
3295

    
3296
	if(is_interface_wireless($wlif)) {
3297
		$cloned_interface = get_real_interface($interface);
3298
		$chan_list = "/sbin/ifconfig {$cloned_interface} list chan";
3299
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
3300
		$format_list = "/usr/bin/awk '{print \$5 \" \" \$6 \",\" \$1}'";
3301

    
3302
		$interface_channels = "";
3303
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
3304
		$interface_channel_count = count($interface_channels);
3305

    
3306
		$c = 0;
3307
		while ($c < $interface_channel_count)
3308
		{
3309
			$channel_line = explode(",", $interface_channels["$c"]);
3310
			$wireless_mode = trim($channel_line[0]);
3311
			$wireless_channel = trim($channel_line[1]);
3312
			if(trim($wireless_mode) != "") {
3313
				/* if we only have 11g also set 11b channels */
3314
				if($wireless_mode == "11g") {
3315
					if(!isset($wireless_modes["11b"]))
3316
						$wireless_modes["11b"] = array();
3317
				} else if($wireless_mode == "11g ht") {
3318
					if(!isset($wireless_modes["11b"]))
3319
						$wireless_modes["11b"] = array();
3320
					if(!isset($wireless_modes["11g"]))
3321
						$wireless_modes["11g"] = array();
3322
					$wireless_mode = "11ng";
3323
				} else if($wireless_mode == "11a ht") {
3324
					if(!isset($wireless_modes["11a"]))
3325
						$wireless_modes["11a"] = array();
3326
					$wireless_mode = "11na";
3327
				}
3328
				$wireless_modes["$wireless_mode"]["$c"] = $wireless_channel;
3329
			}
3330
			$c++;
3331
		}
3332
	}
3333
	return($wireless_modes);
3334
}
3335

    
3336
/* return channel numbers, frequency, max txpower, and max regulation txpower */
3337
function get_wireless_channel_info($interface) {
3338
	$wireless_channels = array();
3339

    
3340
	$wlif = interface_translate_type_to_real($interface);
3341

    
3342
	if(is_interface_wireless($wlif)) {
3343
		$cloned_interface = get_real_interface($interface);
3344
		$chan_list = "/sbin/ifconfig {$cloned_interface} list txpower";
3345
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
3346
		$format_list = "/usr/bin/awk '{print \$1 \",\" \$3 \" \" \$4 \",\" \$5 \",\" \$7}'";
3347

    
3348
		$interface_channels = "";
3349
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
3350

    
3351
		foreach ($interface_channels as $channel_line) {
3352
			$channel_line = explode(",", $channel_line);
3353
			if(!isset($wireless_channels[$channel_line[0]]))
3354
				$wireless_channels[$channel_line[0]] = $channel_line;
3355
		}
3356
	}
3357
	return($wireless_channels);
3358
}
3359

    
3360
/****f* interfaces/get_interface_mtu
3361
 * NAME
3362
 *   get_interface_mtu - Return the mtu of an interface
3363
 * RESULT
3364
 *   $tmp       - Returns the mtu of an interface
3365
 ******/
3366
function get_interface_mtu($interface) {
3367
        $mtu = pfSense_get_interface_addresses($interface);
3368
        return $mtu['mtu'];
3369
}
3370

    
3371
function get_interface_mac($interface) {
3372

    
3373
	$macinfo = pfSense_get_interface_addresses($interface);
3374
	return $macinfo["macaddr"];
3375
}
3376

    
3377
/****f* pfsense-utils/generate_random_mac_address
3378
 * NAME
3379
 *   generate_random_mac - generates a random mac address
3380
 * INPUTS
3381
 *   none
3382
 * RESULT
3383
 *   $mac - a random mac address
3384
 ******/
3385
function generate_random_mac_address() {
3386
        $mac = "02";
3387
        for($x=0; $x<5; $x++)
3388
                $mac .= ":" . dechex(rand(16, 255));
3389
        return $mac;
3390
}
3391

    
3392
/****f* interfaces/is_jumbo_capable
3393
 * NAME
3394
 *   is_jumbo_capable - Test if interface is jumbo frame capable.  Useful for determining VLAN capability.
3395
 * INPUTS
3396
 *   $int             - string containing interface name
3397
 * RESULT
3398
 *   boolean          - true or false
3399
 ******/
3400
function is_jumbo_capable($int) {
3401
        global $g;
3402

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

    
3405
        if (in_array($int_family[0], $g['vlan_long_frame']))
3406
                return true;
3407
        else
3408
                return false;
3409
}
3410

    
3411
function setup_pppoe_reset_file($pppif, $iface="") {
3412
	global $g;
3413
	$cron_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
3414

    
3415
	if(!empty($iface) && !empty($pppif)){
3416
		$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";
3417
		file_put_contents($cron_file, $cron_cmd);
3418
		chmod($cron_file, 0700);
3419
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
3420
	} else
3421
		unlink_if_exists($cron_file);
3422
}
3423

    
3424
?>
(22-22/54)