Project

General

Profile

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

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

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

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

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

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

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

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

    
42
*/
43

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

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

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

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

    
67
        return $interface_arr_cache;
68
}
69

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

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

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

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

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

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

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

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

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

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

    
145
	interfaces_bring_up($vlanif);
146

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

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

    
153
	return $vlanif;
154
}
155

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

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

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

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

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

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

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

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

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

    
222
        return $vlanif;
223
}
224

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

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

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

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

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

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

    
265
        return $vlanif;
266
}
267

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

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

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

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

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

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

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

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

    
319
	$checklist = get_configured_interface_list();
320

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

    
328
	/* Calculate smaller mtu and enforce it */
329
	$smallermtu = 0;
330
	foreach ($members as $member) {
331
		$realif = get_real_interface($member);
332
		$mtu = get_interface_mtu($realif);
333
		if ($smallermtu == 0 && !empty($mtu))
334
			$smallermtu = $mtu;
335
		else if (!empty($mtu) && $mtu < $smallermtu)
336
			$smallermtu = $mtu;
337
	}
338
	 
339
	/* Just in case anything is not working well */
340
	if ($smallermtu == 0)
341
		$smallermtu = 1500; 
342

    
343
	/* Add interfaces to bridge */
344
	foreach ($members as $member) {
345
		if (!array_key_exists($member, $checklist))
346
			continue;
347
		$realif1 = get_real_interface($member);
348
		$realif =  escapeshellarg($realif1);
349
		/* make sure the parent interface is up */
350
		pfSense_interface_mtu($realif, $smallermtu);
351
		if(!$realif) 
352
			log_error("realif not defined in interfaces bridge - up");
353
		interfaces_bring_up($realif1);
354
		mwexec("/sbin/ifconfig {$bridgeif} addm {$realif}");	
355
	}
356

    
357
	if (isset($bridge['enablestp'])) {
358
		/* Choose spanning tree proto */
359
		mwexec("/sbin/ifconfig {$bridgeif} proto {$bridge['proto']}");	
360
		
361
		if (!empty($bridge['stp'])) {
362
			$stpifs = explode(',', $bridge['stp']);
363
			foreach ($stpifs as $stpif) {
364
				$realif = get_real_interface($stpif);
365
				mwexec("/sbin/ifconfig {$bridgeif} stp {$realif}");
366
			}
367
		}
368
		if (!empty($bridge['maxage']))
369
			mwexec("/sbin/ifconfig {$bridgeif} maxage {$bridge['maxage']}");
370
		if (!empty($brige['fwdelay']))
371
			mwexec("/sbin/ifconfig {$bridgeif} fwddelay {$bridge['fwdelay']}");
372
		if (!empty($brige['hellotime']))
373
                        mwexec("/sbin/ifconfig {$bridgeif} hellotime {$bridge['hellotime']}");
374
		if (!empty($brige['priority']))
375
                        mwexec("/sbin/ifconfig {$bridgeif} priority {$bridge['priority']}");
376
		if (!empty($brige['holdcount']))
377
                        mwexec("/sbin/ifconfig {$bridgeif} holdcnt {$bridge['holdcnt']}");
378
		if (!empty($bridge['ifpriority'])) {
379
			$pconfig = explode(",", $bridge['ifpriority']);
380
			$ifpriority = array();
381
			foreach ($pconfig as $cfg) {
382
				$embcfg = explode(":", $cfg);
383
				foreach ($embcfg as $key => $value)
384
					$ifpriority[$key] = $value;
385
			}
386
			foreach ($ifpriority as $key => $value) {
387
				$realif = get_real_interface($key);
388
				mwexec("/sbin/ifconfig ${bridgeif} ifpriority {$realif} {$value}"); 
389
			}
390
		}
391
		if (!empty($bridge['ifpathcost'])) {
392
			$pconfig = explode(",", $bridges['ifpathcost']);
393
			$ifpathcost = array();
394
			foreach ($pconfig as $cfg) {
395
				$embcfg = explode(":", $cfg);
396
				foreach ($embcfg as $key => $value)
397
					$ifpathcost[$key] = $value;
398
			}
399
			foreach ($ifpathcost as $key => $value) {
400
                        	$realif = get_real_interface($key);
401
                        	mwexec("/sbin/ifconfig ${bridgeif} ifpathcost {$realif} {$value}");
402
                	}
403
		}
404
	}
405

    
406
	if ($bridge['maxaddr'] <> "")
407
		mwexec("/sbin/ifconfig {$bridgeif} maxaddr {$bridge['maxaddr']}");
408
        if ($bridge['timeout'] <> "")
409
                mwexec("/sbin/ifconfig {$bridgeif} timeout {$bridge['timeout']}");
410
        if ($bridge['span'] <> "") {
411
		$realif = get_real_interface($bridge['span']);
412
                mwexec("/sbin/ifconfig {$bridgeif} span {$realif}");
413
	}
414
	if (!empty($bridge['edge'])) {
415
        	$edgeifs = explode(',', $bridge['edge']);
416
        	foreach ($edgeifs as $edgeif) {
417
			$realif = get_real_interface($edgeif);
418
                	mwexec("/sbin/ifconfig {$bridgeif} edge {$realif}");
419
        	}
420
	}
421
	if (!empty($bridge['autoedge'])) {
422
        	$edgeifs = explode(',', $bridge['autoedge']);
423
        	foreach ($edgeifs as $edgeif) {
424
                	$realif = get_real_interface($edgeif);
425
                	mwexec("/sbin/ifconfig {$bridgeif} -autoedge {$realif}");
426
        	}
427
	}
428
	if (!empty($bridge['ptp'])) {
429
        	$ptpifs = explode(',', $bridge['ptp']);
430
        	foreach ($ptpifs as $ptpif) {
431
                	$realif = get_real_interface($ptpif);
432
                	mwexec("/sbin/ifconfig {$bridgeif} ptp {$realif}");
433
        	}
434
	}
435
	if (!empty($bridge['autoptp'])) {
436
        	$ptpifs = explode(',', $bridge['autoptp']);
437
        	foreach ($ptpifs as $ptpif) {
438
                	$realif = get_real_interface($ptpif);
439
                	mwexec("/sbin/ifconfig {$bridgeif} -autoptp {$realif}");
440
        	}
441
	}
442
	if (!empty($bridge['static'])) {
443
        	$stickyifs = explode(',', $bridge['static']);
444
        	foreach ($stickyifs as $stickyif) {
445
                	$realif = get_real_interface($stickyif);
446
                	mwexec("/sbin/ifconfig {$bridgeif} sticky {$realif}");
447
        	}
448
	}
449
	if (!empty($bridge['private'])) {
450
        	$privateifs = explode(',', $bridge['private']);
451
        	foreach ($privateifs as $privateif) {
452
                	$realif = get_real_interface($privateif);
453
               	 	mwexec("/sbin/ifconfig {$bridgeif} private {$realif}");
454
        	}
455
	}
456

    
457
	if($bridgeif)
458
		interfaces_bring_up($bridgeif);	
459
	else 
460
		log_error("bridgeif not defined -- could not bring interface up");
461

    
462
	return $bridgeif;
463
}
464

    
465
function interface_bridge_add_member($bridgeif, $interface) {
466

    
467
	if (!does_interface_exist($bridgeif) || !does_interface_exist($interface))
468
		return;
469

    
470
	$mtu = get_interface_mtu($brigeif);
471
	$mtum = get_interface_mtu($interface);
472
	
473
	if ($mtu != $mtum)
474
		pfSense_interface_mtu($interface, $mtu);
475

    
476
	pfSense_get_interface_addresses($bridgeif);
477
	if (isset($options['encaps']['txcsum']))
478
		pfSense_interface_capabilities($interface, -IFCAP_TXCSUM);
479
	else
480
		pfSense_interface_capabilities($interface, IFCAP_TXCSUM);
481

    
482
	interfaces_bring_up($interface);
483
	mwexec("/sbin/ifconfig {$bridgeif} addm {$interface}");
484
}
485

    
486
function interfaces_lagg_configure() 
487
{
488
        global $config, $g;
489
		if($g['booting']) 
490
			echo "Configuring LAGG interfaces...";
491
        $i = 0;
492
		if (is_array($config['laggs']['lagg']) && count($config['laggs']['lagg'])) {
493
			foreach ($config['laggs']['lagg'] as $lagg) {
494
				if(empty($lagg['laggif']))
495
					$lagg['laggif'] = "lagg{$i}";
496
				/* XXX: Maybe we should report any errors?! */
497
				interface_lagg_configure($lagg);
498
				$i++;
499
			}
500
		}
501
		if($g['booting']) 
502
			echo "done.\n";
503
}
504

    
505
function interface_lagg_configure(&$lagg) {
506
        global $config, $g;
507

    
508
        if (!is_array($lagg))
509
		return -1;
510

    
511
	$members = explode(',', $lagg['members']);
512
	if (!count($members))
513
		return -1;
514
	
515
	$checklist = get_interface_list();
516

    
517
	if ($g['booting'] || !(empty($lagg['laggif']))) {
518
		pfSense_interface_destroy($lagg['laggif']);
519
		pfSense_interface_create($lagg['laggif']);
520
                $laggif = $lagg['laggif'];
521
        } else
522
		$laggif = pfSense_interface_create("lagg");
523

    
524
	/* Calculate smaller mtu and enforce it */
525
        $smallermtu = 0;
526
        foreach ($members as $member) {
527
                $mtu = get_interface_mtu($member);
528
		if ($smallermtu == 0 && !empty($mtu))
529
			$smallermtu = $mtu;
530
                else if (!empty($mtu) && $mtu < $smallermtu)
531
                        $smallermtu = $mtu;
532
        }
533

    
534
	/* Just in case anything is not working well */
535
        if ($smallermtu == 0)
536
                $smallermtu = 1500;
537

    
538
	foreach ($members as $member) {
539
		if (!array_key_exists($member, $checklist))
540
			continue;
541
		/* make sure the parent interface is up */
542
		pfSense_interface_mtu($member, $smallermtu);
543
		interfaces_bring_up($member);
544
		mwexec("/sbin/ifconfig {$laggif} laggport {$member}");
545
	}
546
	
547
	mwexec("/sbin/ifconfig {$laggif} laggproto {$lagg['proto']}");
548

    
549
	interfaces_bring_up($laggif);
550

    
551
	return $laggif;
552
}
553

    
554
function interfaces_gre_configure() {
555
        global $config;
556

    
557
        $i = 0;
558
        if (is_array($config['gres']['gre']) && count($config['gres']['gre'])) {
559
                foreach ($config['gres']['gre'] as $gre) {
560
                        if(empty($gre['greif']))
561
                                $gre['greif'] = "gre{$i}";
562
                        /* XXX: Maybe we should report any errors?! */
563
                        interface_gre_configure($gre);
564
                        $i++;
565
                }
566
        }
567
}
568

    
569
function interface_gre_configure(&$gre) {
570
        global $config, $g;
571

    
572
	if (!is_array($gre))
573
		return -1;
574

    
575
	$realif = get_real_interface($gre['if']);
576
	$realifip = get_interface_ip($gre['if']);
577

    
578
	/* make sure the parent interface is up */
579
	interfaces_bring_up($realif);
580

    
581
	if ($g['booting'] || !(empty($gre['greif']))) {
582
		pfSense_interface_destroy($gre['greif']);
583
		pfSense_interface_create($gre['greif']);
584
		$greif = $gre['greif'];
585
	} else
586
		$greif = pfSense_interface_create("gre");
587

    
588
	/* Do not change the order here for more see gre(4) NOTES section. */
589
	mwexec("/sbin/ifconfig {$greif} tunnel {$realifip} {$gre['remote-addr']}");
590
	mwexec("/sbin/ifconfig {$greif} {$gre['tunnel-local-addr']} {$gre['tunnel-remote-addr']} netmask " . gen_subnet_mask($gre['tunnel-remote-net']));
591
	if (isset($gre['link0']) && $gre['link0'])
592
		pfSense_interface_flags($greif, IFF_LINK0);
593
	if (isset($gre['link1']) && $gre['link1'])
594
		pfSense_interface_flags($greif, IFF_LINK1);
595
	if (isset($gre['link2']) && $gre['link2'])
596
		pfSense_interface_flags($greif, IFF_LINK2);
597

    
598
	if($greif)
599
		interfaces_bring_up($greif);
600
	else 
601
		log_error("Could not bring greif up -- variable not defined.");
602

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

    
607
	return $greif;
608
}
609

    
610
function interfaces_gif_configure() {
611
	global $config;
612
	$i = 0;
613
	if (is_array($config['gifs']['gif']) && count($config['gifs']['gif'])) {
614
		foreach ($config['gifs']['gif'] as $gif) {
615
			if(empty($gif['gifif']))
616
				$gre['gifif'] = "gif{$i}";
617
			/* XXX: Maybe we should report any errors?! */
618
			interface_gif_configure($gif);
619
			$i++;
620
		}
621
	}
622
}
623

    
624
function interface_gif_configure(&$gif) {
625
	global $config, $g;
626

    
627
	if (!is_array($gif))
628
		return -1;
629

    
630
	$realif = get_real_interface($gif['if']);
631
	$realifip = get_interface_ip($gif['if']);
632

    
633
	/* make sure the parent interface is up */
634
	if($realif)
635
		interfaces_bring_up($realif);
636
	else 
637
		log_error("could not bring realif up -- variable not defined -- interface_gif_configure()");
638

    
639
	if ($g['booting'] || !(empty($gif['gifif']))) {
640
		pfSense_interface_destroy($gif['gifif']);
641
		pfSense_interface_create($gif['gifif']);
642
		$gifif = $gif['gifif'];
643
	} else
644
		$gifif = pfSense_interface_create("gif");
645

    
646
	/* Do not change the order here for more see gif(4) NOTES section. */
647
	mwexec("/sbin/ifconfig {$gifif} tunnel {$realifip} {$gif['remote-addr']}");
648
	mwexec("/sbin/ifconfig {$gifif} {$gif['tunnel-local-addr']} {$gif['tunnel-remote-addr']} netmask " . gen_subnet_mask($gif['tunnel-remote-net']));
649
	if (isset($gif['link0']) && $gif['link0'])
650
		pfSense_interface_flags($gifif, IFF_LINK0);
651
	if (isset($gif['link1']) && $gif['link1'])
652
		pfSense_interface_flags($gifif, IFF_LINK1);
653
	if($gifif)
654
		interfaces_bring_up($gifif);
655
	else
656
		log_error("could not bring gifif up -- variable not defined");
657

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

    
662
	return $gifif;
663
}
664

    
665
function interfaces_configure() {
666
	global $config, $g;
667

    
668
	/* Set up our loopback interface */
669
	interfaces_loopback_configure();
670

    
671
	/* set up LAGG virtual interfaces */
672
	interfaces_lagg_configure();
673

    
674
	/* set up VLAN virtual interfaces */
675
	interfaces_vlan_configure();
676

    
677
	interfaces_qinq_configure();
678

    
679
	$iflist = get_configured_interface_with_descr();
680
	$delayed_list = array();
681
	$bridge_list = array();
682
	
683
	/* This is needed to speedup interfaces on bootup. */
684
	$reload = false;
685
	if ($g['booting'])
686
		$reload = true;
687

    
688
	foreach($iflist as $if => $ifname) {
689
		$realif = $config['interfaces'][$if]['if'];
690
		if (strstr($realif, "bridge")) 
691
			$bridge_list[$if] = $ifname;
692
		else if (strstr($realif, "gre"))
693
			$delayed_list[$if] = $ifname;
694
		else if (strstr($realif, "gif"))
695
			$delayed_list[$if] = $ifname;
696
		else {
697
			if ($g['booting'])
698
				echo "Configuring {$ifname} interface...";
699
			if($g['debug'])
700
				log_error("Configuring {$ifname}");
701
			interface_configure($if, $reload);
702
			if ($g['booting']) 
703
				echo "done.\n";
704
		}
705
	}
706

    
707
	/* create the unconfigured wireless clones */
708
	interfaces_create_wireless_clones();
709

    
710
	/* set up GRE virtual interfaces */
711
	interfaces_gre_configure();
712

    
713
	/* set up GIF virtual interfaces */
714
	interfaces_gif_configure();
715
	
716
	foreach ($delayed_list as $if => $ifname) {
717
		if ($g['booting'])
718
			echo "Configuring {$ifname} interface...";
719
        	if ($g['debug'])
720
        		log_error("Configuring {$ifname}");
721

    
722
		interface_configure($if, $reload);
723

    
724
		if ($g['booting'])
725
			echo "done.\n";
726
	}
727

    
728
	/* set up BRIDGe virtual interfaces */
729
	interfaces_bridge_configure();
730

    
731
	foreach ($bridge_list as $if => $ifname) {
732
		if ($g['booting'])
733
			echo "Configuring {$ifname} interface...";
734
		if($g['debug'])
735
			log_error("Configuring {$ifname}");
736

    
737
		interface_configure($if, $reload);
738

    
739
		if ($g['booting'])
740
			echo "done.\n";
741
	}
742

    
743
	/* bring up vip interfaces */
744
	interfaces_vips_configure();
745

    
746
	/* configure interface groups */
747
	interfaces_group_setup();
748

    
749
	if (!$g['booting']) {
750
		/* reconfigure static routes (kernel may have deleted them) */
751
		system_routing_configure();
752

    
753
		/* reload IPsec tunnels */
754
		vpn_ipsec_configure();
755

    
756
		/* reload dhcpd (interface enabled/disabled status may have changed) */
757
		services_dhcpd_configure();
758

    
759
		/* restart dnsmasq */
760
		services_dnsmasq_configure();
761

    
762
		/* reload captive portal */
763
		captiveportal_init_rules();
764

    
765
		/* set the reload filter dity flag */
766
		filter_configure();
767
	}
768

    
769
	return 0;
770
}
771

    
772
function interface_reconfigure($interface = "wan") {
773
	interface_bring_down($interface);
774
	interface_configure($interface, true);
775
}
776

    
777
function interface_vip_bring_down(&$vip) {
778
	global $g;
779

    
780
	switch ($vip['mode']) {
781
	case "proxyarp":
782
		$vipif = get_real_interface($vip['interface']);
783
		if (file_exists("{$g['varrun_path']}/choparp_{$vipif}.pid"))
784
			killbypid("{$g['varrun_path']}/choparp_{$vipif}.pid");
785
		break;
786
	case "ipalias":
787
		$vipif = get_real_interface($vip['interface']);
788
		if(does_interface_exist($vipif))
789
			pfSense_interface_deladdress($vipif, $vip['subnet']);
790
		break;
791
	case "carp":
792
		$vipif = "vip" . $vip['vhid'];
793
		if(does_interface_exist($vipif)) 
794
			pfSense_interface_destroy($vipif);
795
		break;
796
	case "carpdev-dhcp":
797
		$vipif = "vip" . $vip['vhid'];
798
		if(does_interface_exist($vipif)) 
799
			pfSense_interface_destroy($vipif);
800
		break;
801
	}
802
}
803

    
804
function interface_bring_down($interface = "wan", $destroy = false) {
805
	global $config, $g;
806

    
807
	if (!isset($config['interfaces'][$interface]))
808
		return; 
809

    
810
	$ifcfg = $config['interfaces'][$interface];
811

    
812
	$realif = get_real_interface($interface);
813

    
814
	switch ($ifcfg['ipaddr']) {
815
	case "ppp":
816
	case "pppoe":
817
	case "pptp":
818
	case "l2tp":
819
		if (is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) {
820
			foreach ($config['ppps']['ppp'] as $pppid => $ppp) {
821
				if ($realif == $ppp['if']) {
822
					killbypid("{$g['varrun_path']}/{$ifcfg['ipaddr']}_{$interface}.pid");
823
					sleep(2);
824
					unlink_if_exists("{$g['varetc_path']}/mpd_{$interface}.conf");
825
					if (isset($ppp['ondemand']) && !$destroy) {
826
						interface_configure("wan");
827
					}
828
					break;
829
				}
830
			}
831
		}
832
		break;
833
	case "carpdev-dhcp":
834
		/* 
835
		 * NB: When carpdev gets enabled it would be better to be handled as all
836
		 *	   other interfaces! 
837
		 */
838
	case "dhcp":
839
		$pid = find_dhclient_process($realif);
840
		if($pid)
841
			mwexec("kill {$pid}");
842
		sleep(1);
843
		unlink_if_exists("{$g['varetc_path']}/dhclient_{$interface}.conf");
844
		if(does_interface_exist("$realif")) {
845
			mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete", true);
846
			pfSense_interface_flags($realif, -IFF_UP);
847
			mwexec("/usr/sbin/arp -d -i {$realif} -a");
848
		}
849
		break;
850
	default:
851
		if(does_interface_exist("$realif")) {
852
			mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete", true);
853
			pfSense_interface_flags($realif, -IFF_UP);
854
			mwexec("/usr/sbin/arp -d -i {$realif} -a");
855
		}
856
		break;
857
	}
858

    
859
	/* remove interface up file if it exists */
860
	unlink_if_exists("{$g['tmp_path']}/{$realif}up");
861
	unlink_if_exists("{$g['vardb_path']}/{$interface}ip");
862
	unlink_if_exists("{$g['tmp_path']}/{$realif}_router");
863
	
864
	/* hostapd and wpa_supplicant do not need to be running when the interface is down.
865
	 * They will also use 100% CPU if running after the wireless clone gets deleted. */
866
	if (is_array($ifcfg['wireless'])) {
867
		mwexec(kill_hostapd($realif));
868
		mwexec(kill_wpasupplicant($realif));
869
	}
870

    
871
	if ($destroy == true) {
872
		if (preg_match("/^vip|^tun|^ovpn|^gif|^gre|^lagg|^bridge|vlan/i", $realif))
873
			pfSense_interface_destroy($realif);
874
	}	
875

    
876
	return;
877
}
878

    
879
function interfaces_ptpid_used($ptpid) {
880
	global $config;
881

    
882
	if (is_array($config['ppps']['ppp']))
883
		foreach ($config['ppps']['ppp'] as & $settings)
884
			if ($ptpid == $settings['ptpid'])
885
				return true;
886

    
887
	return false;
888
}
889

    
890
function interfaces_ptpid_next() {
891

    
892
	$ptpid = 0;
893
	while(interfaces_ptpid_used($ptpid))
894
		$ptpid++;
895

    
896
	return $ptpid;
897
}
898

    
899
function getMPDCRONSettings($pppif_) {
900
	global $config;
901
	$cron_cmd_file = "{$g['varetc_path']}/pppoe_restart_";
902
	if (is_array($config['cron']['item'])) {
903
		for ($i = 0; $i < count($config['cron']['item']); $i++) {
904
			$item = $config['cron']['item'][$i];
905
			if (strpos($item['command'], $cron_cmd_file.$pppif_) !== false) {
906
				return array("ID" => $i, "ITEM" => $item);
907
			}
908
		}
909
	}
910
	return NULL;
911
}
912

    
913
function handle_pppoe_reset($post_array) {
914
	global $config, $g;
915

    
916
	$cron_cmd_file = "{$g['varetc_path']}/pppoe_restart_";
917

    
918
	$pppif = $post_array['type'].$post_array['ptpid'];
919
	if (!is_array($config['cron']['item'])) 
920
		$config['cron']['item'] = array(); 
921
	$itemhash = getMPDCRONSettings($pppif);
922
	$item = $itemhash['ITEM'];
923
	
924
	// reset cron items if necessary and return
925
	if (empty($post_array['pppoe-reset-type'])) {
926
		if (isset($item))
927
			unset($config['cron']['item'][$itemhash['ID']]);
928
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
929
		return;
930
	}
931

    
932
	if (empty($item)) 
933
		$item = array();
934
	if (isset($post_array['pppoe-reset-type']) && $post_array['pppoe-reset-type'] == "custom") {
935
		$item['minute'] = $post_array['pppoe_resetminute'];
936
		$item['hour'] = $post_array['pppoe_resethour'];
937
		if (isset($post_array['pppoe_resetdate']) && $post_array['pppoe_resetdate'] <> "") {
938
			$date = explode("/", $post_array['pppoe_resetdate']);
939
			$item['mday'] = $date[1];
940
			$item['month'] = $date[0];
941
		} else {
942
			$item['mday'] = "*";
943
			$item['month'] = "*";
944
		}
945
		$item['wday'] = "*";
946
		$item['who'] = "root";
947
		$item['command'] = $cron_cmd_file.$pppif;
948
	} else if (isset($post_array['pppoe-reset-type']) && $post_array['pppoe-reset-type'] == "preset") {
949
		switch ($post_array['pppoe_pr_preset_val']) {
950
			case "monthly":
951
				$item['minute'] = "0";
952
				$item['hour'] = "0";
953
				$item['mday'] = "1";
954
				$item['month'] = "*";
955
				$item['wday'] = "*";
956
				$item['who'] = "root";
957
				$item['command'] = $cron_cmd_file.$pppif;
958
				break;
959
	        case "weekly":
960
				$item['minute'] = "0";
961
				$item['hour'] = "0";
962
				$item['mday'] = "*";
963
				$item['month'] = "*";
964
				$item['wday'] = "0";
965
				$item['who'] = "root";
966
				$item['command'] = $cron_cmd_file.$pppif;
967
				break;
968
			case "daily":
969
				$item['minute'] = "0";
970
				$item['hour'] = "0";
971
				$item['mday'] = "*";
972
				$item['month'] = "*";
973
				$item['wday'] = "*";
974
				$item['who'] = "root";
975
				$item['command'] = $cron_cmd_file.$pppif;
976
				break;
977
			case "hourly":
978
				$item['minute'] = "0";
979
				$item['hour'] = "*";
980
				$item['mday'] = "*";
981
				$item['month'] = "*";
982
				$item['wday'] = "*";
983
				$item['who'] = "root";
984
				$item['command'] = $cron_cmd_file.$pppif;
985
				break;
986
		} // end switch
987
	} else {
988
		/* test whether a cron item exists and unset() it if necessary */
989
		$itemhash = getMPDCRONSettings($pppif);
990
		$item = $itemhash['ITEM'];
991
		if (isset($item))
992
			unset($config['cron']['item'][$itemhash['ID']]); 
993
	}// end if
994
	if (isset($itemhash['ID'])) 
995
		$config['cron']['item'][$itemhash['ID']] = $item;
996
	else 
997
		$config['cron']['item'][] = $item;
998
}
999

    
1000
/*	This function can configure PPPoE, MLPPP (PPPoE), PPtP.
1001
*	It writes the mpd config file to /var/etc every time the link is opened.
1002
*/
1003

    
1004
function interface_ppps_configure($interface) {
1005
	global $config, $g;
1006
	
1007
	// mpd5 requires a /var/spool/lock directory for PPP modem links.
1008
	if(!is_dir("/var/spool/lock")) {
1009
		exec("/bin/mkdir -p /var/spool/lock");
1010
		exec("/bin/chmod a+rw /var/spool/lock/.");
1011
	}
1012
	// mpd5 modem chat script expected in the same directory as the mpd_xxx.conf files	
1013
	if (!file_exists("{$g['varetc_path']}/mpd.script"))
1014
		mwexec("/bin/ln -s /usr/local/sbin/mpd.script {$g['varetc_path']}/.");
1015
		
1016
	$ifcfg = &$config['interfaces'][$interface];
1017
	if (!isset($ifcfg['enable']))
1018
		return 0;
1019
	if (is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) {
1020
		foreach ($config['ppps']['ppp'] as $pppid => $ppp) {
1021
			if ($ifcfg['if'] == $ppp['if'])
1022
				break;
1023
		}
1024
	}
1025
	if (!$ppp || $ifcfg['if'] != $ppp['if']){
1026
		log_error("Can't find PPP config for {$ifcfg['if']} in interface_ppps_configure().");
1027
		return 0;
1028
	}
1029
	$pppif = $ifcfg['if'];
1030
	if ($ppp['type'] == "ppp")
1031
		$type = "modem";
1032
	else
1033
		$type = $ppp['type'];
1034
	$upper_type = strtoupper($ppp['type']);	
1035
	
1036
	if($g['booting']) {
1037
		$descr = isset($ifcfg['descr']) ? $ifcfg['descr'] : strtoupper($interface);
1038
		echo " configuring {$upper_type} on {$descr} interface...\n";
1039
		// Do not re-configure the interface if we are booting and it's already been started
1040
		if(file_exists("{$g['varrun_path']}/{$ppp['type']}_{$interface}.pid"))
1041
			return 0;
1042
	}
1043
	
1044
	$ports = explode(',',$ppp['ports']);
1045
	if ($type != "modem") {
1046
		foreach ($ports as $pid => $port)
1047
			$ports[$pid] = get_real_interface($port);
1048
	}
1049
	$localips = explode(',',$ppp['localip']);
1050
	$gateways = explode(',',$ppp['gateway']);
1051
	$subnets = explode(',',$ppp['subnet']);
1052
	
1053
	/* We bring up the parent interface first because if DHCP is configured on the parent we need
1054
	to obtain an address first so we can write it in the mpd .conf file for PPtP and L2tP configs
1055
	*/
1056
	foreach($ports as $pid => $port){
1057
		switch ($ppp['type']) {
1058
			case "pppoe": 
1059
				/* Bring the parent interface up */
1060
				interfaces_bring_up($port);
1061
				break;
1062
			case "pptp":
1063
			case "l2tp":
1064
				/* configure interface */
1065
				if(is_ipaddr($localips[$pid])){
1066
					// Manually configure interface IP/subnet
1067
					pfSense_interface_setaddress($port, "{$localips[$pid]}/{$subnets[$pid]}");
1068
					interfaces_bring_up($port);
1069
				} else if (empty($localips[$pid]))
1070
					$localips[$pid] = get_interface_ip($port); // try to get the interface IP from the port
1071
				
1072
				if(!is_ipaddr($localips[$pid])){
1073
					log_error("Could not get a Local IP address for PPtP/L2tP link on {$port} in interfaces_ppps_configure.");
1074
					return 0;
1075
				}
1076
				/* XXX: This needs to go away soon! [It's commented out!] */
1077
				/* Configure the gateway (remote IP ) */
1078
				if (!$g['booting'] && !is_ipaddr($gateways[$pid]) && is_hostname($gateways[$pid])) {
1079
					/* XXX: Fix later 
1080
					$gateways[$pid] = gethostbyname($gateways[$pid]);
1081
					if(!is_ipaddr($gateways[$pid])) {
1082
						log_error("Could not get a valid Gateway IP from {$port} via DNS in interfaces_ppps_configure.");
1083
						return 0;
1084
					}
1085
					*/
1086
				}
1087
				if(!is_ipaddr($gateways[$pid])){
1088
					log_error("Could not get a PPtP/L2tP Remote IP address from {$dhcp_gateway} for {$gway} in interfaces_ppps_configure.");
1089
					return 0;
1090
				}
1091
				break;
1092
			case "ppp":
1093
				if (!file_exists("{$port}")) {
1094
					log_error("Device {$port} does not exist. PPP link cannot start without the modem device.");
1095
					return 0;
1096
				}
1097
				break;
1098
			default:
1099
				log_error("Unkown {$type} configured as ppp interface.");
1100
				break;
1101
		}
1102
	}
1103

    
1104
	/* generate mpd.conf */
1105
	$fd = fopen("{$g['varetc_path']}/mpd_{$interface}.conf", "w");
1106
	if (!$fd) {
1107
		log_error("Error: cannot open mpd_{$interface}.conf in interface_ppps_configure().\n");
1108
		return 0;
1109
	}
1110
	
1111
	if (is_array($ports) && count($ports) > 1)
1112
		$multilink = "enable";
1113
	else
1114
		$multilink = "disable";
1115
	
1116
	if ($type == "modem"){
1117
		if (is_ipaddr($ppp['localip']))
1118
			$localip = $ppp['localip'];
1119
		else
1120
			$localip = '0.0.0.0';
1121

    
1122
		if (is_ipaddr($ppp['gateway']))
1123
			$gateway = $ppp['gateway'];
1124
		else
1125
			$gateway = "10.64.64.{$pppid}";
1126
		$ranges = "{$localip}/0 {$gateway}/0";
1127
		
1128
		if (empty($ppp['apnum']))	
1129
			$ppp['apnum'] = 1;
1130
	} else
1131
		$ranges = "0.0.0.0/0 0.0.0.0/0";
1132

    
1133
	if (isset($ppp['ondemand'])) 
1134
		$ondemand = "enable";
1135
	else
1136
		$ondemand = "disable";
1137
	if (!isset($ppp['idletimeout']))
1138
		$ppp['idletimeout'] = 0;
1139

    
1140
	if (empty($ppp['username']) && $type == "modem"){
1141
		$ppp['username'] = "user";
1142
		$ppp['password'] = "none";
1143
	}
1144
	if (empty($ppp['password']) && $type == "modem")
1145
		$passwd = "none";
1146
	else
1147
		$passwd = base64_decode($ppp['password']);
1148

    
1149
	$bandwidths = explode(',',$ppp['bandwidth']);
1150
	$mtus = explode(',',$ppp['mtu']);
1151
	$mrus = explode(',',$ppp['mru']);
1152

    
1153
	if (isset($ppp['mrru']))
1154
		$mrrus = explode(',',$ppp['mrru']);
1155

    
1156
	// Construct the mpd.conf file
1157
	$mpdconf = <<<EOD
1158
startup:
1159
	# configure the console
1160
	set console close
1161
	# configure the web server
1162
	set web close
1163

    
1164
default:
1165
{$ppp['type']}client:
1166
	create bundle static {$interface}
1167
	set iface name {$pppif}
1168

    
1169
EOD;
1170
	$setdefaultgw = false;
1171
	$founddefaultgw = false;
1172
	if (is_array($config['gateways']['gateway_item'])) {
1173
		foreach($config['gateways']['gateway_item'] as $gateway) {
1174
			if($interface == $gateway['interface'] && isset($gateway['defaultgw'])) {
1175
				$setdefaultgw = true;
1176
				break;
1177
			} else if (isset($gateway['defaultgw']) && !empty($gateway['interface'])) {
1178
				$founddefaultgw = true;
1179
				break;
1180
			}
1181
		}
1182
	}
1183
	
1184
	if (($interface == "wan" && $founddefaultgw == false) || $setdefaultgw == true){
1185
		$setdefaultgw = true;
1186
		$mpdconf .= <<<EOD
1187
	set iface route default
1188

    
1189
EOD;
1190
	}
1191
	$mpdconf .= <<<EOD
1192
	set iface {$ondemand} on-demand
1193
	set iface idle {$ppp['idletimeout']}
1194

    
1195
EOD;
1196

    
1197
	if (isset($ppp['ondemand']))
1198
		$mpdconf .= <<<EOD
1199
	set iface addrs 10.10.1.1 10.10.1.2
1200

    
1201
EOD;
1202
	
1203
	if (isset($ppp['tcpmssfix']))
1204
		$tcpmss = "disable";
1205
	else
1206
		$tcpmss = "enable";
1207
		$mpdconf .= <<<EOD
1208
	set iface {$tcpmss} tcpmssfix
1209

    
1210
EOD;
1211

    
1212
	$mpdconf .= <<<EOD
1213
	set iface up-script /usr/local/sbin/ppp-linkup
1214
	set iface down-script /usr/local/sbin/ppp-linkdown
1215
	set ipcp ranges {$ranges}
1216

    
1217
EOD;
1218
	if (isset($ppp['vjcomp']))
1219
		$mpdconf .= <<<EOD
1220
	set ipcp no vjcomp
1221

    
1222
EOD;
1223

    
1224
	if (isset($config['system']['dnsallowoverride']))
1225
		$mpdconf .= <<<EOD
1226
	set ipcp enable req-pri-dns
1227
	set ipcp enable req-sec-dns
1228

    
1229
EOD;
1230
	if (!isset($ppp['verbose_log']))
1231
		$mpdconf .= <<<EOD
1232
	#log -bund -ccp -chat -iface -ipcp -lcp -link
1233

    
1234
EOD;
1235
	foreach($ports as $pid => $port){
1236
		$port = get_real_interface($port);
1237
		$mpdconf .= <<<EOD
1238

    
1239
	create link static {$interface}_link{$pid} {$type}
1240
	set link action bundle {$interface}
1241
	set link {$multilink} multilink
1242
	set link keep-alive 10 60
1243
	set link max-redial 0
1244

    
1245
EOD;
1246
		if (isset($ppp['shortseq']))
1247
			$mpdconf .= <<<EOD
1248
	set link no shortseq
1249

    
1250
EOD;
1251

    
1252
		if (isset($ppp['acfcomp']))
1253
			$mpdconf .= <<<EOD
1254
	set link no acfcomp
1255

    
1256
EOD;
1257

    
1258
		if (isset($ppp['protocomp']))
1259
			$mpdconf .= <<<EOD
1260
	set link no protocomp
1261

    
1262
EOD;
1263

    
1264
		$mpdconf .= <<<EOD
1265
	set link disable chap pap
1266
	set link accept chap pap eap
1267
	set link disable incoming
1268

    
1269
EOD;
1270

    
1271

    
1272
		if (!empty($bandwidths[$pid]))
1273
			$mpdconf .= <<<EOD
1274
	set link bandwidth {$bandwidths[$pid]}
1275

    
1276
EOD;
1277

    
1278
		if (empty($mtus[$pid]))
1279
			$mtus[$pid] = "1492";
1280
			$mpdconf .= <<<EOD
1281
	set link mtu {$mtus[$pid]}
1282

    
1283
EOD;
1284

    
1285
		if (!empty($mrus[$pid]))
1286
			$mpdconf .= <<<EOD
1287
	set link mru {$mrus[$pid]}
1288

    
1289
EOD;
1290

    
1291
		$mpdconf .= <<<EOD
1292
	set auth authname "{$ppp['username']}"
1293
	set auth password {$passwd}
1294

    
1295
EOD;
1296
		if ($type == "modem") {
1297
			$mpdconf .= <<<EOD
1298
	set modem device {$ppp['ports']}
1299
	set modem script DialPeer
1300
	set modem idle-script Ringback
1301
	set modem watch -cd
1302
	set modem var \$DialPrefix "DT"
1303
	set modem var \$Telephone "{$ppp['phone']}"
1304

    
1305
EOD;
1306
		}
1307
		if (isset($ppp['connect-timeout']) && $type == "modem") {
1308
			$mpdconf .= <<<EOD
1309
	set modem var \$ConnectTimeout "{$ppp['connect-timeout']}"
1310

    
1311
EOD;
1312
		}
1313
		if (isset($ppp['initstr']) && $type == "modem") {
1314
			$initstr = base64_decode($ppp['initstr']);
1315
			$mpdconf .= <<<EOD
1316
	set modem var \$InitString "{$initstr}"
1317

    
1318
EOD;
1319
		}
1320
		if (isset($ppp['simpin']) && $type == "modem") {
1321
			$mpdconf .= <<<EOD
1322
	set modem var \$SimPin "{$ppp['simpin']}"
1323
	set modem var \$PinWait "{$ppp['pin-wait']}"
1324

    
1325
EOD;
1326
		}
1327
		if (isset($ppp['apn']) && $type == "modem") {
1328
			$mpdconf .= <<<EOD
1329
	set modem var \$APN "{$ppp['apn']}"
1330
	set modem var \$APNum "{$ppp['apnum']}"
1331

    
1332
EOD;
1333
		}
1334
		if (isset($ppp['provider']) && $type == "pppoe") {
1335
			$mpdconf .= <<<EOD
1336
	set pppoe service "{$ppp['provider']}"
1337

    
1338
EOD;
1339
		}
1340
		if ($type == "pppoe")
1341
			$mpdconf .= <<<EOD
1342
	set pppoe iface {$port}
1343

    
1344
EOD;
1345

    
1346
		if ($type == "pptp" || $type == "l2tp") {
1347
			$mpdconf .= <<<EOD
1348
	set pptp self {$localips[$pid]}
1349
	set pptp peer {$gateways[$pid]}
1350
	set pptp disable windowing
1351

    
1352
EOD;
1353
		}
1354
		
1355
		$mpdconf .= "\topen\r\n";
1356
	} //end foreach($port)
1357

    
1358
	// Write out mpd_ppp.conf
1359
	fwrite($fd, $mpdconf);
1360
	fclose($fd);
1361

    
1362
	// Create the uptime log if requested and if it doesn't exist already, or delete it if it is no longer requested.
1363
	if (isset($ppp['uptime'])) {
1364
		if (!file_exists("/conf/{$pppif}.log")) {
1365
			conf_mount_rw();
1366
			mwexec("echo /dev/null > /conf/{$pppif}.log");
1367
			conf_mount_ro();
1368
		}
1369
	} else {
1370
		if (file_exists("/conf/{$pppif}.log")) {
1371
			conf_mount_rw();
1372
			mwexec("rm -f /conf/{$pppif}.log");
1373
			conf_mount_ro();
1374
		}
1375
	}
1376
		
1377
	/* fire up mpd */
1378
	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");
1379

    
1380
	// Check for PPPoE periodic reset request 
1381
	if ($type == "pppoe") {
1382
		if (isset($ppp['pppoe-reset-type']))
1383
			setup_pppoe_reset_file($ppp['if'], $interface);
1384
		else
1385
			setup_pppoe_reset_file($ppp['if']);
1386
	}
1387

    
1388
	return 1;
1389
}
1390

    
1391
function interfaces_carp_setup() {
1392
	global $g, $config;
1393

    
1394
	$balanacing = "";
1395
	$pfsyncinterface = "";
1396
	$pfsyncenabled = "";
1397
	if(isset($config['system']['developerspew'])) {
1398
		$mt = microtime();
1399
		echo "interfaces_carp_setup() being called $mt\n";
1400
	}
1401

    
1402
	// Prepare CmdCHAIN that will be used to execute commands.
1403
	$cmdchain = new CmdCHAIN();	
1404

    
1405
	if ($g['booting']) {
1406
		echo "Configuring CARP settings...";
1407
		mute_kernel_msgs();
1408
	}
1409

    
1410
	/* suck in configuration items */
1411
	if($config['installedpackages']['carpsettings']) {
1412
		if($config['installedpackages']['carpsettings']['config']) {
1413
			foreach($config['installedpackages']['carpsettings']['config'] as $carp) {
1414
				$pfsyncenabled = $carp['pfsyncenabled'];
1415
				$balanacing = $carp['balancing'];
1416
				$pfsyncinterface = $carp['pfsyncinterface'];
1417
				$pfsyncpeerip = $carp['pfsyncpeerip'];
1418
			}
1419
		}
1420
	} else {
1421
		unset($pfsyncinterface);
1422
		unset($balanacing);
1423
		unset($pfsyncenabled);
1424
	}
1425

    
1426
	$cmdchain->add("Allow CARP", "/sbin/sysctl net.inet.carp.allow=1", true);			
1427
	if($balanacing) {
1428
		$cmdchain->add("Enable CARP ARP-balancing", "/sbin/sysctl net.inet.carp.arpbalance=1", true);
1429
		$cmdchain->add("Disallow CARP preemption", "/sbin/sysctl net.inet.carp.preempt=0", true);
1430
	} else
1431
		$cmdchain->add("Enable CARP preemption", "/sbin/sysctl net.inet.carp.preempt=1", true);		
1432

    
1433
	$cmdchain->add("Enable CARP logging", "/sbin/sysctl net.inet.carp.log=2", true);
1434
	if (!empty($pfsyncinterface))
1435
		$carp_sync_int = get_real_interface($pfsyncinterface);
1436

    
1437
	if($g['booting']) {
1438
		/*    install rules to alllow pfsync to sync up during boot
1439
		 *    carp interfaces will remain down until the bootup sequence finishes
1440
		 */
1441
		$fd = fopen("{$g['tmp_path']}/rules.boot", "w");
1442
		if ($fd) {
1443
			fwrite($fd, "pass quick proto carp all keep state\n");
1444
			fwrite($fd, "pass quick proto pfsync all\n");
1445
			fwrite($fd, "pass out quick from any to any keep state\n");
1446
			fclose($fd);
1447
			mwexec("/sbin/pfctl -f {$g['tmp_path']}/rules.boot");
1448
		} else
1449
			log_error("Could not create rules.boot file!");
1450
	}
1451

    
1452
	/* setup pfsync interface */
1453
	if($carp_sync_int and $pfsyncenabled) {
1454
		if (is_ipaddr($pfsyncpeerip))
1455
			$cmdchain->add("Bring up pfsync0 syncpeer", "/sbin/ifconfig pfsync0 syncdev {$carp_sync_int} syncpeer {$pfsyncpeerip} up", false);						
1456
		else
1457
			$cmdchain->add("Bring up pfsync0 syncdev", "/sbin/ifconfig pfsync0 syncdev {$carp_sync_int} up", false);			
1458
	} else
1459
		$cmdchain->add("Bring up pfsync0", "/sbin/ifconfig pfsync0 syncdev lo0 up", false);						
1460

    
1461
	if($config['virtualip']['vip'])
1462
		$cmdchain->add("Allow CARP.", "/sbin/sysctl net.inet.carp.allow=1", true);				
1463
	else
1464
		$cmdchain->add("Disallow CARP.", "/sbin/sysctl net.inet.carp.allow=0", true);		
1465
	
1466
	if($g['debug'])
1467
		$cmdchain->setdebug(); // optional for verbose logging
1468

    
1469
	$cmdchain->execute();
1470
	$cmdchain->clear();
1471

    
1472
	if ($g['booting']) {
1473
		unmute_kernel_msgs();
1474
		echo "done.\n";
1475
	}
1476
}
1477

    
1478
function interface_proxyarp_configure($interface = "") {
1479
	global $config, $g;
1480
	if(isset($config['system']['developerspew'])) {
1481
		$mt = microtime();
1482
		echo "interface_proxyarp_configure() being called $mt\n";
1483
	}
1484

    
1485
	/* kill any running choparp */
1486
	if (empty($interface))
1487
		killbyname("choparp");
1488

    
1489
	if (isset($config['virtualip']) && is_array($config['virtualip']['vip'])) {
1490
		$paa = array();
1491

    
1492
		/* group by interface */
1493
		foreach ($config['virtualip']['vip'] as $vipent) {
1494
			if ($vipent['mode'] === "proxyarp") {
1495
				if ($vipent['interface'])
1496
					$proxyif = $vipent['interface'];
1497
				else
1498
					$proxyif = "wan";
1499

    
1500
				if (!is_array($paa[$if]))
1501
					$paa[$proxyif] = array();
1502

    
1503
				$paa[$proxyif][] = $vipent;
1504
			}
1505
		}
1506
	}
1507

    
1508
	if (!empty($interface)) {
1509
		if (is_array($paa[$interface])) {
1510
			$paaifip = get_interface_ip($interface);
1511
                        if (!is_ipaddr($paaifip))
1512
                                return;
1513
                        $args = get_real_interface($interface) . " auto";
1514
                        foreach ($paa[$interface] as $paent) {
1515
                                if (isset($paent['subnet']))
1516
                                        $args .= " " . escapeshellarg("{$paent['subnet']}/{$paent['subnet_bits']}");
1517
                                else if (isset($paent['range']))
1518
                                        $args .= " " . escapeshellarg($paent['range']['from'] . "-" . $paent['range']['to']);
1519
                        }
1520
                        mwexec_bg("/usr/local/sbin/choparp " . $args);	
1521
		}
1522
	} else if (count($paa)) {
1523
		foreach ($paa as $paif => $paents) {
1524
			$paaifip = get_interface_ip($paif);
1525
			if (!(is_ipaddr($paaifip)))
1526
				continue;
1527
			$args = get_real_interface($paif) . " auto";
1528
			foreach ($paents as $paent) {
1529
				if (isset($paent['subnet']))
1530
					$args .= " " . escapeshellarg("{$paent['subnet']}/{$paent['subnet_bits']}");
1531
				else if (isset($paent['range']))
1532
					$args .= " " . escapeshellarg($paent['range']['from'] . "-" . $paent['range']['to']);
1533
			}
1534
			mwexec_bg("/usr/local/sbin/choparp " . $args);
1535
		}
1536
	}
1537
}
1538

    
1539
function interfaces_vips_configure($interface = "") {
1540
	global $g, $config;
1541
	if(isset($config['system']['developerspew'])) {
1542
		$mt = microtime();
1543
		echo "interfaces_vips_configure() being called $mt\n";
1544
	}
1545
	$paa = array();
1546
	if(is_array($config['virtualip']['vip'])) {
1547
		$carp_setuped = false;
1548
		$anyproxyarp = false;
1549
		foreach ($config['virtualip']['vip'] as $vip) {
1550
			switch ($vip['mode']) {
1551
			case "proxyarp":
1552
				/* nothing it is handled on interface_proxyarp_configure() */
1553
				if ($interface <> "" && $vip['interface'] <> $interface)
1554
					continue;
1555
				$anyproxyarp = true;
1556
				break;
1557
			case "ipalias":
1558
				if ($interface <> "" && $vip['interface'] <> $interface)
1559
					continue;
1560
				interface_ipalias_configure(&$vip);
1561
				break;
1562
			case "carp":
1563
				if ($interface <> "" && $vip['interface'] <> $interface)
1564
					continue;
1565
				if ($carp_setuped == false) {
1566
					interfaces_carp_setup();
1567
					$carp_setuped = true;
1568
				}
1569
				interface_carp_configure($vip);
1570
				break;
1571
			case "carpdev-dhcp":
1572
				if ($interface <> "" && $vip['interface'] <> $interface)
1573
					continue;
1574
				interface_carpdev_configure($vip);
1575
				break;
1576
			}
1577
		}
1578
		
1579
		if ($anyproxyarp == true)
1580
			interface_proxyarp_configure();
1581
	}
1582
}
1583

    
1584
function interface_ipalias_configure(&$vip) {
1585

    
1586
	if ($vip['mode'] == "ipalias") {
1587
		$if = get_real_interface($vip['interface']);
1588
		mwexec("/sbin/ifconfig " . escapeshellarg($if) . " " . $vip['subnet'] . "/" . escapeshellarg($vip['subnet_bits']) . " alias");
1589
	}
1590
}
1591

    
1592
function interface_reload_carps($cif) {
1593
	global $config;
1594

    
1595
	$carpifs = link_ip_to_carp_interface(find_interface_ip($cif));
1596
	if (empty($carpifs))
1597
		return;
1598

    
1599
	$carps = explode(" ", $carpifs);
1600
	if(is_array($config['virtualip']['vip'])) {
1601
		$viparr = &$config['virtualip']['vip'];
1602
		foreach ($viparr as $vip) {
1603
			if (in_array($vip['carpif'], $carps)) {
1604
				switch ($vip['mode']) {
1605
					case "carp":
1606
					interface_vip_bring_down($vip);
1607
					sleep(1);
1608
					interface_carp_configure($vip);
1609
					break;
1610
					case "carpdev-dhcp":
1611
					interface_vip_bring_down($vip);
1612
					sleep(1);
1613
					interface_carpdev_configure($vip);
1614
					break;
1615
				}
1616
			}
1617
		}
1618
	}
1619
}
1620

    
1621
function interface_carp_configure(&$vip) {
1622
	global $config, $g;
1623
	if(isset($config['system']['developerspew'])) {
1624
		$mt = microtime();
1625
		echo "interface_carp_configure() being called $mt\n";
1626
	}
1627

    
1628
	if ($vip['mode'] != "carp")
1629
		return;
1630

    
1631
	$vip_password = $vip['password'];
1632
	$vip_password = escapeshellarg(addslashes(str_replace(" ", "", $vip_password)));
1633
	if ($vip['password'] != "")
1634
		$password = " pass {$vip_password}";
1635

    
1636
	// set the vip interface to the vhid
1637
	$vipif = "vip{$vip['vhid']}";
1638

    
1639
	$interface = interface_translate_type_to_real($vip['interface']);
1640
	/*
1641
	 * ensure the interface containing the VIP really exists
1642
 	 * prevents a panic if the interface is missing or invalid
1643
	 */
1644
	$realif = get_real_interface($vip['interface']);
1645
	if (!does_interface_exist($realif)) {
1646
		file_notice("CARP", "Interface specified for the virtual IP address {$vip['subnet']} does not exist. Skipping this VIP.", "Firewall: Virtual IP", "");
1647
		return;
1648
	}
1649

    
1650
	/* Ensure CARP IP really exists prior to loading up. */
1651
	$ww_subnet_ip = find_interface_ip($realif);
1652
	$ww_subnet_bits = find_interface_subnet($realif);
1653
	if (!ip_in_subnet($vip['subnet'], gen_subnet($ww_subnet_ip, $ww_subnet_bits) . "/" . $ww_subnet_bits)) {
1654
		file_notice("CARP", "Sorry but we could not find a matching real interface subnet for the virtual IP address {$vip['subnet']}.", "Firewall: Virtual IP", "");
1655
		return;
1656
	}
1657

    
1658
	/* create the carp interface and setup */
1659
	if (does_interface_exist($vipif)) {
1660
		pfSense_interface_flags($vipif, -IFF_UP);
1661
	} else {
1662
		$carpif = pfSense_interface_create("carp");
1663
		pfSense_interface_rename($carpif, $vipif);
1664
		pfSense_ngctl_name("{$carpif}:", $vipif);
1665
	}
1666

    
1667
	/* invalidate interface cache */
1668
	get_interface_arr(true);
1669

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

    
1673
	interfaces_bring_up($vipif);
1674
	
1675
	return $vipif;
1676
}
1677

    
1678
function interface_carpdev_configure(&$vip) {
1679
	global $g;
1680

    
1681
	if ($vip['mode'] != "carpdev-dhcp")
1682
		return;
1683

    
1684
	$vip_password = $vip['password'];
1685
	$vip_password = str_replace(" ", "", $vip_password);
1686
	if($vip['password'] != "")
1687
		$password = " pass \"" . $vip_password . "\"";
1688

    
1689
	log_error("Found carpdev interface {$vip['interface']} on top of interface {$interface}");
1690
	if (empty($vip['interface']))
1691
		return;
1692

    
1693
	$vipif = "vip" . $vip['vhid'];
1694
	$realif = interface_translate_type_to_real($vip['interface']);
1695
	interfaces_bring_up($realif);
1696
	/*
1697
	 * ensure the interface containing the VIP really exists
1698
	 * prevents a panic if the interface is missing or invalid
1699
	 */
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
	if (does_interface_exist($vipif)) {
1706
		interface_bring_down($vipif);
1707
	} else {
1708
		$carpdevif = exec("/sbin/ifconfig carp create");
1709
		mwexec("/sbin/ifconfig {$carpdevif} name {$vipif}");
1710
		pfSense_ngctl_name("{$carpdevif}:", $vipif);
1711
	}
1712

    
1713
	mwexec("/sbin/ifconfig {$vipif} carpdev {$realif} vhid {$vip['vhid']} advskew {$vip['advskew']} {$password}");
1714
	interfaces_bring_up($vipif);
1715

    
1716
	/*
1717
	 * XXX: BIG HACK but carpdev needs ip services active
1718
	 *      before even starting something as dhclient.
1719
	 *      I do not know if this is a feature or a bug
1720
	 *      but better than track it make it work ;) .
1721
	 */
1722
	//$fakeiptouse = "10.254.254." . ($carp_instances_counter+1);
1723
	//$cmdchain->add("CarpDEV hack", "/sbin/ifconfig {$carpint} inet {$fakeiptouse}", false);
1724

    
1725
	/* generate dhclient_wan.conf */
1726
	$fd = fopen("{$g['varetc_path']}/dhclient_{$vipif}.conf", "w");
1727
	if ($fd) {
1728
		$dhclientconf = "";
1729

    
1730
		$dhclientconf .= <<<EOD
1731
interface "{$vipif}" {
1732
timeout 60;
1733
retry 1;
1734
select-timeout 0;
1735
initial-interval 1;
1736
script "/sbin/dhclient-script";
1737
}
1738

    
1739
EOD;
1740

    
1741
		fwrite($fd, $dhclientconf);
1742
		fclose($fd);
1743

    
1744
		/* fire up dhclient */
1745
		mwexec("/sbin/dhclient -c {$g['varetc_path']}/dhclient_{$vipif}.conf {$vipif} > {$g['tmp_path']}/{$vipif}_output > {$g['tmp_path']}/{$vipif}_error_output", false);
1746
	} else {
1747
		log_error("Error: cannot open dhclient_{$vipif}.conf in interfaces_carpdev_configure() for writing.\n");
1748
		mwexec("/sbin/dhclient -b {$vipif}");
1749
	}
1750

    
1751
	return $vipif;
1752
}
1753

    
1754
function interface_wireless_clone($realif, $wlcfg) {
1755
	global $config, $g;
1756
	/*   Check to see if interface has been cloned as of yet.  
1757
	 *   If it has not been cloned then go ahead and clone it.
1758
	 */
1759
	$needs_clone = false;
1760
	if(is_array($wlcfg['wireless']))
1761
		$wlcfg_mode = $wlcfg['wireless']['mode'];
1762
	else
1763
		$wlcfg_mode = $wlcfg['mode'];
1764
	switch($wlcfg_mode) {
1765
		 case "hostap":
1766
			$mode = "wlanmode hostap";
1767
			break;
1768
		 case "adhoc":
1769
			$mode = "wlanmode adhoc";
1770
			break;
1771
		 default:
1772
			$mode = "";
1773
			break;
1774
	}
1775
	$baseif = interface_get_wireless_base($wlcfg['if']);
1776
	if(does_interface_exist($realif)) {
1777
		exec("/sbin/ifconfig {$realif}", $output, $ret);
1778
		$ifconfig_str = implode($output);
1779
		if(($wlcfg_mode == "hostap") && (! preg_match("/hostap/si", $ifconfig_str))) {
1780
			log_error("Interface {$realif} changed to hostap mode");
1781
			$needs_clone = true;
1782
		}
1783
		if(($wlcfg_mode == "adhoc") && (! preg_match("/adhoc/si", $ifconfig_str))) {
1784
			log_error("Interface {$realif} changed to adhoc mode");
1785
			$needs_clone = true;
1786
		}
1787
		if(($wlcfg_mode == "bss") && (preg_match("/hostap|adhoc/si", $ifconfig_str))) {
1788
			log_error("Interface {$realif} changed to infrastructure mode");
1789
			$needs_clone = true;
1790
		}
1791
	} else {
1792
		$needs_clone = true;
1793
	}
1794

    
1795
	if($needs_clone == true) {
1796
		/* remove previous instance if it exists */
1797
		if(does_interface_exist($realif))
1798
			pfSense_interface_destroy($realif);
1799

    
1800
		log_error("Cloning new wireless interface {$realif}");
1801
		// Create the new wlan interface. FreeBSD returns the new interface name.
1802
		// example:  wlan2
1803
		exec("/sbin/ifconfig wlan create wlandev {$baseif} {$mode} bssid 2>&1", $out, $ret);
1804
		if($ret <> 0) {
1805
			log_error("Failed to clone interface {$baseif} with error code {$ret}, output {$out[0]}");
1806
			return false;
1807
		}
1808
		$newif = trim($out[0]);
1809
		// Rename the interface to {$parentnic}_wlan{$number}#: EX: ath0_wlan0
1810
		pfSense_interface_rename($newif, $realif);
1811
		// FIXME: not sure what ngctl is for. Doesn't work.
1812
		// mwexec("/usr/sbin/ngctl name {$newif}: {$realif}", false);
1813
	}
1814
	return true;
1815
}
1816

    
1817
function interface_sync_wireless_clones(&$ifcfg, $sync_changes = false) {
1818
	global $config, $g;
1819

    
1820
	$shared_settings = array('standard', 'turbo', 'protmode', 'txpower', 'channel', 'distance', 'regdomain', 'regcountry', 'reglocation');
1821

    
1822
	if(!is_interface_wireless($ifcfg['if']))
1823
		return;
1824

    
1825
	$baseif = interface_get_wireless_base($ifcfg['if']);
1826

    
1827
	$iflist = get_configured_interface_list(false, true);
1828
	foreach ($iflist as $if) {
1829
		if ($baseif == interface_get_wireless_base($config['interfaces'][$if]['if']) && $ifcfg['if'] != $config['interfaces'][$if]['if']) {
1830
			if (isset($config['interfaces'][$if]['wireless']['standard']) || $sync_changes) {
1831
				foreach ($shared_settings as $setting) {
1832
					if ($sync_changes) {
1833
						$config['interfaces'][$if]['wireless'][$setting] = $ifcfg['wireless'][$setting];
1834
					} else {
1835
						$ifcfg['wireless'][$setting] = $config['interfaces'][$if]['wireless'][$setting];
1836
					}
1837
				}
1838
				if (!$sync_changes)
1839
					break;
1840
			}
1841
		}
1842
	}
1843

    
1844
	if (interface_is_wireless_clone($ifcfg['if'])) {
1845
		foreach ($config['wireless']['clone'] as &$clone) {
1846
			if ($clone['cloneif'] == $ifcfg['if']) {
1847
				if ($sync_changes) {
1848
					$clone['mode'] = $ifcfg['wireless']['mode'];
1849
				} else {
1850
					$ifcfg['wireless']['mode'] = $clone['mode'];
1851
				}
1852
				break;
1853
			}
1854
		}
1855
		unset($clone);
1856
	}
1857
}
1858

    
1859
function interface_wireless_configure($if, &$wl, &$wlcfg) {
1860
	global $config, $g;
1861

    
1862
	/*    open up a shell script that will be used to output the commands.
1863
	 *    since wireless is changing a lot, these series of commands are fragile
1864
     *    and will sometimes need to be verified by a operator by executing the command
1865
     *    and returning the output of the command to the developers for inspection.  please
1866
     *    do not change this routine from a shell script to individul exec commands.  -sullrich
1867
	 */
1868

    
1869
	// Remove script file
1870
	unlink_if_exists("{$g['tmp_path']}/{$if}_setup.sh");
1871

    
1872
	// Clone wireless nic if needed.
1873
	interface_wireless_clone($if, $wl);
1874

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

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

    
1882
	/* set values for /path/program */
1883
	$hostapd = "/usr/sbin/hostapd";
1884
	$wpa_supplicant = "/usr/sbin/wpa_supplicant";
1885
	$ifconfig = "/sbin/ifconfig";
1886
	$killall = "/usr/bin/killall";
1887

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

    
1890
	$wlcmd = array();
1891
	/* Make sure it's up */
1892
	$wlcmd[] = "up";
1893
	/* Set a/b/g standard */
1894
	$standard = str_replace(" Turbo", "", $wlcfg['standard']);
1895
	$wlcmd[] = "mode " . escapeshellarg($standard);
1896

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

    
1902
	/* Set ssid */
1903
	if($wlcfg['ssid'])
1904
		$wlcmd[] = "ssid " .escapeshellarg($wlcfg['ssid']);
1905

    
1906
	/* Set 802.11g protection mode */
1907
	$wlcmd[] = "protmode " . escapeshellarg($wlcfg['protmode']);
1908

    
1909
	/* set wireless channel value */
1910
	if(isset($wlcfg['channel'])) {
1911
		if($wlcfg['channel'] == "0") {
1912
			$wlcmd[] = "channel any";
1913
		} else {
1914
			$wlcmd[] = "channel " . escapeshellarg($wlcfg['channel']);
1915
		}
1916
	}
1917

    
1918
	/* set Distance value */
1919
	if($wlcfg['distance'])
1920
		$distance = escapeshellarg($wlcfg['distance']);
1921

    
1922
	/* Set wireless hostap mode */
1923
	if ($wlcfg['mode'] == "hostap") {
1924
		$wlcmd[] = "mediaopt hostap";
1925
	} else {
1926
		$wlcmd[] = "-mediaopt hostap";
1927
	}
1928

    
1929
	/* Set wireless adhoc mode */
1930
	if ($wlcfg['mode'] == "adhoc") {
1931
		$wlcmd[] = "mediaopt adhoc";
1932
	} else {
1933
		$wlcmd[] = "-mediaopt adhoc";
1934
	}
1935

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

    
1938
	/* handle hide ssid option */
1939
	if(isset($wlcfg['hidessid']['enable'])) {
1940
		$wlcmd[] = "hidessid";
1941
	} else {
1942
		$wlcmd[] = "-hidessid";
1943
	}
1944

    
1945
	/* handle pureg (802.11g) only option */
1946
	if(isset($wlcfg['pureg']['enable'])) {
1947
		$wlcmd[] = "mode 11g pureg";
1948
	} else {
1949
		$wlcmd[] = "-pureg";
1950
	}
1951

    
1952
	/* handle puren (802.11n) only option */
1953
	if(isset($wlcfg['puren']['enable'])) {
1954
		$wlcmd[] = "puren";
1955
	} else {
1956
		$wlcmd[] = "-puren";
1957
	}
1958

    
1959
	/* enable apbridge option */
1960
	if(isset($wlcfg['apbridge']['enable'])) {
1961
		$wlcmd[] = "apbridge";
1962
	} else {
1963
		$wlcmd[] = "-apbridge";
1964
	}
1965

    
1966
	/* handle turbo option */
1967
	if(isset($wlcfg['turbo']['enable'])) {
1968
		$wlcmd[] = "mediaopt turbo";
1969
	} else {
1970
		$wlcmd[] = "-mediaopt turbo";
1971
	}
1972

    
1973
	/* handle txpower setting */
1974
	/* if($wlcfg['txpower'] <> "")
1975
		$wlcmd[] = "txpower " . escapeshellarg($wlcfg['txpower']);
1976
	*/
1977
	/* handle wme option */
1978
	if(isset($wlcfg['wme']['enable'])) {
1979
		$wlcmd[] = "wme";
1980
	} else {
1981
		$wlcmd[] = "-wme";
1982
	}
1983

    
1984
	/* set up wep if enabled */
1985
	$wepset = "";
1986
	if (isset($wlcfg['wep']['enable']) && is_array($wlcfg['wep']['key'])) {
1987
		switch($wlcfg['wpa']['auth_algs']) {
1988
			case "1":
1989
				$wepset .= "authmode open wepmode on ";
1990
				break;
1991
			case "2":
1992
				$wepset .= "authmode shared wepmode on ";
1993
				break;
1994
			case "3":
1995
				$wepset .= "authmode mixed wepmode on ";
1996
		}
1997
		$i = 1;
1998
		foreach ($wlcfg['wep']['key'] as $wepkey) {
1999
			$wepset .= "wepkey " . escapeshellarg("{$i}:{$wepkey['value']}") . " ";
2000
			if (isset($wepkey['txkey'])) {
2001
				$wlcmd[] = "weptxkey {$i} ";
2002
			}
2003
			$i++;
2004
		}
2005
		$wlcmd[] = $wepset;
2006
	} else {
2007
		$wlcmd[] = "authmode open wepmode off ";
2008
	}
2009

    
2010
	mwexec(kill_hostapd("{$if}"));
2011
	mwexec(kill_wpasupplicant("{$if}"));
2012

    
2013
	/* generate wpa_supplicant/hostap config if wpa is enabled */
2014
	conf_mount_rw();
2015

    
2016
	switch ($wlcfg['mode']) {
2017
		case 'bss':
2018
			if (isset($wlcfg['wpa']['enable'])) {
2019
				$wpa .= <<<EOD
2020
ctrl_interface={$g['varrun_path']}/wpa_supplicant
2021
ctrl_interface_group=0
2022
ap_scan=1
2023
#fast_reauth=1
2024
network={
2025
ssid="{$wlcfg['ssid']}"
2026
scan_ssid=1
2027
priority=5
2028
key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
2029
psk="{$wlcfg['wpa']['passphrase']}"
2030
pairwise={$wlcfg['wpa']['wpa_pairwise']}
2031
group={$wlcfg['wpa']['wpa_pairwise']}
2032
}
2033
EOD;
2034

    
2035
				$fd = fopen("{$g['varetc_path']}/wpa_supplicant_{$if}.conf", "w");
2036
				fwrite($fd, "{$wpa}");
2037
				fclose($fd);
2038
			}
2039
			break;
2040
		case 'hostap':
2041
			if($wlcfg['wpa']['passphrase']) 
2042
				$wpa_passphrase = "wpa_passphrase={$wlcfg['wpa']['passphrase']}\n";
2043
			else 
2044
				$wpa_passphrase = "";
2045
			if (isset($wlcfg['wpa']['enable'])) {
2046
				$wpa .= <<<EOD
2047
interface={$if}
2048
driver=bsd
2049
logger_syslog=-1
2050
logger_syslog_level=0
2051
logger_stdout=-1
2052
logger_stdout_level=0
2053
dump_file={$g['tmp_path']}/hostapd_{$if}.dump
2054
ctrl_interface={$g['varrun_path']}/hostapd
2055
ctrl_interface_group=wheel
2056
#accept_mac_file={$g['tmp_path']}/hostapd_{$if}.accept
2057
#deny_mac_file={$g['tmp_path']}/hostapd_{$if}.deny
2058
#macaddr_acl={$wlcfg['wpa']['macaddr_acl']}
2059
ssid={$wlcfg['ssid']}
2060
debug={$wlcfg['wpa']['debug_mode']}
2061
auth_algs={$wlcfg['wpa']['auth_algs']}
2062
wpa={$wlcfg['wpa']['wpa_mode']}
2063
wpa_key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
2064
wpa_pairwise={$wlcfg['wpa']['wpa_pairwise']}
2065
wpa_group_rekey={$wlcfg['wpa']['wpa_group_rekey']}
2066
wpa_gmk_rekey={$wlcfg['wpa']['wpa_gmk_rekey']}
2067
wpa_strict_rekey={$wlcfg['wpa']['wpa_strict_rekey']}
2068
{$wpa_passphrase}
2069
#Enable the next lines for preauth when roaming. Interface = wired or wireless interface talking to the AP you want to roam from/to
2070
#rsn_preauth=1
2071
#rsn_preauth_interfaces=eth0
2072

    
2073
EOD;
2074

    
2075
				if($wlcfg['auth_server_addr'] && $wlcfg['auth_server_shared_secret']) {
2076
					$auth_server_port = "1812";
2077
					if($wlcfg['auth_server_port']) 
2078
						$auth_server_port = $wlcfg['auth_server_port'];
2079
					$wpa .= <<<EOD
2080

    
2081
ieee8021x=1
2082
auth_server_addr={$wlcfg['auth_server_addr']}
2083
auth_server_port={$auth_server_port}
2084
auth_server_shared_secret={$wlcfg['auth_server_shared_secret']}
2085

    
2086
EOD;
2087
				} else {
2088
					$wpa .= "ieee8021x={$wlcfg['wpa']['ieee8021x']}\n";
2089
				}
2090

    
2091
				$fd = fopen("{$g['varetc_path']}/hostapd_{$if}.conf", "w");
2092
				fwrite($fd, "{$wpa}");
2093
				fclose($fd);
2094

    
2095
			}
2096
			break;
2097
	}
2098

    
2099
	/*
2100
	 *    all variables are set, lets start up everything
2101
	 */
2102

    
2103
	$baseif = interface_get_wireless_base($if);
2104

    
2105
	/* set ack timers according to users preference (if he/she has any) */
2106
	if($distance) {
2107
		fwrite($fd_set, "# Enable ATH distance settings\n");
2108
		fwrite($fd_set, "/sbin/athctrl.sh -i {$baseif} -d {$distance}\n");
2109
	}
2110

    
2111
	if (isset($wlcfg['wpa']['enable'])) {
2112
		if ($wlcfg['mode'] == "bss") {
2113
			fwrite($fd_set, "{$wpa_supplicant} -B -i {$if} -c {$g['varetc_path']}/wpa_supplicant_{$if}.conf\n");
2114
		}
2115
		if ($wlcfg['mode'] == "hostap") {
2116
			fwrite($fd_set, "{$hostapd} -B {$g['varetc_path']}/hostapd_{$if}.conf\n");
2117
		}
2118
	}
2119

    
2120
	fclose($fd_set);
2121
	conf_mount_ro();
2122

    
2123
	/* Making sure regulatory settings have actually changed
2124
	 * before applying, because changing them requires bringing
2125
	 * down all wireless networks on the interface. */
2126
	exec("{$ifconfig} " . escapeshellarg($if), $output);
2127
	$ifconfig_str = implode($output);
2128
	unset($output);
2129
	$reg_changing = false;
2130

    
2131
	/* special case for the debug country code */
2132
	if ($wlcfg['regcountry'] == 'DEBUG' && !preg_match("/\sregdomain\s+DEBUG\s/si", $ifconfig_str))
2133
		$reg_changing = true;
2134
	else if ($wlcfg['regdomain'] && !preg_match("/\sregdomain\s+{$wlcfg['regdomain']}\s/si", $ifconfig_str))
2135
		$reg_changing = true;
2136
	else if ($wlcfg['regcountry'] && !preg_match("/\scountry\s+{$wlcfg['regcountry']}\s/si", $ifconfig_str))
2137
		$reg_changing = true;
2138
	else if ($wlcfg['reglocation'] == 'anywhere' && preg_match("/\s(indoor|outdoor)\s/si", $ifconfig_str))
2139
		$reg_changing = true;
2140
	else if ($wlcfg['reglocation'] && $wlcfg['reglocation'] != 'anywhere' && !preg_match("/\s{$wlcfg['reglocation']}\s/si", $ifconfig_str))
2141
		$reg_changing = true;
2142

    
2143
	if ($reg_changing) {
2144
		/* set regulatory domain */
2145
		if($wlcfg['regdomain'])
2146
			$wlregcmd[] = "regdomain " . escapeshellarg($wlcfg['regdomain']);
2147

    
2148
		/* set country */
2149
		if($wlcfg['regcountry'])
2150
			$wlregcmd[] = "country " . escapeshellarg($wlcfg['regcountry']);
2151

    
2152
		/* set location */
2153
		if($wlcfg['reglocation'])
2154
			$wlregcmd[] = escapeshellarg($wlcfg['reglocation']);
2155

    
2156
		$wlregcmd_args = implode(" ", $wlregcmd);
2157

    
2158
		/* build a complete list of the wireless clones for this interface */
2159
		$clone_list = array();
2160
		if (does_interface_exist(interface_get_wireless_clone($baseif)))
2161
			$clone_list[] = interface_get_wireless_clone($baseif);
2162
		if (is_array($config['wireless']['clone'])) {
2163
			foreach ($config['wireless']['clone'] as $clone) {
2164
				if ($clone['if'] == $baseif)
2165
					$clone_list[] = $clone['cloneif'];
2166
			}
2167
		}
2168

    
2169
		/* find which clones are up and bring them down */
2170
		$clones_up = array();
2171
		foreach ($clone_list as $clone_if) {
2172
			$clone_status = pfSense_get_interface_addresses($clone_if);
2173
			if ($clone_status['status'] == 'up') {
2174
				$clones_up[] = $clone_if;
2175
				mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " down");
2176
			}
2177
		}
2178

    
2179
		/* apply the regulatory settings */
2180
		mwexec("{$ifconfig} " . escapeshellarg($if) . " {$wlregcmd_args}");
2181

    
2182
		/* bring the clones back up that were previously up */
2183
		foreach ($clones_up as $clone_if) {
2184
			mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " up");
2185
		}
2186
	}
2187

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

    
2192
	/* configure wireless */
2193
	$wlcmd_args = implode(" ", $wlcmd);
2194
	mwexec("/sbin/ifconfig {$if} $wlcmd_args", false);
2195

    
2196
	
2197
	sleep(1);
2198
	/* execute hostapd and wpa_supplicant if required in shell */
2199
	mwexec("/bin/sh {$g['tmp_path']}/{$if}_setup.sh");
2200

    
2201
	return 0;
2202

    
2203
}
2204

    
2205
function kill_hostapd($interface) {
2206
	return "/bin/pkill -f \"hostapd .*{$interface}\"\n";
2207
}
2208

    
2209
function kill_wpasupplicant($interface) {
2210
	return "/bin/pkill -f \"wpa_supplicant .*{$interface}\"\n";
2211
}
2212

    
2213
function find_dhclient_process($interface) {
2214
	if($interface) {
2215
		$pid = `/bin/pgrep -xf "dhclient: {$interface}"`;
2216
	}
2217
	return $pid;
2218
}
2219

    
2220
function interface_configure($interface = "wan", $reloadall = false) {
2221
	global $config, $g;
2222
	global $interface_sn_arr_cache, $interface_ip_arr_cache;
2223

    
2224
	$wancfg = $config['interfaces'][$interface];
2225

    
2226
	$realif = get_real_interface($interface);
2227

    
2228
	if (!$g['booting']) {
2229
		/* remove all IPv4 addresses */
2230
		while (mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " -alias", true) == 0);
2231
			interface_bring_down($interface, true);
2232
	}
2233

    
2234
	/* wireless configuration? */
2235
	if (is_array($wancfg['wireless']))
2236
		interface_wireless_configure($realif, $wancfg, $wancfg['wireless']);
2237

    
2238
	if ($wancfg['spoofmac']) {
2239
		mwexec("/sbin/ifconfig " . escapeshellarg($realif) .
2240
			" link " . escapeshellarg($wancfg['spoofmac']));
2241

    
2242
                /*
2243
                 * All vlans need to spoof their parent mac address, too.  see
2244
                 * ticket #1514: http://cvstrac.pfsense.com/tktview?tn=1514,33
2245
                 */
2246
                if (is_array($config['vlans']['vlan'])) {
2247
                        foreach ($config['vlans']['vlan'] as $vlan) {
2248
                                if ($vlan['if'] == $realif)
2249
                                        mwexec("/sbin/ifconfig " . escapeshellarg($vlan['vlanif']) .
2250
                                                " link " . escapeshellarg($wancfg['spoofmac']));
2251
                        }
2252
                }
2253
	}  else {
2254
		$mac = get_interface_mac(get_real_interface($wancfg['if']));
2255
		if($mac == "ff:ff:ff:ff:ff:ff") {
2256
			/*   this is not a valid mac address.  generate a
2257
			 *   temporary mac address so the machine can get online.
2258
			 */
2259
			echo "Generating new MAC address.";
2260
			$random_mac = generate_random_mac_address();
2261
			mwexec("/sbin/ifconfig " . escapeshellarg(get_real_interface($wancfg['if'])) .
2262
				" link " . escapeshellarg($random_mac));
2263
			$wancfg['spoofmac'] = $random_mac;
2264
			write_config();
2265
			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");
2266
		}
2267
	}
2268

    
2269
	/* media */
2270
	if ($wancfg['media'] || $wancfg['mediaopt']) {
2271
		$cmd = "/sbin/ifconfig " . escapeshellarg(get_real_interface($wancfg['if']));
2272
		if ($wancfg['media'])
2273
			$cmd .= " media " . escapeshellarg($wancfg['media']);
2274
		if ($wancfg['mediaopt'])
2275
			$cmd .= " mediaopt " . escapeshellarg($wancfg['mediaopt']);
2276
		mwexec($cmd);
2277
	}
2278
	if (!empty($wancfg['mtu']))
2279
		pfSense_interface_mtu($realif, $wancfg['mtu']);
2280

    
2281
	/* invalidate interface/ip/sn cache */
2282
	get_interface_arr(true);
2283
	unset($interface_ip_arr_cache[$realif]);
2284
	unset($interface_sn_arr_cache[$realif]);
2285

    
2286
	switch ($wancfg['ipaddr']) {
2287
		case 'carpdev-dhcp':
2288
			interface_carpdev_dhcp_configure($interface);
2289
			break;
2290
		case 'dhcp':
2291
			interface_dhcp_configure($interface);
2292
			break;
2293
		case 'pppoe':
2294
		case 'l2tp':
2295
		case 'pptp':
2296
		case 'ppp':
2297
			interface_ppps_configure($interface);
2298
			break;
2299
		default:
2300
			if ($wancfg['ipaddr'] <> "" && $wancfg['subnet'] <> "") {
2301
				pfSense_interface_setaddress($realif, "{$wancfg['ipaddr']}/{$wancfg['subnet']}");
2302
			} else if (substr($realif, 0, 3) == "gre") {
2303
				if (is_array($config['gres']['gre'])) {
2304
					foreach ($config['gres']['gre'] as $gre)
2305
						if ($gre['greif'] == $realif)
2306
							interface_gre_configure($gre);
2307
				}
2308
			} else if (substr($realif, 0, 3) == "gif") {
2309
				 if (is_array($config['gifs']['gif'])) {
2310
					foreach ($config['gifs']['gif'] as $gif)
2311
						if($gif['gifif'] == $interface)
2312
							interface_gif_configure($gif);
2313
				}
2314
			} else if (substr($realif, 0, 4) == "ovpn") {
2315
				/* XXX: Should be done anything?! */
2316
			}
2317

    
2318
			if (is_ipaddr($wancfg['gateway']))
2319
				file_put_contents("{$g['tmp_path']}/{$realif}_router", $wancfg['gateway']);
2320
			break;
2321
	}
2322

    
2323
	if(does_interface_exist($wancfg['if']))
2324
		interfaces_bring_up($wancfg['if']);
2325
 	
2326
	if (!$g['booting'])
2327
		interface_reload_carps($realif);
2328
	
2329
	if (!$g['booting']) {
2330
		if (link_interface_to_gre($interface)) {
2331
			foreach ($config['gres']['gre'] as $gre)
2332
				if ($gre['if'] == $interface)
2333
					interface_gre_configure($gre);
2334
		}
2335
		if (link_interface_to_gif($interface)) {
2336
                	foreach ($config['gifs']['gif'] as $gif)
2337
				if ($gif['if'] == $interface)
2338
                        		interface_gif_configure($gif);
2339
        	}
2340
		if (link_interface_to_bridge($interface)) {
2341
			foreach ($config['bridges']['bridged'] as $bridge)
2342
				if (stristr($bridge['members'], "{$interface}"))
2343
					interface_bridge_add_member($bridge['bridgeif'], $realif);
2344
		}
2345

    
2346
		link_interface_to_vips($interface, "update");
2347

    
2348
		if ($interface == "lan")
2349
			/* make new hosts file */
2350
			system_hosts_generate();
2351

    
2352
		if ($reloadall == true) {
2353

    
2354
			/* reconfigure static routes (kernel may have deleted them) */
2355
			system_routing_configure($interface);
2356

    
2357
			/* reload ipsec tunnels */
2358
			vpn_ipsec_configure();
2359

    
2360
			/* update dyndns */
2361
			services_dyndns_configure($interface);
2362

    
2363
			/* force DNS update */
2364
			services_dnsupdate_process($interface);
2365

    
2366
			/* restart dnsmasq */
2367
			services_dnsmasq_configure();
2368

    
2369
			/* reload captive portal */
2370
			captiveportal_init_rules();
2371

    
2372
			/* set the reload filter dity flag */
2373
			filter_configure();
2374
		}
2375
	}
2376

    
2377
	return 0;
2378
}
2379

    
2380
function interface_carpdev_dhcp_configure($interface = "wan") {
2381
	global $config, $g;
2382

    
2383
	$wancfg = $config['interfaces'][$interface];
2384
	$wanif = $wancfg['if'];
2385
	/* bring wan interface up before starting dhclient */
2386
	if($wanif)
2387
		interfaces_bring_up($wanif);
2388
	else 
2389
		log_error("Could not bring wanif up in terface_carpdev_dhcp_configure()");
2390

    
2391
	return 0;
2392
}
2393

    
2394
function interface_dhcp_configure($interface = "wan") {
2395
	global $config, $g;
2396

    
2397
	$wancfg = $config['interfaces'][$interface];
2398
	if (empty($wancfg))
2399
		$wancfg = array();
2400

    
2401
	/* generate dhclient_wan.conf */
2402
	$fd = fopen("{$g['varetc_path']}/dhclient_{$interface}.conf", "w");
2403
	if (!$fd) {
2404
		printf("Error: cannot open dhclient_{$interface}.conf in interfaces_wan_dhcp_configure() for writing.\n");
2405
		return 1;
2406
	}
2407

    
2408
	if ($wancfg['dhcphostname']) {
2409
		$dhclientconf_hostname = "send dhcp-client-identifier \"{$wancfg['dhcphostname']}\";\n";
2410
		$dhclientconf_hostname .= "\tsend host-name \"{$wancfg['dhcphostname']}\";\n";
2411
	} else {
2412
		$dhclientconf_hostname = "";
2413
	}
2414

    
2415
	$wanif = get_real_interface($interface);
2416
	if (empty($wanif)) {
2417
		log_error("Invalid interface \"{$interface}\" in interface_dhcp_configure()");
2418
		return 0;
2419
	}
2420
 	$dhclientconf = "";
2421
	
2422
	$dhclientconf .= <<<EOD
2423
interface "{$wanif}" {
2424
timeout 60;
2425
retry 1;
2426
select-timeout 0;
2427
initial-interval 1;
2428
	{$dhclientconf_hostname}
2429
	script "/sbin/dhclient-script";
2430
}
2431

    
2432
EOD;
2433

    
2434
if(is_ipaddr($wancfg['alias-address'])) {
2435
	$subnetmask = gen_subnet_mask($wancfg['alias-subnet']);
2436
	$dhclientconf .= <<<EOD
2437
alias {
2438
	interface  "{$wanif}";
2439
	fixed-address {$wancfg['alias-address']};
2440
	option subnet-mask {$subnetmask};
2441
}
2442

    
2443
EOD;
2444
}
2445
	fwrite($fd, $dhclientconf);
2446
	fclose($fd);
2447

    
2448
	/* bring wan interface up before starting dhclient */
2449
	if($wanif)
2450
		interfaces_bring_up($wanif);
2451
	else 
2452
		log_error("Could not bring up {$wanif} interface in interface_dhcp_configure()");
2453

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

    
2457
	return 0;
2458
}
2459

    
2460
function interfaces_group_setup() {
2461
	global $config;
2462

    
2463
	if (!is_array($config['ifgroups']['ifgroupentry']))
2464
		return;
2465

    
2466
	foreach ($config['ifgroups']['ifgroupentry'] as $groupar)
2467
		interface_group_setup($groupar);
2468

    
2469
	return;
2470
}
2471

    
2472
function interface_group_setup(&$groupname /* The parameter is an array */) {
2473
	global $config;
2474

    
2475
	if (!is_array($groupname))
2476
		return;
2477
	$members = explode(" ", $groupname['members']);
2478
	foreach($members as $ifs) {
2479
		$realif = get_real_interface($ifs);
2480
		if ($realif)
2481
			mwexec("/sbin/ifconfig {$realif} group {$groupname['ifname']}");
2482
	}
2483

    
2484
	return;
2485
}
2486
 
2487
/* COMPAT Function */
2488
function convert_friendly_interface_to_real_interface_name($interface) {
2489
	return get_real_interface($interface);
2490
}
2491

    
2492
/* COMPAT Function */
2493
function get_real_wan_interface($interface = "wan") {
2494
	return get_real_interface($interface);
2495
}
2496

    
2497
/* COMPAT Function */
2498
function get_current_wan_address($interface = "wan") {
2499
	return get_interface_ip($interface);
2500
}
2501

    
2502
/*
2503
 * convert_real_interface_to_friendly_interface_name($interface): convert fxp0 -> wan, etc.
2504
 */
2505
function convert_real_interface_to_friendly_interface_name($interface = "wan") {
2506
        global $config;
2507

    
2508
	if (stristr($interface, "vip")) {
2509
                $index = intval(substr($interface, 3));
2510
                foreach ($config['virtualip']['vip'] as $counter => $vip) {
2511
                        if ($vip['mode'] == "carpdev-dhcp" || $vip['mode'] == "carp")  {
2512
                                if ($index == $counter)
2513
                                        return $vip['interface'];
2514
                        }
2515
                }
2516
        } else if (stristr($interface, "carp")) {
2517
                $index = intval(substr($interface, 4));
2518
                foreach ($config['virtualip']['vip'] as $counter => $vip) {
2519
                        if ($vip['mode'] == "carpdev-dhcp" || $vip['mode'] == "carp")  {
2520
                                if ($index == $counter)
2521
                                        return $vip['interface'];
2522
                        }
2523
                }
2524
        }
2525

    
2526
        /* XXX: For speed reasons reference directly the interface array */
2527
	$ifdescrs = $config['interfaces'];
2528
        //$ifdescrs = get_configured_interface_list(false, true);
2529

    
2530
        foreach ($ifdescrs as $if => $ifname) {
2531
                if ($config['interfaces'][$if]['if'] == $interface)
2532
                        return $if;
2533

    
2534
                /* XXX: ermal - The 3 lines below are totally bogus code. */
2535
                $int = interface_translate_type_to_real($if);
2536
                if ($int == $interface)
2537
                        return $ifname;
2538
        }
2539
        return NULL;
2540
}
2541

    
2542
/* attempt to resolve interface to friendly descr */
2543
function convert_friendly_interface_to_friendly_descr($interface) {
2544
        global $config;
2545

    
2546
        switch ($interface) {
2547
                case "l2tp":
2548
                                $ifdesc = "L2TP";
2549
                                break;
2550
                case "pptp":
2551
                                $ifdesc = "pptp";
2552
                                break;
2553
                case "pppoe":
2554
                                $ifdesc = "pppoe";
2555
                                break;
2556
                case "openvpn":
2557
                                $ifdesc = "OpenVPN";
2558
                                break;
2559
                case "enc0":
2560
                        case "ipsec":
2561
                                $ifdesc = "IPsec";
2562
                                break;
2563
        default:
2564
                /* if list */
2565
                $ifdescrs = get_configured_interface_with_descr(false, true);
2566
                foreach ($ifdescrs as $if => $ifname) {
2567
                                if ($if == $interface || $ifname == $interface)
2568
                                        return $ifname;
2569
                }
2570
                break;
2571
        }
2572

    
2573
        return $ifdesc;
2574
}
2575

    
2576
function convert_real_interface_to_friendly_descr($interface) {
2577
        global $config;
2578

    
2579
        $ifdesc = convert_real_interface_to_friendly_interface_name("{$interface}");
2580

    
2581
        if ($ifdesc) {
2582
                $iflist = get_configured_interface_with_descr(false, true);
2583
                return $iflist[$ifdesc];
2584
        }
2585

    
2586
        return $interface;
2587
}
2588

    
2589
/*
2590
 *  interface_translate_type_to_real($interface):
2591
 *              returns the real hardware interface name for a friendly interface.  ie: wan
2592
 */
2593
function interface_translate_type_to_real($interface) {
2594
        global $config;
2595

    
2596
        if ($config['interfaces'][$interface]['if'] <> "")
2597
                return $config['interfaces'][$interface]['if'];
2598
        else
2599
		return $interface;
2600
}
2601

    
2602
function interface_is_wireless_clone($wlif) {
2603
	if(!stristr($wlif, "_wlan")) {
2604
		return false;
2605
	} else {
2606
		return true;
2607
	}
2608
}
2609

    
2610
function interface_get_wireless_base($wlif) {
2611
	if(!stristr($wlif, "_wlan")) {
2612
		return $wlif;
2613
	} else {
2614
		return substr($wlif, 0, stripos($wlif, "_wlan"));
2615
	}
2616
}
2617

    
2618
function interface_get_wireless_clone($wlif) {
2619
	if(!stristr($wlif, "_wlan")) {
2620
		return $wlif . "_wlan0";
2621
	} else {
2622
		return $wlif;
2623
	}
2624
}
2625

    
2626
function get_real_interface($interface = "wan") {
2627
    global $config;
2628

    
2629
	$wanif = NULL;
2630

    
2631
	switch ($interface) {
2632
	case "l2tp":
2633
		$wanif = "l2tp";
2634
		break;
2635
	case "pptp":
2636
		$wanif = "pptp";
2637
		break;
2638
	case "pppoe":
2639
		$wanif = "pppoe";
2640
		break;
2641
	case "openvpn":
2642
		$wanif = "openvpn";
2643
		break;
2644
	case "ipsec":
2645
	case "enc0":
2646
		$wanif = "enc0";
2647
		break;
2648
	case "ppp":
2649
		$wanif = "ppp";
2650
		break;
2651
	default:
2652
		// If a real interface was alread passed simply
2653
		// pass the real interface back.  This encourages
2654
		// the usage of this function in more cases so that
2655
		// we can combine logic for more flexibility.
2656
		if(does_interface_exist($interface)) {
2657
			$wanif = $interface;
2658
			break;
2659
		}
2660
		if (empty($config['interfaces'][$interface]))
2661
			break;
2662

    
2663
		$cfg =& $config['interfaces'][$interface];
2664

    
2665
		// Wireless cloned NIC support (FreeBSD 8+)
2666
		// interface name format: $parentnic_wlanparentnic#
2667
		// example: ath0_wlan0
2668
		if (is_interface_wireless($cfg['if'])) {
2669
			$wanif = interface_get_wireless_clone($cfg['if']);
2670
			break;
2671
		}
2672
		/*
2673
		if (empty($cfg['if'])) {
2674
			$wancfg = $cfg['if'];
2675
			break;
2676
		}
2677
		*/
2678

    
2679
		switch ($cfg['ipaddr']) {
2680
			case "carpdev-dhcp":
2681
				$viparr = &$config['virtualip']['vip'];
2682
				if(is_array($viparr))
2683
				foreach ($viparr as $counter => $vip) {
2684
					if ($vip['mode'] == "carpdev-dhcp") {
2685
						if($vip['interface'] == $interface) {
2686
							$wanif = "carp{$counter}";
2687
							break;
2688
						}
2689
					}
2690
				}
2691
				break;
2692
			case "pppoe": 
2693
			case "pptp": 
2694
			case "l2tp": 
2695
			case "ppp":
2696
				$wanif = $cfg['if'];
2697
				break;
2698
			default:
2699
				$wanif = $cfg['if'];
2700
				break;
2701
		}
2702
		break;
2703
	}
2704

    
2705
    return $wanif;
2706
}
2707

    
2708
/* Guess the physical interface by providing a IP address */
2709
function guess_interface_from_ip($ipaddress) {
2710
	if(! is_ipaddr($ipaddress)) {
2711
		return false;
2712
	}
2713
	/* create a route table we can search */
2714
	exec("netstat -rnW", $output, $ret);
2715
	foreach($output as $line) {
2716
		if(preg_match("/^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\/[0-9]+[ ]+link[#]/", $line)) {
2717
			$fields = preg_split("/[ ]+/", $line);
2718
			if(ip_in_subnet($ipaddress, $fields[0])) {
2719
				return $fields[6];
2720
			}
2721
		}
2722
	}
2723
	$ret = exec_command("/sbin/route -n get {$ipaddress} | /usr/bin/awk '/interface/ { print \$2; };'");
2724
	if(empty($ret)) {
2725
        	return false;
2726
	}
2727
	return $ret;
2728
}
2729

    
2730
/*
2731
 * find_ip_interface($ip): return the interface where an ip is defined
2732
 */
2733
function find_ip_interface($ip)
2734
{
2735
        /* if list */
2736
        $ifdescrs = get_configured_interface_list();
2737

    
2738
        foreach ($ifdescrs as $ifdescr => $ifname) {
2739
		if ($ip == get_interface_ip($ifname)) {
2740
                	$int = get_real_interface($ifname);
2741
			return $int;
2742
		}
2743
        }
2744
        return false;
2745
}
2746

    
2747
/*
2748
 *   find_number_of_created_carp_interfaces: return the number of carp interfaces
2749
 */
2750
function find_number_of_created_carp_interfaces() {
2751
	return `/sbin/ifconfig | grep "carp:" | wc -l`;
2752
}
2753

    
2754
function get_all_carp_interfaces() {
2755
	$ints = str_replace("\n", " ", `ifconfig | grep "carp:" -B2 | grep ": flag" | cut -d: -f1`);
2756
	return $ints;
2757
}
2758

    
2759
/*
2760
 * find_carp_interface($ip): return the carp interface where an ip is defined
2761
 */
2762
function find_carp_interface($ip) {
2763
	global $config;
2764
	if (is_array($config['virtualip']['vip'])) {
2765
		foreach ($config['virtualip']['vip'] as $vip) {
2766
			if ($vip['mode'] == "carp" || $vip['mode'] == "carpdev") {
2767
				$carp_ip = get_interface_ip($vip['interface']);
2768
				$if = `ifconfig | grep '$ip ' -B1 | head -n1 | cut -d: -f1`;
2769
				if ($if)
2770
					return $if;
2771
			}
2772
		}
2773
	}
2774
}
2775

    
2776
function link_carp_interface_to_parent($interface) {
2777
        global $config;
2778

    
2779
        if ($interface == "")
2780
                return;
2781

    
2782
        $carp_ip = get_interface_ip($interface);
2783
        if (!is_ipaddr($carp_ip))
2784
                return;
2785

    
2786
        /* if list */
2787
        $ifdescrs = get_configured_interface_list();
2788
        foreach ($ifdescrs as $ifdescr => $ifname) {
2789
                $interfaceip = get_interface_ip($ifname);
2790
                $subnet_bits = get_interface_subnet($ifname);
2791
                $subnet_ip = gen_subnet("{$interfaceip}", "{$subnet_bits}");
2792
                if(ip_in_subnet($carp_ip, "{$subnet_ip}/{$subnet_bits}"))
2793
                        return $ifname;
2794
        }
2795

    
2796
        return "";
2797
}
2798

    
2799
/****f* interfaces/link_ip_to_carp_interface
2800
 * NAME
2801
 *   link_ip_to_carp_interface - Find where a CARP interface links to.
2802
 * INPUTS
2803
 *   $ip
2804
 * RESULT
2805
 *   $carp_ints
2806
 ******/
2807
function link_ip_to_carp_interface($ip) {
2808
        global $config;
2809

    
2810
        if (!is_ipaddr($ip))
2811
                return;
2812

    
2813
        $carp_ints = "";
2814
        if (is_array($config['virtualip']['vip'])) {
2815
		$first = 0;
2816
		$carp_int = array();
2817
                foreach ($config['virtualip']['vip'] as $vip) {
2818
                        if ($vip['mode'] == "carp" || $vip['mode'] == "carpdev") {
2819
                                $carp_ip = $vip['subnet'];
2820
                                $carp_sn = $vip['subnet_bits'];
2821
                                $carp_nw = gen_subnet($carp_ip, $carp_sn);
2822
                                if (ip_in_subnet($ip, "{$carp_nw}/{$carp_sn}"))
2823
					$carp_int[] = "vip{$vip['vhid']}";
2824
                        }
2825
                }
2826
		if (!empty($carp_int))
2827
			$carp_ints = implode(" ", array_unique($carp_int));
2828
        }
2829

    
2830
        return $carp_ints;
2831
}
2832

    
2833
function link_interface_to_vlans($int, $action = "") {
2834
	global $config;
2835

    
2836
	if (empty($int))
2837
		return;
2838

    
2839
	if (is_array($config['vlans']['vlan'])) {
2840
                foreach ($config['vlans']['vlan'] as $vlan) {
2841
			if ($int == $vlan['if']) {
2842
				if ($action == "update") {
2843
					interfaces_bring_up($int);
2844
				} else if ($action == "")
2845
					return $vlan;
2846
			}
2847
		}
2848
	}
2849
}
2850

    
2851
function link_interface_to_vips($int, $action = "") {
2852
        global $config;
2853

    
2854
        if (is_array($config['virtualip']['vip']))
2855
                foreach ($config['virtualip']['vip'] as $vip)
2856
                        if ($int == $vip['interface']) {
2857
				if ($action == "update")
2858
					interfaces_vips_configure($int);
2859
				else
2860
                                	return $vip;
2861
			}
2862
}
2863

    
2864
/****f* interfaces/link_interface_to_bridge
2865
 * NAME
2866
 *   link_interface_to_bridge - Finds out a bridge group for an interface
2867
 * INPUTS
2868
 *   $ip
2869
 * RESULT
2870
 *   bridge[0-99]
2871
 ******/
2872
function link_interface_to_bridge($int) {
2873
        global $config;
2874

    
2875
        if (is_array($config['bridges']['bridged']))
2876
                foreach ($config['bridges']['bridged'] as $bridge)
2877
                        if(stristr($bridge['members'], "{$int}"))
2878
                                return "{$bridge['bridgeif']}";
2879
}
2880

    
2881
function link_interface_to_gre($interface) {
2882
        global $config;
2883

    
2884
        if (is_array($config['gres']['gre']))
2885
                foreach ($config['gres']['gre'] as $gre)
2886
                        if($gre['if'] == $interface)
2887
                                return "{$gre['greif']}";
2888
}
2889

    
2890
function link_interface_to_gif($interface) {
2891
        global $config;
2892

    
2893
        if (is_array($config['gifs']['gif']))
2894
                foreach ($config['gifs']['gif'] as $gif)
2895
                        if($gif['if'] == $interface)
2896
                                return "{$gif['gifif']}";
2897
}
2898

    
2899
/*
2900
 * find_interface_ip($interface): return the interface ip (first found)
2901
 */
2902
function find_interface_ip($interface, $flush = false)
2903
{
2904
	global $interface_ip_arr_cache;
2905

    
2906
	$interface = str_replace("\n", "", $interface);
2907
	
2908
	if (!does_interface_exist($interface))
2909
		return;
2910

    
2911
	/* Setup IP cache */
2912
	if (!isset($interface_ip_arr_cache[$interface]) or $flush) {
2913
		$ifinfo = pfSense_get_interface_addresses($interface);
2914
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
2915
	}
2916

    
2917
	return $interface_ip_arr_cache[$interface];
2918
}
2919

    
2920
function find_interface_subnet($interface, $flush = false)
2921
{
2922
	global $interface_sn_arr_cache;
2923

    
2924
	$interface = str_replace("\n", "", $interface);
2925
	if (does_interface_exist($interface) == false)
2926
		return;
2927

    
2928
	if (!isset($interface_sn_arr_cache[$interface]) or $flush) {
2929
		$ifinfo = pfSense_get_interface_addresses($interface);
2930
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
2931
        }
2932

    
2933
	return $interface_sn_arr_cache[$interface];
2934
}
2935

    
2936
function get_interface_ip($interface = "wan")
2937
{
2938
	$realif = get_real_interface($interface);
2939
	if (!$realif) {
2940
		if (preg_match("/^carp/i", $interface))
2941
			$realif = $interface;
2942
		else if (preg_match("/^vip/i", $interface))
2943
			$realif = $interface;
2944
		else
2945
			return null;
2946
	}
2947

    
2948
	$curip = find_interface_ip($realif);
2949
	if ($curip && is_ipaddr($curip) && ($curip != "0.0.0.0"))
2950
		return $curip;
2951
	else
2952
		return null;
2953
}
2954

    
2955
function get_interface_subnet($interface = "wan")
2956
{
2957
	$realif = get_real_interface($interface);
2958
	if (!$realif) {
2959
                if (preg_match("/^carp/i", $interface))
2960
                        $realif = $interface;
2961
                else if (preg_match("/^vip/i", $interface))
2962
                        $realif = $interface;
2963
                else
2964
                        return null;
2965
        }
2966

    
2967
	$cursn = find_interface_subnet($realif);
2968
	if (!empty($cursn))
2969
		return $cursn;
2970

    
2971
	return null;
2972
}
2973

    
2974
/* return outside interfaces with a gateway */
2975
function get_interfaces_with_gateway() {
2976
	global $config;
2977

    
2978
	$ints = array();
2979

    
2980
	/* loop interfaces, check config for outbound */
2981
	foreach($config['interfaces'] as $ifdescr => $ifname) {
2982

    
2983
		switch ($ifname['ipaddr']) {
2984
			case "dhcp":
2985
			case "carpdev-dhcp":
2986
			case "ppp";
2987
			case "pppoe":
2988
			case "pptp":
2989
			case "l2tp":
2990
			case "ppp";
2991
				$ints[$ifdescr] = $ifdescr;
2992
			break;
2993
			default:
2994
				if (!empty($ifname['gateway']))
2995
					$ints[$ifdescr] = $ifdescr;
2996
			break;
2997
		}
2998
	}
2999
	return $ints;
3000
}
3001

    
3002
/* return true if interface has a gateway */
3003
function interface_has_gateway($friendly) {
3004
	global $config;
3005

    
3006
	if (!empty($config['interfaces'][$friendly])) {
3007
		$ifname =& $config['interfaces'][$friendly];
3008
		switch ($ifname['ipaddr']) {
3009
			case "dhcp":
3010
			case "carpdev-dhcp":
3011
			case "pppoe":
3012
			case "pptp":
3013
			case "l2tp":
3014
			case "ppp";
3015
				return true;
3016
			break;
3017
			default:
3018
				if (!empty($ifname['gateway']))
3019
					return true;
3020
			break;
3021
		}
3022
	}
3023

    
3024
	return false;
3025
}
3026

    
3027
/****f* interfaces/is_altq_capable
3028
 * NAME
3029
 *   is_altq_capable - Test if interface is capable of using ALTQ
3030
 * INPUTS
3031
 *   $int            - string containing interface name
3032
 * RESULT
3033
 *   boolean         - true or false
3034
 ******/
3035

    
3036
function is_altq_capable($int) {
3037
        /* Per:
3038
         * http://www.freebsd.org/cgi/man.cgi?query=altq&manpath=FreeBSD+7.2-current&format=html
3039
         * Only the following drivers have ALTQ support
3040
         */
3041
	$capable = array("age", "ale", "an", "ath", "aue", "awi", "bce",
3042
			"bfe", "bge", "dc", "de", "ed", "em", "ep", "fxp", "gem",
3043
			"hme", "ipw", "iwi", "jme", "le", "msk", "mxge", "my", "nfe",
3044
			"npe", "nve", "ral", "re", "rl", "rum", "sf", "sis", "sk",
3045
			"ste", "stge", "txp", "udav", "ural", "vge", "vr", "wi", "xl",
3046
			"ndis", "tun", "ovpns", "ovpnc", "vlan", "pppoe", "pptp", "ng", "ppp");
3047

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

    
3050
        if (in_array($int_family[0], $capable))
3051
                return true;
3052
	else if (stristr($int_family, "vlan")) /* VLANs are name $parent.$vlan now */
3053
		return true;
3054
        else
3055
                return false;
3056
}
3057

    
3058
/****f* interfaces/is_interface_wireless
3059
 * NAME
3060
 *   is_interface_wireless - Returns if an interface is wireless
3061
 * RESULT
3062
 *   $tmp       - Returns if an interface is wireless
3063
 ******/
3064
function is_interface_wireless($interface) {
3065
        global $config, $g;
3066

    
3067
        $friendly = convert_real_interface_to_friendly_interface_name($interface);
3068
        if(!isset($config['interfaces'][$friendly]['wireless'])) {
3069
                if (preg_match($g['wireless_regex'], $interface)) {
3070
                        $config['interfaces'][$friendly]['wireless'] = array();
3071
                        return true;
3072
                }
3073
                unset($config['interfaces'][$friendly]['wireless']);
3074
                return false;
3075
        } else
3076
                return true;
3077
}
3078

    
3079
function get_wireless_modes($interface) {
3080
	/* return wireless modes and channels */
3081
	$wireless_modes = array();
3082

    
3083
	$wlif = interface_translate_type_to_real($interface);
3084

    
3085
	if(is_interface_wireless($wlif)) {
3086
		$cloned_interface = get_real_interface($interface);
3087
		$chan_list = "/sbin/ifconfig {$cloned_interface} list chan";
3088
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
3089
		$format_list = "/usr/bin/awk '{print \$5 \" \" \$6 \",\" \$1}'";
3090

    
3091
		$interface_channels = "";
3092
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
3093
		$interface_channel_count = count($interface_channels);
3094

    
3095
		$c = 0;
3096
		while ($c < $interface_channel_count)
3097
		{
3098
			$channel_line = explode(",", $interface_channels["$c"]);
3099
			$wireless_mode = trim($channel_line[0]);
3100
			$wireless_channel = trim($channel_line[1]);
3101
			if(trim($wireless_mode) != "") {
3102
				/* if we only have 11g also set 11b channels */
3103
				if($wireless_mode == "11g") {
3104
					if(!isset($wireless_modes["11b"]))
3105
						$wireless_modes["11b"] = array();
3106
				} else if($wireless_mode == "11g ht") {
3107
					if(!isset($wireless_modes["11b"]))
3108
						$wireless_modes["11b"] = array();
3109
					if(!isset($wireless_modes["11g"]))
3110
						$wireless_modes["11g"] = array();
3111
					$wireless_mode = "11ng";
3112
				} else if($wireless_mode == "11a ht") {
3113
					if(!isset($wireless_modes["11a"]))
3114
						$wireless_modes["11a"] = array();
3115
					$wireless_mode = "11na";
3116
				}
3117
				$wireless_modes["$wireless_mode"]["$c"] = $wireless_channel;
3118
			}
3119
			$c++;
3120
		}
3121
	}
3122
	return($wireless_modes);
3123
}
3124

    
3125
/* return channel numbers, frequency, max txpower, and max regulation txpower */
3126
function get_wireless_channel_info($interface) {
3127
	$wireless_channels = array();
3128

    
3129
	$wlif = interface_translate_type_to_real($interface);
3130

    
3131
	if(is_interface_wireless($wlif)) {
3132
		$cloned_interface = get_real_interface($interface);
3133
		$chan_list = "/sbin/ifconfig {$cloned_interface} list txpower";
3134
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
3135
		$format_list = "/usr/bin/awk '{print \$1 \",\" \$3 \" \" \$4 \",\" \$5 \",\" \$7}'";
3136

    
3137
		$interface_channels = "";
3138
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
3139

    
3140
		foreach ($interface_channels as $channel_line) {
3141
			$channel_line = explode(",", $channel_line);
3142
			if(!isset($wireless_channels[$channel_line[0]]))
3143
				$wireless_channels[$channel_line[0]] = $channel_line;
3144
		}
3145
	}
3146
	return($wireless_channels);
3147
}
3148

    
3149
/****f* interfaces/get_interface_mtu
3150
 * NAME
3151
 *   get_interface_mtu - Return the mtu of an interface
3152
 * RESULT
3153
 *   $tmp       - Returns the mtu of an interface
3154
 ******/
3155
function get_interface_mtu($interface) {
3156
        $mtu = pfSense_get_interface_addresses($interface);
3157
        return $mtu['mtu'];
3158
}
3159

    
3160
function get_interface_mac($interface) {
3161

    
3162
	$macinfo = pfSense_get_interface_addresses($interface);
3163
	return $macinfo["macaddr"];
3164
}
3165

    
3166
/****f* pfsense-utils/generate_random_mac_address
3167
 * NAME
3168
 *   generate_random_mac - generates a random mac address
3169
 * INPUTS
3170
 *   none
3171
 * RESULT
3172
 *   $mac - a random mac address
3173
 ******/
3174
function generate_random_mac_address() {
3175
        $mac = "02";
3176
        for($x=0; $x<5; $x++)
3177
                $mac .= ":" . dechex(rand(16, 255));
3178
        return $mac;
3179
}
3180

    
3181
/****f* interfaces/is_jumbo_capable
3182
 * NAME
3183
 *   is_jumbo_capable - Test if interface is jumbo frame capable.  Useful for determining VLAN capability.
3184
 * INPUTS
3185
 *   $int             - string containing interface name
3186
 * RESULT
3187
 *   boolean          - true or false
3188
 ******/
3189
function is_jumbo_capable($int) {
3190
        global $g;
3191

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

    
3194
        if (in_array($int_family[0], $g['vlan_long_frame']))
3195
                return true;
3196
        else
3197
                return false;
3198
}
3199

    
3200
function setup_pppoe_reset_file($pppif, $iface="") {
3201
	global $g;
3202
	$cron_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
3203

    
3204
	if(!empty($iface) && !empty($pppif)){
3205
		$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";
3206
		file_put_contents($cron_file, $cron_cmd);
3207
		chmod($cron_file, 0700);
3208
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
3209
	} else
3210
		unlink_if_exists($cron_file);
3211
}
3212

    
3213
?>
(21-21/51)