Project

General

Profile

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

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

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

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

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

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

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

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

    
42
*/
43

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

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

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

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

    
67
        return $interface_arr_cache;
68
}
69

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

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

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

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

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

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

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

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

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

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

    
145
	interfaces_bring_up($vlanif);
146

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

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

    
153
	return $vlanif;
154
}
155

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

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

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

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

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

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

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

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

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

    
222
        return $vlanif;
223
}
224

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

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

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

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

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

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

    
265
        return $vlanif;
266
}
267

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

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

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

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

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

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

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

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

    
319
	$checklist = get_configured_interface_list();
320

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

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

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

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

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

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

    
478
	return $bridgeif;
479
}
480

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
569
	interfaces_bring_up($laggif);
570

    
571
	return $laggif;
572
}
573

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

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

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

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

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

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

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

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

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

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

    
627
	return $greif;
628
}
629

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

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

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

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

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

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

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

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

    
682
	return $gifif;
683
}
684

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

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

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

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

    
697
	interfaces_qinq_configure();
698

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

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

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

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

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

    
745
		interface_configure($if, $reload);
746

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

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

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

    
760
		interface_configure($if, $reload);
761

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

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

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

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

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

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

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

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

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

    
792
	return 0;
793
}
794

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

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

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

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

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

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

    
835
	$realif = get_real_interface($interface);
836

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

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

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

    
900
	return;
901
}
902

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

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

    
911
	return false;
912
}
913

    
914
function interfaces_ptpid_next() {
915

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

    
920
	return $ptpid;
921
}
922

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1212
EOD;
1213

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

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

    
1227
EOD;
1228

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

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

    
1239
EOD;
1240

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

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

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

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

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

    
1267
EOD;
1268

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

    
1273
EOD;
1274

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

    
1279
EOD;
1280

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

    
1286
EOD;
1287

    
1288

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

    
1293
EOD;
1294

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

    
1300
EOD;
1301

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

    
1306
EOD;
1307

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

    
1312
EOD;
1313

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

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

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

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

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

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

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

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

    
1367
EOD;
1368

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

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

    
1381

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

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

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

    
1422
	return 1;
1423
}
1424

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1626
function interface_ipalias_configure(&$vip) {
1627

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1786
EOD;
1787

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

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

    
1798
	return $vipif;
1799
}
1800

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2158
EOD;
2159

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

    
2166
EOD;
2167

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

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

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

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

    
2189
			}
2190
			break;
2191
	}
2192

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2305
	return 0;
2306

    
2307
}
2308

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

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

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

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

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

    
2330
	$realif = get_real_interface($interface);
2331

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

    
2338
	/* wireless configuration? */
2339
	if (is_array($wancfg['wireless']))
2340
		interface_wireless_configure($realif, $wancfg, $wancfg['wireless']);
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_carpdev_dhcp_configure($interface);
2443
			break;
2444
		case 'dhcp':
2445
			interface_dhcp_configure($interface);
2446
			break;
2447
		case 'pppoe':
2448
		case 'l2tp':
2449
		case 'pptp':
2450
		case 'ppp':
2451
			interface_ppps_configure($interface);
2452
			break;
2453
		default:
2454
			if ($wancfg['ipaddr'] <> "" && $wancfg['subnet'] <> "") {
2455
				pfSense_interface_setaddress($realif, "{$wancfg['ipaddr']}/{$wancfg['subnet']}");
2456
			} else if (substr($realif, 0, 3) == "gre") {
2457
				if (is_array($config['gres']['gre'])) {
2458
					foreach ($config['gres']['gre'] as $gre)
2459
						if ($gre['greif'] == $realif)
2460
							interface_gre_configure($gre);
2461
				}
2462
			} else if (substr($realif, 0, 3) == "gif") {
2463
				 if (is_array($config['gifs']['gif'])) {
2464
					foreach ($config['gifs']['gif'] as $gif)
2465
						if($gif['gifif'] == $interface)
2466
							interface_gif_configure($gif);
2467
				}
2468
			} else if (substr($realif, 0, 4) == "ovpn") {
2469
				/* XXX: Should be done anything?! */
2470
			}
2471

    
2472
			if (is_ipaddr($wancfg['gateway']))
2473
				file_put_contents("{$g['tmp_path']}/{$realif}_router", $wancfg['gateway']);
2474
			break;
2475
	}
2476

    
2477
	if(does_interface_exist($wancfg['if']))
2478
		interfaces_bring_up($wancfg['if']);
2479
 	
2480
	if (!$g['booting']) {
2481
		interface_reload_carps($realif);
2482

    
2483
		unset($gre);
2484
		$gre = link_interface_to_gre($interface);
2485
		if (!empty($gre))
2486
			interface_gre_configure($gre);
2487

    
2488
		unset($gif);
2489
		$gif = link_interface_to_gif($interface);
2490
		if (!empty($gif))
2491
                       	interface_gif_configure($gif);
2492

    
2493
		if ($linkupevent == false) {
2494
			unset($bridgetmp);
2495
			$bridgetmp = link_interface_to_bridge($interface);
2496
			if (!empty($bridgetmp))
2497
				interface_bridge_add_member($bridgetmp, $realif);
2498
		}
2499

    
2500
		link_interface_to_vips($interface, "update");
2501

    
2502
		$grouptmp = link_interface_to_group($interface);
2503
		if (!empty($grouptmp))
2504
			interface_group_add_member($realif, $grouptmp);
2505

    
2506
		if ($interface == "lan")
2507
			/* make new hosts file */
2508
			system_hosts_generate();
2509

    
2510
		if ($reloadall == true) {
2511

    
2512
			/* reconfigure static routes (kernel may have deleted them) */
2513
			system_routing_configure($interface);
2514

    
2515
			/* reload ipsec tunnels */
2516
			vpn_ipsec_configure();
2517

    
2518
			/* update dyndns */
2519
			services_dyndns_configure($interface);
2520

    
2521
			/* force DNS update */
2522
			services_dnsupdate_process($interface);
2523

    
2524
			/* restart dnsmasq */
2525
			services_dnsmasq_configure();
2526

    
2527
			/* reload captive portal */
2528
			captiveportal_init_rules();
2529

    
2530
			/* set the reload filter dity flag */
2531
			filter_configure();
2532
		}
2533
	}
2534

    
2535
	return 0;
2536
}
2537

    
2538
function interface_carpdev_dhcp_configure($interface = "wan") {
2539
	global $config, $g;
2540

    
2541
	$wancfg = $config['interfaces'][$interface];
2542
	$wanif = $wancfg['if'];
2543
	/* bring wan interface up before starting dhclient */
2544
	if($wanif)
2545
		interfaces_bring_up($wanif);
2546
	else 
2547
		log_error("Could not bring wanif up in terface_carpdev_dhcp_configure()");
2548

    
2549
	return 0;
2550
}
2551

    
2552
function interface_dhcp_configure($interface = "wan") {
2553
	global $config, $g;
2554

    
2555
	$wancfg = $config['interfaces'][$interface];
2556
	if (empty($wancfg))
2557
		$wancfg = array();
2558

    
2559
	/* generate dhclient_wan.conf */
2560
	$fd = fopen("{$g['varetc_path']}/dhclient_{$interface}.conf", "w");
2561
	if (!$fd) {
2562
		printf("Error: cannot open dhclient_{$interface}.conf in interfaces_wan_dhcp_configure() for writing.\n");
2563
		return 1;
2564
	}
2565

    
2566
	if ($wancfg['dhcphostname']) {
2567
		$dhclientconf_hostname = "send dhcp-client-identifier \"{$wancfg['dhcphostname']}\";\n";
2568
		$dhclientconf_hostname .= "\tsend host-name \"{$wancfg['dhcphostname']}\";\n";
2569
	} else {
2570
		$dhclientconf_hostname = "";
2571
	}
2572

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

    
2590
EOD;
2591

    
2592
if(is_ipaddr($wancfg['alias-address'])) {
2593
	$subnetmask = gen_subnet_mask($wancfg['alias-subnet']);
2594
	$dhclientconf .= <<<EOD
2595
alias {
2596
	interface  "{$wanif}";
2597
	fixed-address {$wancfg['alias-address']};
2598
	option subnet-mask {$subnetmask};
2599
}
2600

    
2601
EOD;
2602
}
2603
	fwrite($fd, $dhclientconf);
2604
	fclose($fd);
2605

    
2606
	/* bring wan interface up before starting dhclient */
2607
	if($wanif)
2608
		interfaces_bring_up($wanif);
2609
	else 
2610
		log_error("Could not bring up {$wanif} interface in interface_dhcp_configure()");
2611

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

    
2615
	return 0;
2616
}
2617

    
2618
function interfaces_group_setup() {
2619
	global $config;
2620

    
2621
	if (!is_array($config['ifgroups']['ifgroupentry']))
2622
		return;
2623

    
2624
	foreach ($config['ifgroups']['ifgroupentry'] as $groupar)
2625
		interface_group_setup($groupar);
2626

    
2627
	return;
2628
}
2629

    
2630
function interface_group_setup(&$groupname /* The parameter is an array */) {
2631
	global $config;
2632

    
2633
	if (!is_array($groupname))
2634
		return;
2635
	$members = explode(" ", $groupname['members']);
2636
	foreach($members as $ifs) {
2637
		$realif = get_real_interface($ifs);
2638
		if ($realif)
2639
			mwexec("/sbin/ifconfig {$realif} group {$groupname['ifname']}");
2640
	}
2641

    
2642
	return;
2643
}
2644

    
2645
function interface_group_add_member($interface, $groupname) {
2646
	mwexec("/sbin/ifconfig {$interface} group {$groupname}", true);
2647
}
2648
 
2649
/* COMPAT Function */
2650
function convert_friendly_interface_to_real_interface_name($interface) {
2651
	return get_real_interface($interface);
2652
}
2653

    
2654
/* COMPAT Function */
2655
function get_real_wan_interface($interface = "wan") {
2656
	return get_real_interface($interface);
2657
}
2658

    
2659
/* COMPAT Function */
2660
function get_current_wan_address($interface = "wan") {
2661
	return get_interface_ip($interface);
2662
}
2663

    
2664
/*
2665
 * convert_real_interface_to_friendly_interface_name($interface): convert fxp0 -> wan, etc.
2666
 */
2667
function convert_real_interface_to_friendly_interface_name($interface = "wan") {
2668
        global $config;
2669

    
2670
	if (stristr($interface, "vip")) {
2671
                $index = intval(substr($interface, 3));
2672
                foreach ($config['virtualip']['vip'] as $counter => $vip) {
2673
                        if ($vip['mode'] == "carpdev-dhcp" || $vip['mode'] == "carp")  {
2674
                                if ($index == $counter)
2675
                                        return $vip['interface'];
2676
                        }
2677
                }
2678
        }
2679

    
2680
        /* XXX: For speed reasons reference directly the interface array */
2681
	$ifdescrs =& $config['interfaces'];
2682
        //$ifdescrs = get_configured_interface_list(false, true);
2683

    
2684
        foreach ($ifdescrs as $if => $ifname) {
2685
                if ($config['interfaces'][$if]['if'] == $interface)
2686
                        return $if;
2687

    
2688
                if (stristr($interface, "_wlan0") && $config['interfaces'][$if]['if'] == interface_get_wireless_base($interface))
2689
                        return $if;
2690

    
2691
                $int = interface_translate_type_to_real($if);
2692
                if ($int == $interface)
2693
                        return $ifname;
2694
        }
2695
        return NULL;
2696
}
2697

    
2698
/* attempt to resolve interface to friendly descr */
2699
function convert_friendly_interface_to_friendly_descr($interface) {
2700
        global $config;
2701

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

    
2736
        return $ifdesc;
2737
}
2738

    
2739
function convert_real_interface_to_friendly_descr($interface) {
2740
        global $config;
2741

    
2742
        $ifdesc = convert_real_interface_to_friendly_interface_name("{$interface}");
2743

    
2744
        if ($ifdesc) {
2745
                $iflist = get_configured_interface_with_descr(false, true);
2746
                return $iflist[$ifdesc];
2747
        }
2748

    
2749
        return $interface;
2750
}
2751

    
2752
/*
2753
 *  interface_translate_type_to_real($interface):
2754
 *              returns the real hardware interface name for a friendly interface.  ie: wan
2755
 */
2756
function interface_translate_type_to_real($interface) {
2757
        global $config;
2758

    
2759
        if ($config['interfaces'][$interface]['if'] <> "")
2760
                return $config['interfaces'][$interface]['if'];
2761
        else
2762
		return $interface;
2763
}
2764

    
2765
function interface_is_wireless_clone($wlif) {
2766
	if(!stristr($wlif, "_wlan")) {
2767
		return false;
2768
	} else {
2769
		return true;
2770
	}
2771
}
2772

    
2773
function interface_get_wireless_base($wlif) {
2774
	if(!stristr($wlif, "_wlan")) {
2775
		return $wlif;
2776
	} else {
2777
		return substr($wlif, 0, stripos($wlif, "_wlan"));
2778
	}
2779
}
2780

    
2781
function interface_get_wireless_clone($wlif) {
2782
	if(!stristr($wlif, "_wlan")) {
2783
		return $wlif . "_wlan0";
2784
	} else {
2785
		return $wlif;
2786
	}
2787
}
2788

    
2789
function get_real_interface($interface = "wan") {
2790
    global $config;
2791

    
2792
	$wanif = NULL;
2793

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

    
2826
		$cfg =& $config['interfaces'][$interface];
2827

    
2828
		// Wireless cloned NIC support (FreeBSD 8+)
2829
		// interface name format: $parentnic_wlanparentnic#
2830
		// example: ath0_wlan0
2831
		if (is_interface_wireless($cfg['if'])) {
2832
			$wanif = interface_get_wireless_clone($cfg['if']);
2833
			break;
2834
		}
2835
		/*
2836
		if (empty($cfg['if'])) {
2837
			$wancfg = $cfg['if'];
2838
			break;
2839
		}
2840
		*/
2841

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

    
2868
    return $wanif;
2869
}
2870

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

    
2893
/*
2894
 * find_ip_interface($ip): return the interface where an ip is defined
2895
 */
2896
function find_ip_interface($ip)
2897
{
2898
        /* if list */
2899
        $ifdescrs = get_configured_interface_list();
2900

    
2901
        foreach ($ifdescrs as $ifdescr => $ifname) {
2902
		if ($ip == get_interface_ip($ifname)) {
2903
                	$int = get_real_interface($ifname);
2904
			return $int;
2905
		}
2906
        }
2907
        return false;
2908
}
2909

    
2910
/*
2911
 *   find_number_of_created_carp_interfaces: return the number of carp interfaces
2912
 */
2913
function find_number_of_created_carp_interfaces() {
2914
	return `/sbin/ifconfig | grep "carp:" | wc -l`;
2915
}
2916

    
2917
function get_all_carp_interfaces() {
2918
	$ints = str_replace("\n", " ", `ifconfig | grep "carp:" -B2 | grep ": flag" | cut -d: -f1`);
2919
	$ints = explode(" ", $ints);
2920
	return $ints;
2921
}
2922

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

    
2940
function link_carp_interface_to_parent($interface) {
2941
        global $config;
2942

    
2943
        if ($interface == "")
2944
                return;
2945

    
2946
        $carp_ip = get_interface_ip($interface);
2947
        if (!is_ipaddr($carp_ip))
2948
                return;
2949

    
2950
        /* if list */
2951
        $ifdescrs = get_configured_interface_list();
2952
        foreach ($ifdescrs as $ifdescr => $ifname) {
2953
                $interfaceip = get_interface_ip($ifname);
2954
                $subnet_bits = get_interface_subnet($ifname);
2955
                $subnet_ip = gen_subnet("{$interfaceip}", "{$subnet_bits}");
2956
                if(ip_in_subnet($carp_ip, "{$subnet_ip}/{$subnet_bits}"))
2957
                        return $ifname;
2958
        }
2959

    
2960
        return "";
2961
}
2962

    
2963
/****f* interfaces/link_ip_to_carp_interface
2964
 * NAME
2965
 *   link_ip_to_carp_interface - Find where a CARP interface links to.
2966
 * INPUTS
2967
 *   $ip
2968
 * RESULT
2969
 *   $carp_ints
2970
 ******/
2971
function link_ip_to_carp_interface($ip) {
2972
        global $config;
2973

    
2974
        if (!is_ipaddr($ip))
2975
                return;
2976

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

    
2994
        return $carp_ints;
2995
}
2996

    
2997
function link_interface_to_vlans($int, $action = "") {
2998
	global $config;
2999

    
3000
	if (empty($int))
3001
		return;
3002

    
3003
	if (is_array($config['vlans']['vlan'])) {
3004
                foreach ($config['vlans']['vlan'] as $vlan) {
3005
			if ($int == $vlan['if']) {
3006
				if ($action == "update") {
3007
					interfaces_bring_up($int);
3008
				} else if ($action == "")
3009
					return $vlan;
3010
			}
3011
		}
3012
	}
3013
}
3014

    
3015
function link_interface_to_vips($int, $action = "") {
3016
        global $config;
3017

    
3018
        if (is_array($config['virtualip']['vip']))
3019
                foreach ($config['virtualip']['vip'] as $vip)
3020
                        if ($int == $vip['interface']) {
3021
				if ($action == "update")
3022
					interfaces_vips_configure($int);
3023
				else
3024
                                	return $vip;
3025
			}
3026
}
3027

    
3028
/****f* interfaces/link_interface_to_bridge
3029
 * NAME
3030
 *   link_interface_to_bridge - Finds out a bridge group for an interface
3031
 * INPUTS
3032
 *   $ip
3033
 * RESULT
3034
 *   bridge[0-99]
3035
 ******/
3036
function link_interface_to_bridge($int) {
3037
        global $config;
3038

    
3039
        if (is_array($config['bridges']['bridged'])) {
3040
                foreach ($config['bridges']['bridged'] as $bridge) {
3041
			if (in_array($int, explode(',', $bridge['members'])))
3042
                                return "{$bridge['bridgeif']}";
3043
		}
3044
	}
3045
}
3046

    
3047
function link_interface_to_group($int) {
3048
        global $config;
3049

    
3050
        if (is_array($config['ifgroups']['ifgroupentry'])) {
3051
                foreach ($config['ifgroups']['ifgroupentry'] as $group) {
3052
			if (in_array($int, explode(" ", $groupname['members'])))
3053
                                return "{$group['ifname']}";
3054
		}
3055
	}
3056
}
3057

    
3058
function link_interface_to_gre($interface) {
3059
        global $config;
3060

    
3061
        if (is_array($config['gres']['gre']))
3062
                foreach ($config['gres']['gre'] as $gre)
3063
                        if($gre['if'] == $interface)
3064
                                return $gre;
3065
}
3066

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

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

    
3076
/*
3077
 * find_interface_ip($interface): return the interface ip (first found)
3078
 */
3079
function find_interface_ip($interface, $flush = false)
3080
{
3081
	global $interface_ip_arr_cache;
3082

    
3083
	$interface = str_replace("\n", "", $interface);
3084
	
3085
	if (!does_interface_exist($interface))
3086
		return;
3087

    
3088
	/* Setup IP cache */
3089
	if (!isset($interface_ip_arr_cache[$interface]) or $flush) {
3090
		$ifinfo = pfSense_get_interface_addresses($interface);
3091
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
3092
	}
3093

    
3094
	return $interface_ip_arr_cache[$interface];
3095
}
3096

    
3097
function find_interface_subnet($interface, $flush = false)
3098
{
3099
	global $interface_sn_arr_cache;
3100

    
3101
	$interface = str_replace("\n", "", $interface);
3102
	if (does_interface_exist($interface) == false)
3103
		return;
3104

    
3105
	if (!isset($interface_sn_arr_cache[$interface]) or $flush) {
3106
		$ifinfo = pfSense_get_interface_addresses($interface);
3107
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
3108
        }
3109

    
3110
	return $interface_sn_arr_cache[$interface];
3111
}
3112

    
3113
function ip_in_interface_alias_subnet($interface, $ipalias) {
3114
	global $config;
3115

    
3116
	if (empty($interface) || !is_ipaddr($ipalias))
3117
		return 0;
3118
	if (is_array($config['virtualip']['vip'])) {
3119
                foreach ($config['virtualip']['vip'] as $vip) {
3120
                        switch ($vip['mode']) {
3121
                        case "ipalias":
3122
                                if ($vip['interface'] <> $interface)
3123
                                        continue;
3124
				if (ip_in_subnet($ipalias, gen_subnet($vip['subnet'], $vip['subnet_bits']) . "/" . $vip['subnet_bits']))
3125
					return 1;
3126
                                break;
3127
                        }
3128
                }
3129
	}
3130
}
3131

    
3132
function get_interface_ip($interface = "wan")
3133
{
3134
	$realif = get_real_interface($interface);
3135
	if (!$realif) {
3136
		if (preg_match("/^carp/i", $interface))
3137
			$realif = $interface;
3138
		else if (preg_match("/^vip/i", $interface))
3139
			$realif = $interface;
3140
		else
3141
			return null;
3142
	}
3143

    
3144
	$curip = find_interface_ip($realif);
3145
	if ($curip && is_ipaddr($curip) && ($curip != "0.0.0.0"))
3146
		return $curip;
3147
	else
3148
		return null;
3149
}
3150

    
3151
function get_interface_subnet($interface = "wan")
3152
{
3153
	$realif = get_real_interface($interface);
3154
	if (!$realif) {
3155
                if (preg_match("/^carp/i", $interface))
3156
                        $realif = $interface;
3157
                else if (preg_match("/^vip/i", $interface))
3158
                        $realif = $interface;
3159
                else
3160
                        return null;
3161
        }
3162

    
3163
	$cursn = find_interface_subnet($realif);
3164
	if (!empty($cursn))
3165
		return $cursn;
3166

    
3167
	return null;
3168
}
3169

    
3170
/* return outside interfaces with a gateway */
3171
function get_interfaces_with_gateway() {
3172
	global $config;
3173

    
3174
	$ints = array();
3175

    
3176
	/* loop interfaces, check config for outbound */
3177
	foreach($config['interfaces'] as $ifdescr => $ifname) {
3178
		if (substr($ifdescr, 0, 5) ==  "ovpnc")
3179
			return true;
3180

    
3181
		switch ($ifname['ipaddr']) {
3182
			case "dhcp":
3183
			case "carpdev-dhcp":
3184
			case "ppp";
3185
			case "pppoe":
3186
			case "pptp":
3187
			case "l2tp":
3188
			case "ppp";
3189
				$ints[$ifdescr] = $ifdescr;
3190
			break;
3191
			default:
3192
				if (!empty($ifname['gateway']))
3193
					$ints[$ifdescr] = $ifdescr;
3194
			break;
3195
		}
3196
	}
3197
	return $ints;
3198
}
3199

    
3200
/* return true if interface has a gateway */
3201
function interface_has_gateway($friendly) {
3202
	global $config;
3203

    
3204
	if (!empty($config['interfaces'][$friendly])) {
3205
		if (substr($friendly, 0, 5) ==  "ovpnc")
3206
			return true;
3207
		$ifname =& $config['interfaces'][$friendly];
3208
		switch ($ifname['ipaddr']) {
3209
			case "dhcp":
3210
			case "carpdev-dhcp":
3211
			case "pppoe":
3212
			case "pptp":
3213
			case "l2tp":
3214
			case "ppp";
3215
				return true;
3216
			break;
3217
			default:
3218
				if (!empty($ifname['gateway']))
3219
					return true;
3220
			break;
3221
		}
3222
	}
3223

    
3224
	return false;
3225
}
3226

    
3227
/****f* interfaces/is_altq_capable
3228
 * NAME
3229
 *   is_altq_capable - Test if interface is capable of using ALTQ
3230
 * INPUTS
3231
 *   $int            - string containing interface name
3232
 * RESULT
3233
 *   boolean         - true or false
3234
 ******/
3235

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

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

    
3251
        if (in_array($int_family[0], $capable))
3252
                return true;
3253
	else if (stristr($int_family, "vlan")) /* VLANs are name $parent_$vlan now */
3254
		return true;
3255
	else if (stristr($int_family, "_wlan")) /* WLANs are name $parent_$wlan now */
3256
		return true;
3257
        else
3258
                return false;
3259
}
3260

    
3261
/****f* interfaces/is_interface_wireless
3262
 * NAME
3263
 *   is_interface_wireless - Returns if an interface is wireless
3264
 * RESULT
3265
 *   $tmp       - Returns if an interface is wireless
3266
 ******/
3267
function is_interface_wireless($interface) {
3268
        global $config, $g;
3269

    
3270
        $friendly = convert_real_interface_to_friendly_interface_name($interface);
3271
        if(!isset($config['interfaces'][$friendly]['wireless'])) {
3272
                if (preg_match($g['wireless_regex'], $interface)) {
3273
                        if (isset($config['interfaces'][$friendly]))
3274
                                $config['interfaces'][$friendly]['wireless'] = array();
3275
                        return true;
3276
                }
3277
                return false;
3278
        } else
3279
                return true;
3280
}
3281

    
3282
function get_wireless_modes($interface) {
3283
	/* return wireless modes and channels */
3284
	$wireless_modes = array();
3285

    
3286
	$wlif = interface_translate_type_to_real($interface);
3287

    
3288
	if(is_interface_wireless($wlif)) {
3289
		$cloned_interface = get_real_interface($interface);
3290
		$chan_list = "/sbin/ifconfig {$cloned_interface} list chan";
3291
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
3292
		$format_list = "/usr/bin/awk '{print \$5 \" \" \$6 \",\" \$1}'";
3293

    
3294
		$interface_channels = "";
3295
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
3296
		$interface_channel_count = count($interface_channels);
3297

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

    
3328
/* return channel numbers, frequency, max txpower, and max regulation txpower */
3329
function get_wireless_channel_info($interface) {
3330
	$wireless_channels = array();
3331

    
3332
	$wlif = interface_translate_type_to_real($interface);
3333

    
3334
	if(is_interface_wireless($wlif)) {
3335
		$cloned_interface = get_real_interface($interface);
3336
		$chan_list = "/sbin/ifconfig {$cloned_interface} list txpower";
3337
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
3338
		$format_list = "/usr/bin/awk '{print \$1 \",\" \$3 \" \" \$4 \",\" \$5 \",\" \$7}'";
3339

    
3340
		$interface_channels = "";
3341
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
3342

    
3343
		foreach ($interface_channels as $channel_line) {
3344
			$channel_line = explode(",", $channel_line);
3345
			if(!isset($wireless_channels[$channel_line[0]]))
3346
				$wireless_channels[$channel_line[0]] = $channel_line;
3347
		}
3348
	}
3349
	return($wireless_channels);
3350
}
3351

    
3352
/****f* interfaces/get_interface_mtu
3353
 * NAME
3354
 *   get_interface_mtu - Return the mtu of an interface
3355
 * RESULT
3356
 *   $tmp       - Returns the mtu of an interface
3357
 ******/
3358
function get_interface_mtu($interface) {
3359
        $mtu = pfSense_get_interface_addresses($interface);
3360
        return $mtu['mtu'];
3361
}
3362

    
3363
function get_interface_mac($interface) {
3364

    
3365
	$macinfo = pfSense_get_interface_addresses($interface);
3366
	return $macinfo["macaddr"];
3367
}
3368

    
3369
/****f* pfsense-utils/generate_random_mac_address
3370
 * NAME
3371
 *   generate_random_mac - generates a random mac address
3372
 * INPUTS
3373
 *   none
3374
 * RESULT
3375
 *   $mac - a random mac address
3376
 ******/
3377
function generate_random_mac_address() {
3378
        $mac = "02";
3379
        for($x=0; $x<5; $x++)
3380
                $mac .= ":" . dechex(rand(16, 255));
3381
        return $mac;
3382
}
3383

    
3384
/****f* interfaces/is_jumbo_capable
3385
 * NAME
3386
 *   is_jumbo_capable - Test if interface is jumbo frame capable.  Useful for determining VLAN capability.
3387
 * INPUTS
3388
 *   $int             - string containing interface name
3389
 * RESULT
3390
 *   boolean          - true or false
3391
 ******/
3392
function is_jumbo_capable($int) {
3393
        global $g;
3394

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

    
3397
        if (in_array($int_family[0], $g['vlan_long_frame']))
3398
                return true;
3399
        else
3400
                return false;
3401
}
3402

    
3403
function setup_pppoe_reset_file($pppif, $iface="") {
3404
	global $g;
3405
	$cron_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
3406

    
3407
	if(!empty($iface) && !empty($pppif)){
3408
		$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";
3409
		file_put_contents($cron_file, $cron_cmd);
3410
		chmod($cron_file, 0700);
3411
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
3412
	} else
3413
		unlink_if_exists($cron_file);
3414
}
3415

    
3416
?>
(22-22/54)