Project

General

Profile

Download (102 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, true);
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
	if((is_ipaddrv6($gif['tunnel-local-addr'])) || (is_ipaddrv6($gif['tunnel-remote-addr']))) {
669
		mwexec("/sbin/ifconfig {$gifif} inet6 {$gif['tunnel-local-addr']} {$gif['tunnel-remote-addr']} prefixlen {$gif['tunnel-remote-net']} ");
670
	} else {
671
		mwexec("/sbin/ifconfig {$gifif} {$gif['tunnel-local-addr']} {$gif['tunnel-remote-addr']} netmask " . gen_subnet_mask($gif['tunnel-remote-net']));
672
	}
673
	if (isset($gif['link0']) && $gif['link0'])
674
		pfSense_interface_flags($gifif, IFF_LINK0);
675
	if (isset($gif['link1']) && $gif['link1'])
676
		pfSense_interface_flags($gifif, IFF_LINK1);
677
	if($gifif)
678
		interfaces_bring_up($gifif);
679
	else
680
		log_error("could not bring gifif up -- variable not defined");
681

    
682
	/* XXX: Needed?! Let them use the defined gateways instead */
683
	//mwexec("/sbin/route add {$gif['tunnel-remote-addr']}/{$gif['tunnel-remote-net']} -iface {$gifif}");
684
	file_put_contents("{$g['tmp_path']}/{$gifif}_router", $gif['tunnel-remote-addr']);
685

    
686
	return $gifif;
687
}
688

    
689
function interfaces_configure() {
690
	global $config, $g;
691

    
692
	/* Set up our loopback interface */
693
	interfaces_loopback_configure();
694

    
695
	/* set up LAGG virtual interfaces */
696
	interfaces_lagg_configure();
697

    
698
	/* set up VLAN virtual interfaces */
699
	interfaces_vlan_configure();
700

    
701
	interfaces_qinq_configure();
702

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

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

    
734
	/* create the unconfigured wireless clones */
735
	interfaces_create_wireless_clones();
736

    
737
	/* set up GRE virtual interfaces */
738
	interfaces_gre_configure();
739

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

    
749
		interface_configure($if, $reload);
750

    
751
		if ($g['booting'])
752
			echo "done.\n";
753
	}
754

    
755
	/* set up BRIDGe virtual interfaces */
756
	interfaces_bridge_configure();
757

    
758
	foreach ($bridge_list as $if => $ifname) {
759
		if ($g['booting'])
760
			echo "Configuring {$ifname} interface...";
761
		if($g['debug'])
762
			log_error("Configuring {$ifname}");
763

    
764
		interface_configure($if, $reload);
765

    
766
		if ($g['booting'])
767
			echo "done.\n";
768
	}
769

    
770
	/* bring up vip interfaces */
771
	interfaces_vips_configure();
772

    
773
	/* configure interface groups */
774
	interfaces_group_setup();
775

    
776
	if (!$g['booting']) {
777
		/* reconfigure static routes (kernel may have deleted them) */
778
		system_routing_configure();
779

    
780
		/* reload IPsec tunnels */
781
		vpn_ipsec_configure();
782

    
783
		/* reload dhcpd (interface enabled/disabled status may have changed) */
784
		services_dhcpd_configure();
785

    
786
		/* restart dnsmasq */
787
		services_dnsmasq_configure();
788

    
789
		/* reload captive portal */
790
		captiveportal_init_rules();
791

    
792
		/* set the reload filter dity flag */
793
		filter_configure();
794
	}
795

    
796
	return 0;
797
}
798

    
799
function interface_reconfigure($interface = "wan") {
800
	interface_bring_down($interface);
801
	interface_configure($interface, true);
802
}
803

    
804
function interface_vip_bring_down($vip) {
805
	global $g;
806

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

    
831
function interface_bring_down($interface = "wan", $destroy = false) {
832
	global $config, $g;
833

    
834
	if (!isset($config['interfaces'][$interface]))
835
		return; 
836

    
837
	$ifcfg = $config['interfaces'][$interface];
838

    
839
	$realif = get_real_interface($interface);
840

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

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

    
903
	if ($destroy == true) {
904
		if (preg_match("/^vip|^tun|^ovpn|^gif|^gre|^lagg|^bridge|vlan/i", $realif))
905
			pfSense_interface_destroy($realif);
906
	}	
907

    
908
	return;
909
}
910

    
911
function interfaces_ptpid_used($ptpid) {
912
	global $config;
913

    
914
	if (is_array($config['ppps']['ppp']))
915
		foreach ($config['ppps']['ppp'] as & $settings)
916
			if ($ptpid == $settings['ptpid'])
917
				return true;
918

    
919
	return false;
920
}
921

    
922
function interfaces_ptpid_next() {
923

    
924
	$ptpid = 0;
925
	while(interfaces_ptpid_used($ptpid))
926
		$ptpid++;
927

    
928
	return $ptpid;
929
}
930

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

    
945
function handle_pppoe_reset($post_array) {
946
	global $config, $g;
947

    
948
	$cron_cmd_file = "{$g['varetc_path']}/pppoe_restart_";
949

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

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

    
1032
/*	This function can configure PPPoE, MLPPP (PPPoE), PPTP.
1033
*	It writes the mpd config file to /var/etc every time the link is opened.
1034
*/
1035

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

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

    
1158
	if (isset($ppp['ondemand'])) 
1159
		$ondemand = "enable";
1160
	else
1161
		$ondemand = "disable";
1162
	if (!isset($ppp['idletimeout']))
1163
		$ppp['idletimeout'] = 0;
1164

    
1165
	if (empty($ppp['username']) && $type == "modem"){
1166
		$ppp['username'] = "user";
1167
		$ppp['password'] = "none";
1168
	}
1169
	if (empty($ppp['password']) && $type == "modem")
1170
		$passwd = "none";
1171
	else
1172
		$passwd = base64_decode($ppp['password']);
1173

    
1174
	$bandwidths = explode(',',$ppp['bandwidth']);
1175
	$mtus = explode(',',$ppp['mtu']);
1176
	$mrus = explode(',',$ppp['mru']);
1177

    
1178
	if (isset($ppp['mrru']))
1179
		$mrrus = explode(',',$ppp['mrru']);
1180

    
1181
	// Construct the mpd.conf file
1182
	$mpdconf = <<<EOD
1183
startup:
1184
	# configure the console
1185
	set console close
1186
	# configure the web server
1187
	set web close
1188

    
1189
default:
1190
{$ppp['type']}client:
1191
	create bundle static {$interface}
1192
	set iface name {$pppif}
1193

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

    
1214
EOD;
1215
	}
1216
	$mpdconf .= <<<EOD
1217
	set iface {$ondemand} on-demand
1218
	set iface idle {$ppp['idletimeout']}
1219

    
1220
EOD;
1221

    
1222
	if (isset($ppp['ondemand']))
1223
		$mpdconf .= <<<EOD
1224
	set iface addrs 10.10.1.1 10.10.1.2
1225

    
1226
EOD;
1227
	
1228
	if (isset($ppp['tcpmssfix']))
1229
		$tcpmss = "disable";
1230
	else
1231
		$tcpmss = "enable";
1232
		$mpdconf .= <<<EOD
1233
	set iface {$tcpmss} tcpmssfix
1234

    
1235
EOD;
1236

    
1237
	$mpdconf .= <<<EOD
1238
	set iface up-script /usr/local/sbin/ppp-linkup
1239
	set iface down-script /usr/local/sbin/ppp-linkdown
1240
	set ipcp ranges {$ranges}
1241

    
1242
EOD;
1243
	if (isset($ppp['vjcomp']))
1244
		$mpdconf .= <<<EOD
1245
	set ipcp no vjcomp
1246

    
1247
EOD;
1248

    
1249
	if (isset($config['system']['dnsallowoverride']))
1250
		$mpdconf .= <<<EOD
1251
	set ipcp enable req-pri-dns
1252
	set ipcp enable req-sec-dns
1253

    
1254
EOD;
1255
	if (!isset($ppp['verbose_log']))
1256
		$mpdconf .= <<<EOD
1257
	#log -bund -ccp -chat -iface -ipcp -lcp -link
1258

    
1259
EOD;
1260
	foreach($ports as $pid => $port){
1261
		$port = get_real_interface($port);
1262
		$mpdconf .= <<<EOD
1263

    
1264
	create link static {$interface}_link{$pid} {$type}
1265
	set link action bundle {$interface}
1266
	set link {$multilink} multilink
1267
	set link keep-alive 10 60
1268
	set link max-redial 0
1269

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

    
1275
EOD;
1276

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

    
1281
EOD;
1282

    
1283
		if (isset($ppp['protocomp']))
1284
			$mpdconf .= <<<EOD
1285
	set link no protocomp
1286

    
1287
EOD;
1288

    
1289
		$mpdconf .= <<<EOD
1290
	set link disable chap pap
1291
	set link accept chap pap eap
1292
	set link disable incoming
1293

    
1294
EOD;
1295

    
1296

    
1297
		if (!empty($bandwidths[$pid]))
1298
			$mpdconf .= <<<EOD
1299
	set link bandwidth {$bandwidths[$pid]}
1300

    
1301
EOD;
1302

    
1303
		if (empty($mtus[$pid]))
1304
			$mtus[$pid] = "1492";
1305
			$mpdconf .= <<<EOD
1306
	set link mtu {$mtus[$pid]}
1307

    
1308
EOD;
1309

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

    
1314
EOD;
1315

    
1316
		if (!empty($mrrus[$pid]))
1317
			$mpdconf .= <<<EOD
1318
	set link mrru {$mrrus[$pid]}
1319

    
1320
EOD;
1321

    
1322
		$mpdconf .= <<<EOD
1323
	set auth authname "{$ppp['username']}"
1324
	set auth password {$passwd}
1325

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

    
1336
EOD;
1337
		}
1338
		if (isset($ppp['connect-timeout']) && $type == "modem") {
1339
			$mpdconf .= <<<EOD
1340
	set modem var \$ConnectTimeout "{$ppp['connect-timeout']}"
1341

    
1342
EOD;
1343
		}
1344
		if (isset($ppp['initstr']) && $type == "modem") {
1345
			$initstr = base64_decode($ppp['initstr']);
1346
			$mpdconf .= <<<EOD
1347
	set modem var \$InitString "{$initstr}"
1348

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

    
1356
EOD;
1357
		}
1358
		if (isset($ppp['apn']) && $type == "modem") {
1359
			$mpdconf .= <<<EOD
1360
	set modem var \$APN "{$ppp['apn']}"
1361
	set modem var \$APNum "{$ppp['apnum']}"
1362

    
1363
EOD;
1364
		}
1365
		if (isset($ppp['provider']) && $type == "pppoe") {
1366
			$mpdconf .= <<<EOD
1367
	set pppoe service "{$ppp['provider']}"
1368

    
1369
EOD;
1370
		}
1371
		if ($type == "pppoe")
1372
			$mpdconf .= <<<EOD
1373
	set pppoe iface {$port}
1374

    
1375
EOD;
1376

    
1377
		if ($type == "pptp" || $type == "l2tp") {
1378
			$mpdconf .= <<<EOD
1379
	set {$type} self {$localips[$pid]}
1380
	set {$type} peer {$gateways[$pid]}
1381
	set {$type} disable windowing
1382

    
1383
EOD;
1384
		}
1385
		
1386
		$mpdconf .= "\topen\r\n";
1387
	} //end foreach($port)
1388

    
1389

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

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

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

    
1430
	return 1;
1431
}
1432

    
1433
function interfaces_carp_setup() {
1434
	global $g, $config;
1435

    
1436
	$balanacing = "";
1437
	$pfsyncinterface = "";
1438
	$pfsyncenabled = "";
1439
	if(isset($config['system']['developerspew'])) {
1440
		$mt = microtime();
1441
		echo "interfaces_carp_setup() being called $mt\n";
1442
	}
1443

    
1444
	// Prepare CmdCHAIN that will be used to execute commands.
1445
	$cmdchain = new CmdCHAIN();	
1446

    
1447
	if ($g['booting']) {
1448
		echo "Configuring CARP settings...";
1449
		mute_kernel_msgs();
1450
	}
1451

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

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

    
1475
	$cmdchain->add("Enable CARP logging", "/sbin/sysctl net.inet.carp.log=2", true);
1476
	if (!empty($pfsyncinterface))
1477
		$carp_sync_int = get_real_interface($pfsyncinterface);
1478

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

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

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

    
1511
	$cmdchain->execute();
1512
	$cmdchain->clear();
1513

    
1514
	if ($g['booting']) {
1515
		unmute_kernel_msgs();
1516
		echo "done.\n";
1517
	}
1518
}
1519

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

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

    
1536
	$paa = array();
1537
	if (!empty($config['virtualip']) && is_array($config['virtualip']['vip'])) {
1538

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

    
1550
				if (!is_array($paa[$proxyif]))
1551
					$paa[$proxyif] = array();
1552

    
1553
				$paa[$proxyif][] = $vipent;
1554
			}
1555
		}
1556
	}
1557

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

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

    
1634
function interface_ipalias_configure(&$vip) {
1635

    
1636
	if ($vip['mode'] == "ipalias") {
1637
		$if = get_real_interface($vip['interface']);
1638
		mwexec("/sbin/ifconfig " . escapeshellarg($if) . " " . $vip['subnet'] . "/" . escapeshellarg($vip['subnet_bits']) . " alias");
1639
	}
1640
}
1641

    
1642
function interface_reload_carps($cif) {
1643
	global $config;
1644

    
1645
	$carpifs = link_ip_to_carp_interface(find_interface_ip($cif));
1646
	if (empty($carpifs))
1647
		return;
1648

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

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

    
1683
	if ($vip['mode'] != "carp")
1684
		return;
1685

    
1686
	$vip_password = $vip['password'];
1687
	$vip_password = escapeshellarg(addslashes(str_replace(" ", "", $vip_password)));
1688
	if ($vip['password'] != "")
1689
		$password = " pass {$vip_password}";
1690

    
1691
	// set the vip interface to the vhid
1692
	$vipif = "vip{$vip['vhid']}";
1693

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

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

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

    
1722
	/* invalidate interface cache */
1723
	get_interface_arr(true);
1724

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

    
1728
	interfaces_bring_up($vipif);
1729
	
1730
	return $vipif;
1731
}
1732

    
1733
function interface_carpdev_configure(&$vip) {
1734
	global $g;
1735

    
1736
	if ($vip['mode'] != "carpdev-dhcp")
1737
		return;
1738

    
1739
	$vip_password = $vip['password'];
1740
	$vip_password = str_replace(" ", "", $vip_password);
1741
	if($vip['password'] != "")
1742
		$password = " pass \"" . $vip_password . "\"";
1743

    
1744
	log_error("Found carpdev interface {$vip['interface']} on top of interface {$interface}");
1745
	if (empty($vip['interface']))
1746
		return;
1747

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

    
1760
	if (does_interface_exist($vipif)) {
1761
		interface_bring_down($vipif);
1762
	} else {
1763
		$carpdevif = exec("/sbin/ifconfig carp create");
1764
		mwexec("/sbin/ifconfig {$carpdevif} name {$vipif}");
1765
		pfSense_ngctl_name("{$carpdevif}:", $vipif);
1766
	}
1767

    
1768
	mwexec("/sbin/ifconfig {$vipif} carpdev {$realif} vhid {$vip['vhid']} advskew {$vip['advskew']} {$password}");
1769
	interfaces_bring_up($vipif);
1770

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

    
1780
	/* generate dhclient_wan.conf */
1781
	$fd = fopen("{$g['varetc_path']}/dhclient_{$vipif}.conf", "w");
1782
	if ($fd) {
1783
		$dhclientconf = "";
1784

    
1785
		$dhclientconf .= <<<EOD
1786
interface "{$vipif}" {
1787
timeout 60;
1788
retry 1;
1789
select-timeout 0;
1790
initial-interval 1;
1791
script "/sbin/dhclient-script";
1792
}
1793

    
1794
EOD;
1795

    
1796
		fwrite($fd, $dhclientconf);
1797
		fclose($fd);
1798

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

    
1806
	return $vipif;
1807
}
1808

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

    
1850
	if($needs_clone == true) {
1851
		/* remove previous instance if it exists */
1852
		if(does_interface_exist($realif))
1853
			pfSense_interface_destroy($realif);
1854

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

    
1872
function interface_sync_wireless_clones(&$ifcfg, $sync_changes = false) {
1873
	global $config, $g;
1874

    
1875
	$shared_settings = array('standard', 'turbo', 'protmode', 'txpower', 'channel',
1876
	                         'diversity', 'txantenna', 'rxantenna', 'distance',
1877
	                         'regdomain', 'regcountry', 'reglocation');
1878

    
1879
	if(!is_interface_wireless($ifcfg['if']))
1880
		return;
1881

    
1882
	$baseif = interface_get_wireless_base($ifcfg['if']);
1883

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

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

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

    
1941
function interface_wireless_configure($if, &$wl, &$wlcfg) {
1942
	global $config, $g;
1943

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

    
1951
	// Remove script file
1952
	unlink_if_exists("{$g['tmp_path']}/{$if}_setup.sh");
1953

    
1954
	// Clone wireless nic if needed.
1955
	interface_wireless_clone($if, $wl);
1956

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

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

    
1964
	/* set values for /path/program */
1965
	$hostapd = "/usr/sbin/hostapd";
1966
	$wpa_supplicant = "/usr/sbin/wpa_supplicant";
1967
	$ifconfig = "/sbin/ifconfig";
1968
	$sysctl = "/sbin/sysctl";
1969
	$killall = "/usr/bin/killall";
1970

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

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

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

    
1986
	/* Set ssid */
1987
	if($wlcfg['ssid'])
1988
		$wlcmd[] = "ssid " .escapeshellarg($wlcfg['ssid']);
1989

    
1990
	/* Set 802.11g protection mode */
1991
	$wlcmd[] = "protmode " . escapeshellarg($wlcfg['protmode']);
1992

    
1993
	/* set wireless channel value */
1994
	if(isset($wlcfg['channel'])) {
1995
		if($wlcfg['channel'] == "0") {
1996
			$wlcmd[] = "channel any";
1997
		} else {
1998
			$wlcmd[] = "channel " . escapeshellarg($wlcfg['channel']);
1999
		}
2000
	}
2001

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

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

    
2010
	/* Set rxantenna value */
2011
	if(isset($wlcfg['rxantenna']))
2012
		$wl_sysctl[] = "rxantenna=" . escapeshellarg($wlcfg['rxantenna']);
2013

    
2014
	/* set Distance value */
2015
	if($wlcfg['distance'])
2016
		$distance = escapeshellarg($wlcfg['distance']);
2017

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

    
2025
	/* Set wireless adhoc mode */
2026
	if ($wlcfg['mode'] == "adhoc") {
2027
		$wlcmd[] = "mediaopt adhoc";
2028
	} else {
2029
		$wlcmd[] = "-mediaopt adhoc";
2030
	}
2031

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

    
2034
	/* handle hide ssid option */
2035
	if(isset($wlcfg['hidessid']['enable'])) {
2036
		$wlcmd[] = "hidessid";
2037
	} else {
2038
		$wlcmd[] = "-hidessid";
2039
	}
2040

    
2041
	/* handle pureg (802.11g) only option */
2042
	if(isset($wlcfg['pureg']['enable'])) {
2043
		$wlcmd[] = "mode 11g pureg";
2044
	} else {
2045
		$wlcmd[] = "-pureg";
2046
	}
2047

    
2048
	/* handle puren (802.11n) only option */
2049
	if(isset($wlcfg['puren']['enable'])) {
2050
		$wlcmd[] = "puren";
2051
	} else {
2052
		$wlcmd[] = "-puren";
2053
	}
2054

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

    
2062
	/* handle turbo option */
2063
	if(isset($wlcfg['turbo']['enable'])) {
2064
		$wlcmd[] = "mediaopt turbo";
2065
	} else {
2066
		$wlcmd[] = "-mediaopt turbo";
2067
	}
2068

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

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

    
2106
	mwexec(kill_hostapd("{$if}"));
2107
	mwexec(kill_wpasupplicant("{$if}"));
2108

    
2109
	/* generate wpa_supplicant/hostap config if wpa is enabled */
2110
	conf_mount_rw();
2111

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

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

    
2166
EOD;
2167

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

    
2174
EOD;
2175

    
2176
}
2177
				if($wlcfg['auth_server_addr'] && $wlcfg['auth_server_shared_secret']) {
2178
					$auth_server_port = "1812";
2179
					if($wlcfg['auth_server_port']) 
2180
						$auth_server_port = $wlcfg['auth_server_port'];
2181
					$wpa .= <<<EOD
2182

    
2183
ieee8021x=1
2184
auth_server_addr={$wlcfg['auth_server_addr']}
2185
auth_server_port={$auth_server_port}
2186
auth_server_shared_secret={$wlcfg['auth_server_shared_secret']}
2187

    
2188
EOD;
2189
				} else {
2190
					$wpa .= "ieee8021x={$wlcfg['wpa']['ieee8021x']}\n";
2191
				}
2192

    
2193
				$fd = fopen("{$g['varetc_path']}/hostapd_{$if}.conf", "w");
2194
				fwrite($fd, "{$wpa}");
2195
				fclose($fd);
2196

    
2197
			}
2198
			break;
2199
	}
2200

    
2201
	/*
2202
	 *    all variables are set, lets start up everything
2203
	 */
2204

    
2205
	$baseif = interface_get_wireless_base($if);
2206
	preg_match("/^(.*?)([0-9]*)$/", $baseif, $baseif_split);
2207
	$wl_sysctl_prefix = 'dev.' . $baseif_split[1] . '.' . $baseif_split[2];
2208

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

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

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

    
2232
	fclose($fd_set);
2233
	conf_mount_ro();
2234

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

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

    
2255
	if ($reg_changing) {
2256
		/* set regulatory domain */
2257
		if($wlcfg['regdomain'])
2258
			$wlregcmd[] = "regdomain " . escapeshellarg($wlcfg['regdomain']);
2259

    
2260
		/* set country */
2261
		if($wlcfg['regcountry'])
2262
			$wlregcmd[] = "country " . escapeshellarg($wlcfg['regcountry']);
2263

    
2264
		/* set location */
2265
		if($wlcfg['reglocation'])
2266
			$wlregcmd[] = escapeshellarg($wlcfg['reglocation']);
2267

    
2268
		$wlregcmd_args = implode(" ", $wlregcmd);
2269

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

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

    
2291
		/* apply the regulatory settings */
2292
		mwexec("{$ifconfig} " . escapeshellarg($if) . " {$wlregcmd_args}");
2293

    
2294
		/* bring the clones back up that were previously up */
2295
		foreach ($clones_up as $clone_if) {
2296
			mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " up");
2297

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

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

    
2318
	/* configure wireless */
2319
	$wlcmd_args = implode(" ", $wlcmd);
2320
	mwexec("/sbin/ifconfig {$if} $wlcmd_args", false);
2321

    
2322
	
2323
	sleep(1);
2324
	/* execute hostapd and wpa_supplicant if required in shell */
2325
	mwexec("/bin/sh {$g['tmp_path']}/{$if}_setup.sh");
2326

    
2327
	return 0;
2328

    
2329
}
2330

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

    
2335
function kill_wpasupplicant($interface) {
2336
	return "/bin/pkill -f \"wpa_supplicant .*{$interface}\"\n";
2337
}
2338

    
2339
function find_dhclient_process($interface) {
2340
	if ($interface)
2341
		$pid = `/bin/pgrep -xf "dhclient: {$interface}"`;
2342
	else
2343
		$pid = 0;
2344

    
2345
	return $pid;
2346
}
2347

    
2348
function interface_configure($interface = "wan", $reloadall = false, $linkupevent = false) {
2349
	global $config, $g;
2350
	global $interface_sn_arr_cache, $interface_ip_arr_cache;
2351

    
2352
	$wancfg = $config['interfaces'][$interface];
2353

    
2354
	$realif = get_real_interface($interface);
2355

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

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

    
2373
	/* wireless configuration? */
2374
	if (is_array($wancfg['wireless']))
2375
		interface_wireless_configure($realif, $wancfg, $wancfg['wireless']);
2376

    
2377
	if ($wancfg['spoofmac']) {
2378
		mwexec("/sbin/ifconfig " . escapeshellarg($realif) .
2379
			" link " . escapeshellarg($wancfg['spoofmac']));
2380

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

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

    
2420
	$options = pfSense_get_interface_addresses($realif);
2421
	if (is_array($options) && isset($options['caps']['polling'])) {
2422
		if (isset($config['system']['polling']))
2423
			pfSense_interface_capabilities($realif, IFCAP_POLLING);
2424
		else
2425
			pfSense_interface_capabilities($realif, -IFCAP_POLLING);
2426
	}
2427

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

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

    
2455
        	if(isset($config['system']['disablelargereceiveoffloading'])) {
2456
                	if (isset($options['encaps']['lro']))
2457
				$flags |= IFCAP_LRO;
2458
        	} else {
2459
                	if (!isset($options['caps']['lro']))
2460
				$flags |= IFCAP_LRO;
2461
        	}
2462

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

    
2470
	/* invalidate interface/ip/sn cache */
2471
	get_interface_arr(true);
2472
	unset($interface_ip_arr_cache[$realif]);
2473
	unset($interface_sn_arr_cache[$realif]);
2474
	unset($interface_ipv6_arr_cache[$realif]);
2475
	unset($interface_snv6_arr_cache[$realif]);
2476

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

    
2511
	switch ($wancfg['ipaddrv6']) {
2512
		case 'dhcpv6':
2513
			interface_dhcpv6_configure($interface);
2514
			break;
2515
		default:
2516
			if ($wancfg['ipaddrv6'] <> "" && $wancfg['subnetv6'] <> "") {
2517
				pfSense_interface_setaddress($realif, "{$wancfg['ipaddrv6']}/{$wancfg['subnetv6']}");
2518
				mwexec("/sbin/ifconfig {$realif} inet6 {$wancfg['ipaddrv6']} prefixlen {$wancfg['subnetv6']} ");
2519
			}
2520
			break;
2521
	}
2522

    
2523
	if(does_interface_exist($wancfg['if']))
2524
		interfaces_bring_up($wancfg['if']);
2525
 	
2526
	if (!$g['booting']) {
2527
		interface_reload_carps($realif);
2528

    
2529
		unset($gre);
2530
		$gre = link_interface_to_gre($interface);
2531
		if (!empty($gre))
2532
			interface_gre_configure($gre);
2533

    
2534
		unset($gif);
2535
		$gif = link_interface_to_gif($interface);
2536
		if (!empty($gif))
2537
                       	interface_gif_configure($gif);
2538

    
2539
		if ($linkupevent == false) {
2540
			unset($bridgetmp);
2541
			$bridgetmp = link_interface_to_bridge($interface);
2542
			if (!empty($bridgetmp))
2543
				interface_bridge_add_member($bridgetmp, $realif);
2544
		}
2545

    
2546
		link_interface_to_vips($interface, "update");
2547

    
2548
		$grouptmp = link_interface_to_group($interface);
2549
		if (!empty($grouptmp))
2550
			interface_group_add_member($realif, $grouptmp);
2551

    
2552
		if ($interface == "lan")
2553
			/* make new hosts file */
2554
			system_hosts_generate();
2555

    
2556
		if ($reloadall == true) {
2557

    
2558
			/* reconfigure static routes (kernel may have deleted them) */
2559
			system_routing_configure($interface);
2560

    
2561
			/* reload ipsec tunnels */
2562
			vpn_ipsec_configure();
2563

    
2564
			/* restart dnsmasq */
2565
			services_dnsmasq_configure();
2566

    
2567
			/* update dyndns */
2568
			services_dyndns_configure($interface);
2569

    
2570
			/* force DNS update */
2571
			services_dnsupdate_process($interface);
2572

    
2573
			/* reload captive portal */
2574
			captiveportal_init_rules();
2575

    
2576
			/* set the reload filter dity flag */
2577
			filter_configure();
2578
		}
2579
	}
2580

    
2581
	return 0;
2582
}
2583

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

    
2587
	$wancfg = $config['interfaces'][$interface];
2588
	$wanif = $wancfg['if'];
2589
	/* bring wan interface up before starting dhclient */
2590
	if($wanif)
2591
		interfaces_bring_up($wanif);
2592
	else 
2593
		log_error("Could not bring wanif up in terface_carpdev_dhcp_configure()");
2594

    
2595
	return 0;
2596
}
2597

    
2598
function interface_dhcp_configure($interface = "wan") {
2599
	global $config, $g;
2600

    
2601
	$wancfg = $config['interfaces'][$interface];
2602
	if (empty($wancfg))
2603
		$wancfg = array();
2604

    
2605
	/* generate dhclient_wan.conf */
2606
	$fd = fopen("{$g['varetc_path']}/dhclient_{$interface}.conf", "w");
2607
	if (!$fd) {
2608
		printf("Error: cannot open dhclient_{$interface}.conf in interfaces_wan_dhcp_configure() for writing.\n");
2609
		return 1;
2610
	}
2611

    
2612
	if ($wancfg['dhcphostname']) {
2613
		$dhclientconf_hostname = "send dhcp-client-identifier \"{$wancfg['dhcphostname']}\";\n";
2614
		$dhclientconf_hostname .= "\tsend host-name \"{$wancfg['dhcphostname']}\";\n";
2615
	} else {
2616
		$dhclientconf_hostname = "";
2617
	}
2618

    
2619
	$wanif = get_real_interface($interface);
2620
	if (empty($wanif)) {
2621
		log_error("Invalid interface \"{$interface}\" in interface_dhcp_configure()");
2622
		return 0;
2623
	}
2624
 	$dhclientconf = "";
2625
	
2626
	$dhclientconf .= <<<EOD
2627
interface "{$wanif}" {
2628
timeout 60;
2629
retry 1;
2630
select-timeout 0;
2631
initial-interval 1;
2632
	{$dhclientconf_hostname}
2633
	script "/sbin/dhclient-script";
2634
}
2635

    
2636
EOD;
2637

    
2638
if(is_ipaddr($wancfg['alias-address'])) {
2639
	$subnetmask = gen_subnet_mask($wancfg['alias-subnet']);
2640
	$dhclientconf .= <<<EOD
2641
alias {
2642
	interface  "{$wanif}";
2643
	fixed-address {$wancfg['alias-address']};
2644
	option subnet-mask {$subnetmask};
2645
}
2646

    
2647
EOD;
2648
}
2649
	fwrite($fd, $dhclientconf);
2650
	fclose($fd);
2651

    
2652
	/* bring wan interface up before starting dhclient */
2653
	if($wanif)
2654
		interfaces_bring_up($wanif);
2655
	else 
2656
		log_error("Could not bring up {$wanif} interface in interface_dhcp_configure()");
2657

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

    
2661
	return 0;
2662
}
2663

    
2664
function interfaces_group_setup() {
2665
	global $config;
2666

    
2667
	if (!is_array($config['ifgroups']['ifgroupentry']))
2668
		return;
2669

    
2670
	foreach ($config['ifgroups']['ifgroupentry'] as $groupar)
2671
		interface_group_setup($groupar);
2672

    
2673
	return;
2674
}
2675

    
2676
function interface_group_setup(&$groupname /* The parameter is an array */) {
2677
	global $config;
2678

    
2679
	if (!is_array($groupname))
2680
		return;
2681
	$members = explode(" ", $groupname['members']);
2682
	foreach($members as $ifs) {
2683
		$realif = get_real_interface($ifs);
2684
		if ($realif)
2685
			mwexec("/sbin/ifconfig {$realif} group {$groupname['ifname']}");
2686
	}
2687

    
2688
	return;
2689
}
2690

    
2691
function interface_group_add_member($interface, $groupname) {
2692
	mwexec("/sbin/ifconfig {$interface} group {$groupname}", true);
2693
}
2694
 
2695
/* COMPAT Function */
2696
function convert_friendly_interface_to_real_interface_name($interface) {
2697
	return get_real_interface($interface);
2698
}
2699

    
2700
/* COMPAT Function */
2701
function get_real_wan_interface($interface = "wan") {
2702
	return get_real_interface($interface);
2703
}
2704

    
2705
/* COMPAT Function */
2706
function get_current_wan_address($interface = "wan") {
2707
	return get_interface_ip($interface);
2708
}
2709

    
2710
/*
2711
 * convert_real_interface_to_friendly_interface_name($interface): convert fxp0 -> wan, etc.
2712
 */
2713
function convert_real_interface_to_friendly_interface_name($interface = "wan") {
2714
        global $config;
2715

    
2716
	if (stristr($interface, "vip")) {
2717
                $index = intval(substr($interface, 3));
2718
                foreach ($config['virtualip']['vip'] as $counter => $vip) {
2719
                        if ($vip['mode'] == "carpdev-dhcp" || $vip['mode'] == "carp")  {
2720
                                if ($index == $counter)
2721
                                        return $vip['interface'];
2722
                        }
2723
                }
2724
        }
2725

    
2726
        /* XXX: For speed reasons reference directly the interface array */
2727
	$ifdescrs = &$config['interfaces'];
2728
        //$ifdescrs = get_configured_interface_list(false, true);
2729

    
2730
        foreach ($ifdescrs as $if => $ifname) {
2731
                if ($config['interfaces'][$if]['if'] == $interface)
2732
                        return $if;
2733

    
2734
                if (stristr($interface, "_wlan0") && $config['interfaces'][$if]['if'] == interface_get_wireless_base($interface))
2735
                        return $if;
2736

    
2737
                $int = interface_translate_type_to_real($if);
2738
                if ($int == $interface)
2739
                        return $ifname;
2740
        }
2741
        return NULL;
2742
}
2743

    
2744
/* attempt to resolve interface to friendly descr */
2745
function convert_friendly_interface_to_friendly_descr($interface) {
2746
        global $config;
2747

    
2748
        switch ($interface) {
2749
                case "l2tp":
2750
                                $ifdesc = "L2TP";
2751
                                break;
2752
                case "pptp":
2753
                                $ifdesc = "PPTP";
2754
                                break;
2755
                case "pppoe":
2756
                                $ifdesc = "PPPoE";
2757
                                break;
2758
                case "openvpn":
2759
                                $ifdesc = "OpenVPN";
2760
                                break;
2761
                case "enc0":
2762
                        case "ipsec":
2763
                                $ifdesc = "IPsec";
2764
                                break;
2765
        default:
2766
                if (isset($config['interfaces'][$interface])) {
2767
                        if (empty($config['interfaces'][$interface]['descr']))
2768
                                $ifdesc = strtoupper($interface);
2769
                        else
2770
                                $ifdesc = strtoupper($config['interfaces'][$interface]['descr']);
2771
			break;
2772
		}
2773
                /* if list */
2774
                $ifdescrs = get_configured_interface_with_descr(false, true);
2775
                foreach ($ifdescrs as $if => $ifname) {
2776
                                if ($if == $interface || $ifname == $interface)
2777
                                        return $ifname;
2778
                }
2779
                break;
2780
        }
2781

    
2782
        return $ifdesc;
2783
}
2784

    
2785
function convert_real_interface_to_friendly_descr($interface) {
2786
        global $config;
2787

    
2788
        $ifdesc = convert_real_interface_to_friendly_interface_name("{$interface}");
2789

    
2790
        if ($ifdesc) {
2791
                $iflist = get_configured_interface_with_descr(false, true);
2792
                return $iflist[$ifdesc];
2793
        }
2794

    
2795
        return $interface;
2796
}
2797

    
2798
/*
2799
 *  interface_translate_type_to_real($interface):
2800
 *              returns the real hardware interface name for a friendly interface.  ie: wan
2801
 */
2802
function interface_translate_type_to_real($interface) {
2803
        global $config;
2804

    
2805
        if ($config['interfaces'][$interface]['if'] <> "")
2806
                return $config['interfaces'][$interface]['if'];
2807
        else
2808
		return $interface;
2809
}
2810

    
2811
function interface_is_wireless_clone($wlif) {
2812
	if(!stristr($wlif, "_wlan")) {
2813
		return false;
2814
	} else {
2815
		return true;
2816
	}
2817
}
2818

    
2819
function interface_get_wireless_base($wlif) {
2820
	if(!stristr($wlif, "_wlan")) {
2821
		return $wlif;
2822
	} else {
2823
		return substr($wlif, 0, stripos($wlif, "_wlan"));
2824
	}
2825
}
2826

    
2827
function interface_get_wireless_clone($wlif) {
2828
	if(!stristr($wlif, "_wlan")) {
2829
		return $wlif . "_wlan0";
2830
	} else {
2831
		return $wlif;
2832
	}
2833
}
2834

    
2835
function get_real_interface($interface = "wan") {
2836
    global $config;
2837

    
2838
	$wanif = NULL;
2839

    
2840
	switch ($interface) {
2841
	case "l2tp":
2842
		$wanif = "l2tp";
2843
		break;
2844
	case "pptp":
2845
		$wanif = "pptp";
2846
		break;
2847
	case "pppoe":
2848
		$wanif = "pppoe";
2849
		break;
2850
	case "openvpn":
2851
		$wanif = "openvpn";
2852
		break;
2853
	case "ipsec":
2854
	case "enc0":
2855
		$wanif = "enc0";
2856
		break;
2857
	case "ppp":
2858
		$wanif = "ppp";
2859
		break;
2860
	default:
2861
		// If a real interface was alread passed simply
2862
		// pass the real interface back.  This encourages
2863
		// the usage of this function in more cases so that
2864
		// we can combine logic for more flexibility.
2865
		if(does_interface_exist($interface)) {
2866
			$wanif = $interface;
2867
			break;
2868
		}
2869
		if (empty($config['interfaces'][$interface]))
2870
			break;
2871

    
2872
		$cfg = &$config['interfaces'][$interface];
2873

    
2874
		// Wireless cloned NIC support (FreeBSD 8+)
2875
		// interface name format: $parentnic_wlanparentnic#
2876
		// example: ath0_wlan0
2877
		if (is_interface_wireless($cfg['if'])) {
2878
			$wanif = interface_get_wireless_clone($cfg['if']);
2879
			break;
2880
		}
2881
		/*
2882
		if (empty($cfg['if'])) {
2883
			$wancfg = $cfg['if'];
2884
			break;
2885
		}
2886
		*/
2887

    
2888
		switch ($cfg['ipaddr']) {
2889
			case "carpdev-dhcp":
2890
				$viparr = &$config['virtualip']['vip'];
2891
				if(is_array($viparr))
2892
				foreach ($viparr as $counter => $vip) {
2893
					if ($vip['mode'] == "carpdev-dhcp") {
2894
						if($vip['interface'] == $interface) {
2895
							$wanif = "carp{$counter}";
2896
							break;
2897
						}
2898
					}
2899
				}
2900
				break;
2901
			case "pppoe": 
2902
			case "pptp": 
2903
			case "l2tp": 
2904
			case "ppp":
2905
				$wanif = $cfg['if'];
2906
				break;
2907
			default:
2908
				$wanif = $cfg['if'];
2909
				break;
2910
		}
2911
		break;
2912
	}
2913

    
2914
    return $wanif;
2915
}
2916

    
2917
/* Guess the physical interface by providing a IP address */
2918
function guess_interface_from_ip($ipaddress) {
2919
	if(! is_ipaddr($ipaddress)) {
2920
		return false;
2921
	}
2922
	/* create a route table we can search */
2923
	exec("netstat -rnWf inet", $output, $ret);
2924
	foreach($output as $line) {
2925
		if(preg_match("/^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\/[0-9]+[ ]+link[#]/", $line)) {
2926
			$fields = preg_split("/[ ]+/", $line);
2927
			if(ip_in_subnet($ipaddress, $fields[0])) {
2928
				return $fields[6];
2929
			}
2930
		}
2931
	}
2932
	$ret = exec_command("/sbin/route -n get {$ipaddress} | /usr/bin/awk '/interface/ { print \$2; };'");
2933
	if(empty($ret)) {
2934
        	return false;
2935
	}
2936
	return $ret;
2937
}
2938

    
2939
/*
2940
 * find_ip_interface($ip): return the interface where an ip is defined
2941
 */
2942
function find_ip_interface($ip)
2943
{
2944
        /* if list */
2945
        $ifdescrs = get_configured_interface_list();
2946

    
2947
        foreach ($ifdescrs as $ifdescr => $ifname) {
2948
		if ($ip == get_interface_ip($ifname)) {
2949
                	$int = get_real_interface($ifname);
2950
			return $int;
2951
		}
2952
        }
2953
        return false;
2954
}
2955

    
2956
/*
2957
 *   find_number_of_created_carp_interfaces: return the number of carp interfaces
2958
 */
2959
function find_number_of_created_carp_interfaces() {
2960
	return `/sbin/ifconfig | grep "carp:" | wc -l`;
2961
}
2962

    
2963
function get_all_carp_interfaces() {
2964
	$ints = str_replace("\n", " ", `ifconfig | grep "carp:" -B2 | grep ": flag" | cut -d: -f1`);
2965
	$ints = explode(" ", $ints);
2966
	return $ints;
2967
}
2968

    
2969
/*
2970
 * find_carp_interface($ip): return the carp interface where an ip is defined
2971
 */
2972
function find_carp_interface($ip) {
2973
	global $config;
2974
	if (is_array($config['virtualip']['vip'])) {
2975
		foreach ($config['virtualip']['vip'] as $vip) {
2976
			if ($vip['mode'] == "carp" || $vip['mode'] == "carpdev") {
2977
				$carp_ip = get_interface_ip($vip['interface']);
2978
				$if = `ifconfig | grep '$ip ' -B1 | head -n1 | cut -d: -f1`;
2979
				if ($if)
2980
					return $if;
2981
			}
2982
		}
2983
	}
2984
}
2985

    
2986
function link_carp_interface_to_parent($interface) {
2987
        global $config;
2988

    
2989
        if ($interface == "")
2990
                return;
2991

    
2992
        $carp_ip = get_interface_ip($interface);
2993
        if (!is_ipaddr($carp_ip))
2994
                return;
2995

    
2996
        /* if list */
2997
        $ifdescrs = get_configured_interface_list();
2998
        foreach ($ifdescrs as $ifdescr => $ifname) {
2999
                $interfaceip = get_interface_ip($ifname);
3000
                $subnet_bits = get_interface_subnet($ifname);
3001
                $subnet_ip = gen_subnet("{$interfaceip}", "{$subnet_bits}");
3002
                if(ip_in_subnet($carp_ip, "{$subnet_ip}/{$subnet_bits}"))
3003
                        return $ifname;
3004
        }
3005

    
3006
        return "";
3007
}
3008

    
3009
/****f* interfaces/link_ip_to_carp_interface
3010
 * NAME
3011
 *   link_ip_to_carp_interface - Find where a CARP interface links to.
3012
 * INPUTS
3013
 *   $ip
3014
 * RESULT
3015
 *   $carp_ints
3016
 ******/
3017
function link_ip_to_carp_interface($ip) {
3018
        global $config;
3019

    
3020
        if (!is_ipaddr($ip))
3021
                return;
3022

    
3023
        $carp_ints = "";
3024
        if (is_array($config['virtualip']['vip'])) {
3025
		$first = 0;
3026
		$carp_int = array();
3027
                foreach ($config['virtualip']['vip'] as $vip) {
3028
                        if ($vip['mode'] == "carp" || $vip['mode'] == "carpdev") {
3029
                                $carp_ip = $vip['subnet'];
3030
                                $carp_sn = $vip['subnet_bits'];
3031
                                $carp_nw = gen_subnet($carp_ip, $carp_sn);
3032
                                if (ip_in_subnet($ip, "{$carp_nw}/{$carp_sn}"))
3033
					$carp_int[] = "vip{$vip['vhid']}";
3034
                        }
3035
                }
3036
		if (!empty($carp_int))
3037
			$carp_ints = implode(" ", array_unique($carp_int));
3038
        }
3039

    
3040
        return $carp_ints;
3041
}
3042

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

    
3046
	if (empty($int))
3047
		return;
3048

    
3049
	if (is_array($config['vlans']['vlan'])) {
3050
                foreach ($config['vlans']['vlan'] as $vlan) {
3051
			if ($int == $vlan['if']) {
3052
				if ($action == "update") {
3053
					interfaces_bring_up($int);
3054
				} else if ($action == "")
3055
					return $vlan;
3056
			}
3057
		}
3058
	}
3059
}
3060

    
3061
function link_interface_to_vips($int, $action = "") {
3062
        global $config;
3063

    
3064
        if (is_array($config['virtualip']['vip']))
3065
                foreach ($config['virtualip']['vip'] as $vip)
3066
                        if ($int == $vip['interface']) {
3067
				if ($action == "update")
3068
					interfaces_vips_configure($int);
3069
				else
3070
                                	return $vip;
3071
			}
3072
}
3073

    
3074
/****f* interfaces/link_interface_to_bridge
3075
 * NAME
3076
 *   link_interface_to_bridge - Finds out a bridge group for an interface
3077
 * INPUTS
3078
 *   $ip
3079
 * RESULT
3080
 *   bridge[0-99]
3081
 ******/
3082
function link_interface_to_bridge($int) {
3083
        global $config;
3084

    
3085
        if (is_array($config['bridges']['bridged'])) {
3086
                foreach ($config['bridges']['bridged'] as $bridge) {
3087
			if (in_array($int, explode(',', $bridge['members'])))
3088
                                return "{$bridge['bridgeif']}";
3089
		}
3090
	}
3091
}
3092

    
3093
function link_interface_to_group($int) {
3094
        global $config;
3095

    
3096
        if (is_array($config['ifgroups']['ifgroupentry'])) {
3097
                foreach ($config['ifgroups']['ifgroupentry'] as $group) {
3098
			if (in_array($int, explode(" ", $groupname['members'])))
3099
                                return "{$group['ifname']}";
3100
		}
3101
	}
3102
}
3103

    
3104
function link_interface_to_gre($interface) {
3105
        global $config;
3106

    
3107
        if (is_array($config['gres']['gre']))
3108
                foreach ($config['gres']['gre'] as $gre)
3109
                        if($gre['if'] == $interface)
3110
                                return $gre;
3111
}
3112

    
3113
function link_interface_to_gif($interface) {
3114
        global $config;
3115

    
3116
        if (is_array($config['gifs']['gif']))
3117
                foreach ($config['gifs']['gif'] as $gif)
3118
                        if($gif['if'] == $interface)
3119
                                return $gif;
3120
}
3121

    
3122
/*
3123
 * find_interface_ip($interface): return the interface ip (first found)
3124
 */
3125
function find_interface_ip($interface, $flush = false)
3126
{
3127
	global $interface_ip_arr_cache;
3128
	global $interface_sn_arr_cache;
3129

    
3130
	$interface = str_replace("\n", "", $interface);
3131
	
3132
	if (!does_interface_exist($interface))
3133
		return;
3134

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

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

    
3145
/*
3146
 * find_interface_ipv6($interface): return the interface ip (first found)
3147
 */
3148
function find_interface_ipv6($interface, $flush = false)
3149
{
3150
	global $interface_ipv6_arr_cache;
3151
	global $interface_snv6_arr_cache;
3152

    
3153
	$interface = str_replace("\n", "", $interface);
3154
	
3155
	if (!does_interface_exist($interface))
3156
		return;
3157

    
3158
	/* Setup IP cache */
3159
	if (!isset($interface_ipv6_arr_cache[$interface]) or $flush) {
3160
		$ifinfo = pfSense_get_interface_addresses($interface);
3161
		$interface_ipv6_arr_cache[$interface] = $ifinfo['ipaddrv6'];
3162
		$interface_snv6_arr_cache[$interface] = $ifinfo['subnetbitsv6'];
3163
	}
3164

    
3165
	return $interface_ipv6_arr_cache[$interface];
3166
}
3167

    
3168
function find_interface_subnet($interface, $flush = false)
3169
{
3170
	global $interface_sn_arr_cache;
3171
	global $interface_ip_arr_cache;
3172

    
3173
	$interface = str_replace("\n", "", $interface);
3174
	if (does_interface_exist($interface) == false)
3175
		return;
3176

    
3177
	if (!isset($interface_sn_arr_cache[$interface]) or $flush) {
3178
		$ifinfo = pfSense_get_interface_addresses($interface);
3179
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
3180
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
3181
        }
3182

    
3183
	return $interface_sn_arr_cache[$interface];
3184
}
3185

    
3186
function find_interface_subnetv6($interface, $flush = false)
3187
{
3188
	global $interface_snv6_arr_cache;
3189
	global $interface_ipv6_arr_cache;
3190

    
3191
	$interface = str_replace("\n", "", $interface);
3192
	if (does_interface_exist($interface) == false)
3193
		return;
3194

    
3195
	if (!isset($interface_snv6_arr_cache[$interface]) or $flush) {
3196
		$ifinfo = pfSense_get_interface_addresses($interface);
3197
		$interface_ipv6_arr_cache[$interface] = $ifinfo['ipaddrv6'];
3198
		$interface_snv6_arr_cache[$interface] = $ifinfo['subnetbitsv6'];
3199
        }
3200

    
3201
	return $interface_snv6_arr_cache[$interface];
3202
}
3203

    
3204
function ip_in_interface_alias_subnet($interface, $ipalias) {
3205
	global $config;
3206

    
3207
	if (empty($interface) || !is_ipaddr($ipalias))
3208
		return false;
3209
	if (is_array($config['virtualip']['vip'])) {
3210
                foreach ($config['virtualip']['vip'] as $vip) {
3211
                        switch ($vip['mode']) {
3212
                        case "ipalias":
3213
                                if ($vip['interface'] <> $interface)
3214
                                        break;
3215
				if (ip_in_subnet($ipalias, gen_subnet($vip['subnet'], $vip['subnet_bits']) . "/" . $vip['subnet_bits']))
3216
					return true;
3217
                                break;
3218
                        }
3219
                }
3220
	}
3221

    
3222
	return false;
3223
}
3224

    
3225
function get_interface_ip($interface = "wan")
3226
{
3227
	$realif = get_real_interface($interface);
3228
	if (!$realif) {
3229
		if (preg_match("/^carp/i", $interface))
3230
			$realif = $interface;
3231
		else if (preg_match("/^vip/i", $interface))
3232
			$realif = $interface;
3233
		else
3234
			return null;
3235
	}
3236

    
3237
	$curip = find_interface_ip($realif);
3238
	if ($curip && is_ipaddr($curip) && ($curip != "0.0.0.0"))
3239
		return $curip;
3240
	else
3241
		return null;
3242
}
3243

    
3244
function get_interface_ipv6($interface = "wan")
3245
{
3246
	$realif = get_real_interface($interface);
3247
	if (!$realif) {
3248
		if (preg_match("/^carp/i", $interface))
3249
			$realif = $interface;
3250
		else if (preg_match("/^vip/i", $interface))
3251
			$realif = $interface;
3252
		else
3253
			return null;
3254
	}
3255

    
3256
	$curip = find_interface_ipv6($realif);
3257
	if ($curip && is_ipaddrv6($curip) && ($curip != "::"))
3258
		return $curip;
3259
	else
3260
		return null;
3261
}
3262

    
3263
function get_interface_subnet($interface = "wan")
3264
{
3265
	$realif = get_real_interface($interface);
3266
	if (!$realif) {
3267
                if (preg_match("/^carp/i", $interface))
3268
                        $realif = $interface;
3269
                else if (preg_match("/^vip/i", $interface))
3270
                        $realif = $interface;
3271
                else
3272
                        return null;
3273
        }
3274

    
3275
	$cursn = find_interface_subnet($realif);
3276
	if (!empty($cursn))
3277
		return $cursn;
3278

    
3279
	return null;
3280
}
3281

    
3282
function get_interface_subnetv6($interface = "wan")
3283
{
3284
	$realif = get_real_interface($interface);
3285
	if (!$realif) {
3286
                if (preg_match("/^carp/i", $interface))
3287
                        $realif = $interface;
3288
                else if (preg_match("/^vip/i", $interface))
3289
                        $realif = $interface;
3290
                else
3291
                        return null;
3292
        }
3293

    
3294
	$cursn = find_interface_subnetv6($realif);
3295
	if (!empty($cursn))
3296
		return $cursn;
3297

    
3298
	return null;
3299
}
3300

    
3301
/* return outside interfaces with a gateway */
3302
function get_interfaces_with_gateway() {
3303
	global $config;
3304

    
3305
	$ints = array();
3306

    
3307
	/* loop interfaces, check config for outbound */
3308
	foreach($config['interfaces'] as $ifdescr => $ifname) {
3309
		if (substr($ifdescr, 0, 5) ==  "ovpnc")
3310
			return true;
3311

    
3312
		switch ($ifname['ipaddr']) {
3313
			case "dhcp":
3314
			case "carpdev-dhcp":
3315
			case "ppp";
3316
			case "pppoe":
3317
			case "pptp":
3318
			case "l2tp":
3319
			case "ppp";
3320
				$ints[$ifdescr] = $ifdescr;
3321
			break;
3322
			default:
3323
				if (!empty($ifname['gateway']))
3324
					$ints[$ifdescr] = $ifdescr;
3325
			break;
3326
		}
3327
	}
3328
	return $ints;
3329
}
3330

    
3331
/* return true if interface has a gateway */
3332
function interface_has_gateway($friendly) {
3333
	global $config;
3334

    
3335
	if (!empty($config['interfaces'][$friendly])) {
3336
		if (substr($friendly, 0, 5) ==  "ovpnc")
3337
			return true;
3338
		$ifname = &$config['interfaces'][$friendly];
3339
		switch ($ifname['ipaddr']) {
3340
			case "dhcp":
3341
			case "carpdev-dhcp":
3342
			case "pppoe":
3343
			case "pptp":
3344
			case "l2tp":
3345
			case "ppp";
3346
				return true;
3347
			break;
3348
			default:
3349
				if (!empty($ifname['gateway']))
3350
					return true;
3351
			break;
3352
		}
3353
	}
3354

    
3355
	return false;
3356
}
3357

    
3358
/****f* interfaces/is_altq_capable
3359
 * NAME
3360
 *   is_altq_capable - Test if interface is capable of using ALTQ
3361
 * INPUTS
3362
 *   $int            - string containing interface name
3363
 * RESULT
3364
 *   boolean         - true or false
3365
 ******/
3366

    
3367
function is_altq_capable($int) {
3368
        /* Per:
3369
         * http://www.freebsd.org/cgi/man.cgi?query=altq&manpath=FreeBSD+7.2-current&format=html
3370
         * Only the following drivers have ALTQ support
3371
         */
3372
	$capable = array("age", "ale", "an", "ath", "aue", "awi", "bce",
3373
			"bfe", "bge", "dc", "de", "ed", "em", "ep", "fxp", "gem",
3374
			"hme", "igb", "ipw", "iwi", "jme", "le", "msk", "mxge", "my", "nfe",
3375
			"npe", "nve", "ral", "re", "rl", "rum", "run", "bwn", "sf", "sis", "sk",
3376
			"ste", "stge", "txp", "udav", "ural", "vge", "vr", "wi", "xl",
3377
			"ndis", "tun", "ovpns", "ovpnc", "vlan", "pppoe", "pptp", "ng",
3378
			"l2tp", "ppp");
3379

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

    
3382
        if (in_array($int_family[0], $capable))
3383
                return true;
3384
	else if (stristr($int_family, "vlan")) /* VLANs are name $parent_$vlan now */
3385
		return true;
3386
	else if (stristr($int_family, "_wlan")) /* WLANs are name $parent_$wlan now */
3387
		return true;
3388
        else
3389
                return false;
3390
}
3391

    
3392
/****f* interfaces/is_interface_wireless
3393
 * NAME
3394
 *   is_interface_wireless - Returns if an interface is wireless
3395
 * RESULT
3396
 *   $tmp       - Returns if an interface is wireless
3397
 ******/
3398
function is_interface_wireless($interface) {
3399
        global $config, $g;
3400

    
3401
        $friendly = convert_real_interface_to_friendly_interface_name($interface);
3402
        if(!isset($config['interfaces'][$friendly]['wireless'])) {
3403
                if (preg_match($g['wireless_regex'], $interface)) {
3404
                        if (isset($config['interfaces'][$friendly]))
3405
                                $config['interfaces'][$friendly]['wireless'] = array();
3406
                        return true;
3407
                }
3408
                return false;
3409
        } else
3410
                return true;
3411
}
3412

    
3413
function get_wireless_modes($interface) {
3414
	/* return wireless modes and channels */
3415
	$wireless_modes = array();
3416

    
3417
	$wlif = interface_translate_type_to_real($interface);
3418

    
3419
	if(is_interface_wireless($wlif)) {
3420
		$cloned_interface = get_real_interface($interface);
3421
		$chan_list = "/sbin/ifconfig {$cloned_interface} list chan";
3422
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
3423
		$format_list = "/usr/bin/awk '{print \$5 \" \" \$6 \",\" \$1}'";
3424

    
3425
		$interface_channels = "";
3426
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
3427
		$interface_channel_count = count($interface_channels);
3428

    
3429
		$c = 0;
3430
		while ($c < $interface_channel_count)
3431
		{
3432
			$channel_line = explode(",", $interface_channels["$c"]);
3433
			$wireless_mode = trim($channel_line[0]);
3434
			$wireless_channel = trim($channel_line[1]);
3435
			if(trim($wireless_mode) != "") {
3436
				/* if we only have 11g also set 11b channels */
3437
				if($wireless_mode == "11g") {
3438
					if(!isset($wireless_modes["11b"]))
3439
						$wireless_modes["11b"] = array();
3440
				} else if($wireless_mode == "11g ht") {
3441
					if(!isset($wireless_modes["11b"]))
3442
						$wireless_modes["11b"] = array();
3443
					if(!isset($wireless_modes["11g"]))
3444
						$wireless_modes["11g"] = array();
3445
					$wireless_mode = "11ng";
3446
				} else if($wireless_mode == "11a ht") {
3447
					if(!isset($wireless_modes["11a"]))
3448
						$wireless_modes["11a"] = array();
3449
					$wireless_mode = "11na";
3450
				}
3451
				$wireless_modes["$wireless_mode"]["$c"] = $wireless_channel;
3452
			}
3453
			$c++;
3454
		}
3455
	}
3456
	return($wireless_modes);
3457
}
3458

    
3459
/* return channel numbers, frequency, max txpower, and max regulation txpower */
3460
function get_wireless_channel_info($interface) {
3461
	$wireless_channels = array();
3462

    
3463
	$wlif = interface_translate_type_to_real($interface);
3464

    
3465
	if(is_interface_wireless($wlif)) {
3466
		$cloned_interface = get_real_interface($interface);
3467
		$chan_list = "/sbin/ifconfig {$cloned_interface} list txpower";
3468
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
3469
		$format_list = "/usr/bin/awk '{print \$1 \",\" \$3 \" \" \$4 \",\" \$5 \",\" \$7}'";
3470

    
3471
		$interface_channels = "";
3472
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
3473

    
3474
		foreach ($interface_channels as $channel_line) {
3475
			$channel_line = explode(",", $channel_line);
3476
			if(!isset($wireless_channels[$channel_line[0]]))
3477
				$wireless_channels[$channel_line[0]] = $channel_line;
3478
		}
3479
	}
3480
	return($wireless_channels);
3481
}
3482

    
3483
/****f* interfaces/get_interface_mtu
3484
 * NAME
3485
 *   get_interface_mtu - Return the mtu of an interface
3486
 * RESULT
3487
 *   $tmp       - Returns the mtu of an interface
3488
 ******/
3489
function get_interface_mtu($interface) {
3490
        $mtu = pfSense_get_interface_addresses($interface);
3491
        return $mtu['mtu'];
3492
}
3493

    
3494
function get_interface_mac($interface) {
3495

    
3496
	$macinfo = pfSense_get_interface_addresses($interface);
3497
	return $macinfo["macaddr"];
3498
}
3499

    
3500
/****f* pfsense-utils/generate_random_mac_address
3501
 * NAME
3502
 *   generate_random_mac - generates a random mac address
3503
 * INPUTS
3504
 *   none
3505
 * RESULT
3506
 *   $mac - a random mac address
3507
 ******/
3508
function generate_random_mac_address() {
3509
        $mac = "02";
3510
        for($x=0; $x<5; $x++)
3511
                $mac .= ":" . dechex(rand(16, 255));
3512
        return $mac;
3513
}
3514

    
3515
/****f* interfaces/is_jumbo_capable
3516
 * NAME
3517
 *   is_jumbo_capable - Test if interface is jumbo frame capable.  Useful for determining VLAN capability.
3518
 * INPUTS
3519
 *   $int             - string containing interface name
3520
 * RESULT
3521
 *   boolean          - true or false
3522
 ******/
3523
function is_jumbo_capable($int) {
3524
        global $g;
3525

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

    
3528
        if (in_array($int_family[0], $g['vlan_long_frame']))
3529
                return true;
3530
        else
3531
                return false;
3532
}
3533

    
3534
function setup_pppoe_reset_file($pppif, $iface="") {
3535
	global $g;
3536
	$cron_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
3537

    
3538
	if(!empty($iface) && !empty($pppif)){
3539
		$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";
3540
		file_put_contents($cron_file, $cron_cmd);
3541
		chmod($cron_file, 0700);
3542
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
3543
	} else
3544
		unlink_if_exists($cron_file);
3545
}
3546

    
3547
?>
(22-22/54)