Project

General

Profile

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

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

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

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

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

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

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

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

    
42
*/
43

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

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

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

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

    
67
        return $interface_arr_cache;
68
}
69

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

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

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

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

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

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

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

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

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

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

    
145
	interfaces_bring_up($vlanif);
146

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

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

    
153
	return $vlanif;
154
}
155

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

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

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

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

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

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

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

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

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

    
222
        return $vlanif;
223
}
224

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

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

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

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

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

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

    
265
        return $vlanif;
266
}
267

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

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

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

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

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

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

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

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

    
319
	$checklist = get_configured_interface_list();
320

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

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

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

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

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

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

    
478
	return $bridgeif;
479
}
480

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
569
	interfaces_bring_up($laggif);
570

    
571
	return $laggif;
572
}
573

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

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

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

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

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

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

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

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

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

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

    
627
	return $greif;
628
}
629

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

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

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

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

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

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

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

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

    
682
	return $gifif;
683
}
684

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

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

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

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

    
697
	interfaces_qinq_configure();
698

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

    
708
	foreach($iflist as $if => $ifname) {
709
		$realif = $config['interfaces'][$if]['if'];
710
		if (strstr($realif, "bridge")) 
711
			$bridge_list[$if] = $ifname;
712
		else if (strstr($realif, "gre"))
713
			$delayed_list[$if] = $ifname;
714
		else if (strstr($realif, "gif"))
715
			$delayed_list[$if] = $ifname;
716
		else 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
			if ($destroy == true)
871
				pfSense_interface_flags($realif, -IFF_UP);
872
			mwexec("/usr/sbin/arp -d -i {$realif} -a");
873
		}
874
		break;
875
	default:
876
		if(does_interface_exist("$realif")) {
877
			mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete", true);
878
			if ($destroy == true)
879
				pfSense_interface_flags($realif, -IFF_UP);
880
			mwexec("/usr/sbin/arp -d -i {$realif} -a");
881
		}
882
		break;
883
	}
884

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

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

    
902
	return;
903
}
904

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

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

    
913
	return false;
914
}
915

    
916
function interfaces_ptpid_next() {
917

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

    
922
	return $ptpid;
923
}
924

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1214
EOD;
1215

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

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

    
1229
EOD;
1230

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

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

    
1241
EOD;
1242

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

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

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

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

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

    
1269
EOD;
1270

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

    
1275
EOD;
1276

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

    
1281
EOD;
1282

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

    
1288
EOD;
1289

    
1290

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

    
1295
EOD;
1296

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

    
1302
EOD;
1303

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

    
1308
EOD;
1309

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

    
1314
EOD;
1315

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

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

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

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

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

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

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

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

    
1369
EOD;
1370

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

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

    
1383

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

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

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

    
1424
	return 1;
1425
}
1426

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1628
function interface_ipalias_configure(&$vip) {
1629

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1788
EOD;
1789

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

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

    
1800
	return $vipif;
1801
}
1802

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2157
EOD;
2158

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

    
2165
EOD;
2166

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

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

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

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

    
2188
			}
2189
			break;
2190
	}
2191

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2304
	return 0;
2305

    
2306
}
2307

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

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

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

    
2322
	return $pid;
2323
}
2324

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

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

    
2331
	$realif = get_real_interface($interface);
2332

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

    
2338
	/* Clone wireless nic if needed. */
2339
	if (is_array($wancfg['wireless']))
2340
		interface_wireless_clone($realif, $wancfg);
2341

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

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

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

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

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

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

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

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

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

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

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

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

    
2482
	/* wireless configuration? */
2483
	if (is_array($wancfg['wireless']))
2484
		interface_wireless_configure($realif, $wancfg, $wancfg['wireless']);
2485

    
2486
	if(does_interface_exist($wancfg['if']))
2487
		interfaces_bring_up($wancfg['if']);
2488
 	
2489
	if (!$g['booting']) {
2490
		interface_reload_carps($realif);
2491

    
2492
		unset($gre);
2493
		$gre = link_interface_to_gre($interface);
2494
		if (!empty($gre))
2495
			interface_gre_configure($gre);
2496

    
2497
		unset($gif);
2498
		$gif = link_interface_to_gif($interface);
2499
		if (!empty($gif))
2500
                       	interface_gif_configure($gif);
2501

    
2502
		if ($linkupevent == false) {
2503
			unset($bridgetmp);
2504
			$bridgetmp = link_interface_to_bridge($interface);
2505
			if (!empty($bridgetmp))
2506
				interface_bridge_add_member($bridgetmp, $realif);
2507
		}
2508

    
2509
		link_interface_to_vips($interface, "update");
2510

    
2511
		$grouptmp = link_interface_to_group($interface);
2512
		if (!empty($grouptmp))
2513
			interface_group_add_member($realif, $grouptmp);
2514

    
2515
		if ($interface == "lan")
2516
			/* make new hosts file */
2517
			system_hosts_generate();
2518

    
2519
		if ($reloadall == true) {
2520

    
2521
			/* reconfigure static routes (kernel may have deleted them) */
2522
			system_routing_configure($interface);
2523

    
2524
			/* reload ipsec tunnels */
2525
			vpn_ipsec_configure();
2526

    
2527
			/* update dyndns */
2528
			services_dyndns_configure($interface);
2529

    
2530
			/* force DNS update */
2531
			services_dnsupdate_process($interface);
2532

    
2533
			/* restart dnsmasq */
2534
			services_dnsmasq_configure();
2535

    
2536
			/* reload captive portal */
2537
			captiveportal_init_rules();
2538

    
2539
			/* set the reload filter dity flag */
2540
			filter_configure();
2541
		}
2542
	}
2543

    
2544
	return 0;
2545
}
2546

    
2547
function interface_carpdev_dhcp_configure($interface = "wan") {
2548
	global $config, $g;
2549

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

    
2558
	return 0;
2559
}
2560

    
2561
function interface_dhcp_configure($interface = "wan") {
2562
	global $config, $g;
2563

    
2564
	$wancfg = $config['interfaces'][$interface];
2565
	if (empty($wancfg))
2566
		$wancfg = array();
2567

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

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

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

    
2599
EOD;
2600

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

    
2610
EOD;
2611
}
2612
	fwrite($fd, $dhclientconf);
2613
	fclose($fd);
2614

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

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

    
2624
	return 0;
2625
}
2626

    
2627
function interfaces_group_setup() {
2628
	global $config;
2629

    
2630
	if (!is_array($config['ifgroups']['ifgroupentry']))
2631
		return;
2632

    
2633
	foreach ($config['ifgroups']['ifgroupentry'] as $groupar)
2634
		interface_group_setup($groupar);
2635

    
2636
	return;
2637
}
2638

    
2639
function interface_group_setup(&$groupname /* The parameter is an array */) {
2640
	global $config;
2641

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

    
2651
	return;
2652
}
2653

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

    
2663
/* COMPAT Function */
2664
function get_real_wan_interface($interface = "wan") {
2665
	return get_real_interface($interface);
2666
}
2667

    
2668
/* COMPAT Function */
2669
function get_current_wan_address($interface = "wan") {
2670
	return get_interface_ip($interface);
2671
}
2672

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

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

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

    
2693
        foreach ($ifdescrs as $if => $ifname) {
2694
                if ($config['interfaces'][$if]['if'] == $interface)
2695
                        return $if;
2696

    
2697
                if (stristr($interface, "_wlan0") && $config['interfaces'][$if]['if'] == interface_get_wireless_base($interface))
2698
                        return $if;
2699

    
2700
                $int = interface_translate_type_to_real($if);
2701
                if ($int == $interface)
2702
                        return $ifname;
2703
        }
2704
        return NULL;
2705
}
2706

    
2707
/* attempt to resolve interface to friendly descr */
2708
function convert_friendly_interface_to_friendly_descr($interface) {
2709
        global $config;
2710

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

    
2745
        return $ifdesc;
2746
}
2747

    
2748
function convert_real_interface_to_friendly_descr($interface) {
2749
        global $config;
2750

    
2751
        $ifdesc = convert_real_interface_to_friendly_interface_name("{$interface}");
2752

    
2753
        if ($ifdesc) {
2754
                $iflist = get_configured_interface_with_descr(false, true);
2755
                return $iflist[$ifdesc];
2756
        }
2757

    
2758
        return $interface;
2759
}
2760

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

    
2768
        if ($config['interfaces'][$interface]['if'] <> "")
2769
                return $config['interfaces'][$interface]['if'];
2770
        else
2771
		return $interface;
2772
}
2773

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

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

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

    
2798
function get_real_interface($interface = "wan") {
2799
    global $config;
2800

    
2801
	$wanif = NULL;
2802

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

    
2835
		$cfg =& $config['interfaces'][$interface];
2836

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

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

    
2877
    return $wanif;
2878
}
2879

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

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

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

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

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

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

    
2949
function link_carp_interface_to_parent($interface) {
2950
        global $config;
2951

    
2952
        if ($interface == "")
2953
                return;
2954

    
2955
        $carp_ip = get_interface_ip($interface);
2956
        if (!is_ipaddr($carp_ip))
2957
                return;
2958

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

    
2969
        return "";
2970
}
2971

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

    
2983
        if (!is_ipaddr($ip))
2984
                return;
2985

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

    
3003
        return $carp_ints;
3004
}
3005

    
3006
function link_interface_to_vlans($int, $action = "") {
3007
	global $config;
3008

    
3009
	if (empty($int))
3010
		return;
3011

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

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

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

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

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

    
3056
function link_interface_to_group($int) {
3057
        global $config;
3058

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

    
3067
function link_interface_to_gre($interface) {
3068
        global $config;
3069

    
3070
        if (is_array($config['gres']['gre']))
3071
                foreach ($config['gres']['gre'] as $gre)
3072
                        if($gre['if'] == $interface)
3073
                                return $gre;
3074
}
3075

    
3076
function link_interface_to_gif($interface) {
3077
        global $config;
3078

    
3079
        if (is_array($config['gifs']['gif']))
3080
                foreach ($config['gifs']['gif'] as $gif)
3081
                        if($gif['if'] == $interface)
3082
                                return $gif;
3083
}
3084

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

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

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

    
3103
	return $interface_ip_arr_cache[$interface];
3104
}
3105

    
3106
function find_interface_subnet($interface, $flush = false)
3107
{
3108
	global $interface_sn_arr_cache;
3109

    
3110
	$interface = str_replace("\n", "", $interface);
3111
	if (does_interface_exist($interface) == false)
3112
		return;
3113

    
3114
	if (!isset($interface_sn_arr_cache[$interface]) or $flush) {
3115
		$ifinfo = pfSense_get_interface_addresses($interface);
3116
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
3117
        }
3118

    
3119
	return $interface_sn_arr_cache[$interface];
3120
}
3121

    
3122
function ip_in_interface_alias_subnet($interface, $ipalias) {
3123
	global $config;
3124

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

    
3140
	return false;
3141
}
3142

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

    
3155
	$curip = find_interface_ip($realif);
3156
	if ($curip && is_ipaddr($curip) && ($curip != "0.0.0.0"))
3157
		return $curip;
3158
	else
3159
		return null;
3160
}
3161

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

    
3174
	$cursn = find_interface_subnet($realif);
3175
	if (!empty($cursn))
3176
		return $cursn;
3177

    
3178
	return null;
3179
}
3180

    
3181
/* return outside interfaces with a gateway */
3182
function get_interfaces_with_gateway() {
3183
	global $config;
3184

    
3185
	$ints = array();
3186

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

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

    
3211
/* return true if interface has a gateway */
3212
function interface_has_gateway($friendly) {
3213
	global $config;
3214

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

    
3235
	return false;
3236
}
3237

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

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

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

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

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

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

    
3293
function get_wireless_modes($interface) {
3294
	/* return wireless modes and channels */
3295
	$wireless_modes = array();
3296

    
3297
	$wlif = interface_translate_type_to_real($interface);
3298

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

    
3305
		$interface_channels = "";
3306
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
3307
		$interface_channel_count = count($interface_channels);
3308

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

    
3339
/* return channel numbers, frequency, max txpower, and max regulation txpower */
3340
function get_wireless_channel_info($interface) {
3341
	$wireless_channels = array();
3342

    
3343
	$wlif = interface_translate_type_to_real($interface);
3344

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

    
3351
		$interface_channels = "";
3352
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
3353

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

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

    
3374
function get_interface_mac($interface) {
3375

    
3376
	$macinfo = pfSense_get_interface_addresses($interface);
3377
	return $macinfo["macaddr"];
3378
}
3379

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

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

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

    
3408
        if (in_array($int_family[0], $g['vlan_long_frame']))
3409
                return true;
3410
        else
3411
                return false;
3412
}
3413

    
3414
function setup_pppoe_reset_file($pppif, $iface="") {
3415
	global $g;
3416
	$cron_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
3417

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

    
3427
?>
(22-22/54)