Project

General

Profile

Download (106 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:	/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(true);
81
	if (in_array($interface, $ints))
82
		return true;
83
	else
84
		return false;
85
}
86

    
87
function interface_netgraph_needed($interface = "wan") {
88
	global $config;
89

    
90
	$found = false;
91
	if (!empty($config['pptpd']) &&
92
		$config['pptpd']['mode'] == "server")
93
		$found = true;
94
	if ($found == false && !empty($config['l2tp']) &&
95
		$config['l2tp']['mode'] == "server")
96
		$found = true;
97
	if ($found == false && is_array($config['pppoes']['pppoe'])) {
98
		foreach ($config['pppoes']['pppoe'] as $pppoe) {
99
			if ($pppoe['mode'] != "server")
100
				continue;
101
			if ($pppoe['interface'] == $interface)
102
				$found = true;
103
				break;
104
		}
105
	}
106
	if ($found == false) {
107
		if (!empty($config['interfaces'][$interface])) {
108
			switch ($config['interfaces'][$interface]['ipaddr']) {
109
			case "ppp":
110
			case "pppoe":
111
			case "l2tp":
112
			case "pptp":
113
				$found = true;
114
				break;
115
			default:
116
				$found = false;
117
				break;
118
			}
119
		}
120
	}
121
	if ($found == false) {
122
		$realif = get_real_interface($interface);
123
		if (is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) {
124
			foreach ($config['ppps']['ppp'] as $pppid => $ppp) {
125

    
126
/* This if block doesn't do anything. It can be deleted.
127
PPP interfaces are found above in the previous if ($found == false) block.
128
This block of code is only entered for OPTx interfaces that are configured for PPPoE modem access, so $realif != $ppp['if']
129

    
130
				if ($realif == $ppp['if']) {
131
					$found = true;
132
					break;
133
				}
134
*/			
135
				$ports = explode(',',$ppp['ports']);
136
				foreach($ports as $pid => $port){
137
					$port = get_real_interface($port);
138
					if ($realif == $port) {
139
						$found = true;
140
						break;
141
					}
142
					/* Find the parent interfaces of the vlans in the MLPPP configs 
143
					* there should be only one element in the array here 
144
					* -- this could be better . . . */
145
					$parent_if = get_parent_interface($port);
146
					if ($realif == $parent_if[0]) {
147
						$found = true;
148
						break;
149
					}
150
				}
151
			}
152
		}
153
	}
154
	
155
	if ($found == false) {
156
		$realif = get_real_interface($interface);
157
		pfSense_ngctl_detach("{$realif}:", $realif);
158
	}
159
	/* NOTE: We make sure for this on interface_ppps_configure()
160
	 *	no need to do it here agan.
161
	 *	else
162
	 *		pfSense_ngctl_attach(".", $realif);
163
	 */
164
}
165

    
166
function interfaces_loopback_configure() {
167
	if($g['booting'])
168
		echo "Configuring loopback interface...";
169
	pfSense_interface_setaddress("lo0", "127.0.0.1");
170
	interfaces_bring_up("lo0");
171
	if($g['booting'])
172
		echo "done.\n";
173
	return 0;
174
}
175

    
176
function interfaces_vlan_configure() {
177
	global $config, $g;
178
	if($g['booting'])
179
		echo "Configuring VLAN interfaces...";
180
	if (is_array($config['vlans']['vlan']) && count($config['vlans']['vlan'])) {
181
		foreach ($config['vlans']['vlan'] as $vlan) {
182
			if(empty($vlan['vlanif']))
183
				$vlan['vlanif'] = "{$vlan['if']}_vlan{$vlan['tag']}";
184
			/* XXX: Maybe we should report any errors?! */
185
			interface_vlan_configure($vlan);
186
		}
187
	}
188
	if($g['booting'])
189
		echo "done.\n";
190
}
191

    
192
function interface_vlan_configure(&$vlan) {
193
        global $config, $g;
194

    
195
	if (!is_array($vlan)) {
196
		log_error("VLAN: called with wrong options. Problems with config!");
197
		return;
198
	}
199
	$if = $vlan['if'];
200
	$vlanif  = empty($vlan['vlanif']) ? "{$if}_vlan{$vlan['tag']}" : $vlan['vlanif'];
201
	$tag = $vlan['tag'];
202

    
203
	if (empty($if)) {
204
		log_error("interface_vlan_confgure called with if undefined.");
205
		return;
206
	}
207

    
208
	/* make sure the parent interface is up */
209
	interfaces_bring_up($if);
210
	/* Since we are going to add vlan(4) try to enable all that hardware supports. */
211
	pfSense_interface_capabilities($if, IFCAP_VLAN_HWTAGGING|IFCAP_VLAN_MTU|IFCAP_VLAN_HWFILTER);
212

    
213
	if (!empty($vlanif) && does_interface_exist($vlanif)) {
214
		interface_bring_down($vlanif, true);
215
	} else {
216
		$tmpvlanif = pfSense_interface_create("vlan");
217
		pfSense_interface_rename($tmpvlanif, $vlanif);
218
		pfSense_ngctl_name("{$tmpvlanif}:", $vlanif);
219
	}
220

    
221
	pfSense_vlan_create($vlanif, $if, $tag);
222

    
223
	interfaces_bring_up($vlanif);
224

    
225
	/* invalidate interface cache */
226
	get_interface_arr(true);
227

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

    
231
	return $vlanif;
232
}
233

    
234
function interface_qinq_configure(&$vlan, $fd = NULL) {
235
        global $config, $g;
236

    
237
        if (!is_array($vlan)) {
238
                log_error("QinQ compat VLAN: called with wrong options. Problems with config!\n");
239
                return;
240
        }
241

    
242
        $qinqif = $vlan['if'];
243
        $tag = $vlan['tag'];
244
        if(empty($qinqif)) {
245
                log_error("interface_qinq_confgure called with if undefined.\n");
246
                return;
247
        }
248
	$vlanif = interface_vlan_configure($vlan);
249

    
250
        if ($fd == NULL) {
251
                $exec = true;
252
                $fd = fopen("{$g['tmp_path']}/netgraphcmd", "w");
253
        } else
254
                $exec = false;
255
        /* make sure the parent is converted to ng_vlan(4) and is up */
256
        interfaces_bring_up($qinqif);
257

    
258
	pfSense_ngctl_attach(".", $qinqif);
259
        if (!empty($vlanif) && does_interface_exist($vlanif)) {
260
                fwrite($fd, "shutdown {$qinqif}qinq:\n");
261
                exec("/usr/sbin/ngctl msg {$qinqif}qinq: gettable", $result);
262
                if (empty($result)) {
263
                        fwrite($fd, "mkpeer {$qinqif}: vlan lower downstream\n");
264
                        fwrite($fd, "name {$qinqif}:lower {$vlanif}qinq\n");
265
                        fwrite($fd, "connect {$qinqif}: {$vlanif}qinq: upper nomatch\n");
266
                }
267
        } else {
268
                fwrite($fd, "mkpeer {$qinqif}: vlan lower downstream\n");
269
                fwrite($fd, "name {$qinqif}:lower {$vlanif}qinq\n");
270
                fwrite($fd, "connect {$qinqif}: {$vlanif}qinq: upper nomatch\n");
271
        }
272

    
273
        /* invalidate interface cache */
274
        get_interface_arr(true);
275

    
276
        if (!stristr($qinqif, "vlan"))
277
                mwexec("/sbin/ifconfig {$qinqif} promisc\n");
278

    
279
        $macaddr = get_interface_mac($qinqif);
280
        if (!empty($vlan['members'])) {
281
                $members = explode(" ", $vlan['members']);
282
                foreach ($members as $qtag) {
283
                        $qinq = array();
284
                        $qinq['tag'] = $qtag;
285
                        $qinq['if'] = $vlanif;
286
                        interface_qinq2_configure($qinq, $fd, $macaddr);
287
                }
288
        }
289
        if ($exec == true) {
290
                fclose($fd);
291
                mwexec("/usr/sbin/ngctl -f {$g['tmp_path']}/netgraphcmd");
292
        }
293

    
294
        interfaces_bring_up($qinqif);
295
        if (!empty($vlan['members'])) {
296
                $members = explode(" ", $vlan['members']);
297
                foreach ($members as $qif)
298
                        interfaces_bring_up("{$vlanif}_{$qif}");
299
        }
300

    
301
        return $vlanif;
302
}
303

    
304
function interfaces_qinq_configure() {
305
	global $config, $g;
306
	if($g['booting'])
307
		echo "Configuring QinQ interfaces...";
308
	if (is_array($config['qinqs']['qinqentry']) && count($config['qinqs']['qinqentry'])) {
309
		foreach ($config['qinqs']['qinqentry'] as $qinq) {
310
			/* XXX: Maybe we should report any errors?! */
311
			interface_qinq_configure($qinq);
312
		}
313
	}
314
	if($g['booting'])
315
		echo "done.\n";
316
}
317

    
318
function interface_qinq2_configure(&$qinq, $fd, $macaddr) {
319
        global $config, $g;
320

    
321
        if (!is_array($qinq)) {
322
                log_error("QinQ compat VLAN: called with wrong options. Problems with config!\n");
323
                return;
324
        }
325

    
326
        $if = $qinq['if'];
327
        $tag = $qinq['tag'];
328
        $vlanif = "{$if}_{$tag}";
329
        if(empty($if)) {
330
                log_error("interface_qinq_confgure called with if undefined.\n");
331
                return;
332
        }
333

    
334
        fwrite($fd, "shutdown {$if}h{$tag}:\n");
335
        fwrite($fd, "mkpeer {$if}qinq: eiface {$if}{$tag} ether\n");
336
        fwrite($fd, "name {$if}qinq:{$if}{$tag} {$if}h{$tag}\n");
337
        fwrite($fd, "msg {$if}qinq: addfilter { vlan={$tag} hook=\"{$if}{$tag}\" }\n");
338
        fwrite($fd, "msg {$if}h{$tag}: setifname \"{$vlanif}\"\n");
339
        fwrite($fd, "msg {$if}h{$tag}: set {$macaddr}\n");
340

    
341
        /* invalidate interface cache */
342
        get_interface_arr(true);
343

    
344
        return $vlanif;
345
}
346

    
347
function interfaces_create_wireless_clones() {
348
	global $config;
349

    
350
	if($g['booting'])
351
		echo "Creating other wireless clone interfaces...";
352
	if (is_array($config['wireless']['clone']) && count($config['wireless']['clone'])) {
353
		foreach ($config['wireless']['clone'] as $clone) {
354
			if(empty($clone['cloneif']))
355
				continue;
356
			if(does_interface_exist($clone['cloneif']))
357
				continue;
358
			/* XXX: Maybe we should report any errors?! */
359
			if(interface_wireless_clone($clone['cloneif'], $clone))
360
				if($g['booting'])
361
					echo " " . $clone['cloneif'];
362
		}
363
	}
364
	if($g['booting'])
365
		echo " done.\n";
366
}
367

    
368
function interfaces_bridge_configure($checkmember = 0) {
369
        global $config;
370

    
371
        $i = 0;
372
        if (is_array($config['bridges']['bridged']) && count($config['bridges']['bridged'])) {
373
                foreach ($config['bridges']['bridged'] as $bridge) {
374
                        if(empty($bridge['bridgeif']))
375
                                $bridge['bridgeif'] = "bridge{$i}";
376
			if ($checkmember == 1 && (strstr($bridge['members'], "gif") || strstr($bridge['members'], "gre")))
377
				continue;
378
			if ($checkmember == 2 && !strstr($bridge['members'], "gif") && !strstr($bridge['members'], "gre"))
379
				continue;
380
                        /* XXX: Maybe we should report any errors?! */
381
                        interface_bridge_configure($bridge);
382
                        $i++;
383
                }
384
        }
385
}
386

    
387
function interface_bridge_configure(&$bridge) {
388
	global $config, $g;
389

    
390
	if (!is_array($bridge))
391
	        return -1;
392

    
393
	if (empty($bridge['members'])) {
394
		log_error("No members found on {$bridge['bridgeif']}");
395
		return -1;
396
	}
397

    
398
	$members = explode(',', $bridge['members']);
399
	if (!count($members))
400
		return -1;
401

    
402
	$checklist = get_configured_interface_list();
403

    
404
	if ($g['booting'] || !empty($bridge['bridgeif'])) {
405
		pfSense_interface_destroy($bridge['bridgeif']);
406
		pfSense_interface_create($bridge['bridgeif']);
407
		$bridgeif = $bridge['bridgeif'];
408
	} else
409
		$bridgeif = pfSense_interface_create("bridge");
410

    
411
	/* Calculate smaller mtu and enforce it */
412
	$smallermtu = 0;
413
	$commonrx = true;
414
	$commontx = true;
415
	foreach ($members as $member) {
416
		$realif = get_real_interface($member);
417
		$opts = pfSense_get_interface_addresses($realif);
418
		$mtu = $opts['mtu'];
419
		if (substr($realif, 0, 3) == "gif" && $mtu < 1500)
420
			continue;
421
		if (!isset($opts['encaps']['txcsum']))
422
			$commontx = false;
423
		if (!isset($opts['encaps']['rxcsum']))
424
			$commonrx = false;
425
		if (!isset($opts['encaps']['tso4']))
426
			$commontso4 = false;
427
		if (!isset($opts['encaps']['tso6']))
428
			$commontso6 = false;
429
		if (!isset($opts['encaps']['lro']))
430
			$commonlro = false;
431
		if ($smallermtu == 0 && !empty($mtu))
432
			$smallermtu = $mtu;
433
		else if (!empty($mtu) && $mtu < $smallermtu)
434
			$smallermtu = $mtu;
435
	}
436
	 
437
	/* Just in case anything is not working well */
438
	if ($smallermtu == 0)
439
		$smallermtu = 1500; 
440

    
441
	$flags = 0;
442
	if ($commonrx === false)
443
		$flags |= IFCAP_RXCSUM;
444
	if ($commontx === false)
445
		$flags |= IFCAP_TXCSUM;
446
	if ($commontso4 === false)
447
		$flags |= IFCAP_TSO4;
448
	if ($commontso6 === false)
449
		$flags |= IFCAP_TSO6;
450
	if ($commonlro === false)
451
		$flags |= IFCAP_LRO;
452
		
453
	/* Add interfaces to bridge */
454
	foreach ($members as $member) {
455
		if (!array_key_exists($member, $checklist))
456
			continue;
457
		$realif1 = get_real_interface($member);
458
		$realif =  escapeshellarg($realif1);
459
		if (!$realif) {
460
			log_error("realif not defined in interfaces bridge - up");
461
			continue;
462
		}
463
		/* make sure the parent interface is up */
464
		pfSense_interface_mtu($realif1, $smallermtu);
465
		pfSense_interface_capabilities($realif1, -$flags);
466
		interfaces_bring_up($realif1);
467
		mwexec("/sbin/ifconfig {$bridgeif} addm {$realif}");	
468
	}
469

    
470
	if (isset($bridge['enablestp'])) {
471
		/* Choose spanning tree proto */
472
		mwexec("/sbin/ifconfig {$bridgeif} proto {$bridge['proto']}");	
473
		
474
		if (!empty($bridge['stp'])) {
475
			$stpifs = explode(',', $bridge['stp']);
476
			foreach ($stpifs as $stpif) {
477
				$realif = get_real_interface($stpif);
478
				mwexec("/sbin/ifconfig {$bridgeif} stp {$realif}");
479
			}
480
		}
481
		if (!empty($bridge['maxage']))
482
			mwexec("/sbin/ifconfig {$bridgeif} maxage {$bridge['maxage']}");
483
		if (!empty($brige['fwdelay']))
484
			mwexec("/sbin/ifconfig {$bridgeif} fwddelay {$bridge['fwdelay']}");
485
		if (!empty($brige['hellotime']))
486
                        mwexec("/sbin/ifconfig {$bridgeif} hellotime {$bridge['hellotime']}");
487
		if (!empty($brige['priority']))
488
                        mwexec("/sbin/ifconfig {$bridgeif} priority {$bridge['priority']}");
489
		if (!empty($brige['holdcount']))
490
                        mwexec("/sbin/ifconfig {$bridgeif} holdcnt {$bridge['holdcnt']}");
491
		if (!empty($bridge['ifpriority'])) {
492
			$pconfig = explode(",", $bridge['ifpriority']);
493
			$ifpriority = array();
494
			foreach ($pconfig as $cfg) {
495
				$embcfg = explode(":", $cfg);
496
				foreach ($embcfg as $key => $value)
497
					$ifpriority[$key] = $value;
498
			}
499
			foreach ($ifpriority as $key => $value) {
500
				$realif = get_real_interface($key);
501
				mwexec("/sbin/ifconfig ${bridgeif} ifpriority {$realif} {$value}"); 
502
			}
503
		}
504
		if (!empty($bridge['ifpathcost'])) {
505
			$pconfig = explode(",", $bridges['ifpathcost']);
506
			$ifpathcost = array();
507
			foreach ($pconfig as $cfg) {
508
				$embcfg = explode(":", $cfg);
509
				foreach ($embcfg as $key => $value)
510
					$ifpathcost[$key] = $value;
511
			}
512
			foreach ($ifpathcost as $key => $value) {
513
                        	$realif = get_real_interface($key);
514
                        	mwexec("/sbin/ifconfig ${bridgeif} ifpathcost {$realif} {$value}");
515
                	}
516
		}
517
	}
518

    
519
	if ($bridge['maxaddr'] <> "")
520
		mwexec("/sbin/ifconfig {$bridgeif} maxaddr {$bridge['maxaddr']}");
521
        if ($bridge['timeout'] <> "")
522
                mwexec("/sbin/ifconfig {$bridgeif} timeout {$bridge['timeout']}");
523
        if ($bridge['span'] <> "") {
524
		$realif = get_real_interface($bridge['span']);
525
                mwexec("/sbin/ifconfig {$bridgeif} span {$realif}");
526
	}
527
	if (!empty($bridge['edge'])) {
528
        	$edgeifs = explode(',', $bridge['edge']);
529
        	foreach ($edgeifs as $edgeif) {
530
			$realif = get_real_interface($edgeif);
531
                	mwexec("/sbin/ifconfig {$bridgeif} edge {$realif}");
532
        	}
533
	}
534
	if (!empty($bridge['autoedge'])) {
535
        	$edgeifs = explode(',', $bridge['autoedge']);
536
        	foreach ($edgeifs as $edgeif) {
537
                	$realif = get_real_interface($edgeif);
538
                	mwexec("/sbin/ifconfig {$bridgeif} -autoedge {$realif}");
539
        	}
540
	}
541
	if (!empty($bridge['ptp'])) {
542
        	$ptpifs = explode(',', $bridge['ptp']);
543
        	foreach ($ptpifs as $ptpif) {
544
                	$realif = get_real_interface($ptpif);
545
                	mwexec("/sbin/ifconfig {$bridgeif} ptp {$realif}");
546
        	}
547
	}
548
	if (!empty($bridge['autoptp'])) {
549
        	$ptpifs = explode(',', $bridge['autoptp']);
550
        	foreach ($ptpifs as $ptpif) {
551
                	$realif = get_real_interface($ptpif);
552
                	mwexec("/sbin/ifconfig {$bridgeif} -autoptp {$realif}");
553
        	}
554
	}
555
	if (!empty($bridge['static'])) {
556
        	$stickyifs = explode(',', $bridge['static']);
557
        	foreach ($stickyifs as $stickyif) {
558
                	$realif = get_real_interface($stickyif);
559
                	mwexec("/sbin/ifconfig {$bridgeif} sticky {$realif}");
560
        	}
561
	}
562
	if (!empty($bridge['private'])) {
563
        	$privateifs = explode(',', $bridge['private']);
564
        	foreach ($privateifs as $privateif) {
565
                	$realif = get_real_interface($privateif);
566
               	 	mwexec("/sbin/ifconfig {$bridgeif} private {$realif}");
567
        	}
568
	}
569

    
570
	if($bridgeif)
571
		interfaces_bring_up($bridgeif);	
572
	else 
573
		log_error("bridgeif not defined -- could not bring interface up");
574

    
575
	return $bridgeif;
576
}
577

    
578
function interface_bridge_add_member($bridgeif, $interface) {
579

    
580
	if (!does_interface_exist($bridgeif) || !does_interface_exist($interface))
581
		return;
582

    
583
	$mtu = get_interface_mtu($brigeif);
584
	$mtum = get_interface_mtu($interface);
585
	
586
	if ($mtu != $mtum)
587
		pfSense_interface_mtu($interface, $mtu);
588

    
589
	$options = pfSense_get_interface_addresses($bridgeif);
590
	$flags = 0;
591
	if (!isset($options['encaps']['txcsum']))
592
		$flags |= IFCAP_TXCSUM;
593

    
594
	if (!isset($options['encaps']['rxcsum']))
595
		$flags |= IFCAP_RXCSUM;
596

    
597
	pfSense_interface_capabilities($interface, -$flags);
598

    
599
	interfaces_bring_up($interface);
600
	mwexec("/sbin/ifconfig {$bridgeif} addm {$interface}");
601
}
602

    
603
function interfaces_lagg_configure() 
604
{
605
        global $config, $g;
606
		if($g['booting']) 
607
			echo "Configuring LAGG interfaces...";
608
        $i = 0;
609
		if (is_array($config['laggs']['lagg']) && count($config['laggs']['lagg'])) {
610
			foreach ($config['laggs']['lagg'] as $lagg) {
611
				if(empty($lagg['laggif']))
612
					$lagg['laggif'] = "lagg{$i}";
613
				/* XXX: Maybe we should report any errors?! */
614
				interface_lagg_configure($lagg);
615
				$i++;
616
			}
617
		}
618
		if($g['booting']) 
619
			echo "done.\n";
620
}
621

    
622
function interface_lagg_configure(&$lagg) {
623
        global $config, $g;
624

    
625
        if (!is_array($lagg))
626
		return -1;
627

    
628
	$members = explode(',', $lagg['members']);
629
	if (!count($members))
630
		return -1;
631
	
632
	$checklist = get_interface_list();
633

    
634
	if ($g['booting'] || !(empty($lagg['laggif']))) {
635
		pfSense_interface_destroy($lagg['laggif']);
636
		pfSense_interface_create($lagg['laggif']);
637
                $laggif = $lagg['laggif'];
638
        } else
639
		$laggif = pfSense_interface_create("lagg");
640

    
641
	/* Calculate smaller mtu and enforce it */
642
        $smallermtu = 0;
643
        foreach ($members as $member) {
644
		$opts = pfSense_get_interface_addresses($member);
645
                $mtu = $opts['mtu'];
646
		if (!isset($opts['encaps']['txcsum']))
647
                        $commontx = false;
648
                if (!isset($opts['encaps']['rxcsum']))
649
                        $commonrx = false;
650
		if (!isset($opts['encaps']['tso4']))
651
			$commontso4 = false;
652
		if (!isset($opts['encaps']['tso6']))
653
			$commontso6 = false;
654
		if (!isset($opts['encaps']['lro']))
655
			$commonlro = false;
656
		if ($smallermtu == 0 && !empty($mtu))
657
			$smallermtu = $mtu;
658
                else if (!empty($mtu) && $mtu < $smallermtu)
659
                        $smallermtu = $mtu;
660
        }
661

    
662
	/* Just in case anything is not working well */
663
        if ($smallermtu == 0)
664
                $smallermtu = 1500;
665

    
666
	$flags = 0;
667
        if ($commonrx === false)
668
                $flags |= IFCAP_RXCSUM;
669
        if ($commontx === false)
670
                $flags |= IFCAP_TXCSUM;
671
	if ($commontso4 === false)
672
                $flags |= IFCAP_TSO4;
673
        if ($commontso6 === false)
674
                $flags |= IFCAP_TSO6;
675
        if ($commonlro === false)
676
                $flags |= IFCAP_LRO;
677

    
678
	foreach ($members as $member) {
679
		if (!array_key_exists($member, $checklist))
680
			continue;
681
		/* make sure the parent interface is up */
682
		pfSense_interface_mtu($member, $smallermtu);
683
		pfSense_interface_capabilities($member, -$flags);
684
		interfaces_bring_up($member);
685
		mwexec("/sbin/ifconfig {$laggif} laggport {$member}");
686
	}
687
	
688
	mwexec("/sbin/ifconfig {$laggif} laggproto {$lagg['proto']}");
689

    
690
	interfaces_bring_up($laggif);
691

    
692
	return $laggif;
693
}
694

    
695
function interfaces_gre_configure($checkparent = 0) {
696
        global $config;
697

    
698
        if (is_array($config['gres']['gre']) && count($config['gres']['gre'])) {
699
                foreach ($config['gres']['gre'] as $i => $gre) {
700
                        if(empty($gre['greif']))
701
                                $gre['greif'] = "gre{$i}";
702
			if ($checkparent == 1 && strstr($gre['if'], "vip"))
703
				continue;
704
			if ($checkparent == 2 && !strstr($gre['if'], "vip"))
705
				continue;
706
                        /* XXX: Maybe we should report any errors?! */
707
                        interface_gre_configure($gre);
708
                }
709
        }
710
}
711

    
712
/* NOTE: $grekey is not used but useful for passing this function to array_walk. */
713
function interface_gre_configure(&$gre, $grekey = "") {
714
        global $config, $g;
715

    
716
	if (!is_array($gre))
717
		return -1;
718

    
719
	$realif = get_real_interface($gre['if']);
720
	$realifip = get_interface_ip($gre['if']);
721

    
722
	/* make sure the parent interface is up */
723
	interfaces_bring_up($realif);
724

    
725
	if ($g['booting'] || !(empty($gre['greif']))) {
726
		pfSense_interface_destroy($gre['greif']);
727
		pfSense_interface_create($gre['greif']);
728
		$greif = $gre['greif'];
729
	} else
730
		$greif = pfSense_interface_create("gre");
731

    
732
	/* Do not change the order here for more see gre(4) NOTES section. */
733
	mwexec("/sbin/ifconfig {$greif} tunnel {$realifip} {$gre['remote-addr']}");
734
	mwexec("/sbin/ifconfig {$greif} {$gre['tunnel-local-addr']} {$gre['tunnel-remote-addr']} netmask " . gen_subnet_mask($gre['tunnel-remote-net']));
735
	if (isset($gre['link0']) && $gre['link0'])
736
		pfSense_interface_flags($greif, IFF_LINK0);
737
	if (isset($gre['link1']) && $gre['link1'])
738
		pfSense_interface_flags($greif, IFF_LINK1);
739
	if (isset($gre['link2']) && $gre['link2'])
740
		pfSense_interface_flags($greif, IFF_LINK2);
741

    
742
	if($greif)
743
		interfaces_bring_up($greif);
744
	else 
745
		log_error("Could not bring greif up -- variable not defined.");
746

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

    
751
	return $greif;
752
}
753

    
754
function interfaces_gif_configure($checkparent = 0) {
755
	global $config;
756

    
757
	if (is_array($config['gifs']['gif']) && count($config['gifs']['gif'])) {
758
		foreach ($config['gifs']['gif'] as $i => $gif) {
759
			if(empty($gif['gifif']))
760
				$gre['gifif'] = "gif{$i}";
761
			if ($checkparent == 1 && strstr($gif['if'], "vip"))
762
				continue;
763
			if ($checkparent == 2 && !strstr($gif['if'], "vip"))
764
				continue;
765
			/* XXX: Maybe we should report any errors?! */
766
			interface_gif_configure($gif);
767
		}
768
	}
769
}
770

    
771
/* NOTE: $gifkey is not used but useful for passing this function to array_walk. */
772
function interface_gif_configure(&$gif, $gifkey = "") {
773
	global $config, $g;
774

    
775
	if (!is_array($gif))
776
		return -1;
777

    
778
	$realif = get_real_interface($gif['if']);
779
	$realifip = get_interface_ip($gif['if']);
780

    
781
	/* make sure the parent interface is up */
782
	if($realif)
783
		interfaces_bring_up($realif);
784
	else 
785
		log_error("could not bring realif up -- variable not defined -- interface_gif_configure()");
786

    
787
	if ($g['booting'] || !(empty($gif['gifif']))) {
788
		pfSense_interface_destroy($gif['gifif']);
789
		pfSense_interface_create($gif['gifif']);
790
		$gifif = $gif['gifif'];
791
	} else
792
		$gifif = pfSense_interface_create("gif");
793

    
794
	/* Do not change the order here for more see gif(4) NOTES section. */
795
	mwexec("/sbin/ifconfig {$gifif} tunnel {$realifip} {$gif['remote-addr']}");
796
	mwexec("/sbin/ifconfig {$gifif} {$gif['tunnel-local-addr']} {$gif['tunnel-remote-addr']} netmask " . gen_subnet_mask($gif['tunnel-remote-net']));
797
	if (isset($gif['link0']) && $gif['link0'])
798
		pfSense_interface_flags($gifif, IFF_LINK0);
799
	if (isset($gif['link1']) && $gif['link1'])
800
		pfSense_interface_flags($gifif, IFF_LINK1);
801
	if($gifif)
802
		interfaces_bring_up($gifif);
803
	else
804
		log_error("could not bring gifif up -- variable not defined");
805

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

    
810
	return $gifif;
811
}
812

    
813
function interfaces_configure() {
814
	global $config, $g;
815

    
816
	/* Set up our loopback interface */
817
	interfaces_loopback_configure();
818

    
819
	/* set up LAGG virtual interfaces */
820
	interfaces_lagg_configure();
821

    
822
	/* set up VLAN virtual interfaces */
823
	interfaces_vlan_configure();
824

    
825
	interfaces_qinq_configure();
826

    
827
	$iflist = get_configured_interface_with_descr();
828
	$delayed_list = array();
829
	$bridge_list = array();
830
	
831
	/* This is needed to speedup interfaces on bootup. */
832
	$reload = false;
833
	if ($g['booting'])
834
		$reload = true;
835

    
836
	foreach($iflist as $if => $ifname) {
837
		$realif = $config['interfaces'][$if]['if'];
838
		if (strstr($realif, "bridge")) 
839
			$bridge_list[$if] = $ifname;
840
		else if (strstr($realif, "gre"))
841
			$delayed_list[$if] = $ifname;
842
		else if (strstr($realif, "gif"))
843
			$delayed_list[$if] = $ifname;
844
		else if (strstr($realif, "ovpn")) {
845
			//echo "Delaying OpenVPN interface configuration...done.\n";
846
			continue;
847
		} else {
848
			if ($g['booting'])
849
				echo "Configuring {$ifname} interface...";
850
			if($g['debug'])
851
				log_error("Configuring {$ifname}");
852
			interface_configure($if, $reload);
853
			if ($g['booting']) 
854
				echo "done.\n";
855
		}
856
	}
857

    
858
	/* create the unconfigured wireless clones */
859
	interfaces_create_wireless_clones();
860

    
861
	/*
862
	 * NOTE: The following function parameter consists of
863
	 *	1 - Do not load gre/gif/bridge with parent/member as vip
864
	 *	2 - Do load gre/gif/bridge with parent/member as vip
865
	 */
866

    
867
	/* set up GRE virtual interfaces */
868
	interfaces_gre_configure(1);
869

    
870
	/* set up GIF virtual interfaces */
871
	interfaces_gif_configure(1);
872

    
873
	/* set up BRIDGe virtual interfaces */
874
	interfaces_bridge_configure(1);
875

    
876
	/* bring up vip interfaces */
877
	interfaces_vips_configure();
878

    
879
	/* set up GRE virtual interfaces */
880
	interfaces_gre_configure(2);
881

    
882
	/* set up GIF virtual interfaces */
883
	interfaces_gif_configure(2);
884

    
885
	foreach ($delayed_list as $if => $ifname) {
886
		if ($g['booting'])
887
			echo "Configuring {$ifname} interface...";
888
        	if ($g['debug'])
889
        		log_error("Configuring {$ifname}");
890

    
891
		interface_configure($if, $reload);
892

    
893
		if ($g['booting'])
894
			echo "done.\n";
895
	}
896

    
897
	/* set up BRIDGe virtual interfaces */
898
	interfaces_bridge_configure(2);
899

    
900
	foreach ($bridge_list as $if => $ifname) {
901
		if ($g['booting'])
902
			echo "Configuring {$ifname} interface...";
903
		if($g['debug'])
904
			log_error("Configuring {$ifname}");
905

    
906
		interface_configure($if, $reload);
907

    
908
		if ($g['booting'])
909
			echo "done.\n";
910
	}
911

    
912
	/* configure interface groups */
913
	interfaces_group_setup();
914

    
915
	if (!$g['booting']) {
916
		/* reconfigure static routes (kernel may have deleted them) */
917
		system_routing_configure();
918

    
919
		/* reload IPsec tunnels */
920
		vpn_ipsec_configure();
921

    
922
		/* reload dhcpd (interface enabled/disabled status may have changed) */
923
		services_dhcpd_configure();
924

    
925
		/* restart dnsmasq */
926
		services_dnsmasq_configure();
927

    
928
		/* reload captive portal */
929
		captiveportal_init_rules();
930
	}
931

    
932
	return 0;
933
}
934

    
935
function interface_reconfigure($interface = "wan") {
936
	interface_bring_down($interface);
937
	interface_configure($interface, true);
938
}
939

    
940
function interface_vip_bring_down($vip) {
941
	global $g;
942

    
943
	switch ($vip['mode']) {
944
	case "proxyarp":
945
		$vipif = get_real_interface($vip['interface']);
946
		if (file_exists("{$g['varrun_path']}/choparp_{$vipif}.pid"))
947
			killbypid("{$g['varrun_path']}/choparp_{$vipif}.pid");
948
		break;
949
	case "ipalias":
950
		$vipif = get_real_interface($vip['interface']);
951
		if(does_interface_exist($vipif))
952
			pfSense_interface_deladdress($vipif, $vip['subnet']);
953
		break;
954
	case "carp":
955
		$vipif = "vip" . $vip['vhid'];
956
		if(does_interface_exist($vipif)) 
957
			pfSense_interface_destroy($vipif);
958
		break;
959
	case "carpdev-dhcp":
960
		$vipif = "vip" . $vip['vhid'];
961
		if(does_interface_exist($vipif)) 
962
			pfSense_interface_destroy($vipif);
963
		break;
964
	}
965
}
966

    
967
function interface_bring_down($interface = "wan", $destroy = false) {
968
	global $config, $g;
969

    
970
	if (!isset($config['interfaces'][$interface]))
971
		return; 
972

    
973
	$ifcfg = $config['interfaces'][$interface];
974

    
975
	$realif = get_real_interface($interface);
976

    
977
	switch ($ifcfg['ipaddr']) {
978
	case "ppp":
979
	case "pppoe":
980
	case "pptp":
981
	case "l2tp":
982
		if (is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) {
983
			foreach ($config['ppps']['ppp'] as $pppid => $ppp) {
984
				if ($realif == $ppp['if']) {
985
					if (isset($ppp['ondemand']) && !$destroy){
986
						send_event("interface reconfigure {$interface}");
987
						break;
988
					}
989
					if (file_exists("{$g['varrun_path']}/{$ppp['type']}_{$interface}.pid")) {
990
						killbypid("{$g['varrun_path']}/{$ppp['type']}_{$interface}.pid");
991
						sleep(2);
992
					}
993
					unlink_if_exists("{$g['varetc_path']}/mpd_{$interface}.conf");
994
					break;
995
				}
996
			}
997
		}
998
		break;
999
	case "carpdev-dhcp":
1000
		/* 
1001
		 * NB: When carpdev gets enabled it would be better to be handled as all
1002
		 *	   other interfaces! 
1003
		 */
1004
	case "dhcp":
1005
		$pid = find_dhclient_process($realif);
1006
		if($pid)
1007
			mwexec("/bin/kill {$pid}");
1008
		sleep(1);
1009
		unlink_if_exists("{$g['varetc_path']}/dhclient_{$interface}.conf");
1010
		if(does_interface_exist("$realif")) {
1011
			mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete", true);
1012
			if ($destroy == true)
1013
				pfSense_interface_flags($realif, -IFF_UP);
1014
			mwexec("/usr/sbin/arp -d -i {$realif} -a");
1015
		}
1016
		break;
1017
	default:
1018
		if(does_interface_exist("$realif")) {
1019
			mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete", true);
1020
			if ($destroy == true)
1021
				pfSense_interface_flags($realif, -IFF_UP);
1022
			mwexec("/usr/sbin/arp -d -i {$realif} -a");
1023
		}
1024
		break;
1025
	}
1026

    
1027
	/* remove interface up file if it exists */
1028
	unlink_if_exists("{$g['tmp_path']}/{$realif}up");
1029
	unlink_if_exists("{$g['vardb_path']}/{$interface}ip");
1030
	unlink_if_exists("{$g['tmp_path']}/{$realif}_router");
1031
	unlink_if_exists("{$g['varetc_path']}/nameserver_{$realif}");
1032
	unlink_if_exists("{$g['varetc_path']}/searchdomain_{$realif}");
1033
	
1034
	/* hostapd and wpa_supplicant do not need to be running when the interface is down.
1035
	 * They will also use 100% CPU if running after the wireless clone gets deleted. */
1036
	if (is_array($ifcfg['wireless'])) {
1037
		mwexec(kill_hostapd($realif));
1038
		mwexec(kill_wpasupplicant($realif));
1039
	}
1040

    
1041
	if ($destroy == true) {
1042
		if (preg_match("/^vip|^tun|^ovpn|^gif|^gre|^lagg|^bridge|vlan/i", $realif))
1043
			pfSense_interface_destroy($realif);
1044
	}	
1045

    
1046
	return;
1047
}
1048

    
1049
function interfaces_ptpid_used($ptpid) {
1050
	global $config;
1051

    
1052
	if (is_array($config['ppps']['ppp']))
1053
		foreach ($config['ppps']['ppp'] as & $settings)
1054
			if ($ptpid == $settings['ptpid'])
1055
				return true;
1056

    
1057
	return false;
1058
}
1059

    
1060
function interfaces_ptpid_next() {
1061

    
1062
	$ptpid = 0;
1063
	while(interfaces_ptpid_used($ptpid))
1064
		$ptpid++;
1065

    
1066
	return $ptpid;
1067
}
1068

    
1069
function getMPDCRONSettings($pppif_) {
1070
	global $config;
1071
	$cron_cmd_file = "{$g['varetc_path']}/pppoe_restart_";
1072
	if (is_array($config['cron']['item'])) {
1073
		for ($i = 0; $i < count($config['cron']['item']); $i++) {
1074
			$item = $config['cron']['item'][$i];
1075
			if (strpos($item['command'], $cron_cmd_file.$pppif_) !== false) {
1076
				return array("ID" => $i, "ITEM" => $item);
1077
			}
1078
		}
1079
	}
1080
	return NULL;
1081
}
1082

    
1083
function handle_pppoe_reset($post_array) {
1084
	global $config, $g;
1085

    
1086
	$cron_cmd_file = "{$g['varetc_path']}/pppoe_restart_";
1087

    
1088
	$pppif = $post_array['type'].$post_array['ptpid'];
1089
	if (!is_array($config['cron']['item'])) 
1090
		$config['cron']['item'] = array(); 
1091
	$itemhash = getMPDCRONSettings($pppif);
1092
	$item = $itemhash['ITEM'];
1093
	
1094
	// reset cron items if necessary and return
1095
	if (empty($post_array['pppoe-reset-type'])) {
1096
		if (isset($item))
1097
			unset($config['cron']['item'][$itemhash['ID']]);
1098
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
1099
		return;
1100
	}
1101

    
1102
	if (empty($item)) 
1103
		$item = array();
1104
	if (isset($post_array['pppoe-reset-type']) && $post_array['pppoe-reset-type'] == "custom") {
1105
		$item['minute'] = $post_array['pppoe_resetminute'];
1106
		$item['hour'] = $post_array['pppoe_resethour'];
1107
		if (isset($post_array['pppoe_resetdate']) && $post_array['pppoe_resetdate'] <> "") {
1108
			$date = explode("/", $post_array['pppoe_resetdate']);
1109
			$item['mday'] = $date[1];
1110
			$item['month'] = $date[0];
1111
		} else {
1112
			$item['mday'] = "*";
1113
			$item['month'] = "*";
1114
		}
1115
		$item['wday'] = "*";
1116
		$item['who'] = "root";
1117
		$item['command'] = $cron_cmd_file.$pppif;
1118
	} else if (isset($post_array['pppoe-reset-type']) && $post_array['pppoe-reset-type'] == "preset") {
1119
		switch ($post_array['pppoe_pr_preset_val']) {
1120
			case "monthly":
1121
				$item['minute'] = "0";
1122
				$item['hour'] = "0";
1123
				$item['mday'] = "1";
1124
				$item['month'] = "*";
1125
				$item['wday'] = "*";
1126
				$item['who'] = "root";
1127
				$item['command'] = $cron_cmd_file.$pppif;
1128
				break;
1129
	        case "weekly":
1130
				$item['minute'] = "0";
1131
				$item['hour'] = "0";
1132
				$item['mday'] = "*";
1133
				$item['month'] = "*";
1134
				$item['wday'] = "0";
1135
				$item['who'] = "root";
1136
				$item['command'] = $cron_cmd_file.$pppif;
1137
				break;
1138
			case "daily":
1139
				$item['minute'] = "0";
1140
				$item['hour'] = "0";
1141
				$item['mday'] = "*";
1142
				$item['month'] = "*";
1143
				$item['wday'] = "*";
1144
				$item['who'] = "root";
1145
				$item['command'] = $cron_cmd_file.$pppif;
1146
				break;
1147
			case "hourly":
1148
				$item['minute'] = "0";
1149
				$item['hour'] = "*";
1150
				$item['mday'] = "*";
1151
				$item['month'] = "*";
1152
				$item['wday'] = "*";
1153
				$item['who'] = "root";
1154
				$item['command'] = $cron_cmd_file.$pppif;
1155
				break;
1156
		} // end switch
1157
	} else {
1158
		/* test whether a cron item exists and unset() it if necessary */
1159
		$itemhash = getMPDCRONSettings($pppif);
1160
		$item = $itemhash['ITEM'];
1161
		if (isset($item))
1162
			unset($config['cron']['item'][$itemhash['ID']]); 
1163
	}// end if
1164
	if (isset($itemhash['ID'])) 
1165
		$config['cron']['item'][$itemhash['ID']] = $item;
1166
	else 
1167
		$config['cron']['item'][] = $item;
1168
}
1169

    
1170
/*	This function can configure PPPoE, MLPPP (PPPoE), PPTP.
1171
*	It writes the mpd config file to /var/etc every time the link is opened.
1172
*/
1173

    
1174
function interface_ppps_configure($interface) {
1175
	global $config, $g;
1176

    
1177
	/* Return for unassigned interfaces. This is a minimum requirement. */
1178
	if (empty($config['interfaces'][$interface]))
1179
		return 0;
1180
	$ifcfg = $config['interfaces'][$interface];
1181
	if (!isset($ifcfg['enable']))
1182
		return 0;
1183

    
1184
	// mpd5 requires a /var/spool/lock directory for PPP modem links.
1185
	if(!is_dir("/var/spool/lock")) {
1186
		exec("/bin/mkdir -p /var/spool/lock");
1187
		exec("/bin/chmod a+rw /var/spool/lock/.");
1188
	}
1189
	// mpd5 modem chat script expected in the same directory as the mpd_xxx.conf files	
1190
	if (!file_exists("{$g['varetc_path']}/mpd.script"))
1191
		mwexec("/bin/ln -s /usr/local/sbin/mpd.script {$g['varetc_path']}/.");
1192

    
1193
	if (is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) {
1194
		foreach ($config['ppps']['ppp'] as $pppid => $ppp) {
1195
			if ($ifcfg['if'] == $ppp['if'])
1196
				break;
1197
		}
1198
	}
1199
	if (!$ppp || $ifcfg['if'] != $ppp['if']){
1200
		log_error("Can't find PPP config for {$ifcfg['if']} in interface_ppps_configure().");
1201
		return 0;
1202
	}
1203
	$pppif = $ifcfg['if'];
1204
	if ($ppp['type'] == "ppp")
1205
		$type = "modem";
1206
	else
1207
		$type = $ppp['type'];
1208
	$upper_type = strtoupper($ppp['type']);	
1209

    
1210
	if($g['booting']) {
1211
		$descr = isset($ifcfg['descr']) ? $ifcfg['descr'] : strtoupper($interface);
1212
		echo "starting {$pppif} link...";
1213
		// Do not re-configure the interface if we are booting and it's already been started
1214
		if(file_exists("{$g['varrun_path']}/{$ppp['type']}_{$interface}.pid"))
1215
			return 0;
1216
	}
1217

    
1218
	$ports = explode(',',$ppp['ports']);
1219
	if ($type != "modem") {
1220
		foreach ($ports as $pid => $port)
1221
			$ports[$pid] = get_real_interface($port);
1222
	}
1223
	$localips = explode(',',$ppp['localip']);
1224
	$gateways = explode(',',$ppp['gateway']);
1225
	$subnets = explode(',',$ppp['subnet']);
1226

    
1227
	/* We bring up the parent interface first because if DHCP is configured on the parent we need
1228
	 * to obtain an address first so we can write it in the mpd .conf file for PPTP and L2TP configs
1229
	 */
1230
	foreach($ports as $pid => $port){
1231
		switch ($ppp['type']) {
1232
			case "pppoe": 
1233
				/* Bring the parent interface up */
1234
				interfaces_bring_up($port);
1235
				pfSense_ngctl_attach(".", $port);
1236
				break;
1237
			case "pptp":
1238
			case "l2tp":
1239
				/* configure interface */
1240
				if(is_ipaddr($localips[$pid])){
1241
					// Manually configure interface IP/subnet
1242
					pfSense_interface_setaddress($port, "{$localips[$pid]}/{$subnets[$pid]}");
1243
					interfaces_bring_up($port);
1244
				} else if (empty($localips[$pid]))
1245
					$localips[$pid] = get_interface_ip($port); // try to get the interface IP from the port
1246
				
1247
				if(!is_ipaddr($localips[$pid])){
1248
					log_error("Could not get a Local IP address for PPTP/L2TP link on {$port} in interfaces_ppps_configure. Using 0.0.0.0 ip!");
1249
					$localips[$pid] = "0.0.0.0";
1250
				}
1251
				/* XXX: This needs to go away soon! [It's commented out!] */
1252
				/* Configure the gateway (remote IP ) */
1253
				if (!$g['booting'] && !is_ipaddr($gateways[$pid]) && is_hostname($gateways[$pid])) {
1254
					/* XXX: Fix later 
1255
					$gateways[$pid] = gethostbyname($gateways[$pid]);
1256
					if(!is_ipaddr($gateways[$pid])) {
1257
						log_error("Could not get a valid Gateway IP from {$port} via DNS in interfaces_ppps_configure.");
1258
						return 0;
1259
					}
1260
					*/
1261
				}
1262
				if(!is_ipaddr($gateways[$pid])){
1263
					log_error("Could not get a PPTP/L2TP Remote IP address from {$dhcp_gateway} for {$gway} in interfaces_ppps_configure.");
1264
					return 0;
1265
				}
1266
				pfSense_ngctl_attach(".", $port);
1267
				break;
1268
			case "ppp":
1269
				if (!file_exists("{$port}")) {
1270
					log_error("Device {$port} does not exist. PPP link cannot start without the modem device.");
1271
					return 0;
1272
				}
1273
				break;
1274
			default:
1275
				log_error("Unkown {$type} configured as ppp interface.");
1276
				break;
1277
		}
1278
	}
1279
	
1280
	if (is_array($ports) && count($ports) > 1)
1281
		$multilink = "enable";
1282
	else
1283
		$multilink = "disable";
1284
	
1285
	if ($type == "modem"){
1286
		if (is_ipaddr($ppp['localip']))
1287
			$localip = $ppp['localip'];
1288
		else
1289
			$localip = '0.0.0.0';
1290

    
1291
		if (is_ipaddr($ppp['gateway']))
1292
			$gateway = $ppp['gateway'];
1293
		else
1294
			$gateway = "10.64.64.{$pppid}";
1295
		$ranges = "{$localip}/0 {$gateway}/0";
1296
		
1297
		if (empty($ppp['apnum']))	
1298
			$ppp['apnum'] = 1;
1299
	} else
1300
		$ranges = "0.0.0.0/0 0.0.0.0/0";
1301

    
1302
	if (isset($ppp['ondemand'])) 
1303
		$ondemand = "enable";
1304
	else
1305
		$ondemand = "disable";
1306
	if (!isset($ppp['idletimeout']))
1307
		$ppp['idletimeout'] = 0;
1308

    
1309
	if (empty($ppp['username']) && $type == "modem"){
1310
		$ppp['username'] = "user";
1311
		$ppp['password'] = "none";
1312
	}
1313
	if (empty($ppp['password']) && $type == "modem")
1314
		$passwd = "none";
1315
	else
1316
		$passwd = base64_decode($ppp['password']);
1317

    
1318
	$bandwidths = explode(',',$ppp['bandwidth']);
1319
	$mtus = explode(',',$ppp['mtu']);
1320
	$mrus = explode(',',$ppp['mru']);
1321

    
1322
	if (isset($ppp['mrru']))
1323
		$mrrus = explode(',',$ppp['mrru']);
1324

    
1325
	// Construct the mpd.conf file
1326
	$mpdconf = <<<EOD
1327
startup:
1328
	# configure the console
1329
	set console close
1330
	# configure the web server
1331
	set web close
1332

    
1333
default:
1334
{$ppp['type']}client:
1335
	create bundle static {$interface}
1336
	set iface name {$pppif}
1337

    
1338
EOD;
1339
	$setdefaultgw = false;
1340
	$founddefaultgw = false;
1341
	if (is_array($config['gateways']['gateway_item'])) {
1342
		foreach($config['gateways']['gateway_item'] as $gateway) {
1343
			if($interface == $gateway['interface'] && isset($gateway['defaultgw'])) {
1344
				$setdefaultgw = true;
1345
				break;
1346
			} else if (isset($gateway['defaultgw']) && !empty($gateway['interface'])) {
1347
				$founddefaultgw = true;
1348
				break;
1349
			}
1350
		}
1351
	}
1352
	
1353
	if (($interface == "wan" && $founddefaultgw == false) || $setdefaultgw == true){
1354
		$setdefaultgw = true;
1355
		$mpdconf .= <<<EOD
1356
	set iface route default
1357

    
1358
EOD;
1359
	}
1360
	$mpdconf .= <<<EOD
1361
	set iface {$ondemand} on-demand
1362
	set iface idle {$ppp['idletimeout']}
1363

    
1364
EOD;
1365

    
1366
	if (isset($ppp['ondemand']))
1367
		$mpdconf .= <<<EOD
1368
	set iface addrs 10.10.1.1 10.10.1.2
1369

    
1370
EOD;
1371
	
1372
	if (isset($ppp['tcpmssfix']))
1373
		$tcpmss = "disable";
1374
	else
1375
		$tcpmss = "enable";
1376
		$mpdconf .= <<<EOD
1377
	set iface {$tcpmss} tcpmssfix
1378

    
1379
EOD;
1380

    
1381
	$mpdconf .= <<<EOD
1382
	set iface up-script /usr/local/sbin/ppp-linkup
1383
	set iface down-script /usr/local/sbin/ppp-linkdown
1384
	set ipcp ranges {$ranges}
1385

    
1386
EOD;
1387
	if (isset($ppp['vjcomp']))
1388
		$mpdconf .= <<<EOD
1389
	set ipcp no vjcomp
1390

    
1391
EOD;
1392

    
1393
	if (isset($config['system']['dnsallowoverride']))
1394
		$mpdconf .= <<<EOD
1395
	set ipcp enable req-pri-dns
1396
	set ipcp enable req-sec-dns
1397

    
1398
EOD;
1399
	if (!isset($ppp['verbose_log']))
1400
		$mpdconf .= <<<EOD
1401
	#log -bund -ccp -chat -iface -ipcp -lcp -link
1402

    
1403
EOD;
1404
	foreach($ports as $pid => $port){
1405
		$port = get_real_interface($port);
1406
		$mpdconf .= <<<EOD
1407

    
1408
	create link static {$interface}_link{$pid} {$type}
1409
	set link action bundle {$interface}
1410
	set link {$multilink} multilink
1411
	set link keep-alive 10 60
1412
	set link max-redial 0
1413

    
1414
EOD;
1415
		if (isset($ppp['shortseq']))
1416
			$mpdconf .= <<<EOD
1417
	set link no shortseq
1418

    
1419
EOD;
1420

    
1421
		if (isset($ppp['acfcomp']))
1422
			$mpdconf .= <<<EOD
1423
	set link no acfcomp
1424

    
1425
EOD;
1426

    
1427
		if (isset($ppp['protocomp']))
1428
			$mpdconf .= <<<EOD
1429
	set link no protocomp
1430

    
1431
EOD;
1432

    
1433
		$mpdconf .= <<<EOD
1434
	set link disable chap pap
1435
	set link accept chap pap eap
1436
	set link disable incoming
1437

    
1438
EOD;
1439

    
1440

    
1441
		if (!empty($bandwidths[$pid]))
1442
			$mpdconf .= <<<EOD
1443
	set link bandwidth {$bandwidths[$pid]}
1444

    
1445
EOD;
1446

    
1447
		if (empty($mtus[$pid]))
1448
			$mtus[$pid] = "1492";
1449
			$mpdconf .= <<<EOD
1450
	set link mtu {$mtus[$pid]}
1451

    
1452
EOD;
1453

    
1454
		if (!empty($mrus[$pid]))
1455
			$mpdconf .= <<<EOD
1456
	set link mru {$mrus[$pid]}
1457

    
1458
EOD;
1459

    
1460
		if (!empty($mrrus[$pid]))
1461
			$mpdconf .= <<<EOD
1462
	set link mrru {$mrrus[$pid]}
1463

    
1464
EOD;
1465

    
1466
		$mpdconf .= <<<EOD
1467
	set auth authname "{$ppp['username']}"
1468
	set auth password {$passwd}
1469

    
1470
EOD;
1471
		if ($type == "modem") {
1472
			$mpdconf .= <<<EOD
1473
	set modem device {$ppp['ports']}
1474
	set modem script DialPeer
1475
	set modem idle-script Ringback
1476
	set modem watch -cd
1477
	set modem var \$DialPrefix "DT"
1478
	set modem var \$Telephone "{$ppp['phone']}"
1479

    
1480
EOD;
1481
		}
1482
		if (isset($ppp['connect-timeout']) && $type == "modem") {
1483
			$mpdconf .= <<<EOD
1484
	set modem var \$ConnectTimeout "{$ppp['connect-timeout']}"
1485

    
1486
EOD;
1487
		}
1488
		if (isset($ppp['initstr']) && $type == "modem") {
1489
			$initstr = base64_decode($ppp['initstr']);
1490
			$mpdconf .= <<<EOD
1491
	set modem var \$InitString "{$initstr}"
1492

    
1493
EOD;
1494
		}
1495
		if (isset($ppp['simpin']) && $type == "modem") {
1496
			$mpdconf .= <<<EOD
1497
	set modem var \$SimPin "{$ppp['simpin']}"
1498
	set modem var \$PinWait "{$ppp['pin-wait']}"
1499

    
1500
EOD;
1501
		}
1502
		if (isset($ppp['apn']) && $type == "modem") {
1503
			$mpdconf .= <<<EOD
1504
	set modem var \$APN "{$ppp['apn']}"
1505
	set modem var \$APNum "{$ppp['apnum']}"
1506

    
1507
EOD;
1508
		}
1509
		if (isset($ppp['provider']) && $type == "pppoe") {
1510
			$mpdconf .= <<<EOD
1511
	set pppoe service "{$ppp['provider']}"
1512

    
1513
EOD;
1514
		}
1515
		if ($type == "pppoe")
1516
			$mpdconf .= <<<EOD
1517
	set pppoe iface {$port}
1518

    
1519
EOD;
1520

    
1521
		if ($type == "pptp" || $type == "l2tp") {
1522
			$mpdconf .= <<<EOD
1523
	set {$type} self {$localips[$pid]}
1524
	set {$type} peer {$gateways[$pid]}
1525

    
1526
EOD;
1527
		}
1528
		
1529
		$mpdconf .= "\topen\r\n";
1530
	} //end foreach($port)
1531

    
1532

    
1533
	/* Generate mpd.conf. If mpd_[interface].conf exists in the conf path, then link to it instead of generating a fresh conf file. */
1534
	if (file_exists("{$g['conf_path']}/mpd_{$interface}.conf"))
1535
		mwexec("/bin/ln -s {$g['conf_path']}/mpd_{$interface}.conf {$g['varetc_path']}/.");
1536
	else {
1537
		$fd = fopen("{$g['varetc_path']}/mpd_{$interface}.conf", "w");
1538
		if (!$fd) {
1539
			log_error("Error: cannot open mpd_{$interface}.conf in interface_ppps_configure().\n");
1540
			return 0;
1541
		}
1542
		// Write out mpd_ppp.conf
1543
		fwrite($fd, $mpdconf);
1544
		fclose($fd);
1545
	}
1546

    
1547
	// Create the uptime log if requested and if it doesn't exist already, or delete it if it is no longer requested.
1548
	if (isset($ppp['uptime'])) {
1549
		if (!file_exists("/conf/{$pppif}.log")) {
1550
			conf_mount_rw();
1551
			mwexec("echo /dev/null > /conf/{$pppif}.log");
1552
			conf_mount_ro();
1553
		}
1554
	} else {
1555
		if (file_exists("/conf/{$pppif}.log")) {
1556
			conf_mount_rw();
1557
			mwexec("rm -f /conf/{$pppif}.log");
1558
			conf_mount_ro();
1559
		}
1560
	}
1561

    
1562
	/* fire up mpd */
1563
	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");
1564

    
1565
	// Check for PPPoE periodic reset request 
1566
	if ($type == "pppoe") {
1567
		if (isset($ppp['pppoe-reset-type']))
1568
			setup_pppoe_reset_file($ppp['if'], $interface);
1569
		else
1570
			setup_pppoe_reset_file($ppp['if']);
1571
	}
1572

    
1573
	return 1;
1574
}
1575

    
1576
function interfaces_carp_setup() {
1577
	global $g, $config;
1578

    
1579
	$balanacing = "";
1580
	$pfsyncinterface = "";
1581
	$pfsyncenabled = "";
1582
	if(isset($config['system']['developerspew'])) {
1583
		$mt = microtime();
1584
		echo "interfaces_carp_setup() being called $mt\n";
1585
	}
1586

    
1587
	// Prepare CmdCHAIN that will be used to execute commands.
1588
	$cmdchain = new CmdCHAIN();	
1589

    
1590
	if ($g['booting']) {
1591
		echo "Configuring CARP settings...";
1592
		mute_kernel_msgs();
1593
	}
1594

    
1595
	/* suck in configuration items */
1596
	if($config['installedpackages']['carpsettings']) {
1597
		if($config['installedpackages']['carpsettings']['config']) {
1598
			foreach($config['installedpackages']['carpsettings']['config'] as $carp) {
1599
				$pfsyncenabled = $carp['pfsyncenabled'];
1600
				$balanacing = $carp['balancing'];
1601
				$pfsyncinterface = $carp['pfsyncinterface'];
1602
				$pfsyncpeerip = $carp['pfsyncpeerip'];
1603
			}
1604
		}
1605
	} else {
1606
		unset($pfsyncinterface);
1607
		unset($balanacing);
1608
		unset($pfsyncenabled);
1609
	}
1610

    
1611
	if($balanacing) {
1612
		$cmdchain->add("Enable CARP ARP-balancing", "/sbin/sysctl net.inet.carp.arpbalance=1", true);
1613
		$cmdchain->add("Disallow CARP preemption", "/sbin/sysctl net.inet.carp.preempt=0", true);
1614
	} else
1615
		$cmdchain->add("Enable CARP preemption", "/sbin/sysctl net.inet.carp.preempt=1", true);		
1616

    
1617
	$cmdchain->add("Enable CARP logging", "/sbin/sysctl net.inet.carp.log=1", true);
1618
	if (!empty($pfsyncinterface))
1619
		$carp_sync_int = get_real_interface($pfsyncinterface);
1620

    
1621
	if($g['booting']) {
1622
		/*    install rules to alllow pfsync to sync up during boot
1623
		 *    carp interfaces will remain down until the bootup sequence finishes
1624
		 */
1625
		$fd = fopen("{$g['tmp_path']}/rules.boot", "w");
1626
		if ($fd) {
1627
			fwrite($fd, "block quick proto carp \n");
1628
			fwrite($fd, "block quick proto pfsync \n");
1629
			fwrite($fd, "pass out quick from any to any keep state\n");
1630
			fclose($fd);
1631
			mwexec("/sbin/pfctl -f {$g['tmp_path']}/rules.boot");
1632
		} else
1633
			log_error("Could not create rules.boot file!");
1634
	}
1635

    
1636
	/* setup pfsync interface */
1637
	if($carp_sync_int and $pfsyncenabled) {
1638
		if (is_ipaddr($pfsyncpeerip))
1639
			$cmdchain->add("Bring up pfsync0 syncpeer", "/sbin/ifconfig pfsync0 syncdev {$carp_sync_int} syncpeer {$pfsyncpeerip} up", false);						
1640
		else
1641
			$cmdchain->add("Bring up pfsync0 syncdev", "/sbin/ifconfig pfsync0 syncdev {$carp_sync_int} up", false);			
1642
	} else
1643
		$cmdchain->add("Bring up pfsync0", "/sbin/ifconfig pfsync0 syncdev lo0 up", false);						
1644

    
1645
	if($config['virtualip']['vip'])
1646
		$cmdchain->add("Allow CARP.", "/sbin/sysctl net.inet.carp.allow=1", true);				
1647
	else
1648
		$cmdchain->add("Disallow CARP.", "/sbin/sysctl net.inet.carp.allow=0", true);		
1649
	
1650
	if($g['debug'])
1651
		$cmdchain->setdebug(); // optional for verbose logging
1652

    
1653
	$cmdchain->execute();
1654
	$cmdchain->clear();
1655

    
1656
	if ($g['booting']) {
1657
		unmute_kernel_msgs();
1658
		echo "done.\n";
1659
	}
1660
}
1661

    
1662
function interface_proxyarp_configure($interface = "") {
1663
	global $config, $g;
1664
	if(isset($config['system']['developerspew'])) {
1665
		$mt = microtime();
1666
		echo "interface_proxyarp_configure() being called $mt\n";
1667
	}
1668

    
1669
	/* kill any running choparp */
1670
	if (empty($interface))
1671
		killbyname("choparp");
1672
	else {
1673
		$vipif = get_real_interface($interface);
1674
		if (file_exists("{$g['varrun_path']}/choparp_{$vipif}.pid"))
1675
			killbypid("{$g['varrun_path']}/choparp_{$vipif}.pid");
1676
	}
1677

    
1678
	$paa = array();
1679
	if (!empty($config['virtualip']) && is_array($config['virtualip']['vip'])) {
1680

    
1681
		/* group by interface */
1682
		foreach ($config['virtualip']['vip'] as $vipent) {
1683
			if ($vipent['mode'] === "proxyarp") {
1684
				if ($vipent['interface'])
1685
					$proxyif = $vipent['interface'];
1686
				else
1687
					$proxyif = "wan";
1688
				
1689
				if (!empty($interface) && $interface != $proxyif)
1690
					continue;
1691

    
1692
				if (!is_array($paa[$proxyif]))
1693
					$paa[$proxyif] = array();
1694

    
1695
				$paa[$proxyif][] = $vipent;
1696
			}
1697
		}
1698
	}
1699

    
1700
	if (!empty($interface)) {
1701
		if (is_array($paa[$interface])) {
1702
			$paaifip = get_interface_ip($interface);
1703
                        if (!is_ipaddr($paaifip))
1704
                                return;
1705
                        $args = get_real_interface($interface) . " auto";
1706
                        foreach ($paa[$interface] as $paent) {
1707
                                if (isset($paent['subnet']))
1708
                                        $args .= " " . escapeshellarg("{$paent['subnet']}/{$paent['subnet_bits']}");
1709
                                else if (isset($paent['range']))
1710
                                        $args .= " " . escapeshellarg($paent['range']['from'] . "-" . $paent['range']['to']);
1711
                        }
1712
                        mwexec_bg("/usr/local/sbin/choparp " . $args);	
1713
		}
1714
	} else if (count($paa) > 0) {
1715
		foreach ($paa as $paif => $paents)  {
1716
			$paaifip = get_interface_ip($paif);
1717
			if (!is_ipaddr($paaifip))
1718
				continue;
1719
			$args = get_real_interface($paif) . " auto";
1720
			foreach ($paents as $paent) {
1721
				if (isset($paent['subnet']))
1722
					$args .= " " . escapeshellarg("{$paent['subnet']}/{$paent['subnet_bits']}");
1723
				else if (isset($paent['range']))
1724
					$args .= " " . escapeshellarg($paent['range']['from'] . "-" . $paent['range']['to']);
1725
			}
1726
			mwexec_bg("/usr/local/sbin/choparp " . $args);
1727
		}
1728
	}
1729
}
1730

    
1731
function interfaces_vips_configure($interface = "") {
1732
	global $g, $config;
1733
	if(isset($config['system']['developerspew'])) {
1734
		$mt = microtime();
1735
		echo "interfaces_vips_configure() being called $mt\n";
1736
	}
1737
	$paa = array();
1738
	if(is_array($config['virtualip']['vip'])) {
1739
		$carp_setuped = false;
1740
		$anyproxyarp = false;
1741
		foreach ($config['virtualip']['vip'] as $vip) {
1742
			switch ($vip['mode']) {
1743
			case "proxyarp":
1744
				/* nothing it is handled on interface_proxyarp_configure() */
1745
				if ($interface <> "" && $vip['interface'] <> $interface)
1746
					continue;
1747
				$anyproxyarp = true;
1748
				break;
1749
			case "ipalias":
1750
				if ($interface <> "" && $vip['interface'] <> $interface)
1751
					continue;
1752
				interface_ipalias_configure(&$vip);
1753
				break;
1754
			case "carp":
1755
				if ($interface <> "" && $vip['interface'] <> $interface)
1756
					continue;
1757
				if ($carp_setuped == false)
1758
					$carp_setuped = true;
1759
				interface_carp_configure($vip);
1760
				break;
1761
			case "carpdev-dhcp":
1762
				if ($interface <> "" && $vip['interface'] <> $interface)
1763
					continue;
1764
				interface_carpdev_configure($vip);
1765
				break;
1766
			}
1767
		}
1768
		if ($carp_setuped == true)
1769
			interfaces_carp_setup();
1770
		if ($anyproxyarp == true)
1771
			interface_proxyarp_configure();
1772
	}
1773
}
1774

    
1775
function interface_ipalias_configure(&$vip) {
1776

    
1777
	if ($vip['mode'] == "ipalias") {
1778
		$if = get_real_interface($vip['interface']);
1779
		mwexec("/sbin/ifconfig " . escapeshellarg($if) . " " . $vip['subnet'] . "/" . escapeshellarg($vip['subnet_bits']) . " alias");
1780
	}
1781
}
1782

    
1783
function interface_reload_carps($cif) {
1784
	global $config;
1785

    
1786
	$carpifs = link_ip_to_carp_interface(find_interface_ip($cif));
1787
	if (empty($carpifs))
1788
		return;
1789

    
1790
	$carps = explode(" ", $carpifs);
1791
	if(is_array($config['virtualip']['vip'])) {
1792
		$viparr = &$config['virtualip']['vip'];
1793
		foreach ($viparr as $vip) {
1794
			if (in_array($vip['carpif'], $carps)) {
1795
				switch ($vip['mode']) {
1796
				case "carp":
1797
					interface_vip_bring_down($vip);
1798
					sleep(1);
1799
					interface_carp_configure($vip);
1800
					break;
1801
				case "carpdev-dhcp":
1802
					interface_vip_bring_down($vip);
1803
					sleep(1);
1804
					interface_carpdev_configure($vip);
1805
					break;
1806
				case "ipalias":
1807
					interface_vip_bring_down($vip);
1808
					sleep(1);
1809
					interface_ipalias_configure($vip);
1810
					break;
1811
				}
1812
			}
1813
		}
1814
	}
1815
}
1816

    
1817
function interface_carp_configure(&$vip) {
1818
	global $config, $g;
1819
	if(isset($config['system']['developerspew'])) {
1820
		$mt = microtime();
1821
		echo "interface_carp_configure() being called $mt\n";
1822
	}
1823

    
1824
	if ($vip['mode'] != "carp")
1825
		return;
1826

    
1827
	$vip_password = $vip['password'];
1828
	$vip_password = escapeshellarg(addslashes(str_replace(" ", "", $vip_password)));
1829
	if ($vip['password'] != "")
1830
		$password = " pass {$vip_password}";
1831

    
1832
	// set the vip interface to the vhid
1833
	$vipif = "vip{$vip['vhid']}";
1834

    
1835
	/*
1836
	 * ensure the interface containing the VIP really exists
1837
 	 * prevents a panic if the interface is missing or invalid
1838
	 */
1839
	$realif = get_real_interface($vip['interface']);
1840
	if (!does_interface_exist($realif)) {
1841
		file_notice("CARP", "Interface specified for the virtual IP address {$vip['subnet']} does not exist. Skipping this VIP.", "Firewall: Virtual IP", "");
1842
		return;
1843
	}
1844

    
1845
	/* Ensure CARP IP really exists prior to loading up. */
1846
	$ww_subnet_ip = find_interface_ip($realif);
1847
	$ww_subnet_bits = find_interface_subnet($realif);
1848
	if (!ip_in_subnet($vip['subnet'], gen_subnet($ww_subnet_ip, $ww_subnet_bits) . "/" . $ww_subnet_bits) && !ip_in_interface_alias_subnet($vip['interface'], $vip['subnet'])) {
1849
		file_notice("CARP", "Sorry but we could not find a matching real interface subnet for the virtual IP address {$vip['subnet']}.", "Firewall: Virtual IP", "");
1850
		return;
1851
	}
1852

    
1853
	/* create the carp interface and setup */
1854
	if (does_interface_exist($vipif)) {
1855
		pfSense_interface_flags($vipif, -IFF_UP);
1856
	} else {
1857
		$carpif = pfSense_interface_create("carp");
1858
		pfSense_interface_rename($carpif, $vipif);
1859
		pfSense_ngctl_name("{$carpif}:", $vipif);
1860
	}
1861

    
1862
	/* invalidate interface cache */
1863
	get_interface_arr(true);
1864

    
1865
	$broadcast_address = gen_subnet_max($vip['subnet'], $vip['subnet_bits']);
1866
	$advbase = "";
1867
	if (!empty($vip['advbase']))
1868
		$advbase = "advbase {$vip['advbase']}";
1869
	mwexec("/sbin/ifconfig {$vipif} {$vip['subnet']}/{$vip['subnet_bits']} vhid {$vip['vhid']} advskew {$vip['advskew']} {$advbase} {$password}");
1870

    
1871
	interfaces_bring_up($vipif);
1872
	
1873
	return $vipif;
1874
}
1875

    
1876
function interface_carpdev_configure(&$vip) {
1877
	global $g;
1878

    
1879
	if ($vip['mode'] != "carpdev-dhcp")
1880
		return;
1881

    
1882
	$vip_password = $vip['password'];
1883
	$vip_password = str_replace(" ", "", $vip_password);
1884
	if($vip['password'] != "")
1885
		$password = " pass \"" . $vip_password . "\"";
1886

    
1887
	if (empty($vip['interface']))
1888
		return;
1889

    
1890
	$vipif = "vip" . $vip['vhid'];
1891
	$realif = get_real_interface($vip['interface']);
1892
	interfaces_bring_up($realif);
1893
	/*
1894
	 * ensure the interface containing the VIP really exists
1895
	 * prevents a panic if the interface is missing or invalid
1896
	 */
1897
	if (!does_interface_exist($realif)) {
1898
		file_notice("CARP", "Interface specified for the virtual IP address {$vip['subnet']} does not exist. Skipping this VIP.", "Firewall: Virtual IP", "");
1899
		return;
1900
	}
1901

    
1902
	if (does_interface_exist($vipif)) {
1903
		interface_bring_down($vipif);
1904
	} else {
1905
		$carpdevif = exec("/sbin/ifconfig carp create");
1906
		mwexec("/sbin/ifconfig {$carpdevif} name {$vipif}");
1907
		pfSense_ngctl_name("{$carpdevif}:", $vipif);
1908
	}
1909

    
1910
	mwexec("/sbin/ifconfig {$vipif} carpdev {$realif} vhid {$vip['vhid']} advskew {$vip['advskew']} advbase {$vip['advbase']} {$password}");
1911
	interfaces_bring_up($vipif);
1912

    
1913
	/*
1914
	 * XXX: BIG HACK but carpdev needs ip services active
1915
	 *      before even starting something as dhclient.
1916
	 *      I do not know if this is a feature or a bug
1917
	 *      but better than track it make it work ;) .
1918
	 */
1919
	//$fakeiptouse = "10.254.254." . ($carp_instances_counter+1);
1920
	//$cmdchain->add("CarpDEV hack", "/sbin/ifconfig {$carpint} inet {$fakeiptouse}", false);
1921

    
1922
	/* generate dhclient_wan.conf */
1923
	$fd = fopen("{$g['varetc_path']}/dhclient_{$vipif}.conf", "w");
1924
	if ($fd) {
1925
		$dhclientconf = "";
1926

    
1927
		$dhclientconf .= <<<EOD
1928
interface "{$vipif}" {
1929
timeout 60;
1930
retry 1;
1931
select-timeout 0;
1932
initial-interval 1;
1933
script "/sbin/dhclient-script";
1934
}
1935

    
1936
EOD;
1937

    
1938
		fwrite($fd, $dhclientconf);
1939
		fclose($fd);
1940

    
1941
		/* fire up dhclient */
1942
		mwexec("/sbin/dhclient -c {$g['varetc_path']}/dhclient_{$vipif}.conf {$vipif} >{$g['tmp_path']}/{$vipif}_output 2>{$g['tmp_path']}/{$vipif}_error_output", false);
1943
	} else {
1944
		log_error("Error: cannot open dhclient_{$vipif}.conf in interfaces_carpdev_configure() for writing.\n");
1945
		mwexec("/sbin/dhclient -b {$vipif}");
1946
	}
1947

    
1948
	return $vipif;
1949
}
1950

    
1951
function interface_wireless_clone($realif, $wlcfg) {
1952
	global $config, $g;
1953
	/*   Check to see if interface has been cloned as of yet.  
1954
	 *   If it has not been cloned then go ahead and clone it.
1955
	 */
1956
	$needs_clone = false;
1957
	if(is_array($wlcfg['wireless']))
1958
		$wlcfg_mode = $wlcfg['wireless']['mode'];
1959
	else
1960
		$wlcfg_mode = $wlcfg['mode'];
1961
	switch($wlcfg_mode) {
1962
		 case "hostap":
1963
			$mode = "wlanmode hostap";
1964
			break;
1965
		 case "adhoc":
1966
			$mode = "wlanmode adhoc";
1967
			break;
1968
		 default:
1969
			$mode = "";
1970
			break;
1971
	}
1972
	$baseif = interface_get_wireless_base($wlcfg['if']);
1973
	if(does_interface_exist($realif)) {
1974
		exec("/sbin/ifconfig {$realif}", $output, $ret);
1975
		$ifconfig_str = implode($output);
1976
		if(($wlcfg_mode == "hostap") && (! preg_match("/hostap/si", $ifconfig_str))) {
1977
			log_error("Interface {$realif} changed to hostap mode");
1978
			$needs_clone = true;
1979
		}
1980
		if(($wlcfg_mode == "adhoc") && (! preg_match("/adhoc/si", $ifconfig_str))) {
1981
			log_error("Interface {$realif} changed to adhoc mode");
1982
			$needs_clone = true;
1983
		}
1984
		if(($wlcfg_mode == "bss") && (preg_match("/hostap|adhoc/si", $ifconfig_str))) {
1985
			log_error("Interface {$realif} changed to infrastructure mode");
1986
			$needs_clone = true;
1987
		}
1988
	} else {
1989
		$needs_clone = true;
1990
	}
1991

    
1992
	if($needs_clone == true) {
1993
		/* remove previous instance if it exists */
1994
		if(does_interface_exist($realif))
1995
			pfSense_interface_destroy($realif);
1996

    
1997
		log_error("Cloning new wireless interface {$realif}");
1998
		// Create the new wlan interface. FreeBSD returns the new interface name.
1999
		// example:  wlan2
2000
		exec("/sbin/ifconfig wlan create wlandev {$baseif} {$mode} bssid 2>&1", $out, $ret);
2001
		if($ret <> 0) {
2002
			log_error("Failed to clone interface {$baseif} with error code {$ret}, output {$out[0]}");
2003
			return false;
2004
		}
2005
		$newif = trim($out[0]);
2006
		// Rename the interface to {$parentnic}_wlan{$number}#: EX: ath0_wlan0
2007
		pfSense_interface_rename($newif, $realif);
2008
		// FIXME: not sure what ngctl is for. Doesn't work.
2009
		// mwexec("/usr/sbin/ngctl name {$newif}: {$realif}", false);
2010
		file_put_contents("{$g['tmp_path']}/{$realif}_oldmac", get_interface_mac($realif));
2011
	}
2012
	return true;
2013
}
2014

    
2015
function interface_sync_wireless_clones(&$ifcfg, $sync_changes = false) {
2016
	global $config, $g;
2017

    
2018
	$shared_settings = array('standard', 'turbo', 'protmode', 'txpower', 'channel',
2019
	                         'diversity', 'txantenna', 'rxantenna', 'distance',
2020
	                         'regdomain', 'regcountry', 'reglocation');
2021

    
2022
	if(!is_interface_wireless($ifcfg['if']))
2023
		return;
2024

    
2025
	$baseif = interface_get_wireless_base($ifcfg['if']);
2026

    
2027
	// Sync shared settings for assigned clones
2028
	$iflist = get_configured_interface_list(false, true);
2029
	foreach ($iflist as $if) {
2030
		if ($baseif == interface_get_wireless_base($config['interfaces'][$if]['if']) && $ifcfg['if'] != $config['interfaces'][$if]['if']) {
2031
			if (isset($config['interfaces'][$if]['wireless']['standard']) || $sync_changes) {
2032
				foreach ($shared_settings as $setting) {
2033
					if ($sync_changes) {
2034
						if (isset($ifcfg['wireless'][$setting]))
2035
							$config['interfaces'][$if]['wireless'][$setting] = $ifcfg['wireless'][$setting];
2036
						else if (isset($config['interfaces'][$if]['wireless'][$setting]))
2037
							unset($config['interfaces'][$if]['wireless'][$setting]);
2038
					} else {
2039
						if (isset($config['interfaces'][$if]['wireless'][$setting]))
2040
							$ifcfg['wireless'][$setting] = $config['interfaces'][$if]['wireless'][$setting];
2041
						else if (isset($ifcfg['wireless'][$setting]))
2042
							unset($ifcfg['wireless'][$setting]);
2043
					}
2044
				}
2045
				if (!$sync_changes)
2046
					break;
2047
			}
2048
		}
2049
	}
2050

    
2051
	// Read or write settings at shared area
2052
	if (isset($config['wireless']['interfaces'][$baseif])) {
2053
		foreach ($shared_settings as $setting) {
2054
			if ($sync_changes) {
2055
				if (isset($ifcfg['wireless'][$setting]))
2056
					$config['wireless']['interfaces'][$baseif][$setting] = $ifcfg['wireless'][$setting];
2057
				else if (isset($config['wireless']['interfaces'][$baseif][$setting]))
2058
					unset($config['wireless']['interfaces'][$baseif][$setting]);
2059
			} else if (isset($config['wireless']['interfaces'][$baseif][$setting])) {
2060
				if (isset($config['wireless']['interfaces'][$baseif][$setting]))
2061
					$ifcfg['wireless'][$setting] = $config['wireless']['interfaces'][$baseif][$setting];
2062
				else if (isset($ifcfg['wireless'][$setting]))
2063
					unset($ifcfg['wireless'][$setting]);
2064
			}
2065
		}
2066
	}
2067

    
2068
	// Sync the mode on the clone creation page with the configured mode on the interface
2069
	if (interface_is_wireless_clone($ifcfg['if'])) {
2070
		foreach ($config['wireless']['clone'] as &$clone) {
2071
			if ($clone['cloneif'] == $ifcfg['if']) {
2072
				if ($sync_changes) {
2073
					$clone['mode'] = $ifcfg['wireless']['mode'];
2074
				} else {
2075
					$ifcfg['wireless']['mode'] = $clone['mode'];
2076
				}
2077
				break;
2078
			}
2079
		}
2080
		unset($clone);
2081
	}
2082
}
2083

    
2084
function interface_wireless_configure($if, &$wl, &$wlcfg) {
2085
	global $config, $g;
2086

    
2087
	/*    open up a shell script that will be used to output the commands.
2088
	 *    since wireless is changing a lot, these series of commands are fragile
2089
     *    and will sometimes need to be verified by a operator by executing the command
2090
     *    and returning the output of the command to the developers for inspection.  please
2091
     *    do not change this routine from a shell script to individul exec commands.  -sullrich
2092
	 */
2093

    
2094
	// Remove script file
2095
	unlink_if_exists("{$g['tmp_path']}/{$if}_setup.sh");
2096

    
2097
	// Clone wireless nic if needed.
2098
	interface_wireless_clone($if, $wl);
2099

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

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

    
2107
	/* set values for /path/program */
2108
	$hostapd = "/usr/sbin/hostapd";
2109
	$wpa_supplicant = "/usr/sbin/wpa_supplicant";
2110
	$ifconfig = "/sbin/ifconfig";
2111
	$sysctl = "/sbin/sysctl";
2112
	$killall = "/usr/bin/killall";
2113

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

    
2116
	$wlcmd = array();
2117
	$wl_sysctl = array();
2118
	/* Make sure it's up */
2119
	$wlcmd[] = "up";
2120
	/* Set a/b/g standard */
2121
	$standard = str_replace(" Turbo", "", $wlcfg['standard']);
2122
	$wlcmd[] = "mode " . escapeshellarg($standard);
2123

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

    
2129
	/* Set ssid */
2130
	if($wlcfg['ssid'])
2131
		$wlcmd[] = "ssid " .escapeshellarg($wlcfg['ssid']);
2132

    
2133
	/* Set 802.11g protection mode */
2134
	$wlcmd[] = "protmode " . escapeshellarg($wlcfg['protmode']);
2135

    
2136
	/* set wireless channel value */
2137
	if(isset($wlcfg['channel'])) {
2138
		if($wlcfg['channel'] == "0") {
2139
			$wlcmd[] = "channel any";
2140
		} else {
2141
			$wlcmd[] = "channel " . escapeshellarg($wlcfg['channel']);
2142
		}
2143
	}
2144

    
2145
	/* Set antenna diversity value */
2146
	if(isset($wlcfg['diversity']))
2147
		$wl_sysctl[] = "diversity=" . escapeshellarg($wlcfg['diversity']);
2148

    
2149
	/* Set txantenna value */
2150
	if(isset($wlcfg['txantenna']))
2151
		$wl_sysctl[] = "txantenna=" . escapeshellarg($wlcfg['txantenna']);
2152

    
2153
	/* Set rxantenna value */
2154
	if(isset($wlcfg['rxantenna']))
2155
		$wl_sysctl[] = "rxantenna=" . escapeshellarg($wlcfg['rxantenna']);
2156

    
2157
	/* set Distance value */
2158
	if($wlcfg['distance'])
2159
		$distance = escapeshellarg($wlcfg['distance']);
2160

    
2161
	/* Set wireless hostap mode */
2162
	if ($wlcfg['mode'] == "hostap") {
2163
		$wlcmd[] = "mediaopt hostap";
2164
	} else {
2165
		$wlcmd[] = "-mediaopt hostap";
2166
	}
2167

    
2168
	/* Set wireless adhoc mode */
2169
	if ($wlcfg['mode'] == "adhoc") {
2170
		$wlcmd[] = "mediaopt adhoc";
2171
	} else {
2172
		$wlcmd[] = "-mediaopt adhoc";
2173
	}
2174

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

    
2177
	/* handle hide ssid option */
2178
	if(isset($wlcfg['hidessid']['enable'])) {
2179
		$wlcmd[] = "hidessid";
2180
	} else {
2181
		$wlcmd[] = "-hidessid";
2182
	}
2183

    
2184
	/* handle pureg (802.11g) only option */
2185
	if(isset($wlcfg['pureg']['enable'])) {
2186
		$wlcmd[] = "mode 11g pureg";
2187
	} else {
2188
		$wlcmd[] = "-pureg";
2189
	}
2190

    
2191
	/* handle puren (802.11n) only option */
2192
	if(isset($wlcfg['puren']['enable'])) {
2193
		$wlcmd[] = "puren";
2194
	} else {
2195
		$wlcmd[] = "-puren";
2196
	}
2197

    
2198
	/* enable apbridge option */
2199
	if(isset($wlcfg['apbridge']['enable'])) {
2200
		$wlcmd[] = "apbridge";
2201
	} else {
2202
		$wlcmd[] = "-apbridge";
2203
	}
2204

    
2205
	/* handle turbo option */
2206
	if(isset($wlcfg['turbo']['enable'])) {
2207
		$wlcmd[] = "mediaopt turbo";
2208
	} else {
2209
		$wlcmd[] = "-mediaopt turbo";
2210
	}
2211

    
2212
	/* handle txpower setting */
2213
	/* if($wlcfg['txpower'] <> "")
2214
		$wlcmd[] = "txpower " . escapeshellarg($wlcfg['txpower']);
2215
	*/
2216
	/* handle wme option */
2217
	if(isset($wlcfg['wme']['enable'])) {
2218
		$wlcmd[] = "wme";
2219
	} else {
2220
		$wlcmd[] = "-wme";
2221
	}
2222

    
2223
	/* set up wep if enabled */
2224
	$wepset = "";
2225
	if (isset($wlcfg['wep']['enable']) && is_array($wlcfg['wep']['key'])) {
2226
		switch($wlcfg['wpa']['auth_algs']) {
2227
			case "1":
2228
				$wepset .= "authmode open wepmode on ";
2229
				break;
2230
			case "2":
2231
				$wepset .= "authmode shared wepmode on ";
2232
				break;
2233
			case "3":
2234
				$wepset .= "authmode mixed wepmode on ";
2235
		}
2236
		$i = 1;
2237
		foreach ($wlcfg['wep']['key'] as $wepkey) {
2238
			$wepset .= "wepkey " . escapeshellarg("{$i}:{$wepkey['value']}") . " ";
2239
			if (isset($wepkey['txkey'])) {
2240
				$wlcmd[] = "weptxkey {$i} ";
2241
			}
2242
			$i++;
2243
		}
2244
		$wlcmd[] = $wepset;
2245
	} else {
2246
		$wlcmd[] = "authmode open wepmode off ";
2247
	}
2248

    
2249
	mwexec(kill_hostapd("{$if}"));
2250
	mwexec(kill_wpasupplicant("{$if}"));
2251

    
2252
	/* generate wpa_supplicant/hostap config if wpa is enabled */
2253
	conf_mount_rw();
2254

    
2255
	switch ($wlcfg['mode']) {
2256
		case 'bss':
2257
			if (isset($wlcfg['wpa']['enable'])) {
2258
				$wpa .= <<<EOD
2259
ctrl_interface={$g['varrun_path']}/wpa_supplicant
2260
ctrl_interface_group=0
2261
ap_scan=1
2262
#fast_reauth=1
2263
network={
2264
ssid="{$wlcfg['ssid']}"
2265
scan_ssid=1
2266
priority=5
2267
key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
2268
psk="{$wlcfg['wpa']['passphrase']}"
2269
pairwise={$wlcfg['wpa']['wpa_pairwise']}
2270
group={$wlcfg['wpa']['wpa_pairwise']}
2271
}
2272
EOD;
2273

    
2274
				$fd = fopen("{$g['varetc_path']}/wpa_supplicant_{$if}.conf", "w");
2275
				fwrite($fd, "{$wpa}");
2276
				fclose($fd);
2277
			}
2278
			break;
2279
		case 'hostap':
2280
			if($wlcfg['wpa']['passphrase']) 
2281
				$wpa_passphrase = "wpa_passphrase={$wlcfg['wpa']['passphrase']}\n";
2282
			else 
2283
				$wpa_passphrase = "";
2284
			if (isset($wlcfg['wpa']['enable'])) {
2285
				$wpa .= <<<EOD
2286
interface={$if}
2287
driver=bsd
2288
logger_syslog=-1
2289
logger_syslog_level=0
2290
logger_stdout=-1
2291
logger_stdout_level=0
2292
dump_file={$g['tmp_path']}/hostapd_{$if}.dump
2293
ctrl_interface={$g['varrun_path']}/hostapd
2294
ctrl_interface_group=wheel
2295
#accept_mac_file={$g['tmp_path']}/hostapd_{$if}.accept
2296
#deny_mac_file={$g['tmp_path']}/hostapd_{$if}.deny
2297
#macaddr_acl={$wlcfg['wpa']['macaddr_acl']}
2298
ssid={$wlcfg['ssid']}
2299
debug={$wlcfg['wpa']['debug_mode']}
2300
auth_algs={$wlcfg['wpa']['auth_algs']}
2301
wpa={$wlcfg['wpa']['wpa_mode']}
2302
wpa_key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
2303
wpa_pairwise={$wlcfg['wpa']['wpa_pairwise']}
2304
wpa_group_rekey={$wlcfg['wpa']['wpa_group_rekey']}
2305
wpa_gmk_rekey={$wlcfg['wpa']['wpa_gmk_rekey']}
2306
wpa_strict_rekey={$wlcfg['wpa']['wpa_strict_rekey']}
2307
{$wpa_passphrase}
2308

    
2309
EOD;
2310

    
2311
if (isset($wlcfg['wpa']['rsn_preauth'])) {
2312
	$wpa .= <<<EOD
2313
# Enable the next lines for preauth when roaming. Interface = wired or wireless interface talking to the AP you want to roam from/to
2314
rsn_preauth=1
2315
rsn_preauth_interfaces={$if}
2316

    
2317
EOD;
2318

    
2319
}
2320
				if($wlcfg['auth_server_addr'] && $wlcfg['auth_server_shared_secret']) {
2321
					$auth_server_port = "1812";
2322
					if($wlcfg['auth_server_port']) 
2323
						$auth_server_port = $wlcfg['auth_server_port'];
2324
					$wpa .= <<<EOD
2325

    
2326
ieee8021x=1
2327
auth_server_addr={$wlcfg['auth_server_addr']}
2328
auth_server_port={$auth_server_port}
2329
auth_server_shared_secret={$wlcfg['auth_server_shared_secret']}
2330

    
2331
EOD;
2332
				} else {
2333
					$wpa .= "ieee8021x={$wlcfg['wpa']['ieee8021x']}\n";
2334
				}
2335

    
2336
				$fd = fopen("{$g['varetc_path']}/hostapd_{$if}.conf", "w");
2337
				fwrite($fd, "{$wpa}");
2338
				fclose($fd);
2339

    
2340
			}
2341
			break;
2342
	}
2343

    
2344
	/*
2345
	 *    all variables are set, lets start up everything
2346
	 */
2347

    
2348
	$baseif = interface_get_wireless_base($if);
2349
	preg_match("/^(.*?)([0-9]*)$/", $baseif, $baseif_split);
2350
	$wl_sysctl_prefix = 'dev.' . $baseif_split[1] . '.' . $baseif_split[2];
2351

    
2352
	/* set sysctls for the wireless interface */
2353
	if (!empty($wl_sysctl)) {
2354
		fwrite($fd_set, "# sysctls for {$baseif}\n");
2355
		foreach ($wl_sysctl as $wl_sysctl_line) {
2356
			fwrite($fd_set, "{$sysctl} {$wl_sysctl_prefix}.{$wl_sysctl_line}\n");
2357
		}
2358
	}
2359

    
2360
	/* set ack timers according to users preference (if he/she has any) */
2361
	if($distance) {
2362
		fwrite($fd_set, "# Enable ATH distance settings\n");
2363
		fwrite($fd_set, "/sbin/athctrl.sh -i {$baseif} -d {$distance}\n");
2364
	}
2365

    
2366
	if (isset($wlcfg['wpa']['enable'])) {
2367
		if ($wlcfg['mode'] == "bss") {
2368
			fwrite($fd_set, "{$wpa_supplicant} -B -i {$if} -c {$g['varetc_path']}/wpa_supplicant_{$if}.conf\n");
2369
		}
2370
		if ($wlcfg['mode'] == "hostap") {
2371
			/* add line to script to restore old mac to make hostapd happy */
2372
			if (file_exists("{$g['tmp_path']}/{$if}_oldmac")) {
2373
				$if_oldmac = file_get_contents("{$g['tmp_path']}/{$if}_oldmac");
2374
				if (is_macaddr($if_oldmac))
2375
					fwrite($fd_set, "{$ifconfig} " . escapeshellarg($if) .
2376
						" link " . escapeshellarg($if_oldmac) . "\n");
2377
			}
2378

    
2379
			fwrite($fd_set, "{$hostapd} -B {$g['varetc_path']}/hostapd_{$if}.conf\n");
2380

    
2381
			/* add line to script to restore spoofed mac after running hostapd */
2382
			if (file_exists("{$g['tmp_path']}/{$if}_oldmac")) {
2383
				if ($wl['spoofmac'])
2384
					$if_curmac = $wl['spoofmac'];
2385
				else
2386
					$if_curmac = get_interface_mac($if);
2387
				if (is_macaddr($if_curmac))
2388
					fwrite($fd_set, "{$ifconfig} " . escapeshellarg($if) .
2389
						" link " . escapeshellarg($if_curmac) . "\n");
2390
			}
2391
		}
2392
	}
2393

    
2394
	fclose($fd_set);
2395
	conf_mount_ro();
2396

    
2397
	/* Making sure regulatory settings have actually changed
2398
	 * before applying, because changing them requires bringing
2399
	 * down all wireless networks on the interface. */
2400
	exec("{$ifconfig} " . escapeshellarg($if), $output);
2401
	$ifconfig_str = implode($output);
2402
	unset($output);
2403
	$reg_changing = false;
2404

    
2405
	/* special case for the debug country code */
2406
	if ($wlcfg['regcountry'] == 'DEBUG' && !preg_match("/\sregdomain\s+DEBUG\s/si", $ifconfig_str))
2407
		$reg_changing = true;
2408
	else if ($wlcfg['regdomain'] && !preg_match("/\sregdomain\s+{$wlcfg['regdomain']}\s/si", $ifconfig_str))
2409
		$reg_changing = true;
2410
	else if ($wlcfg['regcountry'] && !preg_match("/\scountry\s+{$wlcfg['regcountry']}\s/si", $ifconfig_str))
2411
		$reg_changing = true;
2412
	else if ($wlcfg['reglocation'] == 'anywhere' && preg_match("/\s(indoor|outdoor)\s/si", $ifconfig_str))
2413
		$reg_changing = true;
2414
	else if ($wlcfg['reglocation'] && $wlcfg['reglocation'] != 'anywhere' && !preg_match("/\s{$wlcfg['reglocation']}\s/si", $ifconfig_str))
2415
		$reg_changing = true;
2416

    
2417
	if ($reg_changing) {
2418
		/* set regulatory domain */
2419
		if($wlcfg['regdomain'])
2420
			$wlregcmd[] = "regdomain " . escapeshellarg($wlcfg['regdomain']);
2421

    
2422
		/* set country */
2423
		if($wlcfg['regcountry'])
2424
			$wlregcmd[] = "country " . escapeshellarg($wlcfg['regcountry']);
2425

    
2426
		/* set location */
2427
		if($wlcfg['reglocation'])
2428
			$wlregcmd[] = escapeshellarg($wlcfg['reglocation']);
2429

    
2430
		$wlregcmd_args = implode(" ", $wlregcmd);
2431

    
2432
		/* build a complete list of the wireless clones for this interface */
2433
		$clone_list = array();
2434
		if (does_interface_exist(interface_get_wireless_clone($baseif)))
2435
			$clone_list[] = interface_get_wireless_clone($baseif);
2436
		if (is_array($config['wireless']['clone'])) {
2437
			foreach ($config['wireless']['clone'] as $clone) {
2438
				if ($clone['if'] == $baseif)
2439
					$clone_list[] = $clone['cloneif'];
2440
			}
2441
		}
2442

    
2443
		/* find which clones are up and bring them down */
2444
		$clones_up = array();
2445
		foreach ($clone_list as $clone_if) {
2446
			$clone_status = pfSense_get_interface_addresses($clone_if);
2447
			if ($clone_status['status'] == 'up') {
2448
				$clones_up[] = $clone_if;
2449
				mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " down");
2450
			}
2451
		}
2452

    
2453
		/* apply the regulatory settings */
2454
		mwexec("{$ifconfig} " . escapeshellarg($if) . " {$wlregcmd_args}");
2455

    
2456
		/* bring the clones back up that were previously up */
2457
		foreach ($clones_up as $clone_if) {
2458
			mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " up");
2459

    
2460
			/*
2461
			 * Rerun the setup script for the interface if it isn't this interface, the interface
2462
			 * is in infrastructure mode, and WPA is enabled.
2463
			 * This can be removed if wpa_supplicant stops dying when you bring the interface down.
2464
			 */
2465
			if ($clone_if != $if) {
2466
				$friendly_if = convert_real_interface_to_friendly_interface_name($clone_if);
2467
				if ( !empty($friendly_if)
2468
				    && $config['interfaces'][$friendly_if]['wireless']['mode'] == "bss"
2469
				    && isset($config['interfaces'][$friendly_if]['wireless']['wpa']['enable']) ) {
2470
					mwexec("/bin/sh {$g['tmp_path']}/{$clone_if}_setup.sh");
2471
				}
2472
			}
2473
		}
2474
	}
2475

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

    
2480
	/* configure wireless */
2481
	$wlcmd_args = implode(" ", $wlcmd);
2482
	mwexec("/sbin/ifconfig {$if} $wlcmd_args", false);
2483

    
2484
	
2485
	sleep(1);
2486
	/* execute hostapd and wpa_supplicant if required in shell */
2487
	mwexec("/bin/sh {$g['tmp_path']}/{$if}_setup.sh");
2488

    
2489
	return 0;
2490

    
2491
}
2492

    
2493
function kill_hostapd($interface) {
2494
	return "/bin/pkill -f \"hostapd .*{$interface}\"\n";
2495
}
2496

    
2497
function kill_wpasupplicant($interface) {
2498
	return "/bin/pkill -f \"wpa_supplicant .*{$interface}\"\n";
2499
}
2500

    
2501
function find_dhclient_process($interface) {
2502
	if ($interface)
2503
		$pid = `/bin/pgrep -axf "dhclient: {$interface}"`;
2504
	else
2505
		$pid = 0;
2506

    
2507
	return intval($pid);
2508
}
2509

    
2510
function interface_configure($interface = "wan", $reloadall = false, $linkupevent = false) {
2511
	global $config, $g;
2512
	global $interface_sn_arr_cache, $interface_ip_arr_cache;
2513

    
2514
	$wancfg = $config['interfaces'][$interface];
2515

    
2516
	$realif = get_real_interface($interface);
2517
	$realhwif_array = get_parent_interface($interface);
2518
	// Need code to handle MLPPP if we ever use $realhwif for MLPPP handling
2519
	$realhwif = $realhwif_array[0];
2520

    
2521
			
2522
	if (!$g['booting'] && !substr($realif, 0, 4) == "ovpn") {
2523
		/* remove all IPv4 addresses */
2524
		while (mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " -alias", true) == 0);
2525

    
2526
		switch ($wancfg['ipaddr']) {
2527
			case 'pppoe':
2528
			case 'l2tp':
2529
			case 'pptp':
2530
			case 'ppp':
2531
				break;
2532
			default:
2533
				interface_bring_down($interface);
2534
				break;
2535
		}
2536
	}
2537

    
2538
	/* wireless configuration? */
2539
	if (is_array($wancfg['wireless']))
2540
		interface_wireless_configure($realif, $wancfg, $wancfg['wireless']);
2541

    
2542
	if ($wancfg['spoofmac']) {
2543
		mwexec("/sbin/ifconfig " . escapeshellarg($realhwif) .
2544
			" link " . escapeshellarg($wancfg['spoofmac']));
2545

    
2546
                /*
2547
                 * All vlans need to spoof their parent mac address, too.  see
2548
                 * ticket #1514: http://cvstrac.pfsense.com/tktview?tn=1514,33
2549
                 */
2550
                if (is_array($config['vlans']['vlan'])) {
2551
                        foreach ($config['vlans']['vlan'] as $vlan) {
2552
                                if ($vlan['if'] == $realhwif)
2553
                                        mwexec("/sbin/ifconfig " . escapeshellarg($vlan['vlanif']) .
2554
                                                " link " . escapeshellarg($wancfg['spoofmac']));
2555
                        }
2556
                }
2557
	}  else {
2558
		$mac = get_interface_mac($realhwif);
2559
		if ($mac == "ff:ff:ff:ff:ff:ff") {
2560
			/*   this is not a valid mac address.  generate a
2561
			 *   temporary mac address so the machine can get online.
2562
			 */
2563
			echo "Generating new MAC address.";
2564
			$random_mac = generate_random_mac_address();
2565
			mwexec("/sbin/ifconfig " . escapeshellarg($realhwif) .
2566
				" link " . escapeshellarg($random_mac));
2567
			$wancfg['spoofmac'] = $random_mac;
2568
			write_config();
2569
			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");
2570
		}
2571
	}
2572

    
2573
	/* media */
2574
	if ($wancfg['media'] || $wancfg['mediaopt']) {
2575
		$cmd = "/sbin/ifconfig " . escapeshellarg($realhwif);
2576
		if ($wancfg['media'])
2577
			$cmd .= " media " . escapeshellarg($wancfg['media']);
2578
		if ($wancfg['mediaopt'])
2579
			$cmd .= " mediaopt " . escapeshellarg($wancfg['mediaopt']);
2580
		mwexec($cmd);
2581
	}
2582
	if (!empty($wancfg['mtu']))
2583
		pfSense_interface_mtu($realhwif, $wancfg['mtu']);
2584
	else {
2585
		$mtu = get_interface_default_mtu(remove_numbers($realhwif));
2586
		if ($mtu != get_interface_mtu($realhwif))
2587
			pfSense_interface_mtu($realhwif, $mtu);
2588
	}
2589

    
2590
	$options = pfSense_get_interface_addresses($realhwif);
2591
	if (is_array($options) && isset($options['caps']['polling'])) {
2592
		if (isset($config['system']['polling']))
2593
			pfSense_interface_capabilities($realif, IFCAP_POLLING);
2594
		else
2595
			pfSense_interface_capabilities($realif, -IFCAP_POLLING);
2596
	}
2597

    
2598
	/* skip vlans for checksumming and polling */
2599
        if (!stristr($realhwif, "vlan") && is_array($options)) {
2600
		$flags = 0;
2601
		if(isset($config['system']['disablechecksumoffloading'])) {
2602
			if (isset($options['encaps']['txcsum']))
2603
				$flags |= IFCAP_TXCSUM;
2604
			if (isset($options['encaps']['rxcsum']))
2605
				$flags |= IFCAP_RXCSUM;
2606
        	} else {
2607
 			if (!isset($options['caps']['txcsum']))
2608
				$flags |= IFCAP_TXCSUM;
2609
			if (!isset($options['caps']['rxcsum']))
2610
				$flags |= IFCAP_RXCSUM;
2611
        	}
2612

    
2613
        	if(isset($config['system']['disablesegmentationoffloading'])) {
2614
                	if (isset($options['encaps']['tso4']))
2615
				$flags |= IFCAP_TSO;
2616
                	if (isset($options['encaps']['tso6']))
2617
				$flags |= IFCAP_TSO;
2618
        	} else {
2619
                	if (!isset($options['caps']['tso4']))
2620
				$flags |= IFCAP_TSO;
2621
                	if (!isset($options['caps']['tso6']))
2622
				$flags |= IFCAP_TSO;
2623
        	}
2624

    
2625
        	if(isset($config['system']['disablelargereceiveoffloading'])) {
2626
                	if (isset($options['encaps']['lro']))
2627
				$flags |= IFCAP_LRO;
2628
        	} else {
2629
                	if (!isset($options['caps']['lro']))
2630
				$flags |= IFCAP_LRO;
2631
        	}
2632

    
2633
        	/* if the NIC supports polling *AND* it is enabled in the GUI */
2634
        	if (!isset($config['system']['polling']) || !isset($options['caps']['polling'])) {
2635
			$flags |= IFCAP_POLLING;
2636
		}
2637
               	pfSense_interface_capabilities($realhwif, -$flags);
2638
	}
2639

    
2640
	/* invalidate interface/ip/sn cache */
2641
	get_interface_arr(true);
2642
	unset($interface_ip_arr_cache[$realif]);
2643
	unset($interface_sn_arr_cache[$realif]);
2644

    
2645
	switch ($wancfg['ipaddr']) {
2646
		case 'carpdev-dhcp':
2647
			interface_carpdev_dhcp_configure($interface);
2648
			break;
2649
		case 'dhcp':
2650
			interface_dhcp_configure($interface);
2651
			break;
2652
		case 'pppoe':
2653
		case 'l2tp':
2654
		case 'pptp':
2655
		case 'ppp':
2656
			interface_ppps_configure($interface);
2657
			break;
2658
		default:
2659
			if ($wancfg['ipaddr'] <> "" && $wancfg['subnet'] <> "") {
2660
				pfSense_interface_setaddress($realif, "{$wancfg['ipaddr']}/{$wancfg['subnet']}");
2661
			} else if (substr($realif, 0, 3) == "gre") {
2662
				if (is_array($config['gres']['gre'])) {
2663
					foreach ($config['gres']['gre'] as $gre)
2664
						if ($gre['greif'] == $realif)
2665
							interface_gre_configure($gre);
2666
				}
2667
			} else if (substr($realif, 0, 3) == "gif") {
2668
				 if (is_array($config['gifs']['gif'])) {
2669
					foreach ($config['gifs']['gif'] as $gif)
2670
						if($gif['gifif'] == $realif)
2671
							interface_gif_configure($gif);
2672
				}
2673
			} else if (substr($realif, 0, 4) == "ovpn") {
2674
				/* XXX: Should be done anything?! */
2675
			}
2676
			break;
2677
	}
2678

    
2679
	if(does_interface_exist($wancfg['if']))
2680
		interfaces_bring_up($wancfg['if']);
2681

    
2682
	interface_netgraph_needed($interface);
2683
 	
2684
	if (!$g['booting']) {
2685
		link_interface_to_vips($interface, "update");
2686

    
2687
		unset($gre);
2688
		$gre = link_interface_to_gre($interface);
2689
		if (!empty($gre))
2690
			array_walk($gre, 'interface_gre_configure');
2691

    
2692
		unset($gif);
2693
		$gif = link_interface_to_gif($interface);
2694
		if (!empty($gif))
2695
                       	array_walk($gif, 'interface_gif_configure');
2696

    
2697
		if ($linkupevent == false) {
2698
			unset($bridgetmp);
2699
			$bridgetmp = link_interface_to_bridge($interface);
2700
			if (!empty($bridgetmp))
2701
				interface_bridge_add_member($bridgetmp, $realif);
2702
		}
2703

    
2704
		$grouptmp = link_interface_to_group($interface);
2705
		if (!empty($grouptmp))
2706
			array_walk($grouptmp, 'interface_group_add_member');
2707

    
2708
		if ($interface == "lan")
2709
			/* make new hosts file */
2710
			system_hosts_generate();
2711

    
2712
		if ($reloadall == true) {
2713

    
2714
			/* reconfigure static routes (kernel may have deleted them) */
2715
			system_routing_configure($interface);
2716

    
2717
			/* reload ipsec tunnels */
2718
			vpn_ipsec_configure();
2719

    
2720
			/* restart dnsmasq */
2721
			services_dnsmasq_configure();
2722

    
2723
			/* update dyndns */
2724
			send_event("service reload dyndns {$interface}");
2725

    
2726
			/* reload captive portal */
2727
			captiveportal_init_rules();
2728
		}
2729
	}
2730

    
2731
	return 0;
2732
}
2733

    
2734
function interface_carpdev_dhcp_configure($interface = "wan") {
2735
	global $config, $g;
2736

    
2737
	$wancfg = $config['interfaces'][$interface];
2738
	$wanif = $wancfg['if'];
2739
	/* bring wan interface up before starting dhclient */
2740
	if($wanif)
2741
		interfaces_bring_up($wanif);
2742
	else 
2743
		log_error("Could not bring wanif up in terface_carpdev_dhcp_configure()");
2744

    
2745
	return 0;
2746
}
2747

    
2748
function interface_dhcp_configure($interface = "wan") {
2749
	global $config, $g;
2750

    
2751
	$wancfg = $config['interfaces'][$interface];
2752
	if (empty($wancfg))
2753
		$wancfg = array();
2754

    
2755
	/* generate dhclient_wan.conf */
2756
	$fd = fopen("{$g['varetc_path']}/dhclient_{$interface}.conf", "w");
2757
	if (!$fd) {
2758
		printf("Error: cannot open dhclient_{$interface}.conf in interfaces_wan_dhcp_configure() for writing.\n");
2759
		return 1;
2760
	}
2761

    
2762
	if ($wancfg['dhcphostname']) {
2763
		$dhclientconf_hostname = "send dhcp-client-identifier \"{$wancfg['dhcphostname']}\";\n";
2764
		$dhclientconf_hostname .= "\tsend host-name \"{$wancfg['dhcphostname']}\";\n";
2765
	} else {
2766
		$dhclientconf_hostname = "";
2767
	}
2768

    
2769
	$wanif = get_real_interface($interface);
2770
	if (empty($wanif)) {
2771
		log_error("Invalid interface \"{$interface}\" in interface_dhcp_configure()");
2772
		return 0;
2773
	}
2774
 	$dhclientconf = "";
2775
	
2776
	$dhclientconf .= <<<EOD
2777
interface "{$wanif}" {
2778
timeout 60;
2779
retry 1;
2780
select-timeout 0;
2781
initial-interval 1;
2782
	{$dhclientconf_hostname}
2783
	script "/sbin/dhclient-script";
2784
}
2785

    
2786
EOD;
2787

    
2788
if(is_ipaddr($wancfg['alias-address'])) {
2789
	$subnetmask = gen_subnet_mask($wancfg['alias-subnet']);
2790
	$dhclientconf .= <<<EOD
2791
alias {
2792
	interface  "{$wanif}";
2793
	fixed-address {$wancfg['alias-address']};
2794
	option subnet-mask {$subnetmask};
2795
}
2796

    
2797
EOD;
2798
}
2799
	fwrite($fd, $dhclientconf);
2800
	fclose($fd);
2801

    
2802
	/* bring wan interface up before starting dhclient */
2803
	if($wanif)
2804
		interfaces_bring_up($wanif);
2805
	else 
2806
		log_error("Could not bring up {$wanif} interface in interface_dhcp_configure()");
2807

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

    
2811
	return 0;
2812
}
2813

    
2814
function interfaces_group_setup() {
2815
	global $config;
2816

    
2817
	if (!is_array($config['ifgroups']['ifgroupentry']))
2818
		return;
2819

    
2820
	foreach ($config['ifgroups']['ifgroupentry'] as $groupar)
2821
		interface_group_setup($groupar);
2822

    
2823
	return;
2824
}
2825

    
2826
function interface_group_setup(&$groupname /* The parameter is an array */) {
2827
	global $config;
2828

    
2829
	if (!is_array($groupname))
2830
		return;
2831
	$members = explode(" ", $groupname['members']);
2832
	foreach($members as $ifs) {
2833
		$realif = get_real_interface($ifs);
2834
		if ($realif)
2835
			mwexec("/sbin/ifconfig {$realif} group {$groupname['ifname']}");
2836
	}
2837

    
2838
	return;
2839
}
2840

    
2841
function interface_group_add_member($interface, $groupname) {
2842
	$interface = get_real_interface($interface);
2843
	mwexec("/sbin/ifconfig {$interface} group {$groupname}", true);
2844
}
2845
 
2846
/* COMPAT Function */
2847
function convert_friendly_interface_to_real_interface_name($interface) {
2848
	return get_real_interface($interface);
2849
}
2850

    
2851
/* COMPAT Function */
2852
function get_real_wan_interface($interface = "wan") {
2853
	return get_real_interface($interface);
2854
}
2855

    
2856
/* COMPAT Function */
2857
function get_current_wan_address($interface = "wan") {
2858
	return get_interface_ip($interface);
2859
}
2860

    
2861
/*
2862
 * convert_real_interface_to_friendly_interface_name($interface): convert fxp0 -> wan, etc.
2863
 */
2864
function convert_real_interface_to_friendly_interface_name($interface = "wan") {
2865
        global $config;
2866

    
2867
	if (stristr($interface, "vip")) {
2868
                $index = intval(substr($interface, 3));
2869
                foreach ($config['virtualip']['vip'] as $counter => $vip) {
2870
                        if ($vip['mode'] == "carpdev-dhcp" || $vip['mode'] == "carp")  {
2871
                                if ($index == $vip['vhid'])
2872
                                        return $vip['interface'];
2873
                        }
2874
                }
2875
        }
2876

    
2877
        /* XXX: For speed reasons reference directly the interface array */
2878
	$ifdescrs = &$config['interfaces'];
2879
        //$ifdescrs = get_configured_interface_list(false, true);
2880

    
2881
        foreach ($ifdescrs as $if => $ifname) {
2882
                if ($config['interfaces'][$if]['if'] == $interface)
2883
                        return $if;
2884

    
2885
                if (stristr($interface, "_wlan0") && $config['interfaces'][$if]['if'] == interface_get_wireless_base($interface))
2886
                        return $if;
2887

    
2888
		// XXX: This case doesn't work anymore (segfaults - recursion?) - should be replaced with something else or just removed.
2889
		//      Not to be replaced with get_real_interface - causes slow interface listings here because of recursion!
2890
		/*
2891
                $int = get_parent_interface($if);
2892
                if ($int[0] == $interface)
2893
                        return $ifname;
2894
		*/
2895
        }
2896
        return NULL;
2897
}
2898

    
2899
/* attempt to resolve interface to friendly descr */
2900
function convert_friendly_interface_to_friendly_descr($interface) {
2901
        global $config;
2902

    
2903
        switch ($interface) {
2904
        case "l2tp":
2905
        	$ifdesc = "L2TP";
2906
                break;
2907
	case "pptp":
2908
		$ifdesc = "PPTP";
2909
		break;
2910
	case "pppoe":
2911
		$ifdesc = "PPPoE";
2912
		break;
2913
	case "openvpn":
2914
		$ifdesc = "OpenVPN";
2915
		break;
2916
	case "enc0":
2917
	case "ipsec":
2918
		$ifdesc = "IPsec";
2919
		break;
2920
        default:
2921
                if (isset($config['interfaces'][$interface])) {
2922
                        if (empty($config['interfaces'][$interface]['descr']))
2923
                                $ifdesc = strtoupper($interface);
2924
                        else
2925
                                $ifdesc = strtoupper($config['interfaces'][$interface]['descr']);
2926
			break;
2927
		} else if (substr($interface, 0, 3) == "vip") {
2928
			if (is_array($config['virtualip']['vip'])) {
2929
				foreach ($config['virtualip']['vip'] as $counter => $vip) {
2930
					if ($vip['mode'] == "carpdev-dhcp" || $vip['mode'] == "carp")  {
2931
						if ($interface == "vip{$vip['vhid']}")
2932
							return "{$vip['subnet']} - {$vip['descr']}";
2933
					}
2934
				}
2935
                        }
2936
                } else {
2937
			/* if list */
2938
			$ifdescrs = get_configured_interface_with_descr(false, true);
2939
			foreach ($ifdescrs as $if => $ifname) {
2940
					if ($if == $interface || $ifname == $interface)
2941
						return $ifname;
2942
			}
2943
		}
2944
                break;
2945
        }
2946

    
2947
        return $ifdesc;
2948
}
2949

    
2950
function convert_real_interface_to_friendly_descr($interface) {
2951
        global $config;
2952

    
2953
        $ifdesc = convert_real_interface_to_friendly_interface_name("{$interface}");
2954

    
2955
        if ($ifdesc) {
2956
                $iflist = get_configured_interface_with_descr(false, true);
2957
                return $iflist[$ifdesc];
2958
        }
2959

    
2960
        return $interface;
2961
}
2962

    
2963
/*
2964
 *  get_parent_interface($interface):
2965
 *			--returns the (real or virtual) parent interface(s) array for a given interface friendly name (i.e. wan)
2966
 *				or virtual interface (i.e. vlan)
2967
 *				(We need array because MLPPP and bridge interfaces have more than one parent.)
2968
 *			-- returns $interface passed in if $interface parent is not found
2969
 *			-- returns empty array if an invalid interface is passed
2970
 *	(Only handles ppps and vlans now.)
2971
 */
2972
function get_parent_interface($interface) {
2973
	global $config;
2974

    
2975
	$parents = array();
2976
	//Check that we got a valid interface passed
2977
	$realif = get_real_interface($interface);
2978
	if ($realif == NULL)
2979
		return $parents;
2980

    
2981
	// If we got a real interface, find it's friendly assigned name
2982
	$interface = convert_real_interface_to_friendly_interface_name($interface);
2983
		
2984
	if (!empty($interface) && isset($config['interfaces'][$interface])) {
2985
		$ifcfg = $config['interfaces'][$interface];
2986
		switch ($ifcfg['ipaddr']) {
2987
			case "ppp":
2988
			case "pppoe":
2989
			case "pptp":
2990
			case "l2tp":
2991
				if (empty($parents))
2992
					if (is_array($config['ppps']['ppp']))
2993
						foreach ($config['ppps']['ppp'] as $pppidx => $ppp) {
2994
							if ($ppp_if == $ppp['if']) {
2995
								$ports = explode(',', $ppp['ports']);
2996
								foreach ($ports as $pid => $parent_if) 
2997
									$parents[$pid] = get_real_interface($parent_if);
2998
								break;
2999
							}
3000
						}
3001
				break;
3002
			case "dhcp":
3003
			case "static":
3004
			default:
3005
				// Handle _vlans
3006
				if (strstr($realif,"_vlan"))
3007
					if (is_array($config['vlans']['vlan'])) 
3008
						foreach ($config['vlans']['vlan'] as $vlanidx => $vlan)
3009
							if ($ifcfg['if'] == $vlan['vlanif']){
3010
								$parents[0] = $vlan['if'];
3011
								break;
3012
							}
3013
				break;
3014
		}
3015
	}
3016
	
3017
	if (empty($parents))
3018
		$parents[0] = $realif;
3019
	
3020
	return $parents;
3021
}
3022

    
3023
function interface_is_wireless_clone($wlif) {
3024
	if(!stristr($wlif, "_wlan")) {
3025
		return false;
3026
	} else {
3027
		return true;
3028
	}
3029
}
3030

    
3031
function interface_get_wireless_base($wlif) {
3032
	if(!stristr($wlif, "_wlan")) {
3033
		return $wlif;
3034
	} else {
3035
		return substr($wlif, 0, stripos($wlif, "_wlan"));
3036
	}
3037
}
3038

    
3039
function interface_get_wireless_clone($wlif) {
3040
	if(!stristr($wlif, "_wlan")) {
3041
		return $wlif . "_wlan0";
3042
	} else {
3043
		return $wlif;
3044
	}
3045
}
3046

    
3047
function get_real_interface($interface = "wan") {
3048
    global $config;
3049

    
3050
	$wanif = NULL;
3051

    
3052
	switch ($interface) {
3053
	case "l2tp":
3054
		$wanif = "l2tp";
3055
		break;
3056
	case "pptp":
3057
		$wanif = "pptp";
3058
		break;
3059
	case "pppoe":
3060
		$wanif = "pppoe";
3061
		break;
3062
	case "openvpn":
3063
		$wanif = "openvpn";
3064
		break;
3065
	case "ipsec":
3066
	case "enc0":
3067
		$wanif = "enc0";
3068
		break;
3069
	case "ppp":
3070
		$wanif = "ppp";
3071
		break;
3072
	default:
3073
		// If a real interface was alread passed simply
3074
		// pass the real interface back.  This encourages
3075
		// the usage of this function in more cases so that
3076
		// we can combine logic for more flexibility.
3077
		if(does_interface_exist($interface)) {
3078
			$wanif = $interface;
3079
			break;
3080
		}
3081
		if (empty($config['interfaces'][$interface]))
3082
			break;
3083

    
3084
		$cfg = &$config['interfaces'][$interface];
3085

    
3086
		// Wireless cloned NIC support (FreeBSD 8+)
3087
		// interface name format: $parentnic_wlanparentnic#
3088
		// example: ath0_wlan0
3089
		if (is_interface_wireless($cfg['if'])) {
3090
			$wanif = interface_get_wireless_clone($cfg['if']);
3091
			break;
3092
		}
3093
		/*
3094
		if (empty($cfg['if'])) {
3095
			$wancfg = $cfg['if'];
3096
			break;
3097
		}
3098
		*/
3099

    
3100
		switch ($cfg['ipaddr']) {
3101
			case "carpdev-dhcp":
3102
				$viparr = &$config['virtualip']['vip'];
3103
				if(is_array($viparr))
3104
				foreach ($viparr as $counter => $vip) {
3105
					if ($vip['mode'] == "carpdev-dhcp") {
3106
						if($vip['interface'] == $interface) {
3107
							$wanif = "carp{$counter}";
3108
							break;
3109
						}
3110
					}
3111
				}
3112
				break;
3113
			case "pppoe": 
3114
			case "pptp": 
3115
			case "l2tp": 
3116
			case "ppp":
3117
				$wanif = $cfg['if'];
3118
				break;
3119
			default:
3120
				$wanif = $cfg['if'];
3121
				break;
3122
		}
3123
		break;
3124
	}
3125

    
3126
    return $wanif;
3127
}
3128

    
3129
/* Guess the physical interface by providing a IP address */
3130
function guess_interface_from_ip($ipaddress) {
3131
	if(! is_ipaddr($ipaddress)) {
3132
		return false;
3133
	}
3134
	/* create a route table we can search */
3135
	exec("netstat -rnWf inet", $output, $ret);
3136
	foreach($output as $line) {
3137
		if(preg_match("/^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\/[0-9]+[ ]+link[#]/", $line)) {
3138
			$fields = preg_split("/[ ]+/", $line);
3139
			if(ip_in_subnet($ipaddress, $fields[0])) {
3140
				return $fields[6];
3141
			}
3142
		}
3143
	}
3144
	$ret = exec_command("/sbin/route -n get {$ipaddress} | /usr/bin/awk '/interface/ { print \$2; };'");
3145
	if(empty($ret)) {
3146
        	return false;
3147
	}
3148
	return $ret;
3149
}
3150

    
3151
/*
3152
 * find_ip_interface($ip): return the interface where an ip is defined
3153
 */
3154
function find_ip_interface($ip)
3155
{
3156
        /* if list */
3157
        $ifdescrs = get_configured_interface_list();
3158

    
3159
        foreach ($ifdescrs as $ifdescr => $ifname) {
3160
		if ($ip == get_interface_ip($ifname)) {
3161
                	$int = get_real_interface($ifname);
3162
			return $int;
3163
		}
3164
        }
3165
        return false;
3166
}
3167

    
3168
/*
3169
 *   find_number_of_created_carp_interfaces: return the number of carp interfaces
3170
 */
3171
function find_number_of_created_carp_interfaces() {
3172
	return `/sbin/ifconfig | grep "carp:" | wc -l`;
3173
}
3174

    
3175
function get_all_carp_interfaces() {
3176
	$ints = str_replace("\n", " ", `ifconfig | grep "carp:" -B2 | grep ": flag" | cut -d: -f1`);
3177
	$ints = explode(" ", $ints);
3178
	return $ints;
3179
}
3180

    
3181
/*
3182
 * find_carp_interface($ip): return the carp interface where an ip is defined
3183
 */
3184
function find_carp_interface($ip) {
3185
	global $config;
3186
	if (is_array($config['virtualip']['vip'])) {
3187
		foreach ($config['virtualip']['vip'] as $vip) {
3188
			if ($vip['mode'] == "carp" || $vip['mode'] == "carpdev") {
3189
				$carp_ip = get_interface_ip($vip['interface']);
3190
				$if = `ifconfig | grep '$ip ' -B1 | head -n1 | cut -d: -f1`;
3191
				if ($if)
3192
					return $if;
3193
			}
3194
		}
3195
	}
3196
}
3197

    
3198
function link_carp_interface_to_parent($interface) {
3199
        global $config;
3200

    
3201
        if ($interface == "")
3202
                return;
3203

    
3204
        $carp_ip = get_interface_ip($interface);
3205
        if (!is_ipaddr($carp_ip))
3206
                return;
3207

    
3208
        /* if list */
3209
        $ifdescrs = get_configured_interface_list();
3210
        foreach ($ifdescrs as $ifdescr => $ifname) {
3211
                $interfaceip = get_interface_ip($ifname);
3212
                $subnet_bits = get_interface_subnet($ifname);
3213
                $subnet_ip = gen_subnet("{$interfaceip}", "{$subnet_bits}");
3214
                if(ip_in_subnet($carp_ip, "{$subnet_ip}/{$subnet_bits}"))
3215
                        return $ifname;
3216
        }
3217

    
3218
        return "";
3219
}
3220

    
3221
/****f* interfaces/link_ip_to_carp_interface
3222
 * NAME
3223
 *   link_ip_to_carp_interface - Find where a CARP interface links to.
3224
 * INPUTS
3225
 *   $ip
3226
 * RESULT
3227
 *   $carp_ints
3228
 ******/
3229
function link_ip_to_carp_interface($ip) {
3230
        global $config;
3231

    
3232
        if (!is_ipaddr($ip))
3233
                return;
3234

    
3235
        $carp_ints = "";
3236
        if (is_array($config['virtualip']['vip'])) {
3237
		$first = 0;
3238
		$carp_int = array();
3239
                foreach ($config['virtualip']['vip'] as $vip) {
3240
                        if ($vip['mode'] == "carp" || $vip['mode'] == "carpdev") {
3241
                                $carp_ip = $vip['subnet'];
3242
                                $carp_sn = $vip['subnet_bits'];
3243
                                $carp_nw = gen_subnet($carp_ip, $carp_sn);
3244
                                if (ip_in_subnet($ip, "{$carp_nw}/{$carp_sn}"))
3245
					$carp_int[] = "vip{$vip['vhid']}";
3246
                        }
3247
                }
3248
		if (!empty($carp_int))
3249
			$carp_ints = implode(" ", array_unique($carp_int));
3250
        }
3251

    
3252
        return $carp_ints;
3253
}
3254

    
3255
function link_interface_to_vlans($int, $action = "") {
3256
	global $config;
3257

    
3258
	if (empty($int))
3259
		return;
3260

    
3261
	if (is_array($config['vlans']['vlan'])) {
3262
                foreach ($config['vlans']['vlan'] as $vlan) {
3263
			if ($int == $vlan['if']) {
3264
				if ($action == "update") {
3265
					interfaces_bring_up($int);
3266
				} else if ($action == "")
3267
					return $vlan;
3268
			}
3269
		}
3270
	}
3271
}
3272

    
3273
function link_interface_to_vips($int, $action = "") {
3274
        global $config;
3275

    
3276
        if (is_array($config['virtualip']['vip'])) {
3277
		foreach ($config['virtualip']['vip'] as $vip) {
3278
			if ($int == $vip['interface']) {
3279
				if ($action == "update") {
3280
					interface_vip_bring_down($vip);
3281
					interfaces_vips_configure($int);
3282
				} else
3283
					return $vip;
3284
			}
3285
		}
3286
	}
3287
}
3288

    
3289
/****f* interfaces/link_interface_to_bridge
3290
 * NAME
3291
 *   link_interface_to_bridge - Finds out a bridge group for an interface
3292
 * INPUTS
3293
 *   $ip
3294
 * RESULT
3295
 *   bridge[0-99]
3296
 ******/
3297
function link_interface_to_bridge($int) {
3298
        global $config;
3299

    
3300
        if (is_array($config['bridges']['bridged'])) {
3301
                foreach ($config['bridges']['bridged'] as $bridge) {
3302
			if (in_array($int, explode(',', $bridge['members'])))
3303
                                return "{$bridge['bridgeif']}";
3304
		}
3305
	}
3306
}
3307

    
3308
function link_interface_to_group($int) {
3309
        global $config;
3310

    
3311
	$result = array();
3312

    
3313
        if (is_array($config['ifgroups']['ifgroupentry'])) {
3314
                foreach ($config['ifgroups']['ifgroupentry'] as $group) {
3315
			if (in_array($int, explode(" ", $group['members'])))
3316
				$result[$group['ifname']] = $int;
3317
		}
3318
	}
3319

    
3320
	return $result;
3321
}
3322

    
3323
function link_interface_to_gre($interface) {
3324
        global $config;
3325

    
3326
	$result = array();
3327

    
3328
        if (is_array($config['gres']['gre'])) {
3329
                foreach ($config['gres']['gre'] as $gre)
3330
                        if($gre['if'] == $interface)
3331
				$result[] = $gre;
3332
	}
3333

    
3334
	return $result;
3335
}
3336

    
3337
function link_interface_to_gif($interface) {
3338
        global $config;
3339

    
3340
	$result = array();
3341

    
3342
        if (is_array($config['gifs']['gif'])) {
3343
                foreach ($config['gifs']['gif'] as $gif)
3344
                        if($gif['if'] == $interface)
3345
                                $result[] = $gif;
3346
	}
3347

    
3348
	return $result;
3349
}
3350

    
3351
/*
3352
 * find_interface_ip($interface): return the interface ip (first found)
3353
 */
3354
function find_interface_ip($interface, $flush = false)
3355
{
3356
	global $interface_ip_arr_cache;
3357
	global $interface_sn_arr_cache;
3358

    
3359
	$interface = str_replace("\n", "", $interface);
3360
	
3361
	if (!does_interface_exist($interface))
3362
		return;
3363

    
3364
	/* Setup IP cache */
3365
	if (!isset($interface_ip_arr_cache[$interface]) or $flush) {
3366
		$ifinfo = pfSense_get_interface_addresses($interface);
3367
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
3368
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
3369
	}
3370

    
3371
	return $interface_ip_arr_cache[$interface];
3372
}
3373

    
3374
function find_interface_subnet($interface, $flush = false)
3375
{
3376
	global $interface_sn_arr_cache;
3377
	global $interface_ip_arr_cache;
3378

    
3379
	$interface = str_replace("\n", "", $interface);
3380
	if (does_interface_exist($interface) == false)
3381
		return;
3382

    
3383
	if (!isset($interface_sn_arr_cache[$interface]) or $flush) {
3384
		$ifinfo = pfSense_get_interface_addresses($interface);
3385
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
3386
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
3387
        }
3388

    
3389
	return $interface_sn_arr_cache[$interface];
3390
}
3391

    
3392
function ip_in_interface_alias_subnet($interface, $ipalias) {
3393
	global $config;
3394

    
3395
	if (empty($interface) || !is_ipaddr($ipalias))
3396
		return false;
3397
	if (is_array($config['virtualip']['vip'])) {
3398
                foreach ($config['virtualip']['vip'] as $vip) {
3399
                        switch ($vip['mode']) {
3400
                        case "ipalias":
3401
                                if ($vip['interface'] <> $interface)
3402
                                        break;
3403
				if (ip_in_subnet($ipalias, gen_subnet($vip['subnet'], $vip['subnet_bits']) . "/" . $vip['subnet_bits']))
3404
					return true;
3405
                                break;
3406
                        }
3407
                }
3408
	}
3409

    
3410
	return false;
3411
}
3412

    
3413
function get_interface_ip($interface = "wan")
3414
{
3415
	$realif = get_real_interface($interface);
3416
	if (!$realif) {
3417
		if (preg_match("/^carp/i", $interface))
3418
			$realif = $interface;
3419
		else if (preg_match("/^vip/i", $interface))
3420
			$realif = $interface;
3421
		else
3422
			return null;
3423
	}
3424

    
3425
	$curip = find_interface_ip($realif);
3426
	if ($curip && is_ipaddr($curip) && ($curip != "0.0.0.0"))
3427
		return $curip;
3428
	else
3429
		return null;
3430
}
3431

    
3432
function get_interface_subnet($interface = "wan")
3433
{
3434
	$realif = get_real_interface($interface);
3435
	if (!$realif) {
3436
                if (preg_match("/^carp/i", $interface))
3437
                        $realif = $interface;
3438
                else if (preg_match("/^vip/i", $interface))
3439
                        $realif = $interface;
3440
                else
3441
                        return null;
3442
        }
3443

    
3444
	$cursn = find_interface_subnet($realif);
3445
	if (!empty($cursn))
3446
		return $cursn;
3447

    
3448
	return null;
3449
}
3450

    
3451
/* return outside interfaces with a gateway */
3452
function get_interfaces_with_gateway() {
3453
	global $config;
3454

    
3455
	$ints = array();
3456

    
3457
	/* loop interfaces, check config for outbound */
3458
	foreach($config['interfaces'] as $ifdescr => $ifname) {
3459
		switch ($ifname['ipaddr']) {
3460
			case "dhcp":
3461
			case "carpdev-dhcp":
3462
			case "ppp";
3463
			case "pppoe":
3464
			case "pptp":
3465
			case "l2tp":
3466
			case "ppp";
3467
				$ints[$ifdescr] = $ifdescr;
3468
			break;
3469
			default:
3470
				if (substr($ifname['if'], 0, 5) ==  "ovpnc" ||
3471
				    !empty($ifname['gateway']))
3472
					$ints[$ifdescr] = $ifdescr;
3473
			break;
3474
		}
3475
	}
3476
	return $ints;
3477
}
3478

    
3479
/* return true if interface has a gateway */
3480
function interface_has_gateway($friendly) {
3481
	global $config;
3482

    
3483
	if (!empty($config['interfaces'][$friendly])) {
3484
		$ifname = &$config['interfaces'][$friendly];
3485
		switch ($ifname['ipaddr']) {
3486
			case "dhcp":
3487
			case "carpdev-dhcp":
3488
			case "pppoe":
3489
			case "pptp":
3490
			case "l2tp":
3491
			case "ppp";
3492
				return true;
3493
			break;
3494
			default:
3495
				if (substr($ifname['if'], 0, 5) ==  "ovpnc")
3496
					return true;
3497
				if (!empty($ifname['gateway']))
3498
					return true;
3499
			break;
3500
		}
3501
	}
3502

    
3503
	return false;
3504
}
3505

    
3506
/****f* interfaces/is_altq_capable
3507
 * NAME
3508
 *   is_altq_capable - Test if interface is capable of using ALTQ
3509
 * INPUTS
3510
 *   $int            - string containing interface name
3511
 * RESULT
3512
 *   boolean         - true or false
3513
 ******/
3514

    
3515
function is_altq_capable($int) {
3516
        /* Per:
3517
         * http://www.freebsd.org/cgi/man.cgi?query=altq&manpath=FreeBSD+7.2-current&format=html
3518
         * Only the following drivers have ALTQ support
3519
         */
3520
	$capable = array("age", "alc", "ale", "an", "ath", "aue", "awi", "bce",
3521
			"bfe", "bge", "bridge", "cas", "dc", "de", "ed", "em", "ep", "fxp", "gem",
3522
			"hme", "igb", "ipw", "iwi", "jme", "le", "lem", "msk", "mxge", "my", "nfe",
3523
			"npe", "nve", "ral", "re", "rl", "rum", "run", "bwn", "sf", "sis", "sk",
3524
			"ste", "stge", "txp", "udav", "ural", "vge", "vr", "wi", "xl",
3525
			"ndis", "tun", "ovpns", "ovpnc", "vlan", "pppoe", "pptp", "ng",
3526
			"l2tp", "ppp");
3527

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

    
3530
        if (in_array($int_family[0], $capable))
3531
                return true;
3532
	else if (stristr($int, "vlan")) /* VLANs are name $parent_$vlan now */
3533
		return true;
3534
	else if (stristr($int, "_wlan")) /* WLANs are name $parent_$wlan now */
3535
		return true;
3536
        else
3537
                return false;
3538
}
3539

    
3540
/****f* interfaces/is_interface_wireless
3541
 * NAME
3542
 *   is_interface_wireless - Returns if an interface is wireless
3543
 * RESULT
3544
 *   $tmp       - Returns if an interface is wireless
3545
 ******/
3546
function is_interface_wireless($interface) {
3547
        global $config, $g;
3548

    
3549
        $friendly = convert_real_interface_to_friendly_interface_name($interface);
3550
        if(!isset($config['interfaces'][$friendly]['wireless'])) {
3551
                if (preg_match($g['wireless_regex'], $interface)) {
3552
                        if (isset($config['interfaces'][$friendly]))
3553
                                $config['interfaces'][$friendly]['wireless'] = array();
3554
                        return true;
3555
                }
3556
                return false;
3557
        } else
3558
                return true;
3559
}
3560

    
3561
function get_wireless_modes($interface) {
3562
	/* return wireless modes and channels */
3563
	$wireless_modes = array();
3564

    
3565
	$cloned_interface = get_real_interface($interface);
3566

    
3567
	if($cloned_interface && is_interface_wireless($cloned_interface)) {
3568
		$chan_list = "/sbin/ifconfig {$cloned_interface} list chan";
3569
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
3570
		$format_list = "/usr/bin/awk '{print \$5 \" \" \$6 \",\" \$1}'";
3571

    
3572
		$interface_channels = "";
3573
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
3574
		$interface_channel_count = count($interface_channels);
3575

    
3576
		$c = 0;
3577
		while ($c < $interface_channel_count)
3578
		{
3579
			$channel_line = explode(",", $interface_channels["$c"]);
3580
			$wireless_mode = trim($channel_line[0]);
3581
			$wireless_channel = trim($channel_line[1]);
3582
			if(trim($wireless_mode) != "") {
3583
				/* if we only have 11g also set 11b channels */
3584
				if($wireless_mode == "11g") {
3585
					if(!isset($wireless_modes["11b"]))
3586
						$wireless_modes["11b"] = array();
3587
				} else if($wireless_mode == "11g ht") {
3588
					if(!isset($wireless_modes["11b"]))
3589
						$wireless_modes["11b"] = array();
3590
					if(!isset($wireless_modes["11g"]))
3591
						$wireless_modes["11g"] = array();
3592
					$wireless_mode = "11ng";
3593
				} else if($wireless_mode == "11a ht") {
3594
					if(!isset($wireless_modes["11a"]))
3595
						$wireless_modes["11a"] = array();
3596
					$wireless_mode = "11na";
3597
				}
3598
				$wireless_modes["$wireless_mode"]["$c"] = $wireless_channel;
3599
			}
3600
			$c++;
3601
		}
3602
	}
3603
	return($wireless_modes);
3604
}
3605

    
3606
/* return channel numbers, frequency, max txpower, and max regulation txpower */
3607
function get_wireless_channel_info($interface) {
3608
	$wireless_channels = array();
3609

    
3610
	$cloned_interface = get_real_interface($interface);
3611

    
3612
	if($cloned_interface && is_interface_wireless($cloned_interface)) {
3613
		$chan_list = "/sbin/ifconfig {$cloned_interface} list txpower";
3614
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
3615
		$format_list = "/usr/bin/awk '{print \$1 \",\" \$3 \" \" \$4 \",\" \$5 \",\" \$7}'";
3616

    
3617
		$interface_channels = "";
3618
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
3619

    
3620
		foreach ($interface_channels as $channel_line) {
3621
			$channel_line = explode(",", $channel_line);
3622
			if(!isset($wireless_channels[$channel_line[0]]))
3623
				$wireless_channels[$channel_line[0]] = $channel_line;
3624
		}
3625
	}
3626
	return($wireless_channels);
3627
}
3628

    
3629
/****f* interfaces/get_interface_mtu
3630
 * NAME
3631
 *   get_interface_mtu - Return the mtu of an interface
3632
 * RESULT
3633
 *   $tmp       - Returns the mtu of an interface
3634
 ******/
3635
function get_interface_mtu($interface) {
3636
        $mtu = pfSense_get_interface_addresses($interface);
3637
        return $mtu['mtu'];
3638
}
3639

    
3640
function get_interface_mac($interface) {
3641

    
3642
	$macinfo = pfSense_get_interface_addresses($interface);
3643
	return $macinfo["macaddr"];
3644
}
3645

    
3646
/****f* pfsense-utils/generate_random_mac_address
3647
 * NAME
3648
 *   generate_random_mac - generates a random mac address
3649
 * INPUTS
3650
 *   none
3651
 * RESULT
3652
 *   $mac - a random mac address
3653
 ******/
3654
function generate_random_mac_address() {
3655
        $mac = "02";
3656
        for($x=0; $x<5; $x++)
3657
                $mac .= ":" . dechex(rand(16, 255));
3658
        return $mac;
3659
}
3660

    
3661
/****f* interfaces/is_jumbo_capable
3662
 * NAME
3663
 *   is_jumbo_capable - Test if interface is jumbo frame capable.  Useful for determining VLAN capability.
3664
 * INPUTS
3665
 *   $int             - string containing interface name
3666
 * RESULT
3667
 *   boolean          - true or false
3668
 ******/
3669
function is_jumbo_capable($int) {
3670
        global $g;
3671

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

    
3674
        if (in_array($int_family[0], $g['vlan_long_frame']))
3675
                return true;
3676
        else
3677
                return false;
3678
}
3679

    
3680
function setup_pppoe_reset_file($pppif, $iface="") {
3681
	global $g;
3682
	$cron_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
3683

    
3684
	if(!empty($iface) && !empty($pppif)){
3685
		$cron_cmd = <<<EOD
3686
#!/bin/sh
3687
/usr/local/sbin/pfSctl -c 'interface reload {$iface}'
3688
/usr/bin/logger -t pppoe{$iface} "PPPoE periodic reset executed on {$iface}"
3689

    
3690
EOD;
3691

    
3692
		file_put_contents($cron_file, $cron_cmd);
3693
		chmod($cron_file, 0700);
3694
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
3695
	} else
3696
		unlink_if_exists($cron_file);
3697
}
3698

    
3699
function get_interface_default_mtu($type = "ethernet") {
3700
	switch ($type) {
3701
	case "gre":
3702
		return 1476;
3703
		break;
3704
	case "gif":
3705
		return 1280;
3706
		break;
3707
	case "tun":
3708
	case "vlan":
3709
	case "tap":
3710
	case "ethernet":
3711
	default:
3712
		return 1500;
3713
		break;
3714
	}
3715

    
3716
	/* Never reached */
3717
	return 1500;
3718
}
3719

    
3720
function get_vip_descr($ipaddress) {
3721
	global $config;
3722

    
3723
	foreach ($config['virtualip']['vip'] as $vip) {
3724
		if ($vip['subnet'] == $ipaddress) {
3725
			return ($vip['descr']);
3726
		}
3727
	}
3728
	return "";
3729
}
3730

    
3731
?>
(25-25/61)