Project

General

Profile

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

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

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

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

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

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

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

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

    
42
*/
43

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

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

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

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

    
67
        return $interface_arr_cache;
68
}
69

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

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

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

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

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

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

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

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

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

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

    
145
	interfaces_bring_up($vlanif);
146

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

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

    
153
	return $vlanif;
154
}
155

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

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

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

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

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

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

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

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

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

    
222
        return $vlanif;
223
}
224

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

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

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

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

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

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

    
265
        return $vlanif;
266
}
267

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

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

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

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

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

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

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

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

    
319
	$checklist = get_configured_interface_list();
320

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

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

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

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

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

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

    
478
	return $bridgeif;
479
}
480

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
569
	interfaces_bring_up($laggif);
570

    
571
	return $laggif;
572
}
573

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

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

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

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

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

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

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

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

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

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

    
627
	return $greif;
628
}
629

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

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

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

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

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

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

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

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

    
682
	return $gifif;
683
}
684

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

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

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

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

    
697
	interfaces_qinq_configure();
698

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

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

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

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

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

    
745
		interface_configure($if, $reload);
746

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

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

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

    
760
		interface_configure($if, $reload);
761

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

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

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

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

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

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

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

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

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

    
792
	return 0;
793
}
794

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

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

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

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

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

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

    
835
	$realif = get_real_interface($interface);
836

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

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

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

    
904
	return;
905
}
906

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

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

    
915
	return false;
916
}
917

    
918
function interfaces_ptpid_next() {
919

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

    
924
	return $ptpid;
925
}
926

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1216
EOD;
1217

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

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

    
1231
EOD;
1232

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

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

    
1243
EOD;
1244

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

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

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

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

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

    
1271
EOD;
1272

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

    
1277
EOD;
1278

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

    
1283
EOD;
1284

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

    
1290
EOD;
1291

    
1292

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

    
1297
EOD;
1298

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

    
1304
EOD;
1305

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

    
1310
EOD;
1311

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

    
1316
EOD;
1317

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

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

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

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

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

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

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

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

    
1371
EOD;
1372

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

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

    
1385

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

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

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

    
1426
	return 1;
1427
}
1428

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1630
function interface_ipalias_configure(&$vip) {
1631

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1790
EOD;
1791

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

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

    
1802
	return $vipif;
1803
}
1804

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2162
EOD;
2163

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

    
2170
EOD;
2171

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

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

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

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

    
2193
			}
2194
			break;
2195
	}
2196

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2323
	return 0;
2324

    
2325
}
2326

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

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

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

    
2341
	return $pid;
2342
}
2343

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

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

    
2350
	$realif = get_real_interface($interface);
2351

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2503
			if (is_ipaddr($wancfg['gateway']))
2504
				file_put_contents("{$g['tmp_path']}/{$realif}_router", $wancfg['gateway']);
2505
			break;
2506
	}
2507

    
2508
	if(does_interface_exist($wancfg['if']))
2509
		interfaces_bring_up($wancfg['if']);
2510
 	
2511
	if (!$g['booting']) {
2512
		interface_reload_carps($realif);
2513

    
2514
		unset($gre);
2515
		$gre = link_interface_to_gre($interface);
2516
		if (!empty($gre))
2517
			interface_gre_configure($gre);
2518

    
2519
		unset($gif);
2520
		$gif = link_interface_to_gif($interface);
2521
		if (!empty($gif))
2522
                       	interface_gif_configure($gif);
2523

    
2524
		if ($linkupevent == false) {
2525
			unset($bridgetmp);
2526
			$bridgetmp = link_interface_to_bridge($interface);
2527
			if (!empty($bridgetmp))
2528
				interface_bridge_add_member($bridgetmp, $realif);
2529
		}
2530

    
2531
		link_interface_to_vips($interface, "update");
2532

    
2533
		$grouptmp = link_interface_to_group($interface);
2534
		if (!empty($grouptmp))
2535
			interface_group_add_member($realif, $grouptmp);
2536

    
2537
		if ($interface == "lan")
2538
			/* make new hosts file */
2539
			system_hosts_generate();
2540

    
2541
		if ($reloadall == true) {
2542

    
2543
			/* reconfigure static routes (kernel may have deleted them) */
2544
			system_routing_configure($interface);
2545

    
2546
			/* reload ipsec tunnels */
2547
			vpn_ipsec_configure();
2548

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

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

    
2555
			/* restart dnsmasq */
2556
			services_dnsmasq_configure();
2557

    
2558
			/* reload captive portal */
2559
			captiveportal_init_rules();
2560

    
2561
			/* set the reload filter dity flag */
2562
			filter_configure();
2563
		}
2564
	}
2565

    
2566
	return 0;
2567
}
2568

    
2569
function interface_carpdev_dhcp_configure($interface = "wan") {
2570
	global $config, $g;
2571

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

    
2580
	return 0;
2581
}
2582

    
2583
function interface_dhcp_configure($interface = "wan") {
2584
	global $config, $g;
2585

    
2586
	$wancfg = $config['interfaces'][$interface];
2587
	if (empty($wancfg))
2588
		$wancfg = array();
2589

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

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

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

    
2621
EOD;
2622

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

    
2632
EOD;
2633
}
2634
	fwrite($fd, $dhclientconf);
2635
	fclose($fd);
2636

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

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

    
2646
	return 0;
2647
}
2648

    
2649
function interfaces_group_setup() {
2650
	global $config;
2651

    
2652
	if (!is_array($config['ifgroups']['ifgroupentry']))
2653
		return;
2654

    
2655
	foreach ($config['ifgroups']['ifgroupentry'] as $groupar)
2656
		interface_group_setup($groupar);
2657

    
2658
	return;
2659
}
2660

    
2661
function interface_group_setup(&$groupname /* The parameter is an array */) {
2662
	global $config;
2663

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

    
2673
	return;
2674
}
2675

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

    
2685
/* COMPAT Function */
2686
function get_real_wan_interface($interface = "wan") {
2687
	return get_real_interface($interface);
2688
}
2689

    
2690
/* COMPAT Function */
2691
function get_current_wan_address($interface = "wan") {
2692
	return get_interface_ip($interface);
2693
}
2694

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

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

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

    
2715
        foreach ($ifdescrs as $if => $ifname) {
2716
                if ($config['interfaces'][$if]['if'] == $interface)
2717
                        return $if;
2718

    
2719
                if (stristr($interface, "_wlan0") && $config['interfaces'][$if]['if'] == interface_get_wireless_base($interface))
2720
                        return $if;
2721

    
2722
                $int = interface_translate_type_to_real($if);
2723
                if ($int == $interface)
2724
                        return $ifname;
2725
        }
2726
        return NULL;
2727
}
2728

    
2729
/* attempt to resolve interface to friendly descr */
2730
function convert_friendly_interface_to_friendly_descr($interface) {
2731
        global $config;
2732

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

    
2767
        return $ifdesc;
2768
}
2769

    
2770
function convert_real_interface_to_friendly_descr($interface) {
2771
        global $config;
2772

    
2773
        $ifdesc = convert_real_interface_to_friendly_interface_name("{$interface}");
2774

    
2775
        if ($ifdesc) {
2776
                $iflist = get_configured_interface_with_descr(false, true);
2777
                return $iflist[$ifdesc];
2778
        }
2779

    
2780
        return $interface;
2781
}
2782

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

    
2790
        if ($config['interfaces'][$interface]['if'] <> "")
2791
                return $config['interfaces'][$interface]['if'];
2792
        else
2793
		return $interface;
2794
}
2795

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

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

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

    
2820
function get_real_interface($interface = "wan") {
2821
    global $config;
2822

    
2823
	$wanif = NULL;
2824

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

    
2857
		$cfg =& $config['interfaces'][$interface];
2858

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

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

    
2899
    return $wanif;
2900
}
2901

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

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

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

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

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

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

    
2971
function link_carp_interface_to_parent($interface) {
2972
        global $config;
2973

    
2974
        if ($interface == "")
2975
                return;
2976

    
2977
        $carp_ip = get_interface_ip($interface);
2978
        if (!is_ipaddr($carp_ip))
2979
                return;
2980

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

    
2991
        return "";
2992
}
2993

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

    
3005
        if (!is_ipaddr($ip))
3006
                return;
3007

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

    
3025
        return $carp_ints;
3026
}
3027

    
3028
function link_interface_to_vlans($int, $action = "") {
3029
	global $config;
3030

    
3031
	if (empty($int))
3032
		return;
3033

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

    
3046
function link_interface_to_vips($int, $action = "") {
3047
        global $config;
3048

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

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

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

    
3078
function link_interface_to_group($int) {
3079
        global $config;
3080

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

    
3089
function link_interface_to_gre($interface) {
3090
        global $config;
3091

    
3092
        if (is_array($config['gres']['gre']))
3093
                foreach ($config['gres']['gre'] as $gre)
3094
                        if($gre['if'] == $interface)
3095
                                return $gre;
3096
}
3097

    
3098
function link_interface_to_gif($interface) {
3099
        global $config;
3100

    
3101
        if (is_array($config['gifs']['gif']))
3102
                foreach ($config['gifs']['gif'] as $gif)
3103
                        if($gif['if'] == $interface)
3104
                                return $gif;
3105
}
3106

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

    
3115
	$interface = str_replace("\n", "", $interface);
3116
	
3117
	if (!does_interface_exist($interface))
3118
		return;
3119

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

    
3127
	return $interface_ip_arr_cache[$interface];
3128
}
3129

    
3130
function find_interface_subnet($interface, $flush = false)
3131
{
3132
	global $interface_sn_arr_cache;
3133
	global $interface_ip_arr_cache;
3134

    
3135
	$interface = str_replace("\n", "", $interface);
3136
	if (does_interface_exist($interface) == false)
3137
		return;
3138

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

    
3145
	return $interface_sn_arr_cache[$interface];
3146
}
3147

    
3148
function ip_in_interface_alias_subnet($interface, $ipalias) {
3149
	global $config;
3150

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

    
3166
	return false;
3167
}
3168

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

    
3181
	$curip = find_interface_ip($realif);
3182
	if ($curip && is_ipaddr($curip) && ($curip != "0.0.0.0"))
3183
		return $curip;
3184
	else
3185
		return null;
3186
}
3187

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

    
3200
	$cursn = find_interface_subnet($realif);
3201
	if (!empty($cursn))
3202
		return $cursn;
3203

    
3204
	return null;
3205
}
3206

    
3207
/* return outside interfaces with a gateway */
3208
function get_interfaces_with_gateway() {
3209
	global $config;
3210

    
3211
	$ints = array();
3212

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

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

    
3237
/* return true if interface has a gateway */
3238
function interface_has_gateway($friendly) {
3239
	global $config;
3240

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

    
3261
	return false;
3262
}
3263

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

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

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

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

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

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

    
3319
function get_wireless_modes($interface) {
3320
	/* return wireless modes and channels */
3321
	$wireless_modes = array();
3322

    
3323
	$wlif = interface_translate_type_to_real($interface);
3324

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

    
3331
		$interface_channels = "";
3332
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
3333
		$interface_channel_count = count($interface_channels);
3334

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

    
3365
/* return channel numbers, frequency, max txpower, and max regulation txpower */
3366
function get_wireless_channel_info($interface) {
3367
	$wireless_channels = array();
3368

    
3369
	$wlif = interface_translate_type_to_real($interface);
3370

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

    
3377
		$interface_channels = "";
3378
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
3379

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

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

    
3400
function get_interface_mac($interface) {
3401

    
3402
	$macinfo = pfSense_get_interface_addresses($interface);
3403
	return $macinfo["macaddr"];
3404
}
3405

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

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

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

    
3434
        if (in_array($int_family[0], $g['vlan_long_frame']))
3435
                return true;
3436
        else
3437
                return false;
3438
}
3439

    
3440
function setup_pppoe_reset_file($pppif, $iface="") {
3441
	global $g;
3442
	$cron_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
3443

    
3444
	if(!empty($iface) && !empty($pppif)){
3445
		$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";
3446
		file_put_contents($cron_file, $cron_cmd);
3447
		chmod($cron_file, 0700);
3448
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
3449
	} else
3450
		unlink_if_exists($cron_file);
3451
}
3452

    
3453
?>
(22-22/54)