Project

General

Profile

Download (109 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
/*
88
 * does_vip_exist($vip): return true or false if a vip is
89
 * configured.
90
 */
91
function does_vip_exist($vip) {
92
	global $config;
93
	
94
	if(!$vip)
95
		return false;
96

    
97

    
98
	switch ($vip['mode']) {
99
	case "carp":
100
	case "carpdev":
101
		$realif = "vip{$vip['vhid']}";
102
		if (!does_interface_exist($realif)) {
103
			return false;
104
		}
105
		break;
106
	case "ipalias":
107
		$realif = get_real_interface($vip['interface']);
108
		if (!does_interface_exist($realif)) {
109
			return false;
110
		}
111
		break;
112
	case "proxyarp":
113
		/* XXX: Implement this */
114
	default:
115
		return false;
116
	}
117

    
118
	$ifacedata = pfSense_getall_interface_addresses($realif);
119
	foreach ($ifacedata as $vipips) {
120
		if ($vipips == "{$vip['subnet']}/{$vip['subnet_bits']}")
121
			return true;
122
	}
123

    
124
	return false;
125
}
126

    
127
function interface_netgraph_needed($interface = "wan") {
128
	global $config;
129

    
130
	$found = false;
131
	if (!empty($config['pptpd']) &&
132
		$config['pptpd']['mode'] == "server")
133
		$found = true;
134
	if ($found == false && !empty($config['l2tp']) &&
135
		$config['l2tp']['mode'] == "server")
136
		$found = true;
137
	if ($found == false && is_array($config['pppoes']['pppoe'])) {
138
		foreach ($config['pppoes']['pppoe'] as $pppoe) {
139
			if ($pppoe['mode'] != "server")
140
				continue;
141
			if ($pppoe['interface'] == $interface)
142
				$found = true;
143
				break;
144
		}
145
	}
146
	if ($found == false) {
147
		if (!empty($config['interfaces'][$interface])) {
148
			switch ($config['interfaces'][$interface]['ipaddr']) {
149
			case "ppp":
150
			case "pppoe":
151
			case "l2tp":
152
			case "pptp":
153
				$found = true;
154
				break;
155
			default:
156
				$found = false;
157
				break;
158
			}
159
		}
160
	}
161
	if ($found == false) {
162
		$realif = get_real_interface($interface);
163
		if (is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) {
164
			foreach ($config['ppps']['ppp'] as $pppid => $ppp) {
165

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

    
170
				if ($realif == $ppp['if']) {
171
					$found = true;
172
					break;
173
				}
174
*/			
175
				$ports = explode(',',$ppp['ports']);
176
				foreach($ports as $pid => $port){
177
					$port = get_real_interface($port);
178
					if ($realif == $port) {
179
						$found = true;
180
						break;
181
					}
182
					/* Find the parent interfaces of the vlans in the MLPPP configs 
183
					* there should be only one element in the array here 
184
					* -- this could be better . . . */
185
					$parent_if = get_parent_interface($port);
186
					if ($realif == $parent_if[0]) {
187
						$found = true;
188
						break;
189
					}
190
				}
191
			}
192
		}
193
	}
194
	
195
	if ($found == false) {
196
		$realif = get_real_interface($interface);
197
		pfSense_ngctl_detach("{$realif}:", $realif);
198
	}
199
	/* NOTE: We make sure for this on interface_ppps_configure()
200
	 *	no need to do it here agan.
201
	 *	else
202
	 *		pfSense_ngctl_attach(".", $realif);
203
	 */
204
}
205

    
206
function interfaces_loopback_configure() {
207
	if($g['booting'])
208
		echo "Configuring loopback interface...";
209
	pfSense_interface_setaddress("lo0", "127.0.0.1");
210
	interfaces_bring_up("lo0");
211
	if($g['booting'])
212
		echo "done.\n";
213
	return 0;
214
}
215

    
216
function interfaces_vlan_configure() {
217
	global $config, $g;
218
	if($g['booting'])
219
		echo "Configuring VLAN interfaces...";
220
	if (is_array($config['vlans']['vlan']) && count($config['vlans']['vlan'])) {
221
		foreach ($config['vlans']['vlan'] as $vlan) {
222
			if(empty($vlan['vlanif']))
223
				$vlan['vlanif'] = "{$vlan['if']}_vlan{$vlan['tag']}";
224
			/* XXX: Maybe we should report any errors?! */
225
			interface_vlan_configure($vlan);
226
		}
227
	}
228
	if($g['booting'])
229
		echo "done.\n";
230
}
231

    
232
function interface_vlan_configure(&$vlan) {
233
        global $config, $g;
234

    
235
	if (!is_array($vlan)) {
236
		log_error("VLAN: called with wrong options. Problems with config!");
237
		return;
238
	}
239
	$if = $vlan['if'];
240
	$vlanif  = empty($vlan['vlanif']) ? "{$if}_vlan{$vlan['tag']}" : $vlan['vlanif'];
241
	$tag = $vlan['tag'];
242

    
243
	if (empty($if)) {
244
		log_error("interface_vlan_confgure called with if undefined.");
245
		return;
246
	}
247

    
248
	/* make sure the parent interface is up */
249
	interfaces_bring_up($if);
250
	/* Since we are going to add vlan(4) try to enable all that hardware supports. */
251
	pfSense_interface_capabilities($if, IFCAP_VLAN_HWTAGGING|IFCAP_VLAN_MTU|IFCAP_VLAN_HWFILTER);
252

    
253
	if (!empty($vlanif) && does_interface_exist($vlanif)) {
254
		interface_bring_down($vlanif, true);
255
	} else {
256
		$tmpvlanif = pfSense_interface_create("vlan");
257
		pfSense_interface_rename($tmpvlanif, $vlanif);
258
		pfSense_ngctl_name("{$tmpvlanif}:", $vlanif);
259
	}
260

    
261
	pfSense_vlan_create($vlanif, $if, $tag);
262

    
263
	interfaces_bring_up($vlanif);
264

    
265
	/* invalidate interface cache */
266
	get_interface_arr(true);
267

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

    
271
	return $vlanif;
272
}
273

    
274
function interface_qinq_configure(&$vlan, $fd = NULL) {
275
        global $config, $g;
276

    
277
        if (!is_array($vlan)) {
278
                log_error("QinQ compat VLAN: called with wrong options. Problems with config!\n");
279
                return;
280
        }
281

    
282
        $qinqif = $vlan['if'];
283
        $tag = $vlan['tag'];
284
        if(empty($qinqif)) {
285
                log_error("interface_qinq_confgure called with if undefined.\n");
286
                return;
287
        }
288
	$vlanif = interface_vlan_configure($vlan);
289

    
290
        if ($fd == NULL) {
291
                $exec = true;
292
                $fd = fopen("{$g['tmp_path']}/netgraphcmd", "w");
293
        } else
294
                $exec = false;
295
        /* make sure the parent is converted to ng_vlan(4) and is up */
296
        interfaces_bring_up($qinqif);
297

    
298
	pfSense_ngctl_attach(".", $qinqif);
299
        if (!empty($vlanif) && does_interface_exist($vlanif)) {
300
                fwrite($fd, "shutdown {$qinqif}qinq:\n");
301
                exec("/usr/sbin/ngctl msg {$qinqif}qinq: gettable", $result);
302
                if (empty($result)) {
303
                        fwrite($fd, "mkpeer {$qinqif}: vlan lower downstream\n");
304
                        fwrite($fd, "name {$qinqif}:lower {$vlanif}qinq\n");
305
                        fwrite($fd, "connect {$qinqif}: {$vlanif}qinq: upper nomatch\n");
306
                }
307
        } else {
308
                fwrite($fd, "mkpeer {$qinqif}: vlan lower downstream\n");
309
                fwrite($fd, "name {$qinqif}:lower {$vlanif}qinq\n");
310
                fwrite($fd, "connect {$qinqif}: {$vlanif}qinq: upper nomatch\n");
311
        }
312

    
313
        /* invalidate interface cache */
314
        get_interface_arr(true);
315

    
316
        if (!stristr($qinqif, "vlan"))
317
                mwexec("/sbin/ifconfig {$qinqif} promisc\n");
318

    
319
        $macaddr = get_interface_mac($qinqif);
320
        if (!empty($vlan['members'])) {
321
                $members = explode(" ", $vlan['members']);
322
                foreach ($members as $qtag) {
323
                        $qinq = array();
324
                        $qinq['tag'] = $qtag;
325
                        $qinq['if'] = $vlanif;
326
                        interface_qinq2_configure($qinq, $fd, $macaddr);
327
                }
328
        }
329
        if ($exec == true) {
330
                fclose($fd);
331
                mwexec("/usr/sbin/ngctl -f {$g['tmp_path']}/netgraphcmd");
332
        }
333

    
334
        interfaces_bring_up($qinqif);
335
        if (!empty($vlan['members'])) {
336
                $members = explode(" ", $vlan['members']);
337
                foreach ($members as $qif)
338
                        interfaces_bring_up("{$vlanif}_{$qif}");
339
        }
340

    
341
        return $vlanif;
342
}
343

    
344
function interfaces_qinq_configure() {
345
	global $config, $g;
346
	if($g['booting'])
347
		echo "Configuring QinQ interfaces...";
348
	if (is_array($config['qinqs']['qinqentry']) && count($config['qinqs']['qinqentry'])) {
349
		foreach ($config['qinqs']['qinqentry'] as $qinq) {
350
			/* XXX: Maybe we should report any errors?! */
351
			interface_qinq_configure($qinq);
352
		}
353
	}
354
	if($g['booting'])
355
		echo "done.\n";
356
}
357

    
358
function interface_qinq2_configure(&$qinq, $fd, $macaddr) {
359
        global $config, $g;
360

    
361
        if (!is_array($qinq)) {
362
                log_error("QinQ compat VLAN: called with wrong options. Problems with config!\n");
363
                return;
364
        }
365

    
366
        $if = $qinq['if'];
367
        $tag = $qinq['tag'];
368
        $vlanif = "{$if}_{$tag}";
369
        if(empty($if)) {
370
                log_error("interface_qinq_confgure called with if undefined.\n");
371
                return;
372
        }
373

    
374
        fwrite($fd, "shutdown {$if}h{$tag}:\n");
375
        fwrite($fd, "mkpeer {$if}qinq: eiface {$if}{$tag} ether\n");
376
        fwrite($fd, "name {$if}qinq:{$if}{$tag} {$if}h{$tag}\n");
377
        fwrite($fd, "msg {$if}qinq: addfilter { vlan={$tag} hook=\"{$if}{$tag}\" }\n");
378
        fwrite($fd, "msg {$if}h{$tag}: setifname \"{$vlanif}\"\n");
379
        fwrite($fd, "msg {$if}h{$tag}: set {$macaddr}\n");
380

    
381
        /* invalidate interface cache */
382
        get_interface_arr(true);
383

    
384
        return $vlanif;
385
}
386

    
387
function interfaces_create_wireless_clones() {
388
	global $config;
389

    
390
	if($g['booting'])
391
		echo "Creating other wireless clone interfaces...";
392
	if (is_array($config['wireless']['clone']) && count($config['wireless']['clone'])) {
393
		foreach ($config['wireless']['clone'] as $clone) {
394
			if(empty($clone['cloneif']))
395
				continue;
396
			if(does_interface_exist($clone['cloneif']))
397
				continue;
398
			/* XXX: Maybe we should report any errors?! */
399
			if(interface_wireless_clone($clone['cloneif'], $clone))
400
				if($g['booting'])
401
					echo " " . $clone['cloneif'];
402
		}
403
	}
404
	if($g['booting'])
405
		echo " done.\n";
406
}
407

    
408
function interfaces_bridge_configure($checkmember = 0) {
409
        global $config;
410

    
411
        $i = 0;
412
        if (is_array($config['bridges']['bridged']) && count($config['bridges']['bridged'])) {
413
                foreach ($config['bridges']['bridged'] as $bridge) {
414
                        if(empty($bridge['bridgeif']))
415
                                $bridge['bridgeif'] = "bridge{$i}";
416
			if ($checkmember == 1 && (strstr($bridge['members'], "gif") || strstr($bridge['members'], "gre")))
417
				continue;
418
			if ($checkmember == 2 && !strstr($bridge['members'], "gif") && !strstr($bridge['members'], "gre"))
419
				continue;
420
                        /* XXX: Maybe we should report any errors?! */
421
                        interface_bridge_configure($bridge);
422
                        $i++;
423
                }
424
        }
425
}
426

    
427
function interface_bridge_configure(&$bridge) {
428
	global $config, $g;
429

    
430
	if (!is_array($bridge))
431
	        return -1;
432

    
433
	if (empty($bridge['members'])) {
434
		log_error("No members found on {$bridge['bridgeif']}");
435
		return -1;
436
	}
437

    
438
	$members = explode(',', $bridge['members']);
439
	if (!count($members))
440
		return -1;
441

    
442
	$checklist = get_configured_interface_list();
443

    
444
	if ($g['booting'] || !empty($bridge['bridgeif'])) {
445
		pfSense_interface_destroy($bridge['bridgeif']);
446
		pfSense_interface_create($bridge['bridgeif']);
447
		$bridgeif = $bridge['bridgeif'];
448
	} else
449
		$bridgeif = pfSense_interface_create("bridge");
450

    
451
	/* Calculate smaller mtu and enforce it */
452
	$smallermtu = 0;
453
	$commonrx = true;
454
	$commontx = true;
455
	foreach ($members as $member) {
456
		$realif = get_real_interface($member);
457
		$opts = pfSense_get_interface_addresses($realif);
458
		$mtu = $opts['mtu'];
459
		if (substr($realif, 0, 3) == "gif" && $mtu <= 1500)
460
			continue;
461
		if (!isset($opts['encaps']['txcsum']))
462
			$commontx = false;
463
		if (!isset($opts['encaps']['rxcsum']))
464
			$commonrx = false;
465
		if (!isset($opts['encaps']['tso4']))
466
			$commontso4 = false;
467
		if (!isset($opts['encaps']['tso6']))
468
			$commontso6 = false;
469
		if (!isset($opts['encaps']['lro']))
470
			$commonlro = false;
471
		if ($smallermtu == 0 && !empty($mtu))
472
			$smallermtu = $mtu;
473
		else if (!empty($mtu) && $mtu < $smallermtu)
474
			$smallermtu = $mtu;
475
	}
476
	 
477
	/* Just in case anything is not working well */
478
	if ($smallermtu == 0)
479
		$smallermtu = 1500; 
480

    
481
	$flags = 0;
482
	if ($commonrx === false)
483
		$flags |= IFCAP_RXCSUM;
484
	if ($commontx === false)
485
		$flags |= IFCAP_TXCSUM;
486
	if ($commontso4 === false)
487
		$flags |= IFCAP_TSO4;
488
	if ($commontso6 === false)
489
		$flags |= IFCAP_TSO6;
490
	if ($commonlro === false)
491
		$flags |= IFCAP_LRO;
492
		
493
	/* Add interfaces to bridge */
494
	foreach ($members as $member) {
495
		if (!array_key_exists($member, $checklist))
496
			continue;
497
		$realif1 = get_real_interface($member);
498
		$realif =  escapeshellarg($realif1);
499
		if (!$realif) {
500
			log_error("realif not defined in interfaces bridge - up");
501
			continue;
502
		}
503
		/* make sure the parent interface is up */
504
		pfSense_interface_mtu($realif1, $smallermtu);
505
		pfSense_interface_capabilities($realif1, -$flags);
506
		interfaces_bring_up($realif1);
507
		mwexec("/sbin/ifconfig {$bridgeif} addm {$realif}");	
508
	}
509

    
510
	if (isset($bridge['enablestp'])) {
511
		/* Choose spanning tree proto */
512
		mwexec("/sbin/ifconfig {$bridgeif} proto {$bridge['proto']}");	
513
		
514
		if (!empty($bridge['stp'])) {
515
			$stpifs = explode(',', $bridge['stp']);
516
			foreach ($stpifs as $stpif) {
517
				$realif = get_real_interface($stpif);
518
				mwexec("/sbin/ifconfig {$bridgeif} stp {$realif}");
519
			}
520
		}
521
		if (!empty($bridge['maxage']))
522
			mwexec("/sbin/ifconfig {$bridgeif} maxage {$bridge['maxage']}");
523
		if (!empty($brige['fwdelay']))
524
			mwexec("/sbin/ifconfig {$bridgeif} fwddelay {$bridge['fwdelay']}");
525
		if (!empty($brige['hellotime']))
526
                        mwexec("/sbin/ifconfig {$bridgeif} hellotime {$bridge['hellotime']}");
527
		if (!empty($brige['priority']))
528
                        mwexec("/sbin/ifconfig {$bridgeif} priority {$bridge['priority']}");
529
		if (!empty($brige['holdcount']))
530
                        mwexec("/sbin/ifconfig {$bridgeif} holdcnt {$bridge['holdcnt']}");
531
		if (!empty($bridge['ifpriority'])) {
532
			$pconfig = explode(",", $bridge['ifpriority']);
533
			$ifpriority = array();
534
			foreach ($pconfig as $cfg) {
535
				$embcfg = explode(":", $cfg);
536
				foreach ($embcfg as $key => $value)
537
					$ifpriority[$key] = $value;
538
			}
539
			foreach ($ifpriority as $key => $value) {
540
				$realif = get_real_interface($key);
541
				mwexec("/sbin/ifconfig ${bridgeif} ifpriority {$realif} {$value}"); 
542
			}
543
		}
544
		if (!empty($bridge['ifpathcost'])) {
545
			$pconfig = explode(",", $bridges['ifpathcost']);
546
			$ifpathcost = array();
547
			foreach ($pconfig as $cfg) {
548
				$embcfg = explode(":", $cfg);
549
				foreach ($embcfg as $key => $value)
550
					$ifpathcost[$key] = $value;
551
			}
552
			foreach ($ifpathcost as $key => $value) {
553
                        	$realif = get_real_interface($key);
554
                        	mwexec("/sbin/ifconfig ${bridgeif} ifpathcost {$realif} {$value}");
555
                	}
556
		}
557
	}
558

    
559
	if ($bridge['maxaddr'] <> "")
560
		mwexec("/sbin/ifconfig {$bridgeif} maxaddr {$bridge['maxaddr']}");
561
        if ($bridge['timeout'] <> "")
562
                mwexec("/sbin/ifconfig {$bridgeif} timeout {$bridge['timeout']}");
563
        if ($bridge['span'] <> "") {
564
		$realif = get_real_interface($bridge['span']);
565
                mwexec("/sbin/ifconfig {$bridgeif} span {$realif}");
566
	}
567
	if (!empty($bridge['edge'])) {
568
        	$edgeifs = explode(',', $bridge['edge']);
569
        	foreach ($edgeifs as $edgeif) {
570
			$realif = get_real_interface($edgeif);
571
                	mwexec("/sbin/ifconfig {$bridgeif} edge {$realif}");
572
        	}
573
	}
574
	if (!empty($bridge['autoedge'])) {
575
        	$edgeifs = explode(',', $bridge['autoedge']);
576
        	foreach ($edgeifs as $edgeif) {
577
                	$realif = get_real_interface($edgeif);
578
                	mwexec("/sbin/ifconfig {$bridgeif} -autoedge {$realif}");
579
        	}
580
	}
581
	if (!empty($bridge['ptp'])) {
582
        	$ptpifs = explode(',', $bridge['ptp']);
583
        	foreach ($ptpifs as $ptpif) {
584
                	$realif = get_real_interface($ptpif);
585
                	mwexec("/sbin/ifconfig {$bridgeif} ptp {$realif}");
586
        	}
587
	}
588
	if (!empty($bridge['autoptp'])) {
589
        	$ptpifs = explode(',', $bridge['autoptp']);
590
        	foreach ($ptpifs as $ptpif) {
591
                	$realif = get_real_interface($ptpif);
592
                	mwexec("/sbin/ifconfig {$bridgeif} -autoptp {$realif}");
593
        	}
594
	}
595
	if (!empty($bridge['static'])) {
596
        	$stickyifs = explode(',', $bridge['static']);
597
        	foreach ($stickyifs as $stickyif) {
598
                	$realif = get_real_interface($stickyif);
599
                	mwexec("/sbin/ifconfig {$bridgeif} sticky {$realif}");
600
        	}
601
	}
602
	if (!empty($bridge['private'])) {
603
        	$privateifs = explode(',', $bridge['private']);
604
        	foreach ($privateifs as $privateif) {
605
                	$realif = get_real_interface($privateif);
606
               	 	mwexec("/sbin/ifconfig {$bridgeif} private {$realif}");
607
        	}
608
	}
609

    
610
	if($bridgeif)
611
		interfaces_bring_up($bridgeif);	
612
	else 
613
		log_error("bridgeif not defined -- could not bring interface up");
614

    
615
	return $bridgeif;
616
}
617

    
618
function interface_bridge_add_member($bridgeif, $interface) {
619

    
620
	if (!does_interface_exist($bridgeif) || !does_interface_exist($interface))
621
		return;
622

    
623
	$mtu = get_interface_mtu($brigeif);
624
	$mtum = get_interface_mtu($interface);
625
	
626
	if ($mtu != $mtum && !(substr($interface, 0, 3) == "gif" && $mtu <= 1500))
627
		pfSense_interface_mtu($interface, $mtu);
628

    
629
	$options = pfSense_get_interface_addresses($bridgeif);
630
	$flags = 0;
631
	if (!isset($options['encaps']['txcsum']))
632
		$flags |= IFCAP_TXCSUM;
633

    
634
	if (!isset($options['encaps']['rxcsum']))
635
		$flags |= IFCAP_RXCSUM;
636

    
637
	pfSense_interface_capabilities($interface, -$flags);
638

    
639
	interfaces_bring_up($interface);
640
	mwexec("/sbin/ifconfig {$bridgeif} addm {$interface}");
641
}
642

    
643
function interfaces_lagg_configure() 
644
{
645
        global $config, $g;
646
		if($g['booting']) 
647
			echo "Configuring LAGG interfaces...";
648
        $i = 0;
649
		if (is_array($config['laggs']['lagg']) && count($config['laggs']['lagg'])) {
650
			foreach ($config['laggs']['lagg'] as $lagg) {
651
				if(empty($lagg['laggif']))
652
					$lagg['laggif'] = "lagg{$i}";
653
				/* XXX: Maybe we should report any errors?! */
654
				interface_lagg_configure($lagg);
655
				$i++;
656
			}
657
		}
658
		if($g['booting']) 
659
			echo "done.\n";
660
}
661

    
662
function interface_lagg_configure(&$lagg) {
663
        global $config, $g;
664

    
665
        if (!is_array($lagg))
666
		return -1;
667

    
668
	$members = explode(',', $lagg['members']);
669
	if (!count($members))
670
		return -1;
671
	
672
	$checklist = get_interface_list();
673

    
674
	if ($g['booting'] || !(empty($lagg['laggif']))) {
675
		pfSense_interface_destroy($lagg['laggif']);
676
		pfSense_interface_create($lagg['laggif']);
677
                $laggif = $lagg['laggif'];
678
        } else
679
		$laggif = pfSense_interface_create("lagg");
680

    
681
	/* Calculate smaller mtu and enforce it */
682
        $smallermtu = 0;
683
        foreach ($members as $member) {
684
		$opts = pfSense_get_interface_addresses($member);
685
                $mtu = $opts['mtu'];
686
		if (!isset($opts['encaps']['txcsum']))
687
                        $commontx = false;
688
                if (!isset($opts['encaps']['rxcsum']))
689
                        $commonrx = false;
690
		if (!isset($opts['encaps']['tso4']))
691
			$commontso4 = false;
692
		if (!isset($opts['encaps']['tso6']))
693
			$commontso6 = false;
694
		if (!isset($opts['encaps']['lro']))
695
			$commonlro = false;
696
		if ($smallermtu == 0 && !empty($mtu))
697
			$smallermtu = $mtu;
698
                else if (!empty($mtu) && $mtu < $smallermtu)
699
                        $smallermtu = $mtu;
700
        }
701

    
702
	/* Just in case anything is not working well */
703
        if ($smallermtu == 0)
704
                $smallermtu = 1500;
705

    
706
	$flags = 0;
707
        if ($commonrx === false)
708
                $flags |= IFCAP_RXCSUM;
709
        if ($commontx === false)
710
                $flags |= IFCAP_TXCSUM;
711
	if ($commontso4 === false)
712
                $flags |= IFCAP_TSO4;
713
        if ($commontso6 === false)
714
                $flags |= IFCAP_TSO6;
715
        if ($commonlro === false)
716
                $flags |= IFCAP_LRO;
717

    
718
	foreach ($members as $member) {
719
		if (!array_key_exists($member, $checklist))
720
			continue;
721
		/* make sure the parent interface is up */
722
		pfSense_interface_mtu($member, $smallermtu);
723
		pfSense_interface_capabilities($member, -$flags);
724
		interfaces_bring_up($member);
725
		mwexec("/sbin/ifconfig {$laggif} laggport {$member}");
726
	}
727
	
728
	mwexec("/sbin/ifconfig {$laggif} laggproto {$lagg['proto']}");
729

    
730
	interfaces_bring_up($laggif);
731

    
732
	return $laggif;
733
}
734

    
735
function interfaces_gre_configure($checkparent = 0) {
736
        global $config;
737

    
738
        if (is_array($config['gres']['gre']) && count($config['gres']['gre'])) {
739
                foreach ($config['gres']['gre'] as $i => $gre) {
740
                        if(empty($gre['greif']))
741
                                $gre['greif'] = "gre{$i}";
742
			if ($checkparent == 1 && strstr($gre['if'], "vip"))
743
				continue;
744
			if ($checkparent == 2 && !strstr($gre['if'], "vip"))
745
				continue;
746
                        /* XXX: Maybe we should report any errors?! */
747
                        interface_gre_configure($gre);
748
                }
749
        }
750
}
751

    
752
/* NOTE: $grekey is not used but useful for passing this function to array_walk. */
753
function interface_gre_configure(&$gre, $grekey = "") {
754
        global $config, $g;
755

    
756
	if (!is_array($gre))
757
		return -1;
758

    
759
	$realif = get_real_interface($gre['if']);
760
	$realifip = get_interface_ip($gre['if']);
761

    
762
	/* make sure the parent interface is up */
763
	interfaces_bring_up($realif);
764

    
765
	if ($g['booting'] || !(empty($gre['greif']))) {
766
		pfSense_interface_destroy($gre['greif']);
767
		pfSense_interface_create($gre['greif']);
768
		$greif = $gre['greif'];
769
	} else
770
		$greif = pfSense_interface_create("gre");
771

    
772
	/* Do not change the order here for more see gre(4) NOTES section. */
773
	mwexec("/sbin/ifconfig {$greif} tunnel {$realifip} {$gre['remote-addr']}");
774
	mwexec("/sbin/ifconfig {$greif} {$gre['tunnel-local-addr']} {$gre['tunnel-remote-addr']} netmask " . gen_subnet_mask($gre['tunnel-remote-net']));
775
	if (isset($gre['link0']) && $gre['link0'])
776
		pfSense_interface_flags($greif, IFF_LINK0);
777
	if (isset($gre['link1']) && $gre['link1'])
778
		pfSense_interface_flags($greif, IFF_LINK1);
779
	if (isset($gre['link2']) && $gre['link2'])
780
		pfSense_interface_flags($greif, IFF_LINK2);
781

    
782
	if($greif)
783
		interfaces_bring_up($greif);
784
	else 
785
		log_error("Could not bring greif up -- variable not defined.");
786

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

    
791
	return $greif;
792
}
793

    
794
function interfaces_gif_configure($checkparent = 0) {
795
	global $config;
796

    
797
	if (is_array($config['gifs']['gif']) && count($config['gifs']['gif'])) {
798
		foreach ($config['gifs']['gif'] as $i => $gif) {
799
			if(empty($gif['gifif']))
800
				$gre['gifif'] = "gif{$i}";
801
			if ($checkparent == 1 && strstr($gif['if'], "vip"))
802
				continue;
803
			if ($checkparent == 2 && !strstr($gif['if'], "vip"))
804
				continue;
805
			/* XXX: Maybe we should report any errors?! */
806
			interface_gif_configure($gif);
807
		}
808
	}
809
}
810

    
811
/* NOTE: $gifkey is not used but useful for passing this function to array_walk. */
812
function interface_gif_configure(&$gif, $gifkey = "") {
813
	global $config, $g;
814

    
815
	if (!is_array($gif))
816
		return -1;
817

    
818
	$realif = get_real_interface($gif['if']);
819
	$realifip = get_interface_ip($gif['if']);
820

    
821
	/* make sure the parent interface is up */
822
	if($realif)
823
		interfaces_bring_up($realif);
824
	else 
825
		log_error("could not bring realif up -- variable not defined -- interface_gif_configure()");
826

    
827
	if ($g['booting'] || !(empty($gif['gifif']))) {
828
		pfSense_interface_destroy($gif['gifif']);
829
		pfSense_interface_create($gif['gifif']);
830
		$gifif = $gif['gifif'];
831
	} else
832
		$gifif = pfSense_interface_create("gif");
833

    
834
	/* Do not change the order here for more see gif(4) NOTES section. */
835
	mwexec("/sbin/ifconfig {$gifif} tunnel {$realifip} {$gif['remote-addr']}");
836
	mwexec("/sbin/ifconfig {$gifif} {$gif['tunnel-local-addr']} {$gif['tunnel-remote-addr']} netmask " . gen_subnet_mask($gif['tunnel-remote-net']));
837
	if (isset($gif['link0']) && $gif['link0'])
838
		pfSense_interface_flags($gifif, IFF_LINK0);
839
	if (isset($gif['link1']) && $gif['link1'])
840
		pfSense_interface_flags($gifif, IFF_LINK1);
841
	if($gifif)
842
		interfaces_bring_up($gifif);
843
	else
844
		log_error("could not bring gifif up -- variable not defined");
845

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

    
850
	return $gifif;
851
}
852

    
853
function interfaces_configure() {
854
	global $config, $g;
855

    
856
	/* Set up our loopback interface */
857
	interfaces_loopback_configure();
858

    
859
	/* set up LAGG virtual interfaces */
860
	interfaces_lagg_configure();
861

    
862
	/* set up VLAN virtual interfaces */
863
	interfaces_vlan_configure();
864

    
865
	interfaces_qinq_configure();
866

    
867
	$iflist = get_configured_interface_with_descr();
868
	$delayed_list = array();
869
	$bridge_list = array();
870
	
871
	/* This is needed to speedup interfaces on bootup. */
872
	$reload = false;
873
	if ($g['booting'])
874
		$reload = true;
875

    
876
	foreach($iflist as $if => $ifname) {
877
		$realif = $config['interfaces'][$if]['if'];
878
		if (strstr($realif, "bridge")) 
879
			$bridge_list[$if] = $ifname;
880
		else if (strstr($realif, "gre"))
881
			$delayed_list[$if] = $ifname;
882
		else if (strstr($realif, "gif"))
883
			$delayed_list[$if] = $ifname;
884
		else if (strstr($realif, "ovpn")) {
885
			//echo "Delaying OpenVPN interface configuration...done.\n";
886
			continue;
887
		} else {
888
			if ($g['booting'])
889
				echo "Configuring {$ifname} interface...";
890
			if($g['debug'])
891
				log_error("Configuring {$ifname}");
892
			interface_configure($if, $reload);
893
			if ($g['booting']) 
894
				echo "done.\n";
895
		}
896
	}
897

    
898
	/* create the unconfigured wireless clones */
899
	interfaces_create_wireless_clones();
900

    
901
	/*
902
	 * NOTE: The following function parameter consists of
903
	 *	1 - Do not load gre/gif/bridge with parent/member as vip
904
	 *	2 - Do load gre/gif/bridge with parent/member as vip
905
	 */
906

    
907
	/* set up GRE virtual interfaces */
908
	interfaces_gre_configure(1);
909

    
910
	/* set up GIF virtual interfaces */
911
	interfaces_gif_configure(1);
912

    
913
	/* set up BRIDGe virtual interfaces */
914
	interfaces_bridge_configure(1);
915

    
916
	/* bring up vip interfaces */
917
	interfaces_vips_configure();
918

    
919
	/* set up GRE virtual interfaces */
920
	interfaces_gre_configure(2);
921

    
922
	/* set up GIF virtual interfaces */
923
	interfaces_gif_configure(2);
924

    
925
	foreach ($delayed_list as $if => $ifname) {
926
		if ($g['booting'])
927
			echo "Configuring {$ifname} interface...";
928
        	if ($g['debug'])
929
        		log_error("Configuring {$ifname}");
930

    
931
		interface_configure($if, $reload);
932

    
933
		if ($g['booting'])
934
			echo "done.\n";
935
	}
936

    
937
	/* set up BRIDGe virtual interfaces */
938
	interfaces_bridge_configure(2);
939

    
940
	foreach ($bridge_list as $if => $ifname) {
941
		if ($g['booting'])
942
			echo "Configuring {$ifname} interface...";
943
		if($g['debug'])
944
			log_error("Configuring {$ifname}");
945

    
946
		interface_configure($if, $reload);
947

    
948
		if ($g['booting'])
949
			echo "done.\n";
950
	}
951

    
952
	/* configure interface groups */
953
	interfaces_group_setup();
954

    
955
	if (!$g['booting']) {
956
		/* reconfigure static routes (kernel may have deleted them) */
957
		system_routing_configure();
958

    
959
		/* reload IPsec tunnels */
960
		vpn_ipsec_configure();
961

    
962
		/* reload dhcpd (interface enabled/disabled status may have changed) */
963
		services_dhcpd_configure();
964

    
965
		/* restart dnsmasq */
966
		services_dnsmasq_configure();
967

    
968
		/* reload captive portal */
969
		captiveportal_init_rules();
970
	}
971

    
972
	return 0;
973
}
974

    
975
function interface_reconfigure($interface = "wan", $reloadall = false) {
976
	interface_bring_down($interface);
977
	interface_configure($interface, $reloadall);
978
}
979

    
980
function interface_vip_bring_down($vip) {
981
	global $g;
982

    
983
	switch ($vip['mode']) {
984
	case "proxyarp":
985
		$vipif = get_real_interface($vip['interface']);
986
		if (file_exists("{$g['varrun_path']}/choparp_{$vipif}.pid"))
987
			killbypid("{$g['varrun_path']}/choparp_{$vipif}.pid");
988
		break;
989
	case "ipalias":
990
		$vipif = get_real_interface($vip['interface']);
991
		if(does_interface_exist($vipif))
992
			pfSense_interface_deladdress($vipif, $vip['subnet']);
993
		break;
994
	case "carp":
995
		$vipif = "vip" . $vip['vhid'];
996
		if(does_interface_exist($vipif)) 
997
			pfSense_interface_destroy($vipif);
998
		break;
999
	case "carpdev-dhcp":
1000
		$vipif = "vip" . $vip['vhid'];
1001
		if(does_interface_exist($vipif)) 
1002
			pfSense_interface_destroy($vipif);
1003
		break;
1004
	}
1005
}
1006

    
1007
function interface_bring_down($interface = "wan", $destroy = false) {
1008
	global $config, $g;
1009

    
1010
	if (!isset($config['interfaces'][$interface]))
1011
		return; 
1012

    
1013
	$ifcfg = $config['interfaces'][$interface];
1014

    
1015
	$realif = get_real_interface($interface);
1016

    
1017
	switch ($ifcfg['ipaddr']) {
1018
	case "ppp":
1019
	case "pppoe":
1020
	case "pptp":
1021
	case "l2tp":
1022
		if (is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) {
1023
			foreach ($config['ppps']['ppp'] as $pppid => $ppp) {
1024
				if ($realif == $ppp['if']) {
1025
					if (isset($ppp['ondemand']) && !$destroy){
1026
						send_event("interface reconfigure {$interface}");
1027
						break;
1028
					}
1029
					if (file_exists("{$g['varrun_path']}/{$ppp['type']}_{$interface}.pid")) {
1030
						killbypid("{$g['varrun_path']}/{$ppp['type']}_{$interface}.pid");
1031
						sleep(2);
1032
					}
1033
					unlink_if_exists("{$g['varetc_path']}/mpd_{$interface}.conf");
1034
					break;
1035
				}
1036
			}
1037
		}
1038
		break;
1039
	case "carpdev-dhcp":
1040
		/* 
1041
		 * NB: When carpdev gets enabled it would be better to be handled as all
1042
		 *	   other interfaces! 
1043
		 */
1044
	case "dhcp":
1045
		$pid = find_dhclient_process($realif);
1046
		if($pid)
1047
			mwexec("/bin/kill {$pid}");
1048
		sleep(1);
1049
		unlink_if_exists("{$g['varetc_path']}/dhclient_{$interface}.conf");
1050
		if(does_interface_exist("$realif")) {
1051
			mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete", true);
1052
			if ($destroy == true)
1053
				pfSense_interface_flags($realif, -IFF_UP);
1054
			mwexec("/usr/sbin/arp -d -i {$realif} -a");
1055
		}
1056
		break;
1057
	default:
1058
		if(does_interface_exist("$realif")) {
1059
			mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete", true);
1060
			if ($destroy == true)
1061
				pfSense_interface_flags($realif, -IFF_UP);
1062
			mwexec("/usr/sbin/arp -d -i {$realif} -a");
1063
		}
1064
		break;
1065
	}
1066

    
1067
	/* remove interface up file if it exists */
1068
	unlink_if_exists("{$g['tmp_path']}/{$realif}up");
1069
	unlink_if_exists("{$g['vardb_path']}/{$interface}ip");
1070
	unlink_if_exists("{$g['tmp_path']}/{$realif}_router");
1071
	unlink_if_exists("{$g['varetc_path']}/nameserver_{$realif}");
1072
	unlink_if_exists("{$g['varetc_path']}/searchdomain_{$realif}");
1073
	
1074
	/* hostapd and wpa_supplicant do not need to be running when the interface is down.
1075
	 * They will also use 100% CPU if running after the wireless clone gets deleted. */
1076
	if (is_array($ifcfg['wireless'])) {
1077
		mwexec(kill_hostapd($realif));
1078
		mwexec(kill_wpasupplicant($realif));
1079
	}
1080

    
1081
	if ($destroy == true) {
1082
		if (preg_match("/^vip|^tun|^ovpn|^gif|^gre|^lagg|^bridge|vlan/i", $realif))
1083
			pfSense_interface_destroy($realif);
1084
	}	
1085

    
1086
	return;
1087
}
1088

    
1089
function interfaces_ptpid_used($ptpid) {
1090
	global $config;
1091

    
1092
	if (is_array($config['ppps']['ppp']))
1093
		foreach ($config['ppps']['ppp'] as & $settings)
1094
			if ($ptpid == $settings['ptpid'])
1095
				return true;
1096

    
1097
	return false;
1098
}
1099

    
1100
function interfaces_ptpid_next() {
1101

    
1102
	$ptpid = 0;
1103
	while(interfaces_ptpid_used($ptpid))
1104
		$ptpid++;
1105

    
1106
	return $ptpid;
1107
}
1108

    
1109
function getMPDCRONSettings($pppif_) {
1110
	global $config;
1111
	$cron_cmd_file = "{$g['varetc_path']}/pppoe_restart_";
1112
	if (is_array($config['cron']['item'])) {
1113
		for ($i = 0; $i < count($config['cron']['item']); $i++) {
1114
			$item = $config['cron']['item'][$i];
1115
			if (strpos($item['command'], $cron_cmd_file.$pppif_) !== false) {
1116
				return array("ID" => $i, "ITEM" => $item);
1117
			}
1118
		}
1119
	}
1120
	return NULL;
1121
}
1122

    
1123
function handle_pppoe_reset($post_array) {
1124
	global $config, $g;
1125

    
1126
	$cron_cmd_file = "{$g['varetc_path']}/pppoe_restart_";
1127

    
1128
	$pppif = $post_array['type'].$post_array['ptpid'];
1129
	if (!is_array($config['cron']['item'])) 
1130
		$config['cron']['item'] = array(); 
1131
	$itemhash = getMPDCRONSettings($pppif);
1132
	$item = $itemhash['ITEM'];
1133
	
1134
	// reset cron items if necessary and return
1135
	if (empty($post_array['pppoe-reset-type'])) {
1136
		if (isset($item))
1137
			unset($config['cron']['item'][$itemhash['ID']]);
1138
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
1139
		return;
1140
	}
1141

    
1142
	if (empty($item)) 
1143
		$item = array();
1144
	if (isset($post_array['pppoe-reset-type']) && $post_array['pppoe-reset-type'] == "custom") {
1145
		$item['minute'] = $post_array['pppoe_resetminute'];
1146
		$item['hour'] = $post_array['pppoe_resethour'];
1147
		if (isset($post_array['pppoe_resetdate']) && $post_array['pppoe_resetdate'] <> "") {
1148
			$date = explode("/", $post_array['pppoe_resetdate']);
1149
			$item['mday'] = $date[1];
1150
			$item['month'] = $date[0];
1151
		} else {
1152
			$item['mday'] = "*";
1153
			$item['month'] = "*";
1154
		}
1155
		$item['wday'] = "*";
1156
		$item['who'] = "root";
1157
		$item['command'] = $cron_cmd_file.$pppif;
1158
	} else if (isset($post_array['pppoe-reset-type']) && $post_array['pppoe-reset-type'] == "preset") {
1159
		switch ($post_array['pppoe_pr_preset_val']) {
1160
			case "monthly":
1161
				$item['minute'] = "0";
1162
				$item['hour'] = "0";
1163
				$item['mday'] = "1";
1164
				$item['month'] = "*";
1165
				$item['wday'] = "*";
1166
				$item['who'] = "root";
1167
				$item['command'] = $cron_cmd_file.$pppif;
1168
				break;
1169
	        case "weekly":
1170
				$item['minute'] = "0";
1171
				$item['hour'] = "0";
1172
				$item['mday'] = "*";
1173
				$item['month'] = "*";
1174
				$item['wday'] = "0";
1175
				$item['who'] = "root";
1176
				$item['command'] = $cron_cmd_file.$pppif;
1177
				break;
1178
			case "daily":
1179
				$item['minute'] = "0";
1180
				$item['hour'] = "0";
1181
				$item['mday'] = "*";
1182
				$item['month'] = "*";
1183
				$item['wday'] = "*";
1184
				$item['who'] = "root";
1185
				$item['command'] = $cron_cmd_file.$pppif;
1186
				break;
1187
			case "hourly":
1188
				$item['minute'] = "0";
1189
				$item['hour'] = "*";
1190
				$item['mday'] = "*";
1191
				$item['month'] = "*";
1192
				$item['wday'] = "*";
1193
				$item['who'] = "root";
1194
				$item['command'] = $cron_cmd_file.$pppif;
1195
				break;
1196
		} // end switch
1197
	} else {
1198
		/* test whether a cron item exists and unset() it if necessary */
1199
		$itemhash = getMPDCRONSettings($pppif);
1200
		$item = $itemhash['ITEM'];
1201
		if (isset($item))
1202
			unset($config['cron']['item'][$itemhash['ID']]); 
1203
	}// end if
1204
	if (isset($itemhash['ID'])) 
1205
		$config['cron']['item'][$itemhash['ID']] = $item;
1206
	else 
1207
		$config['cron']['item'][] = $item;
1208
}
1209

    
1210
/*	This function can configure PPPoE, MLPPP (PPPoE), PPTP.
1211
*	It writes the mpd config file to /var/etc every time the link is opened.
1212
*/
1213

    
1214
function interface_ppps_configure($interface) {
1215
	global $config, $g;
1216

    
1217
	/* Return for unassigned interfaces. This is a minimum requirement. */
1218
	if (empty($config['interfaces'][$interface]))
1219
		return 0;
1220
	$ifcfg = $config['interfaces'][$interface];
1221
	if (!isset($ifcfg['enable']))
1222
		return 0;
1223

    
1224
	// mpd5 requires a /var/spool/lock directory for PPP modem links.
1225
	if(!is_dir("/var/spool/lock")) {
1226
		exec("/bin/mkdir -p /var/spool/lock");
1227
		exec("/bin/chmod a+rw /var/spool/lock/.");
1228
	}
1229
	// mpd5 modem chat script expected in the same directory as the mpd_xxx.conf files	
1230
	if (!file_exists("{$g['varetc_path']}/mpd.script"))
1231
		mwexec("/bin/ln -s /usr/local/sbin/mpd.script {$g['varetc_path']}/.");
1232

    
1233
	if (is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) {
1234
		foreach ($config['ppps']['ppp'] as $pppid => $ppp) {
1235
			if ($ifcfg['if'] == $ppp['if'])
1236
				break;
1237
		}
1238
	}
1239
	if (!$ppp || $ifcfg['if'] != $ppp['if']){
1240
		log_error("Can't find PPP config for {$ifcfg['if']} in interface_ppps_configure().");
1241
		return 0;
1242
	}
1243
	$pppif = $ifcfg['if'];
1244
	if ($ppp['type'] == "ppp")
1245
		$type = "modem";
1246
	else
1247
		$type = $ppp['type'];
1248
	$upper_type = strtoupper($ppp['type']);	
1249

    
1250
	if($g['booting']) {
1251
		$descr = isset($ifcfg['descr']) ? $ifcfg['descr'] : strtoupper($interface);
1252
		echo "starting {$pppif} link...";
1253
		// Do not re-configure the interface if we are booting and it's already been started
1254
		if(file_exists("{$g['varrun_path']}/{$ppp['type']}_{$interface}.pid"))
1255
			return 0;
1256
	}
1257

    
1258
	$ports = explode(',',$ppp['ports']);
1259
	if ($type != "modem") {
1260
		foreach ($ports as $pid => $port)
1261
			$ports[$pid] = get_real_interface($port);
1262
	}
1263
	$localips = explode(',',$ppp['localip']);
1264
	$gateways = explode(',',$ppp['gateway']);
1265
	$subnets = explode(',',$ppp['subnet']);
1266

    
1267
	/* We bring up the parent interface first because if DHCP is configured on the parent we need
1268
	 * to obtain an address first so we can write it in the mpd .conf file for PPTP and L2TP configs
1269
	 */
1270
	foreach($ports as $pid => $port){
1271
		switch ($ppp['type']) {
1272
			case "pppoe": 
1273
				/* Bring the parent interface up */
1274
				interfaces_bring_up($port);
1275
				pfSense_ngctl_attach(".", $port);
1276
				break;
1277
			case "pptp":
1278
			case "l2tp":
1279
				/* configure interface */
1280
				if(is_ipaddr($localips[$pid])){
1281
					// Manually configure interface IP/subnet
1282
					pfSense_interface_setaddress($port, "{$localips[$pid]}/{$subnets[$pid]}");
1283
					interfaces_bring_up($port);
1284
				} else if (empty($localips[$pid]))
1285
					$localips[$pid] = get_interface_ip($port); // try to get the interface IP from the port
1286
				
1287
				if(!is_ipaddr($localips[$pid])){
1288
					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!");
1289
					$localips[$pid] = "0.0.0.0";
1290
				}
1291
				/* XXX: This needs to go away soon! [It's commented out!] */
1292
				/* Configure the gateway (remote IP ) */
1293
				if (!$g['booting'] && !is_ipaddr($gateways[$pid]) && is_hostname($gateways[$pid])) {
1294
					/* XXX: Fix later 
1295
					$gateways[$pid] = gethostbyname($gateways[$pid]);
1296
					if(!is_ipaddr($gateways[$pid])) {
1297
						log_error("Could not get a valid Gateway IP from {$port} via DNS in interfaces_ppps_configure.");
1298
						return 0;
1299
					}
1300
					*/
1301
				}
1302
				if(!is_ipaddr($gateways[$pid])){
1303
					log_error("Could not get a PPTP/L2TP Remote IP address from {$dhcp_gateway} for {$gway} in interfaces_ppps_configure.");
1304
					return 0;
1305
				}
1306
				pfSense_ngctl_attach(".", $port);
1307
				break;
1308
			case "ppp":
1309
				if (!file_exists("{$port}")) {
1310
					log_error("Device {$port} does not exist. PPP link cannot start without the modem device.");
1311
					return 0;
1312
				}
1313
				break;
1314
			default:
1315
				log_error("Unkown {$type} configured as ppp interface.");
1316
				break;
1317
		}
1318
	}
1319
	
1320
	if (is_array($ports) && count($ports) > 1)
1321
		$multilink = "enable";
1322
	else
1323
		$multilink = "disable";
1324
	
1325
	if ($type == "modem"){
1326
		if (is_ipaddr($ppp['localip']))
1327
			$localip = $ppp['localip'];
1328
		else
1329
			$localip = '0.0.0.0';
1330

    
1331
		if (is_ipaddr($ppp['gateway']))
1332
			$gateway = $ppp['gateway'];
1333
		else
1334
			$gateway = "10.64.64.{$pppid}";
1335
		$ranges = "{$localip}/0 {$gateway}/0";
1336
		
1337
		if (empty($ppp['apnum']))	
1338
			$ppp['apnum'] = 1;
1339
	} else
1340
		$ranges = "0.0.0.0/0 0.0.0.0/0";
1341

    
1342
	if (isset($ppp['ondemand'])) 
1343
		$ondemand = "enable";
1344
	else
1345
		$ondemand = "disable";
1346
	if (!isset($ppp['idletimeout']))
1347
		$ppp['idletimeout'] = 0;
1348

    
1349
	if (empty($ppp['username']) && $type == "modem"){
1350
		$ppp['username'] = "user";
1351
		$ppp['password'] = "none";
1352
	}
1353
	if (empty($ppp['password']) && $type == "modem")
1354
		$passwd = "none";
1355
	else
1356
		$passwd = base64_decode($ppp['password']);
1357

    
1358
	$bandwidths = explode(',',$ppp['bandwidth']);
1359
	$mtus = explode(',',$ppp['mtu']);
1360
	$mrus = explode(',',$ppp['mru']);
1361

    
1362
	if (isset($ppp['mrru']))
1363
		$mrrus = explode(',',$ppp['mrru']);
1364

    
1365
	// Construct the mpd.conf file
1366
	$mpdconf = <<<EOD
1367
startup:
1368
	# configure the console
1369
	set console close
1370
	# configure the web server
1371
	set web close
1372

    
1373
default:
1374
{$ppp['type']}client:
1375
	create bundle static {$interface}
1376
	set iface name {$pppif}
1377

    
1378
EOD;
1379
	$setdefaultgw = false;
1380
	$founddefaultgw = false;
1381
	if (is_array($config['gateways']['gateway_item'])) {
1382
		foreach($config['gateways']['gateway_item'] as $gateway) {
1383
			if($interface == $gateway['interface'] && isset($gateway['defaultgw'])) {
1384
				$setdefaultgw = true;
1385
				break;
1386
			} else if (isset($gateway['defaultgw']) && !empty($gateway['interface'])) {
1387
				$founddefaultgw = true;
1388
				break;
1389
			}
1390
		}
1391
	}
1392
	
1393
	if (($interface == "wan" && $founddefaultgw == false) || $setdefaultgw == true){
1394
		$setdefaultgw = true;
1395
		$mpdconf .= <<<EOD
1396
	set iface route default
1397

    
1398
EOD;
1399
	}
1400
	$mpdconf .= <<<EOD
1401
	set iface {$ondemand} on-demand
1402
	set iface idle {$ppp['idletimeout']}
1403

    
1404
EOD;
1405

    
1406
	if (isset($ppp['ondemand']))
1407
		$mpdconf .= <<<EOD
1408
	set iface addrs 10.10.1.1 10.10.1.2
1409

    
1410
EOD;
1411
	
1412
	if (isset($ppp['tcpmssfix']))
1413
		$tcpmss = "disable";
1414
	else
1415
		$tcpmss = "enable";
1416
		$mpdconf .= <<<EOD
1417
	set iface {$tcpmss} tcpmssfix
1418

    
1419
EOD;
1420

    
1421
	$mpdconf .= <<<EOD
1422
	set iface up-script /usr/local/sbin/ppp-linkup
1423
	set iface down-script /usr/local/sbin/ppp-linkdown
1424
	set ipcp ranges {$ranges}
1425

    
1426
EOD;
1427
	if (isset($ppp['vjcomp']))
1428
		$mpdconf .= <<<EOD
1429
	set ipcp no vjcomp
1430

    
1431
EOD;
1432

    
1433
	if (isset($config['system']['dnsallowoverride']))
1434
		$mpdconf .= <<<EOD
1435
	set ipcp enable req-pri-dns
1436
	set ipcp enable req-sec-dns
1437

    
1438
EOD;
1439
	if (!isset($ppp['verbose_log']))
1440
		$mpdconf .= <<<EOD
1441
	#log -bund -ccp -chat -iface -ipcp -lcp -link
1442

    
1443
EOD;
1444
	foreach($ports as $pid => $port){
1445
		$port = get_real_interface($port);
1446
		$mpdconf .= <<<EOD
1447

    
1448
	create link static {$interface}_link{$pid} {$type}
1449
	set link action bundle {$interface}
1450
	set link {$multilink} multilink
1451
	set link keep-alive 10 60
1452
	set link max-redial 0
1453

    
1454
EOD;
1455
		if (isset($ppp['shortseq']))
1456
			$mpdconf .= <<<EOD
1457
	set link no shortseq
1458

    
1459
EOD;
1460

    
1461
		if (isset($ppp['acfcomp']))
1462
			$mpdconf .= <<<EOD
1463
	set link no acfcomp
1464

    
1465
EOD;
1466

    
1467
		if (isset($ppp['protocomp']))
1468
			$mpdconf .= <<<EOD
1469
	set link no protocomp
1470

    
1471
EOD;
1472

    
1473
		$mpdconf .= <<<EOD
1474
	set link disable chap pap
1475
	set link accept chap pap eap
1476
	set link disable incoming
1477

    
1478
EOD;
1479

    
1480

    
1481
		if (!empty($bandwidths[$pid]))
1482
			$mpdconf .= <<<EOD
1483
	set link bandwidth {$bandwidths[$pid]}
1484

    
1485
EOD;
1486

    
1487
		if (empty($mtus[$pid]))
1488
			$mtus[$pid] = "1492";
1489
			$mpdconf .= <<<EOD
1490
	set link mtu {$mtus[$pid]}
1491

    
1492
EOD;
1493

    
1494
		if (!empty($mrus[$pid]))
1495
			$mpdconf .= <<<EOD
1496
	set link mru {$mrus[$pid]}
1497

    
1498
EOD;
1499

    
1500
		if (!empty($mrrus[$pid]))
1501
			$mpdconf .= <<<EOD
1502
	set link mrru {$mrrus[$pid]}
1503

    
1504
EOD;
1505

    
1506
		$mpdconf .= <<<EOD
1507
	set auth authname "{$ppp['username']}"
1508
	set auth password {$passwd}
1509

    
1510
EOD;
1511
		if ($type == "modem") {
1512
			$mpdconf .= <<<EOD
1513
	set modem device {$ppp['ports']}
1514
	set modem script DialPeer
1515
	set modem idle-script Ringback
1516
	set modem watch -cd
1517
	set modem var \$DialPrefix "DT"
1518
	set modem var \$Telephone "{$ppp['phone']}"
1519

    
1520
EOD;
1521
		}
1522
		if (isset($ppp['connect-timeout']) && $type == "modem") {
1523
			$mpdconf .= <<<EOD
1524
	set modem var \$ConnectTimeout "{$ppp['connect-timeout']}"
1525

    
1526
EOD;
1527
		}
1528
		if (isset($ppp['initstr']) && $type == "modem") {
1529
			$initstr = base64_decode($ppp['initstr']);
1530
			$mpdconf .= <<<EOD
1531
	set modem var \$InitString "{$initstr}"
1532

    
1533
EOD;
1534
		}
1535
		if (isset($ppp['simpin']) && $type == "modem") {
1536
			$mpdconf .= <<<EOD
1537
	set modem var \$SimPin "{$ppp['simpin']}"
1538
	set modem var \$PinWait "{$ppp['pin-wait']}"
1539

    
1540
EOD;
1541
		}
1542
		if (isset($ppp['apn']) && $type == "modem") {
1543
			$mpdconf .= <<<EOD
1544
	set modem var \$APN "{$ppp['apn']}"
1545
	set modem var \$APNum "{$ppp['apnum']}"
1546

    
1547
EOD;
1548
		}
1549
		if ($type == "pppoe") {
1550
			// Send a null service name if none is set.
1551
			$provider = isset($ppp['provider']) ? $ppp['provider'] : "";
1552
			$mpdconf .= <<<EOD
1553
	set pppoe service "{$provider}"
1554

    
1555
EOD;
1556
		}
1557
		if ($type == "pppoe")
1558
			$mpdconf .= <<<EOD
1559
	set pppoe iface {$port}
1560

    
1561
EOD;
1562

    
1563
		if ($type == "pptp" || $type == "l2tp") {
1564
			$mpdconf .= <<<EOD
1565
	set {$type} self {$localips[$pid]}
1566
	set {$type} peer {$gateways[$pid]}
1567

    
1568
EOD;
1569
		}
1570
		
1571
		$mpdconf .= "\topen\r\n";
1572
	} //end foreach($port)
1573

    
1574

    
1575
	/* Generate mpd.conf. If mpd_[interface].conf exists in the conf path, then link to it instead of generating a fresh conf file. */
1576
	if (file_exists("{$g['conf_path']}/mpd_{$interface}.conf"))
1577
		mwexec("/bin/ln -s {$g['conf_path']}/mpd_{$interface}.conf {$g['varetc_path']}/.");
1578
	else {
1579
		$fd = fopen("{$g['varetc_path']}/mpd_{$interface}.conf", "w");
1580
		if (!$fd) {
1581
			log_error("Error: cannot open mpd_{$interface}.conf in interface_ppps_configure().\n");
1582
			return 0;
1583
		}
1584
		// Write out mpd_ppp.conf
1585
		fwrite($fd, $mpdconf);
1586
		fclose($fd);
1587
	}
1588

    
1589
	// Create the uptime log if requested and if it doesn't exist already, or delete it if it is no longer requested.
1590
	if (isset($ppp['uptime'])) {
1591
		if (!file_exists("/conf/{$pppif}.log")) {
1592
			conf_mount_rw();
1593
			mwexec("echo /dev/null > /conf/{$pppif}.log");
1594
			conf_mount_ro();
1595
		}
1596
	} else {
1597
		if (file_exists("/conf/{$pppif}.log")) {
1598
			conf_mount_rw();
1599
			mwexec("rm -f /conf/{$pppif}.log");
1600
			conf_mount_ro();
1601
		}
1602
	}
1603

    
1604
	/* fire up mpd */
1605
	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");
1606

    
1607
	// Check for PPPoE periodic reset request 
1608
	if ($type == "pppoe") {
1609
		if (isset($ppp['pppoe-reset-type']))
1610
			setup_pppoe_reset_file($ppp['if'], $interface);
1611
		else
1612
			setup_pppoe_reset_file($ppp['if']);
1613
	}
1614

    
1615
	return 1;
1616
}
1617

    
1618
function interfaces_carp_setup() {
1619
	global $g, $config;
1620

    
1621
	$balanacing = "";
1622
	$pfsyncinterface = "";
1623
	$pfsyncenabled = "";
1624
	if(isset($config['system']['developerspew'])) {
1625
		$mt = microtime();
1626
		echo "interfaces_carp_setup() being called $mt\n";
1627
	}
1628

    
1629
	// Prepare CmdCHAIN that will be used to execute commands.
1630
	$cmdchain = new CmdCHAIN();	
1631

    
1632
	if ($g['booting']) {
1633
		echo "Configuring CARP settings...";
1634
		mute_kernel_msgs();
1635
	}
1636

    
1637
	/* suck in configuration items */
1638
	if($config['installedpackages']['carpsettings']) {
1639
		if($config['installedpackages']['carpsettings']['config']) {
1640
			foreach($config['installedpackages']['carpsettings']['config'] as $carp) {
1641
				$pfsyncenabled = $carp['pfsyncenabled'];
1642
				$balanacing = $carp['balancing'];
1643
				$pfsyncinterface = $carp['pfsyncinterface'];
1644
				$pfsyncpeerip = $carp['pfsyncpeerip'];
1645
			}
1646
		}
1647
	} else {
1648
		unset($pfsyncinterface);
1649
		unset($balanacing);
1650
		unset($pfsyncenabled);
1651
	}
1652

    
1653
	if($balanacing) {
1654
		$cmdchain->add("Enable CARP ARP-balancing", "/sbin/sysctl net.inet.carp.arpbalance=1", true);
1655
		$cmdchain->add("Disallow CARP preemption", "/sbin/sysctl net.inet.carp.preempt=0", true);
1656
	} else
1657
		$cmdchain->add("Enable CARP preemption", "/sbin/sysctl net.inet.carp.preempt=1", true);		
1658

    
1659
	$cmdchain->add("Enable CARP logging", "/sbin/sysctl net.inet.carp.log=1", true);
1660
	if (!empty($pfsyncinterface))
1661
		$carp_sync_int = get_real_interface($pfsyncinterface);
1662

    
1663
	if($g['booting']) {
1664
		/*    install rules to alllow pfsync to sync up during boot
1665
		 *    carp interfaces will remain down until the bootup sequence finishes
1666
		 */
1667
		$fd = fopen("{$g['tmp_path']}/rules.boot", "w");
1668
		if ($fd) {
1669
			fwrite($fd, "block quick proto carp \n");
1670
			fwrite($fd, "block quick proto pfsync \n");
1671
			fwrite($fd, "pass out quick from any to any keep state\n");
1672
			fclose($fd);
1673
			mwexec("/sbin/pfctl -f {$g['tmp_path']}/rules.boot");
1674
		} else
1675
			log_error("Could not create rules.boot file!");
1676
	}
1677

    
1678
	/* setup pfsync interface */
1679
	if($carp_sync_int and $pfsyncenabled) {
1680
		if (is_ipaddr($pfsyncpeerip))
1681
			$cmdchain->add("Bring up pfsync0 syncpeer", "/sbin/ifconfig pfsync0 syncdev {$carp_sync_int} syncpeer {$pfsyncpeerip} up", false);						
1682
		else
1683
			$cmdchain->add("Bring up pfsync0 syncdev", "/sbin/ifconfig pfsync0 syncdev {$carp_sync_int} up", false);			
1684
	} else
1685
		$cmdchain->add("Bring up pfsync0", "/sbin/ifconfig pfsync0 syncdev lo0 up", false);						
1686

    
1687
	sleep(1);
1688

    
1689
	/* XXX: Handle an issue with pfsync(4) and carp(4). In a cluster carp will come up before pfsync(4) has updated and so will cause issuese
1690
	 * for exiting sessions.
1691
	 */
1692
	$i = 0;
1693
	while (intval(trim(`/sbin/ifconfig pfsync0 | /usr/bin/grep 'syncok: 0' | /usr/bin/grep -v grep | /usr/bin/wc -l`)) == 0 && $i < 30) {
1694
		$i++;
1695
		sleep(1);
1696
	}
1697

    
1698
	if($config['virtualip']['vip'])
1699
		$cmdchain->add("Allow CARP.", "/sbin/sysctl net.inet.carp.allow=1", true);				
1700
	else
1701
		$cmdchain->add("Disallow CARP.", "/sbin/sysctl net.inet.carp.allow=0", true);		
1702
	
1703
	if($g['debug'])
1704
		$cmdchain->setdebug(); // optional for verbose logging
1705

    
1706
	$cmdchain->execute();
1707
	$cmdchain->clear();
1708

    
1709
	if ($g['booting']) {
1710
		unmute_kernel_msgs();
1711
		echo "done.\n";
1712
	}
1713
}
1714

    
1715
function interface_proxyarp_configure($interface = "") {
1716
	global $config, $g;
1717
	if(isset($config['system']['developerspew'])) {
1718
		$mt = microtime();
1719
		echo "interface_proxyarp_configure() being called $mt\n";
1720
	}
1721

    
1722
	/* kill any running choparp */
1723
	if (empty($interface))
1724
		killbyname("choparp");
1725
	else {
1726
		$vipif = get_real_interface($interface);
1727
		if (file_exists("{$g['varrun_path']}/choparp_{$vipif}.pid"))
1728
			killbypid("{$g['varrun_path']}/choparp_{$vipif}.pid");
1729
	}
1730

    
1731
	$paa = array();
1732
	if (!empty($config['virtualip']) && is_array($config['virtualip']['vip'])) {
1733

    
1734
		/* group by interface */
1735
		foreach ($config['virtualip']['vip'] as $vipent) {
1736
			if ($vipent['mode'] === "proxyarp") {
1737
				if ($vipent['interface'])
1738
					$proxyif = $vipent['interface'];
1739
				else
1740
					$proxyif = "wan";
1741
				
1742
				if (!empty($interface) && $interface != $proxyif)
1743
					continue;
1744

    
1745
				if (!is_array($paa[$proxyif]))
1746
					$paa[$proxyif] = array();
1747

    
1748
				$paa[$proxyif][] = $vipent;
1749
			}
1750
		}
1751
	}
1752

    
1753
	if (!empty($interface)) {
1754
		if (is_array($paa[$interface])) {
1755
			$paaifip = get_interface_ip($interface);
1756
                        if (!is_ipaddr($paaifip))
1757
                                return;
1758
                        $args = get_real_interface($interface) . " auto";
1759
                        foreach ($paa[$interface] as $paent) {
1760
                                if (isset($paent['subnet']))
1761
                                        $args .= " " . escapeshellarg("{$paent['subnet']}/{$paent['subnet_bits']}");
1762
                                else if (isset($paent['range']))
1763
                                        $args .= " " . escapeshellarg($paent['range']['from'] . "-" . $paent['range']['to']);
1764
                        }
1765
                        mwexec_bg("/usr/local/sbin/choparp " . $args);	
1766
		}
1767
	} else if (count($paa) > 0) {
1768
		foreach ($paa as $paif => $paents)  {
1769
			$paaifip = get_interface_ip($paif);
1770
			if (!is_ipaddr($paaifip))
1771
				continue;
1772
			$args = get_real_interface($paif) . " auto";
1773
			foreach ($paents as $paent) {
1774
				if (isset($paent['subnet']))
1775
					$args .= " " . escapeshellarg("{$paent['subnet']}/{$paent['subnet_bits']}");
1776
				else if (isset($paent['range']))
1777
					$args .= " " . escapeshellarg($paent['range']['from'] . "-" . $paent['range']['to']);
1778
			}
1779
			mwexec_bg("/usr/local/sbin/choparp " . $args);
1780
		}
1781
	}
1782
}
1783

    
1784
function interfaces_vips_configure($interface = "") {
1785
	global $g, $config;
1786
	if(isset($config['system']['developerspew'])) {
1787
		$mt = microtime();
1788
		echo "interfaces_vips_configure() being called $mt\n";
1789
	}
1790
	$paa = array();
1791
	if(is_array($config['virtualip']['vip'])) {
1792
		$carp_setuped = false;
1793
		$anyproxyarp = false;
1794
		foreach ($config['virtualip']['vip'] as $vip) {
1795
			switch ($vip['mode']) {
1796
			case "proxyarp":
1797
				/* nothing it is handled on interface_proxyarp_configure() */
1798
				if ($interface <> "" && $vip['interface'] <> $interface)
1799
					continue;
1800
				$anyproxyarp = true;
1801
				break;
1802
			case "ipalias":
1803
				if ($interface <> "" && $vip['interface'] <> $interface)
1804
					continue;
1805
				interface_ipalias_configure(&$vip);
1806
				break;
1807
			case "carp":
1808
				if ($interface <> "" && $vip['interface'] <> $interface)
1809
					continue;
1810
				if ($carp_setuped == false)
1811
					$carp_setuped = true;
1812
				interface_carp_configure($vip);
1813
				break;
1814
			case "carpdev-dhcp":
1815
				if ($interface <> "" && $vip['interface'] <> $interface)
1816
					continue;
1817
				interface_carpdev_configure($vip);
1818
				break;
1819
			}
1820
		}
1821
		if ($carp_setuped == true)
1822
			interfaces_carp_setup();
1823
		if ($anyproxyarp == true)
1824
			interface_proxyarp_configure();
1825
	}
1826
}
1827

    
1828
function interface_ipalias_configure(&$vip) {
1829

    
1830
	if ($vip['mode'] == "ipalias") {
1831
		$if = get_real_interface($vip['interface']);
1832
		mwexec("/sbin/ifconfig " . escapeshellarg($if) . " " . $vip['subnet'] . "/" . escapeshellarg($vip['subnet_bits']) . " alias");
1833
	}
1834
}
1835

    
1836
function interface_reload_carps($cif) {
1837
	global $config;
1838

    
1839
	$carpifs = link_ip_to_carp_interface(find_interface_ip($cif));
1840
	if (empty($carpifs))
1841
		return;
1842

    
1843
	$carps = explode(" ", $carpifs);
1844
	if(is_array($config['virtualip']['vip'])) {
1845
		$viparr = &$config['virtualip']['vip'];
1846
		foreach ($viparr as $vip) {
1847
			if (in_array($vip['carpif'], $carps)) {
1848
				switch ($vip['mode']) {
1849
				case "carp":
1850
					interface_vip_bring_down($vip);
1851
					sleep(1);
1852
					interface_carp_configure($vip);
1853
					break;
1854
				case "carpdev-dhcp":
1855
					interface_vip_bring_down($vip);
1856
					sleep(1);
1857
					interface_carpdev_configure($vip);
1858
					break;
1859
				case "ipalias":
1860
					interface_vip_bring_down($vip);
1861
					sleep(1);
1862
					interface_ipalias_configure($vip);
1863
					break;
1864
				}
1865
			}
1866
		}
1867
	}
1868
}
1869

    
1870
function interface_carp_configure(&$vip) {
1871
	global $config, $g;
1872
	if(isset($config['system']['developerspew'])) {
1873
		$mt = microtime();
1874
		echo "interface_carp_configure() being called $mt\n";
1875
	}
1876

    
1877
	if ($vip['mode'] != "carp")
1878
		return;
1879

    
1880
	$vip_password = $vip['password'];
1881
	$vip_password = escapeshellarg(addslashes(str_replace(" ", "", $vip_password)));
1882
	if ($vip['password'] != "")
1883
		$password = " pass {$vip_password}";
1884

    
1885
	// set the vip interface to the vhid
1886
	$vipif = "vip{$vip['vhid']}";
1887

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

    
1898
	/* Ensure CARP IP really exists prior to loading up. */
1899
	$ww_subnet_ip = find_interface_ip($realif);
1900
	$ww_subnet_bits = find_interface_subnet($realif);
1901
	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'])) {
1902
		file_notice("CARP", "Sorry but we could not find a matching real interface subnet for the virtual IP address {$vip['subnet']}.", "Firewall: Virtual IP", "");
1903
		return;
1904
	}
1905

    
1906
	/* create the carp interface and setup */
1907
	if (does_interface_exist($vipif)) {
1908
		pfSense_interface_flags($vipif, -IFF_UP);
1909
	} else {
1910
		$carpif = pfSense_interface_create("carp");
1911
		pfSense_interface_rename($carpif, $vipif);
1912
		pfSense_ngctl_name("{$carpif}:", $vipif);
1913
	}
1914

    
1915
	/* invalidate interface cache */
1916
	get_interface_arr(true);
1917

    
1918
	$broadcast_address = gen_subnet_max($vip['subnet'], $vip['subnet_bits']);
1919
	$advbase = "";
1920
	if (!empty($vip['advbase']))
1921
		$advbase = "advbase {$vip['advbase']}";
1922
	mwexec("/sbin/ifconfig {$vipif} {$vip['subnet']}/{$vip['subnet_bits']} vhid {$vip['vhid']} advskew {$vip['advskew']} {$advbase} {$password}");
1923

    
1924
	interfaces_bring_up($vipif);
1925
	
1926
	return $vipif;
1927
}
1928

    
1929
function interface_carpdev_configure(&$vip) {
1930
	global $g;
1931

    
1932
	if ($vip['mode'] != "carpdev-dhcp")
1933
		return;
1934

    
1935
	$vip_password = $vip['password'];
1936
	$vip_password = str_replace(" ", "", $vip_password);
1937
	if($vip['password'] != "")
1938
		$password = " pass \"" . $vip_password . "\"";
1939

    
1940
	if (empty($vip['interface']))
1941
		return;
1942

    
1943
	$vipif = "vip" . $vip['vhid'];
1944
	$realif = get_real_interface($vip['interface']);
1945
	interfaces_bring_up($realif);
1946
	/*
1947
	 * ensure the interface containing the VIP really exists
1948
	 * prevents a panic if the interface is missing or invalid
1949
	 */
1950
	if (!does_interface_exist($realif)) {
1951
		file_notice("CARP", "Interface specified for the virtual IP address {$vip['subnet']} does not exist. Skipping this VIP.", "Firewall: Virtual IP", "");
1952
		return;
1953
	}
1954

    
1955
	if (does_interface_exist($vipif)) {
1956
		interface_bring_down($vipif);
1957
	} else {
1958
		$carpdevif = exec("/sbin/ifconfig carp create");
1959
		mwexec("/sbin/ifconfig {$carpdevif} name {$vipif}");
1960
		pfSense_ngctl_name("{$carpdevif}:", $vipif);
1961
	}
1962

    
1963
	mwexec("/sbin/ifconfig {$vipif} carpdev {$realif} vhid {$vip['vhid']} advskew {$vip['advskew']} advbase {$vip['advbase']} {$password}");
1964
	interfaces_bring_up($vipif);
1965

    
1966
	/*
1967
	 * XXX: BIG HACK but carpdev needs ip services active
1968
	 *      before even starting something as dhclient.
1969
	 *      I do not know if this is a feature or a bug
1970
	 *      but better than track it make it work ;) .
1971
	 */
1972
	//$fakeiptouse = "10.254.254." . ($carp_instances_counter+1);
1973
	//$cmdchain->add("CarpDEV hack", "/sbin/ifconfig {$carpint} inet {$fakeiptouse}", false);
1974

    
1975
	/* generate dhclient_wan.conf */
1976
	$fd = fopen("{$g['varetc_path']}/dhclient_{$vipif}.conf", "w");
1977
	if ($fd) {
1978
		$dhclientconf = "";
1979

    
1980
		$dhclientconf .= <<<EOD
1981
interface "{$vipif}" {
1982
timeout 60;
1983
retry 1;
1984
select-timeout 0;
1985
initial-interval 1;
1986
script "/sbin/dhclient-script";
1987
}
1988

    
1989
EOD;
1990

    
1991
		fwrite($fd, $dhclientconf);
1992
		fclose($fd);
1993

    
1994
		/* fire up dhclient */
1995
		mwexec("/sbin/dhclient -c {$g['varetc_path']}/dhclient_{$vipif}.conf {$vipif} >{$g['tmp_path']}/{$vipif}_output 2>{$g['tmp_path']}/{$vipif}_error_output", false);
1996
	} else {
1997
		log_error("Error: cannot open dhclient_{$vipif}.conf in interfaces_carpdev_configure() for writing.\n");
1998
		mwexec("/sbin/dhclient -b {$vipif}");
1999
	}
2000

    
2001
	return $vipif;
2002
}
2003

    
2004
function interface_wireless_clone($realif, $wlcfg) {
2005
	global $config, $g;
2006
	/*   Check to see if interface has been cloned as of yet.  
2007
	 *   If it has not been cloned then go ahead and clone it.
2008
	 */
2009
	$needs_clone = false;
2010
	if(is_array($wlcfg['wireless']))
2011
		$wlcfg_mode = $wlcfg['wireless']['mode'];
2012
	else
2013
		$wlcfg_mode = $wlcfg['mode'];
2014
	switch($wlcfg_mode) {
2015
		 case "hostap":
2016
			$mode = "wlanmode hostap";
2017
			break;
2018
		 case "adhoc":
2019
			$mode = "wlanmode adhoc";
2020
			break;
2021
		 default:
2022
			$mode = "";
2023
			break;
2024
	}
2025
	$baseif = interface_get_wireless_base($wlcfg['if']);
2026
	if(does_interface_exist($realif)) {
2027
		exec("/sbin/ifconfig {$realif}", $output, $ret);
2028
		$ifconfig_str = implode($output);
2029
		if(($wlcfg_mode == "hostap") && (! preg_match("/hostap/si", $ifconfig_str))) {
2030
			log_error("Interface {$realif} changed to hostap mode");
2031
			$needs_clone = true;
2032
		}
2033
		if(($wlcfg_mode == "adhoc") && (! preg_match("/adhoc/si", $ifconfig_str))) {
2034
			log_error("Interface {$realif} changed to adhoc mode");
2035
			$needs_clone = true;
2036
		}
2037
		if(($wlcfg_mode == "bss") && (preg_match("/hostap|adhoc/si", $ifconfig_str))) {
2038
			log_error("Interface {$realif} changed to infrastructure mode");
2039
			$needs_clone = true;
2040
		}
2041
	} else {
2042
		$needs_clone = true;
2043
	}
2044

    
2045
	if($needs_clone == true) {
2046
		/* remove previous instance if it exists */
2047
		if(does_interface_exist($realif))
2048
			pfSense_interface_destroy($realif);
2049

    
2050
		log_error("Cloning new wireless interface {$realif}");
2051
		// Create the new wlan interface. FreeBSD returns the new interface name.
2052
		// example:  wlan2
2053
		exec("/sbin/ifconfig wlan create wlandev {$baseif} {$mode} bssid 2>&1", $out, $ret);
2054
		if($ret <> 0) {
2055
			log_error("Failed to clone interface {$baseif} with error code {$ret}, output {$out[0]}");
2056
			return false;
2057
		}
2058
		$newif = trim($out[0]);
2059
		// Rename the interface to {$parentnic}_wlan{$number}#: EX: ath0_wlan0
2060
		pfSense_interface_rename($newif, $realif);
2061
		// FIXME: not sure what ngctl is for. Doesn't work.
2062
		// mwexec("/usr/sbin/ngctl name {$newif}: {$realif}", false);
2063
		file_put_contents("{$g['tmp_path']}/{$realif}_oldmac", get_interface_mac($realif));
2064
	}
2065
	return true;
2066
}
2067

    
2068
function interface_sync_wireless_clones(&$ifcfg, $sync_changes = false) {
2069
	global $config, $g;
2070

    
2071
	$shared_settings = array('standard', 'turbo', 'protmode', 'txpower', 'channel',
2072
	                         'diversity', 'txantenna', 'rxantenna', 'distance',
2073
	                         'regdomain', 'regcountry', 'reglocation');
2074

    
2075
	if(!is_interface_wireless($ifcfg['if']))
2076
		return;
2077

    
2078
	$baseif = interface_get_wireless_base($ifcfg['if']);
2079

    
2080
	// Sync shared settings for assigned clones
2081
	$iflist = get_configured_interface_list(false, true);
2082
	foreach ($iflist as $if) {
2083
		if ($baseif == interface_get_wireless_base($config['interfaces'][$if]['if']) && $ifcfg['if'] != $config['interfaces'][$if]['if']) {
2084
			if (isset($config['interfaces'][$if]['wireless']['standard']) || $sync_changes) {
2085
				foreach ($shared_settings as $setting) {
2086
					if ($sync_changes) {
2087
						if (isset($ifcfg['wireless'][$setting]))
2088
							$config['interfaces'][$if]['wireless'][$setting] = $ifcfg['wireless'][$setting];
2089
						else if (isset($config['interfaces'][$if]['wireless'][$setting]))
2090
							unset($config['interfaces'][$if]['wireless'][$setting]);
2091
					} else {
2092
						if (isset($config['interfaces'][$if]['wireless'][$setting]))
2093
							$ifcfg['wireless'][$setting] = $config['interfaces'][$if]['wireless'][$setting];
2094
						else if (isset($ifcfg['wireless'][$setting]))
2095
							unset($ifcfg['wireless'][$setting]);
2096
					}
2097
				}
2098
				if (!$sync_changes)
2099
					break;
2100
			}
2101
		}
2102
	}
2103

    
2104
	// Read or write settings at shared area
2105
	if (isset($config['wireless']['interfaces'][$baseif])) {
2106
		foreach ($shared_settings as $setting) {
2107
			if ($sync_changes) {
2108
				if (isset($ifcfg['wireless'][$setting]))
2109
					$config['wireless']['interfaces'][$baseif][$setting] = $ifcfg['wireless'][$setting];
2110
				else if (isset($config['wireless']['interfaces'][$baseif][$setting]))
2111
					unset($config['wireless']['interfaces'][$baseif][$setting]);
2112
			} else if (isset($config['wireless']['interfaces'][$baseif][$setting])) {
2113
				if (isset($config['wireless']['interfaces'][$baseif][$setting]))
2114
					$ifcfg['wireless'][$setting] = $config['wireless']['interfaces'][$baseif][$setting];
2115
				else if (isset($ifcfg['wireless'][$setting]))
2116
					unset($ifcfg['wireless'][$setting]);
2117
			}
2118
		}
2119
	}
2120

    
2121
	// Sync the mode on the clone creation page with the configured mode on the interface
2122
	if (interface_is_wireless_clone($ifcfg['if'])) {
2123
		foreach ($config['wireless']['clone'] as &$clone) {
2124
			if ($clone['cloneif'] == $ifcfg['if']) {
2125
				if ($sync_changes) {
2126
					$clone['mode'] = $ifcfg['wireless']['mode'];
2127
				} else {
2128
					$ifcfg['wireless']['mode'] = $clone['mode'];
2129
				}
2130
				break;
2131
			}
2132
		}
2133
		unset($clone);
2134
	}
2135
}
2136

    
2137
function interface_wireless_configure($if, &$wl, &$wlcfg) {
2138
	global $config, $g;
2139

    
2140
	/*    open up a shell script that will be used to output the commands.
2141
	 *    since wireless is changing a lot, these series of commands are fragile
2142
     *    and will sometimes need to be verified by a operator by executing the command
2143
     *    and returning the output of the command to the developers for inspection.  please
2144
     *    do not change this routine from a shell script to individul exec commands.  -sullrich
2145
	 */
2146

    
2147
	// Remove script file
2148
	unlink_if_exists("{$g['tmp_path']}/{$if}_setup.sh");
2149

    
2150
	// Clone wireless nic if needed.
2151
	interface_wireless_clone($if, $wl);
2152

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

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

    
2160
	/* set values for /path/program */
2161
	$hostapd = "/usr/sbin/hostapd";
2162
	$wpa_supplicant = "/usr/sbin/wpa_supplicant";
2163
	$ifconfig = "/sbin/ifconfig";
2164
	$sysctl = "/sbin/sysctl";
2165
	$killall = "/usr/bin/killall";
2166

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

    
2169
	$wlcmd = array();
2170
	$wl_sysctl = array();
2171
	/* Make sure it's up */
2172
	$wlcmd[] = "up";
2173
	/* Set a/b/g standard */
2174
	$standard = str_replace(" Turbo", "", $wlcfg['standard']);
2175
	$wlcmd[] = "mode " . escapeshellarg($standard);
2176

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

    
2182
	/* Set ssid */
2183
	if($wlcfg['ssid'])
2184
		$wlcmd[] = "ssid " .escapeshellarg($wlcfg['ssid']);
2185

    
2186
	/* Set 802.11g protection mode */
2187
	$wlcmd[] = "protmode " . escapeshellarg($wlcfg['protmode']);
2188

    
2189
	/* set wireless channel value */
2190
	if(isset($wlcfg['channel'])) {
2191
		if($wlcfg['channel'] == "0") {
2192
			$wlcmd[] = "channel any";
2193
		} else {
2194
			$wlcmd[] = "channel " . escapeshellarg($wlcfg['channel']);
2195
		}
2196
	}
2197

    
2198
	/* Set antenna diversity value */
2199
	if(isset($wlcfg['diversity']))
2200
		$wl_sysctl[] = "diversity=" . escapeshellarg($wlcfg['diversity']);
2201

    
2202
	/* Set txantenna value */
2203
	if(isset($wlcfg['txantenna']))
2204
		$wl_sysctl[] = "txantenna=" . escapeshellarg($wlcfg['txantenna']);
2205

    
2206
	/* Set rxantenna value */
2207
	if(isset($wlcfg['rxantenna']))
2208
		$wl_sysctl[] = "rxantenna=" . escapeshellarg($wlcfg['rxantenna']);
2209

    
2210
	/* set Distance value */
2211
	if($wlcfg['distance'])
2212
		$distance = escapeshellarg($wlcfg['distance']);
2213

    
2214
	/* Set wireless hostap mode */
2215
	if ($wlcfg['mode'] == "hostap") {
2216
		$wlcmd[] = "mediaopt hostap";
2217
	} else {
2218
		$wlcmd[] = "-mediaopt hostap";
2219
	}
2220

    
2221
	/* Set wireless adhoc mode */
2222
	if ($wlcfg['mode'] == "adhoc") {
2223
		$wlcmd[] = "mediaopt adhoc";
2224
	} else {
2225
		$wlcmd[] = "-mediaopt adhoc";
2226
	}
2227

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

    
2230
	/* handle hide ssid option */
2231
	if(isset($wlcfg['hidessid']['enable'])) {
2232
		$wlcmd[] = "hidessid";
2233
	} else {
2234
		$wlcmd[] = "-hidessid";
2235
	}
2236

    
2237
	/* handle pureg (802.11g) only option */
2238
	if(isset($wlcfg['pureg']['enable'])) {
2239
		$wlcmd[] = "mode 11g pureg";
2240
	} else {
2241
		$wlcmd[] = "-pureg";
2242
	}
2243

    
2244
	/* handle puren (802.11n) only option */
2245
	if(isset($wlcfg['puren']['enable'])) {
2246
		$wlcmd[] = "puren";
2247
	} else {
2248
		$wlcmd[] = "-puren";
2249
	}
2250

    
2251
	/* enable apbridge option */
2252
	if(isset($wlcfg['apbridge']['enable'])) {
2253
		$wlcmd[] = "apbridge";
2254
	} else {
2255
		$wlcmd[] = "-apbridge";
2256
	}
2257

    
2258
	/* handle turbo option */
2259
	if(isset($wlcfg['turbo']['enable'])) {
2260
		$wlcmd[] = "mediaopt turbo";
2261
	} else {
2262
		$wlcmd[] = "-mediaopt turbo";
2263
	}
2264

    
2265
	/* handle txpower setting */
2266
	/* if($wlcfg['txpower'] <> "")
2267
		$wlcmd[] = "txpower " . escapeshellarg($wlcfg['txpower']);
2268
	*/
2269
	/* handle wme option */
2270
	if(isset($wlcfg['wme']['enable'])) {
2271
		$wlcmd[] = "wme";
2272
	} else {
2273
		$wlcmd[] = "-wme";
2274
	}
2275

    
2276
	/* set up wep if enabled */
2277
	$wepset = "";
2278
	if (isset($wlcfg['wep']['enable']) && is_array($wlcfg['wep']['key'])) {
2279
		switch($wlcfg['wpa']['auth_algs']) {
2280
			case "1":
2281
				$wepset .= "authmode open wepmode on ";
2282
				break;
2283
			case "2":
2284
				$wepset .= "authmode shared wepmode on ";
2285
				break;
2286
			case "3":
2287
				$wepset .= "authmode mixed wepmode on ";
2288
		}
2289
		$i = 1;
2290
		foreach ($wlcfg['wep']['key'] as $wepkey) {
2291
			$wepset .= "wepkey " . escapeshellarg("{$i}:{$wepkey['value']}") . " ";
2292
			if (isset($wepkey['txkey'])) {
2293
				$wlcmd[] = "weptxkey {$i} ";
2294
			}
2295
			$i++;
2296
		}
2297
		$wlcmd[] = $wepset;
2298
	} else {
2299
		$wlcmd[] = "authmode open wepmode off ";
2300
	}
2301

    
2302
	mwexec(kill_hostapd("{$if}"));
2303
	mwexec(kill_wpasupplicant("{$if}"));
2304

    
2305
	/* generate wpa_supplicant/hostap config if wpa is enabled */
2306
	conf_mount_rw();
2307

    
2308
	switch ($wlcfg['mode']) {
2309
		case 'bss':
2310
			if (isset($wlcfg['wpa']['enable'])) {
2311
				$wpa .= <<<EOD
2312
ctrl_interface={$g['varrun_path']}/wpa_supplicant
2313
ctrl_interface_group=0
2314
ap_scan=1
2315
#fast_reauth=1
2316
network={
2317
ssid="{$wlcfg['ssid']}"
2318
scan_ssid=1
2319
priority=5
2320
key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
2321
psk="{$wlcfg['wpa']['passphrase']}"
2322
pairwise={$wlcfg['wpa']['wpa_pairwise']}
2323
group={$wlcfg['wpa']['wpa_pairwise']}
2324
}
2325
EOD;
2326

    
2327
				$fd = fopen("{$g['varetc_path']}/wpa_supplicant_{$if}.conf", "w");
2328
				fwrite($fd, "{$wpa}");
2329
				fclose($fd);
2330
			}
2331
			break;
2332
		case 'hostap':
2333
			if($wlcfg['wpa']['passphrase']) 
2334
				$wpa_passphrase = "wpa_passphrase={$wlcfg['wpa']['passphrase']}\n";
2335
			else 
2336
				$wpa_passphrase = "";
2337
			if (isset($wlcfg['wpa']['enable'])) {
2338
				$wpa .= <<<EOD
2339
interface={$if}
2340
driver=bsd
2341
logger_syslog=-1
2342
logger_syslog_level=0
2343
logger_stdout=-1
2344
logger_stdout_level=0
2345
dump_file={$g['tmp_path']}/hostapd_{$if}.dump
2346
ctrl_interface={$g['varrun_path']}/hostapd
2347
ctrl_interface_group=wheel
2348
#accept_mac_file={$g['tmp_path']}/hostapd_{$if}.accept
2349
#deny_mac_file={$g['tmp_path']}/hostapd_{$if}.deny
2350
#macaddr_acl={$wlcfg['wpa']['macaddr_acl']}
2351
ssid={$wlcfg['ssid']}
2352
debug={$wlcfg['wpa']['debug_mode']}
2353
auth_algs={$wlcfg['wpa']['auth_algs']}
2354
wpa={$wlcfg['wpa']['wpa_mode']}
2355
wpa_key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
2356
wpa_pairwise={$wlcfg['wpa']['wpa_pairwise']}
2357
wpa_group_rekey={$wlcfg['wpa']['wpa_group_rekey']}
2358
wpa_gmk_rekey={$wlcfg['wpa']['wpa_gmk_rekey']}
2359
wpa_strict_rekey={$wlcfg['wpa']['wpa_strict_rekey']}
2360
{$wpa_passphrase}
2361

    
2362
EOD;
2363

    
2364
if (isset($wlcfg['wpa']['rsn_preauth'])) {
2365
	$wpa .= <<<EOD
2366
# Enable the next lines for preauth when roaming. Interface = wired or wireless interface talking to the AP you want to roam from/to
2367
rsn_preauth=1
2368
rsn_preauth_interfaces={$if}
2369

    
2370
EOD;
2371

    
2372
}
2373
				if($wlcfg['auth_server_addr'] && $wlcfg['auth_server_shared_secret']) {
2374
					$auth_server_port = "1812";
2375
					if($wlcfg['auth_server_port']) 
2376
						$auth_server_port = $wlcfg['auth_server_port'];
2377
					$wpa .= <<<EOD
2378

    
2379
ieee8021x=1
2380
auth_server_addr={$wlcfg['auth_server_addr']}
2381
auth_server_port={$auth_server_port}
2382
auth_server_shared_secret={$wlcfg['auth_server_shared_secret']}
2383

    
2384
EOD;
2385
				} else {
2386
					$wpa .= "ieee8021x={$wlcfg['wpa']['ieee8021x']}\n";
2387
				}
2388

    
2389
				$fd = fopen("{$g['varetc_path']}/hostapd_{$if}.conf", "w");
2390
				fwrite($fd, "{$wpa}");
2391
				fclose($fd);
2392

    
2393
			}
2394
			break;
2395
	}
2396

    
2397
	/*
2398
	 *    all variables are set, lets start up everything
2399
	 */
2400

    
2401
	$baseif = interface_get_wireless_base($if);
2402
	preg_match("/^(.*?)([0-9]*)$/", $baseif, $baseif_split);
2403
	$wl_sysctl_prefix = 'dev.' . $baseif_split[1] . '.' . $baseif_split[2];
2404

    
2405
	/* set sysctls for the wireless interface */
2406
	if (!empty($wl_sysctl)) {
2407
		fwrite($fd_set, "# sysctls for {$baseif}\n");
2408
		foreach ($wl_sysctl as $wl_sysctl_line) {
2409
			fwrite($fd_set, "{$sysctl} {$wl_sysctl_prefix}.{$wl_sysctl_line}\n");
2410
		}
2411
	}
2412

    
2413
	/* set ack timers according to users preference (if he/she has any) */
2414
	if($distance) {
2415
		fwrite($fd_set, "# Enable ATH distance settings\n");
2416
		fwrite($fd_set, "/sbin/athctrl.sh -i {$baseif} -d {$distance}\n");
2417
	}
2418

    
2419
	if (isset($wlcfg['wpa']['enable'])) {
2420
		if ($wlcfg['mode'] == "bss") {
2421
			fwrite($fd_set, "{$wpa_supplicant} -B -i {$if} -c {$g['varetc_path']}/wpa_supplicant_{$if}.conf\n");
2422
		}
2423
		if ($wlcfg['mode'] == "hostap") {
2424
			/* add line to script to restore old mac to make hostapd happy */
2425
			if (file_exists("{$g['tmp_path']}/{$if}_oldmac")) {
2426
				$if_oldmac = file_get_contents("{$g['tmp_path']}/{$if}_oldmac");
2427
				if (is_macaddr($if_oldmac))
2428
					fwrite($fd_set, "{$ifconfig} " . escapeshellarg($if) .
2429
						" link " . escapeshellarg($if_oldmac) . "\n");
2430
			}
2431

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

    
2434
			/* add line to script to restore spoofed mac after running hostapd */
2435
			if (file_exists("{$g['tmp_path']}/{$if}_oldmac")) {
2436
				if ($wl['spoofmac'])
2437
					$if_curmac = $wl['spoofmac'];
2438
				else
2439
					$if_curmac = get_interface_mac($if);
2440
				if (is_macaddr($if_curmac))
2441
					fwrite($fd_set, "{$ifconfig} " . escapeshellarg($if) .
2442
						" link " . escapeshellarg($if_curmac) . "\n");
2443
			}
2444
		}
2445
	}
2446

    
2447
	fclose($fd_set);
2448
	conf_mount_ro();
2449

    
2450
	/* Making sure regulatory settings have actually changed
2451
	 * before applying, because changing them requires bringing
2452
	 * down all wireless networks on the interface. */
2453
	exec("{$ifconfig} " . escapeshellarg($if), $output);
2454
	$ifconfig_str = implode($output);
2455
	unset($output);
2456
	$reg_changing = false;
2457

    
2458
	/* special case for the debug country code */
2459
	if ($wlcfg['regcountry'] == 'DEBUG' && !preg_match("/\sregdomain\s+DEBUG\s/si", $ifconfig_str))
2460
		$reg_changing = true;
2461
	else if ($wlcfg['regdomain'] && !preg_match("/\sregdomain\s+{$wlcfg['regdomain']}\s/si", $ifconfig_str))
2462
		$reg_changing = true;
2463
	else if ($wlcfg['regcountry'] && !preg_match("/\scountry\s+{$wlcfg['regcountry']}\s/si", $ifconfig_str))
2464
		$reg_changing = true;
2465
	else if ($wlcfg['reglocation'] == 'anywhere' && preg_match("/\s(indoor|outdoor)\s/si", $ifconfig_str))
2466
		$reg_changing = true;
2467
	else if ($wlcfg['reglocation'] && $wlcfg['reglocation'] != 'anywhere' && !preg_match("/\s{$wlcfg['reglocation']}\s/si", $ifconfig_str))
2468
		$reg_changing = true;
2469

    
2470
	if ($reg_changing) {
2471
		/* set regulatory domain */
2472
		if($wlcfg['regdomain'])
2473
			$wlregcmd[] = "regdomain " . escapeshellarg($wlcfg['regdomain']);
2474

    
2475
		/* set country */
2476
		if($wlcfg['regcountry'])
2477
			$wlregcmd[] = "country " . escapeshellarg($wlcfg['regcountry']);
2478

    
2479
		/* set location */
2480
		if($wlcfg['reglocation'])
2481
			$wlregcmd[] = escapeshellarg($wlcfg['reglocation']);
2482

    
2483
		$wlregcmd_args = implode(" ", $wlregcmd);
2484

    
2485
		/* build a complete list of the wireless clones for this interface */
2486
		$clone_list = array();
2487
		if (does_interface_exist(interface_get_wireless_clone($baseif)))
2488
			$clone_list[] = interface_get_wireless_clone($baseif);
2489
		if (is_array($config['wireless']['clone'])) {
2490
			foreach ($config['wireless']['clone'] as $clone) {
2491
				if ($clone['if'] == $baseif)
2492
					$clone_list[] = $clone['cloneif'];
2493
			}
2494
		}
2495

    
2496
		/* find which clones are up and bring them down */
2497
		$clones_up = array();
2498
		foreach ($clone_list as $clone_if) {
2499
			$clone_status = pfSense_get_interface_addresses($clone_if);
2500
			if ($clone_status['status'] == 'up') {
2501
				$clones_up[] = $clone_if;
2502
				mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " down");
2503
			}
2504
		}
2505

    
2506
		/* apply the regulatory settings */
2507
		mwexec("{$ifconfig} " . escapeshellarg($if) . " {$wlregcmd_args}");
2508

    
2509
		/* bring the clones back up that were previously up */
2510
		foreach ($clones_up as $clone_if) {
2511
			mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " up");
2512

    
2513
			/*
2514
			 * Rerun the setup script for the interface if it isn't this interface, the interface
2515
			 * is in infrastructure mode, and WPA is enabled.
2516
			 * This can be removed if wpa_supplicant stops dying when you bring the interface down.
2517
			 */
2518
			if ($clone_if != $if) {
2519
				$friendly_if = convert_real_interface_to_friendly_interface_name($clone_if);
2520
				if ( !empty($friendly_if)
2521
				    && $config['interfaces'][$friendly_if]['wireless']['mode'] == "bss"
2522
				    && isset($config['interfaces'][$friendly_if]['wireless']['wpa']['enable']) ) {
2523
					mwexec("/bin/sh {$g['tmp_path']}/{$clone_if}_setup.sh");
2524
				}
2525
			}
2526
		}
2527
	}
2528

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

    
2533
	/* configure wireless */
2534
	$wlcmd_args = implode(" ", $wlcmd);
2535
	mwexec("/sbin/ifconfig {$if} $wlcmd_args", false);
2536

    
2537
	
2538
	sleep(1);
2539
	/* execute hostapd and wpa_supplicant if required in shell */
2540
	mwexec("/bin/sh {$g['tmp_path']}/{$if}_setup.sh");
2541

    
2542
	return 0;
2543

    
2544
}
2545

    
2546
function kill_hostapd($interface) {
2547
	return "/bin/pkill -f \"hostapd .*{$interface}\"\n";
2548
}
2549

    
2550
function kill_wpasupplicant($interface) {
2551
	return "/bin/pkill -f \"wpa_supplicant .*{$interface}\"\n";
2552
}
2553

    
2554
function find_dhclient_process($interface) {
2555
	if ($interface)
2556
		$pid = `/bin/pgrep -axf "dhclient: {$interface}"`;
2557
	else
2558
		$pid = 0;
2559

    
2560
	return intval($pid);
2561
}
2562

    
2563
function interface_configure($interface = "wan", $reloadall = false, $linkupevent = false) {
2564
	global $config, $g;
2565
	global $interface_sn_arr_cache, $interface_ip_arr_cache;
2566

    
2567
	$wancfg = $config['interfaces'][$interface];
2568

    
2569
	$realif = get_real_interface($interface);
2570
	$realhwif_array = get_parent_interface($interface);
2571
	// Need code to handle MLPPP if we ever use $realhwif for MLPPP handling
2572
	$realhwif = $realhwif_array[0];
2573

    
2574
			
2575
	if (!$g['booting'] && !substr($realif, 0, 4) == "ovpn") {
2576
		/* remove all IPv4 addresses */
2577
		while (mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " -alias", true) == 0);
2578

    
2579
		switch ($wancfg['ipaddr']) {
2580
			case 'pppoe':
2581
			case 'l2tp':
2582
			case 'pptp':
2583
			case 'ppp':
2584
				break;
2585
			default:
2586
				interface_bring_down($interface);
2587
				break;
2588
		}
2589
	}
2590

    
2591
	/* wireless configuration? */
2592
	if (is_array($wancfg['wireless']))
2593
		interface_wireless_configure($realif, $wancfg, $wancfg['wireless']);
2594

    
2595
	$mac = get_interface_mac($realhwif);
2596
	/*	Don't try to reapply the spoofed MAC if it's already applied.
2597
		When ifconfig link is used, it cycles the interface down/up, which triggers 
2598
		the interface config again, which attempts to spoof the MAC again, 
2599
		which cycles the link again... */
2600
	if ($wancfg['spoofmac'] && ($wancfg['spoofmac'] != $mac)) {
2601
		mwexec("/sbin/ifconfig " . escapeshellarg($realhwif) .
2602
			" link " . escapeshellarg($wancfg['spoofmac']));
2603

    
2604
                /*
2605
                 * All vlans need to spoof their parent mac address, too.  see
2606
                 * ticket #1514: http://cvstrac.pfsense.com/tktview?tn=1514,33
2607
                 */
2608
                if (is_array($config['vlans']['vlan'])) {
2609
                        foreach ($config['vlans']['vlan'] as $vlan) {
2610
                                if ($vlan['if'] == $realhwif)
2611
                                        mwexec("/sbin/ifconfig " . escapeshellarg($vlan['vlanif']) .
2612
                                                " link " . escapeshellarg($wancfg['spoofmac']));
2613
                        }
2614
                }
2615
	}  else {
2616
		if ($mac == "ff:ff:ff:ff:ff:ff") {
2617
			/*   this is not a valid mac address.  generate a
2618
			 *   temporary mac address so the machine can get online.
2619
			 */
2620
			echo "Generating new MAC address.";
2621
			$random_mac = generate_random_mac_address();
2622
			mwexec("/sbin/ifconfig " . escapeshellarg($realhwif) .
2623
				" link " . escapeshellarg($random_mac));
2624
			$wancfg['spoofmac'] = $random_mac;
2625
			write_config();
2626
			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");
2627
		}
2628
	}
2629

    
2630
	/* media */
2631
	if ($wancfg['media'] || $wancfg['mediaopt']) {
2632
		$cmd = "/sbin/ifconfig " . escapeshellarg($realhwif);
2633
		if ($wancfg['media'])
2634
			$cmd .= " media " . escapeshellarg($wancfg['media']);
2635
		if ($wancfg['mediaopt'])
2636
			$cmd .= " mediaopt " . escapeshellarg($wancfg['mediaopt']);
2637
		mwexec($cmd);
2638
	}
2639
	if (!empty($wancfg['mtu']))
2640
		pfSense_interface_mtu($realhwif, $wancfg['mtu']);
2641
	else {
2642
		$mtu = get_interface_default_mtu(remove_numbers($realhwif));
2643
		if ($mtu != get_interface_mtu($realhwif))
2644
			pfSense_interface_mtu($realhwif, $mtu);
2645
	}
2646

    
2647
	$options = pfSense_get_interface_addresses($realhwif);
2648
	if (is_array($options) && isset($options['caps']['polling'])) {
2649
		if (isset($config['system']['polling']))
2650
			pfSense_interface_capabilities($realif, IFCAP_POLLING);
2651
		else
2652
			pfSense_interface_capabilities($realif, -IFCAP_POLLING);
2653
	}
2654

    
2655
	/* skip vlans for checksumming and polling */
2656
        if (!stristr($realhwif, "vlan") && is_array($options)) {
2657
		$flags = 0;
2658
		if(isset($config['system']['disablechecksumoffloading'])) {
2659
			if (isset($options['encaps']['txcsum']))
2660
				$flags |= IFCAP_TXCSUM;
2661
			if (isset($options['encaps']['rxcsum']))
2662
				$flags |= IFCAP_RXCSUM;
2663
        	} else {
2664
 			if (!isset($options['caps']['txcsum']))
2665
				$flags |= IFCAP_TXCSUM;
2666
			if (!isset($options['caps']['rxcsum']))
2667
				$flags |= IFCAP_RXCSUM;
2668
        	}
2669

    
2670
        	if(isset($config['system']['disablesegmentationoffloading'])) {
2671
                	if (isset($options['encaps']['tso4']))
2672
				$flags |= IFCAP_TSO;
2673
                	if (isset($options['encaps']['tso6']))
2674
				$flags |= IFCAP_TSO;
2675
        	} else {
2676
                	if (!isset($options['caps']['tso4']))
2677
				$flags |= IFCAP_TSO;
2678
                	if (!isset($options['caps']['tso6']))
2679
				$flags |= IFCAP_TSO;
2680
        	}
2681

    
2682
        	if(isset($config['system']['disablelargereceiveoffloading'])) {
2683
                	if (isset($options['encaps']['lro']))
2684
				$flags |= IFCAP_LRO;
2685
        	} else {
2686
                	if (!isset($options['caps']['lro']))
2687
				$flags |= IFCAP_LRO;
2688
        	}
2689

    
2690
        	/* if the NIC supports polling *AND* it is enabled in the GUI */
2691
        	if (!isset($config['system']['polling']) || !isset($options['caps']['polling'])) {
2692
			$flags |= IFCAP_POLLING;
2693
		}
2694
               	pfSense_interface_capabilities($realhwif, -$flags);
2695
	}
2696

    
2697
	/* invalidate interface/ip/sn cache */
2698
	get_interface_arr(true);
2699
	unset($interface_ip_arr_cache[$realif]);
2700
	unset($interface_sn_arr_cache[$realif]);
2701

    
2702
	switch ($wancfg['ipaddr']) {
2703
		case 'carpdev-dhcp':
2704
			interface_carpdev_dhcp_configure($interface);
2705
			break;
2706
		case 'dhcp':
2707
			interface_dhcp_configure($interface);
2708
			break;
2709
		case 'pppoe':
2710
		case 'l2tp':
2711
		case 'pptp':
2712
		case 'ppp':
2713
			interface_ppps_configure($interface);
2714
			break;
2715
		default:
2716
			if ($wancfg['ipaddr'] <> "" && $wancfg['subnet'] <> "") {
2717
				pfSense_interface_setaddress($realif, "{$wancfg['ipaddr']}/{$wancfg['subnet']}");
2718
			} else if (substr($realif, 0, 3) == "gre") {
2719
				if (is_array($config['gres']['gre'])) {
2720
					foreach ($config['gres']['gre'] as $gre)
2721
						if ($gre['greif'] == $realif)
2722
							interface_gre_configure($gre);
2723
				}
2724
			} else if (substr($realif, 0, 3) == "gif") {
2725
				 if (is_array($config['gifs']['gif'])) {
2726
					foreach ($config['gifs']['gif'] as $gif)
2727
						if($gif['gifif'] == $realif)
2728
							interface_gif_configure($gif);
2729
				}
2730
			} else if (substr($realif, 0, 4) == "ovpn") {
2731
				/* XXX: Should be done anything?! */
2732
			}
2733
			break;
2734
	}
2735

    
2736
	if(does_interface_exist($wancfg['if']))
2737
		interfaces_bring_up($wancfg['if']);
2738

    
2739
	interface_netgraph_needed($interface);
2740
 	
2741
	if (!$g['booting']) {
2742
		link_interface_to_vips($interface, "update");
2743

    
2744
		unset($gre);
2745
		$gre = link_interface_to_gre($interface);
2746
		if (!empty($gre))
2747
			array_walk($gre, 'interface_gre_configure');
2748

    
2749
		unset($gif);
2750
		$gif = link_interface_to_gif($interface);
2751
		if (!empty($gif))
2752
                       	array_walk($gif, 'interface_gif_configure');
2753

    
2754
		if ($linkupevent == false || substr($realif, 0, 4) == "ovpn") {
2755
			unset($bridgetmp);
2756
			$bridgetmp = link_interface_to_bridge($interface);
2757
			if (!empty($bridgetmp))
2758
				interface_bridge_add_member($bridgetmp, $realif);
2759
		}
2760

    
2761
		$grouptmp = link_interface_to_group($interface);
2762
		if (!empty($grouptmp))
2763
			array_walk($grouptmp, 'interface_group_add_member');
2764

    
2765
		if ($interface == "lan")
2766
			/* make new hosts file */
2767
			system_hosts_generate();
2768

    
2769
		if ($reloadall == true) {
2770

    
2771
			/* reconfigure static routes (kernel may have deleted them) */
2772
			system_routing_configure($interface);
2773

    
2774
			/* reload ipsec tunnels */
2775
			vpn_ipsec_configure();
2776

    
2777
			/* restart dnsmasq */
2778
			services_dnsmasq_configure();
2779

    
2780
			/* update dyndns */
2781
			send_event("service reload dyndns {$interface}");
2782

    
2783
			/* reload captive portal */
2784
			captiveportal_init_rules();
2785
		}
2786
	}
2787

    
2788
	return 0;
2789
}
2790

    
2791
function interface_carpdev_dhcp_configure($interface = "wan") {
2792
	global $config, $g;
2793

    
2794
	$wancfg = $config['interfaces'][$interface];
2795
	$wanif = $wancfg['if'];
2796
	/* bring wan interface up before starting dhclient */
2797
	if($wanif)
2798
		interfaces_bring_up($wanif);
2799
	else 
2800
		log_error("Could not bring wanif up in terface_carpdev_dhcp_configure()");
2801

    
2802
	return 0;
2803
}
2804

    
2805
function interface_dhcp_configure($interface = "wan") {
2806
	global $config, $g;
2807

    
2808
	$wancfg = $config['interfaces'][$interface];
2809
	if (empty($wancfg))
2810
		$wancfg = array();
2811

    
2812
	/* generate dhclient_wan.conf */
2813
	$fd = fopen("{$g['varetc_path']}/dhclient_{$interface}.conf", "w");
2814
	if (!$fd) {
2815
		printf("Error: cannot open dhclient_{$interface}.conf in interfaces_wan_dhcp_configure() for writing.\n");
2816
		return 1;
2817
	}
2818

    
2819
	if ($wancfg['dhcphostname']) {
2820
		$dhclientconf_hostname = "send dhcp-client-identifier \"{$wancfg['dhcphostname']}\";\n";
2821
		$dhclientconf_hostname .= "\tsend host-name \"{$wancfg['dhcphostname']}\";\n";
2822
	} else {
2823
		$dhclientconf_hostname = "";
2824
	}
2825

    
2826
	$wanif = get_real_interface($interface);
2827
	if (empty($wanif)) {
2828
		log_error("Invalid interface \"{$interface}\" in interface_dhcp_configure()");
2829
		return 0;
2830
	}
2831
 	$dhclientconf = "";
2832
	
2833
	$dhclientconf .= <<<EOD
2834
interface "{$wanif}" {
2835
timeout 60;
2836
retry 1;
2837
select-timeout 0;
2838
initial-interval 1;
2839
	{$dhclientconf_hostname}
2840
	script "/sbin/dhclient-script";
2841
}
2842

    
2843
EOD;
2844

    
2845
if(is_ipaddr($wancfg['alias-address'])) {
2846
	$subnetmask = gen_subnet_mask($wancfg['alias-subnet']);
2847
	$dhclientconf .= <<<EOD
2848
alias {
2849
	interface  "{$wanif}";
2850
	fixed-address {$wancfg['alias-address']};
2851
	option subnet-mask {$subnetmask};
2852
}
2853

    
2854
EOD;
2855
}
2856
	fwrite($fd, $dhclientconf);
2857
	fclose($fd);
2858

    
2859
	/* bring wan interface up before starting dhclient */
2860
	if($wanif)
2861
		interfaces_bring_up($wanif);
2862
	else 
2863
		log_error("Could not bring up {$wanif} interface in interface_dhcp_configure()");
2864

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

    
2868
	return 0;
2869
}
2870

    
2871
function interfaces_group_setup() {
2872
	global $config;
2873

    
2874
	if (!is_array($config['ifgroups']['ifgroupentry']))
2875
		return;
2876

    
2877
	foreach ($config['ifgroups']['ifgroupentry'] as $groupar)
2878
		interface_group_setup($groupar);
2879

    
2880
	return;
2881
}
2882

    
2883
function interface_group_setup(&$groupname /* The parameter is an array */) {
2884
	global $config;
2885

    
2886
	if (!is_array($groupname))
2887
		return;
2888
	$members = explode(" ", $groupname['members']);
2889
	foreach($members as $ifs) {
2890
		$realif = get_real_interface($ifs);
2891
		if ($realif)
2892
			mwexec("/sbin/ifconfig {$realif} group {$groupname['ifname']}");
2893
	}
2894

    
2895
	return;
2896
}
2897

    
2898
function interface_group_add_member($interface, $groupname) {
2899
	$interface = get_real_interface($interface);
2900
	mwexec("/sbin/ifconfig {$interface} group {$groupname}", true);
2901
}
2902
 
2903
/* COMPAT Function */
2904
function convert_friendly_interface_to_real_interface_name($interface) {
2905
	return get_real_interface($interface);
2906
}
2907

    
2908
/* COMPAT Function */
2909
function get_real_wan_interface($interface = "wan") {
2910
	return get_real_interface($interface);
2911
}
2912

    
2913
/* COMPAT Function */
2914
function get_current_wan_address($interface = "wan") {
2915
	return get_interface_ip($interface);
2916
}
2917

    
2918
/*
2919
 * convert_real_interface_to_friendly_interface_name($interface): convert fxp0 -> wan, etc.
2920
 */
2921
function convert_real_interface_to_friendly_interface_name($interface = "wan") {
2922
        global $config;
2923

    
2924
	if (stristr($interface, "vip")) {
2925
                $index = intval(substr($interface, 3));
2926
                foreach ($config['virtualip']['vip'] as $counter => $vip) {
2927
                        if ($vip['mode'] == "carpdev-dhcp" || $vip['mode'] == "carp")  {
2928
                                if ($index == $vip['vhid'])
2929
                                        return $vip['interface'];
2930
                        }
2931
                }
2932
        }
2933

    
2934
        /* XXX: For speed reasons reference directly the interface array */
2935
	$ifdescrs = &$config['interfaces'];
2936
        //$ifdescrs = get_configured_interface_list(false, true);
2937

    
2938
        foreach ($ifdescrs as $if => $ifname) {
2939
                if ($config['interfaces'][$if]['if'] == $interface)
2940
                        return $if;
2941

    
2942
                if (stristr($interface, "_wlan0") && $config['interfaces'][$if]['if'] == interface_get_wireless_base($interface))
2943
                        return $if;
2944

    
2945
		// XXX: This case doesn't work anymore (segfaults - recursion?) - should be replaced with something else or just removed.
2946
		//      Not to be replaced with get_real_interface - causes slow interface listings here because of recursion!
2947
		/*
2948
                $int = get_parent_interface($if);
2949
                if ($int[0] == $interface)
2950
                        return $ifname;
2951
		*/
2952
        }
2953
        return NULL;
2954
}
2955

    
2956
/* attempt to resolve interface to friendly descr */
2957
function convert_friendly_interface_to_friendly_descr($interface) {
2958
        global $config;
2959

    
2960
        switch ($interface) {
2961
        case "l2tp":
2962
        	$ifdesc = "L2TP";
2963
                break;
2964
	case "pptp":
2965
		$ifdesc = "PPTP";
2966
		break;
2967
	case "pppoe":
2968
		$ifdesc = "PPPoE";
2969
		break;
2970
	case "openvpn":
2971
		$ifdesc = "OpenVPN";
2972
		break;
2973
	case "enc0":
2974
	case "ipsec":
2975
		$ifdesc = "IPsec";
2976
		break;
2977
        default:
2978
                if (isset($config['interfaces'][$interface])) {
2979
                        if (empty($config['interfaces'][$interface]['descr']))
2980
                                $ifdesc = strtoupper($interface);
2981
                        else
2982
                                $ifdesc = strtoupper($config['interfaces'][$interface]['descr']);
2983
			break;
2984
		} else if (substr($interface, 0, 3) == "vip") {
2985
			if (is_array($config['virtualip']['vip'])) {
2986
				foreach ($config['virtualip']['vip'] as $counter => $vip) {
2987
					if ($vip['mode'] == "carpdev-dhcp" || $vip['mode'] == "carp")  {
2988
						if ($interface == "vip{$vip['vhid']}")
2989
							return "{$vip['subnet']} - {$vip['descr']}";
2990
					}
2991
				}
2992
                        }
2993
                } else {
2994
			/* if list */
2995
			$ifdescrs = get_configured_interface_with_descr(false, true);
2996
			foreach ($ifdescrs as $if => $ifname) {
2997
					if ($if == $interface || $ifname == $interface)
2998
						return $ifname;
2999
			}
3000
		}
3001
                break;
3002
        }
3003

    
3004
        return $ifdesc;
3005
}
3006

    
3007
function convert_real_interface_to_friendly_descr($interface) {
3008
        global $config;
3009

    
3010
        $ifdesc = convert_real_interface_to_friendly_interface_name("{$interface}");
3011

    
3012
        if ($ifdesc) {
3013
                $iflist = get_configured_interface_with_descr(false, true);
3014
                return $iflist[$ifdesc];
3015
        }
3016

    
3017
        return $interface;
3018
}
3019

    
3020
/*
3021
 *  get_parent_interface($interface):
3022
 *			--returns the (real or virtual) parent interface(s) array for a given interface friendly name (i.e. wan)
3023
 *				or virtual interface (i.e. vlan)
3024
 *				(We need array because MLPPP and bridge interfaces have more than one parent.)
3025
 *			-- returns $interface passed in if $interface parent is not found
3026
 *			-- returns empty array if an invalid interface is passed
3027
 *	(Only handles ppps and vlans now.)
3028
 */
3029
function get_parent_interface($interface) {
3030
	global $config;
3031

    
3032
	$parents = array();
3033
	//Check that we got a valid interface passed
3034
	$realif = get_real_interface($interface);
3035
	if ($realif == NULL)
3036
		return $parents;
3037

    
3038
	// If we got a real interface, find it's friendly assigned name
3039
	$interface = convert_real_interface_to_friendly_interface_name($interface);
3040
		
3041
	if (!empty($interface) && isset($config['interfaces'][$interface])) {
3042
		$ifcfg = $config['interfaces'][$interface];
3043
		switch ($ifcfg['ipaddr']) {
3044
			case "ppp":
3045
			case "pppoe":
3046
			case "pptp":
3047
			case "l2tp":
3048
				if (empty($parents))
3049
					if (is_array($config['ppps']['ppp']))
3050
						foreach ($config['ppps']['ppp'] as $pppidx => $ppp) {
3051
							if ($ppp_if == $ppp['if']) {
3052
								$ports = explode(',', $ppp['ports']);
3053
								foreach ($ports as $pid => $parent_if) 
3054
									$parents[$pid] = get_real_interface($parent_if);
3055
								break;
3056
							}
3057
						}
3058
				break;
3059
			case "dhcp":
3060
			case "static":
3061
			default:
3062
				// Handle _vlans
3063
				if (strstr($realif,"_vlan"))
3064
					if (is_array($config['vlans']['vlan'])) 
3065
						foreach ($config['vlans']['vlan'] as $vlanidx => $vlan)
3066
							if ($ifcfg['if'] == $vlan['vlanif']){
3067
								$parents[0] = $vlan['if'];
3068
								break;
3069
							}
3070
				break;
3071
		}
3072
	}
3073
	
3074
	if (empty($parents))
3075
		$parents[0] = $realif;
3076
	
3077
	return $parents;
3078
}
3079

    
3080
function interface_is_wireless_clone($wlif) {
3081
	if(!stristr($wlif, "_wlan")) {
3082
		return false;
3083
	} else {
3084
		return true;
3085
	}
3086
}
3087

    
3088
function interface_get_wireless_base($wlif) {
3089
	if(!stristr($wlif, "_wlan")) {
3090
		return $wlif;
3091
	} else {
3092
		return substr($wlif, 0, stripos($wlif, "_wlan"));
3093
	}
3094
}
3095

    
3096
function interface_get_wireless_clone($wlif) {
3097
	if(!stristr($wlif, "_wlan")) {
3098
		return $wlif . "_wlan0";
3099
	} else {
3100
		return $wlif;
3101
	}
3102
}
3103

    
3104
function get_real_interface($interface = "wan") {
3105
    global $config;
3106

    
3107
	$wanif = NULL;
3108

    
3109
	switch ($interface) {
3110
	case "l2tp":
3111
		$wanif = "l2tp";
3112
		break;
3113
	case "pptp":
3114
		$wanif = "pptp";
3115
		break;
3116
	case "pppoe":
3117
		$wanif = "pppoe";
3118
		break;
3119
	case "openvpn":
3120
		$wanif = "openvpn";
3121
		break;
3122
	case "ipsec":
3123
	case "enc0":
3124
		$wanif = "enc0";
3125
		break;
3126
	case "ppp":
3127
		$wanif = "ppp";
3128
		break;
3129
	default:
3130
		// If a real interface was alread passed simply
3131
		// pass the real interface back.  This encourages
3132
		// the usage of this function in more cases so that
3133
		// we can combine logic for more flexibility.
3134
		if(does_interface_exist($interface)) {
3135
			$wanif = $interface;
3136
			break;
3137
		}
3138
		if (empty($config['interfaces'][$interface]))
3139
			break;
3140

    
3141
		$cfg = &$config['interfaces'][$interface];
3142

    
3143
		// Wireless cloned NIC support (FreeBSD 8+)
3144
		// interface name format: $parentnic_wlanparentnic#
3145
		// example: ath0_wlan0
3146
		if (is_interface_wireless($cfg['if'])) {
3147
			$wanif = interface_get_wireless_clone($cfg['if']);
3148
			break;
3149
		}
3150
		/*
3151
		if (empty($cfg['if'])) {
3152
			$wancfg = $cfg['if'];
3153
			break;
3154
		}
3155
		*/
3156

    
3157
		switch ($cfg['ipaddr']) {
3158
			case "carpdev-dhcp":
3159
				$viparr = &$config['virtualip']['vip'];
3160
				if(is_array($viparr))
3161
				foreach ($viparr as $counter => $vip) {
3162
					if ($vip['mode'] == "carpdev-dhcp") {
3163
						if($vip['interface'] == $interface) {
3164
							$wanif = "carp{$counter}";
3165
							break;
3166
						}
3167
					}
3168
				}
3169
				break;
3170
			case "pppoe": 
3171
			case "pptp": 
3172
			case "l2tp": 
3173
			case "ppp":
3174
				$wanif = $cfg['if'];
3175
				break;
3176
			default:
3177
				$wanif = $cfg['if'];
3178
				break;
3179
		}
3180
		break;
3181
	}
3182

    
3183
    return $wanif;
3184
}
3185

    
3186
/* Guess the physical interface by providing a IP address */
3187
function guess_interface_from_ip($ipaddress) {
3188
	if(! is_ipaddr($ipaddress)) {
3189
		return false;
3190
	}
3191
	/* create a route table we can search */
3192
	exec("netstat -rnWf inet", $output, $ret);
3193
	foreach($output as $line) {
3194
		if(preg_match("/^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\/[0-9]+[ ]+link[#]/", $line)) {
3195
			$fields = preg_split("/[ ]+/", $line);
3196
			if(ip_in_subnet($ipaddress, $fields[0])) {
3197
				return $fields[6];
3198
			}
3199
		}
3200
	}
3201
	$ret = exec_command("/sbin/route -n get {$ipaddress} | /usr/bin/awk '/interface/ { print \$2; };'");
3202
	if(empty($ret)) {
3203
        	return false;
3204
	}
3205
	return $ret;
3206
}
3207

    
3208
/*
3209
 * find_ip_interface($ip): return the interface where an ip is defined
3210
 */
3211
function find_ip_interface($ip)
3212
{
3213
        /* if list */
3214
        $ifdescrs = get_configured_interface_list();
3215

    
3216
        foreach ($ifdescrs as $ifdescr => $ifname) {
3217
		if ($ip == get_interface_ip($ifname)) {
3218
                	$int = get_real_interface($ifname);
3219
			return $int;
3220
		}
3221
        }
3222
        return false;
3223
}
3224

    
3225
/*
3226
 *   find_number_of_created_carp_interfaces: return the number of carp interfaces
3227
 */
3228
function find_number_of_created_carp_interfaces() {
3229
	return `/sbin/ifconfig | grep "carp:" | wc -l`;
3230
}
3231

    
3232
function get_all_carp_interfaces() {
3233
	$ints = str_replace("\n", " ", `ifconfig | grep "carp:" -B2 | grep ": flag" | cut -d: -f1`);
3234
	$ints = explode(" ", $ints);
3235
	return $ints;
3236
}
3237

    
3238
/*
3239
 * find_carp_interface($ip): return the carp interface where an ip is defined
3240
 */
3241
function find_carp_interface($ip) {
3242
	global $config;
3243
	if (is_array($config['virtualip']['vip'])) {
3244
		foreach ($config['virtualip']['vip'] as $vip) {
3245
			if ($vip['mode'] == "carp" || $vip['mode'] == "carpdev") {
3246
				$carp_ip = get_interface_ip($vip['interface']);
3247
				$if = `ifconfig | grep '$ip ' -B1 | head -n1 | cut -d: -f1`;
3248
				if ($if)
3249
					return $if;
3250
			}
3251
		}
3252
	}
3253
}
3254

    
3255
function link_carp_interface_to_parent($interface) {
3256
        global $config;
3257

    
3258
        if ($interface == "")
3259
                return;
3260

    
3261
        $carp_ip = get_interface_ip($interface);
3262
        if (!is_ipaddr($carp_ip))
3263
                return;
3264

    
3265
        /* if list */
3266
        $ifdescrs = get_configured_interface_list();
3267
        foreach ($ifdescrs as $ifdescr => $ifname) {
3268
                $interfaceip = get_interface_ip($ifname);
3269
                $subnet_bits = get_interface_subnet($ifname);
3270
                $subnet_ip = gen_subnet("{$interfaceip}", "{$subnet_bits}");
3271
                if(ip_in_subnet($carp_ip, "{$subnet_ip}/{$subnet_bits}"))
3272
                        return $ifname;
3273
        }
3274

    
3275
        return "";
3276
}
3277

    
3278
/****f* interfaces/link_ip_to_carp_interface
3279
 * NAME
3280
 *   link_ip_to_carp_interface - Find where a CARP interface links to.
3281
 * INPUTS
3282
 *   $ip
3283
 * RESULT
3284
 *   $carp_ints
3285
 ******/
3286
function link_ip_to_carp_interface($ip) {
3287
        global $config;
3288

    
3289
        if (!is_ipaddr($ip))
3290
                return;
3291

    
3292
        $carp_ints = "";
3293
        if (is_array($config['virtualip']['vip'])) {
3294
		$first = 0;
3295
		$carp_int = array();
3296
                foreach ($config['virtualip']['vip'] as $vip) {
3297
                        if ($vip['mode'] == "carp" || $vip['mode'] == "carpdev") {
3298
                                $carp_ip = $vip['subnet'];
3299
                                $carp_sn = $vip['subnet_bits'];
3300
                                $carp_nw = gen_subnet($carp_ip, $carp_sn);
3301
                                if (ip_in_subnet($ip, "{$carp_nw}/{$carp_sn}"))
3302
					$carp_int[] = "vip{$vip['vhid']}";
3303
                        }
3304
                }
3305
		if (!empty($carp_int))
3306
			$carp_ints = implode(" ", array_unique($carp_int));
3307
        }
3308

    
3309
        return $carp_ints;
3310
}
3311

    
3312
function link_interface_to_vlans($int, $action = "") {
3313
	global $config;
3314

    
3315
	if (empty($int))
3316
		return;
3317

    
3318
	if (is_array($config['vlans']['vlan'])) {
3319
                foreach ($config['vlans']['vlan'] as $vlan) {
3320
			if ($int == $vlan['if']) {
3321
				if ($action == "update") {
3322
					interfaces_bring_up($int);
3323
				} else if ($action == "")
3324
					return $vlan;
3325
			}
3326
		}
3327
	}
3328
}
3329

    
3330
function link_interface_to_vips($int, $action = "") {
3331
        global $config;
3332

    
3333
        if (is_array($config['virtualip']['vip'])) {
3334
		foreach ($config['virtualip']['vip'] as $vip) {
3335
			if ($int == $vip['interface']) {
3336
				if ($action == "update") {
3337
					if ($vip['mode'] == "carp" && !does_interface_exist("vip{$vip['vhid']}"))
3338
						interfaces_vips_configure($int);
3339
					else {
3340
						interface_vip_bring_down($vip);
3341
						interfaces_vips_configure($int);
3342
					}
3343
				} else
3344
					return $vip;
3345
			}
3346
		}
3347
	}
3348
}
3349

    
3350
/****f* interfaces/link_interface_to_bridge
3351
 * NAME
3352
 *   link_interface_to_bridge - Finds out a bridge group for an interface
3353
 * INPUTS
3354
 *   $ip
3355
 * RESULT
3356
 *   bridge[0-99]
3357
 ******/
3358
function link_interface_to_bridge($int) {
3359
        global $config;
3360

    
3361
        if (is_array($config['bridges']['bridged'])) {
3362
                foreach ($config['bridges']['bridged'] as $bridge) {
3363
			if (in_array($int, explode(',', $bridge['members'])))
3364
                                return "{$bridge['bridgeif']}";
3365
		}
3366
	}
3367
}
3368

    
3369
function link_interface_to_group($int) {
3370
        global $config;
3371

    
3372
	$result = array();
3373

    
3374
        if (is_array($config['ifgroups']['ifgroupentry'])) {
3375
                foreach ($config['ifgroups']['ifgroupentry'] as $group) {
3376
			if (in_array($int, explode(" ", $group['members'])))
3377
				$result[$group['ifname']] = $int;
3378
		}
3379
	}
3380

    
3381
	return $result;
3382
}
3383

    
3384
function link_interface_to_gre($interface) {
3385
        global $config;
3386

    
3387
	$result = array();
3388

    
3389
        if (is_array($config['gres']['gre'])) {
3390
                foreach ($config['gres']['gre'] as $gre)
3391
                        if($gre['if'] == $interface)
3392
				$result[] = $gre;
3393
	}
3394

    
3395
	return $result;
3396
}
3397

    
3398
function link_interface_to_gif($interface) {
3399
        global $config;
3400

    
3401
	$result = array();
3402

    
3403
        if (is_array($config['gifs']['gif'])) {
3404
                foreach ($config['gifs']['gif'] as $gif)
3405
                        if($gif['if'] == $interface)
3406
                                $result[] = $gif;
3407
	}
3408

    
3409
	return $result;
3410
}
3411

    
3412
/*
3413
 * find_interface_ip($interface): return the interface ip (first found)
3414
 */
3415
function find_interface_ip($interface, $flush = false)
3416
{
3417
	global $interface_ip_arr_cache;
3418
	global $interface_sn_arr_cache;
3419

    
3420
	$interface = str_replace("\n", "", $interface);
3421
	
3422
	if (!does_interface_exist($interface))
3423
		return;
3424

    
3425
	/* Setup IP cache */
3426
	if (!isset($interface_ip_arr_cache[$interface]) or $flush) {
3427
		$ifinfo = pfSense_get_interface_addresses($interface);
3428
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
3429
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
3430
	}
3431

    
3432
	return $interface_ip_arr_cache[$interface];
3433
}
3434

    
3435
function find_interface_subnet($interface, $flush = false)
3436
{
3437
	global $interface_sn_arr_cache;
3438
	global $interface_ip_arr_cache;
3439

    
3440
	$interface = str_replace("\n", "", $interface);
3441
	if (does_interface_exist($interface) == false)
3442
		return;
3443

    
3444
	if (!isset($interface_sn_arr_cache[$interface]) or $flush) {
3445
		$ifinfo = pfSense_get_interface_addresses($interface);
3446
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
3447
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
3448
        }
3449

    
3450
	return $interface_sn_arr_cache[$interface];
3451
}
3452

    
3453
function ip_in_interface_alias_subnet($interface, $ipalias) {
3454
	global $config;
3455

    
3456
	if (empty($interface) || !is_ipaddr($ipalias))
3457
		return false;
3458
	if (is_array($config['virtualip']['vip'])) {
3459
                foreach ($config['virtualip']['vip'] as $vip) {
3460
                        switch ($vip['mode']) {
3461
                        case "ipalias":
3462
                                if ($vip['interface'] <> $interface)
3463
                                        break;
3464
				if (ip_in_subnet($ipalias, gen_subnet($vip['subnet'], $vip['subnet_bits']) . "/" . $vip['subnet_bits']))
3465
					return true;
3466
                                break;
3467
                        }
3468
                }
3469
	}
3470

    
3471
	return false;
3472
}
3473

    
3474
function get_interface_ip($interface = "wan")
3475
{
3476
	$realif = get_real_interface($interface);
3477
	if (!$realif) {
3478
		if (preg_match("/^carp/i", $interface))
3479
			$realif = $interface;
3480
		else if (preg_match("/^vip/i", $interface))
3481
			$realif = $interface;
3482
		else
3483
			return null;
3484
	}
3485

    
3486
	$curip = find_interface_ip($realif);
3487
	if ($curip && is_ipaddr($curip) && ($curip != "0.0.0.0"))
3488
		return $curip;
3489
	else
3490
		return null;
3491
}
3492

    
3493
function get_interface_subnet($interface = "wan")
3494
{
3495
	$realif = get_real_interface($interface);
3496
	if (!$realif) {
3497
                if (preg_match("/^carp/i", $interface))
3498
                        $realif = $interface;
3499
                else if (preg_match("/^vip/i", $interface))
3500
                        $realif = $interface;
3501
                else
3502
                        return null;
3503
        }
3504

    
3505
	$cursn = find_interface_subnet($realif);
3506
	if (!empty($cursn))
3507
		return $cursn;
3508

    
3509
	return null;
3510
}
3511

    
3512
/* return outside interfaces with a gateway */
3513
function get_interfaces_with_gateway() {
3514
	global $config;
3515

    
3516
	$ints = array();
3517

    
3518
	/* loop interfaces, check config for outbound */
3519
	foreach($config['interfaces'] as $ifdescr => $ifname) {
3520
		switch ($ifname['ipaddr']) {
3521
			case "dhcp":
3522
			case "carpdev-dhcp":
3523
			case "ppp";
3524
			case "pppoe":
3525
			case "pptp":
3526
			case "l2tp":
3527
			case "ppp";
3528
				$ints[$ifdescr] = $ifdescr;
3529
			break;
3530
			default:
3531
				if (substr($ifname['if'], 0, 5) ==  "ovpnc" ||
3532
				    !empty($ifname['gateway']))
3533
					$ints[$ifdescr] = $ifdescr;
3534
			break;
3535
		}
3536
	}
3537
	return $ints;
3538
}
3539

    
3540
/* return true if interface has a gateway */
3541
function interface_has_gateway($friendly) {
3542
	global $config;
3543

    
3544
	if (!empty($config['interfaces'][$friendly])) {
3545
		$ifname = &$config['interfaces'][$friendly];
3546
		switch ($ifname['ipaddr']) {
3547
			case "dhcp":
3548
			case "carpdev-dhcp":
3549
			case "pppoe":
3550
			case "pptp":
3551
			case "l2tp":
3552
			case "ppp";
3553
				return true;
3554
			break;
3555
			default:
3556
				if (substr($ifname['if'], 0, 5) ==  "ovpnc")
3557
					return true;
3558
				if (!empty($ifname['gateway']))
3559
					return true;
3560
			break;
3561
		}
3562
	}
3563

    
3564
	return false;
3565
}
3566

    
3567
/****f* interfaces/is_altq_capable
3568
 * NAME
3569
 *   is_altq_capable - Test if interface is capable of using ALTQ
3570
 * INPUTS
3571
 *   $int            - string containing interface name
3572
 * RESULT
3573
 *   boolean         - true or false
3574
 ******/
3575

    
3576
function is_altq_capable($int) {
3577
        /* Per:
3578
         * http://www.freebsd.org/cgi/man.cgi?query=altq&manpath=FreeBSD+7.2-current&format=html
3579
         * Only the following drivers have ALTQ support
3580
         */
3581
	$capable = array("age", "alc", "ale", "an", "ath", "aue", "awi", "bce",
3582
			"bfe", "bge", "bridge", "cas", "dc", "de", "ed", "em", "ep", "fxp", "gem",
3583
			"hme", "igb", "ipw", "iwi", "jme", "le", "lem", "msk", "mxge", "my", "nfe",
3584
			"npe", "nve", "ral", "re", "rl", "rum", "run", "bwn", "sf", "sis", "sk",
3585
			"ste", "stge", "txp", "udav", "ural", "vge", "vr", "wi", "xl",
3586
			"ndis", "tun", "ovpns", "ovpnc", "vlan", "pppoe", "pptp", "ng",
3587
			"l2tp", "ppp");
3588

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

    
3591
        if (in_array($int_family[0], $capable))
3592
                return true;
3593
	else if (stristr($int, "l2tp")) /* VLANs are name $parent_$vlan now */
3594
		return true;
3595
	else if (stristr($int, "vlan")) /* VLANs are name $parent_$vlan now */
3596
		return true;
3597
	else if (stristr($int, "_wlan")) /* WLANs are name $parent_$wlan now */
3598
		return true;
3599
        else
3600
                return false;
3601
}
3602

    
3603
/****f* interfaces/is_interface_wireless
3604
 * NAME
3605
 *   is_interface_wireless - Returns if an interface is wireless
3606
 * RESULT
3607
 *   $tmp       - Returns if an interface is wireless
3608
 ******/
3609
function is_interface_wireless($interface) {
3610
        global $config, $g;
3611

    
3612
        $friendly = convert_real_interface_to_friendly_interface_name($interface);
3613
        if(!isset($config['interfaces'][$friendly]['wireless'])) {
3614
                if (preg_match($g['wireless_regex'], $interface)) {
3615
                        if (isset($config['interfaces'][$friendly]))
3616
                                $config['interfaces'][$friendly]['wireless'] = array();
3617
                        return true;
3618
                }
3619
                return false;
3620
        } else
3621
                return true;
3622
}
3623

    
3624
function get_wireless_modes($interface) {
3625
	/* return wireless modes and channels */
3626
	$wireless_modes = array();
3627

    
3628
	$cloned_interface = get_real_interface($interface);
3629

    
3630
	if($cloned_interface && is_interface_wireless($cloned_interface)) {
3631
		$chan_list = "/sbin/ifconfig {$cloned_interface} list chan";
3632
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
3633
		$format_list = "/usr/bin/awk '{print \$5 \" \" \$6 \",\" \$1}'";
3634

    
3635
		$interface_channels = "";
3636
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
3637
		$interface_channel_count = count($interface_channels);
3638

    
3639
		$c = 0;
3640
		while ($c < $interface_channel_count)
3641
		{
3642
			$channel_line = explode(",", $interface_channels["$c"]);
3643
			$wireless_mode = trim($channel_line[0]);
3644
			$wireless_channel = trim($channel_line[1]);
3645
			if(trim($wireless_mode) != "") {
3646
				/* if we only have 11g also set 11b channels */
3647
				if($wireless_mode == "11g") {
3648
					if(!isset($wireless_modes["11b"]))
3649
						$wireless_modes["11b"] = array();
3650
				} else if($wireless_mode == "11g ht") {
3651
					if(!isset($wireless_modes["11b"]))
3652
						$wireless_modes["11b"] = array();
3653
					if(!isset($wireless_modes["11g"]))
3654
						$wireless_modes["11g"] = array();
3655
					$wireless_mode = "11ng";
3656
				} else if($wireless_mode == "11a ht") {
3657
					if(!isset($wireless_modes["11a"]))
3658
						$wireless_modes["11a"] = array();
3659
					$wireless_mode = "11na";
3660
				}
3661
				$wireless_modes["$wireless_mode"]["$c"] = $wireless_channel;
3662
			}
3663
			$c++;
3664
		}
3665
	}
3666
	return($wireless_modes);
3667
}
3668

    
3669
/* return channel numbers, frequency, max txpower, and max regulation txpower */
3670
function get_wireless_channel_info($interface) {
3671
	$wireless_channels = array();
3672

    
3673
	$cloned_interface = get_real_interface($interface);
3674

    
3675
	if($cloned_interface && is_interface_wireless($cloned_interface)) {
3676
		$chan_list = "/sbin/ifconfig {$cloned_interface} list txpower";
3677
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
3678
		$format_list = "/usr/bin/awk '{print \$1 \",\" \$3 \" \" \$4 \",\" \$5 \",\" \$7}'";
3679

    
3680
		$interface_channels = "";
3681
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
3682

    
3683
		foreach ($interface_channels as $channel_line) {
3684
			$channel_line = explode(",", $channel_line);
3685
			if(!isset($wireless_channels[$channel_line[0]]))
3686
				$wireless_channels[$channel_line[0]] = $channel_line;
3687
		}
3688
	}
3689
	return($wireless_channels);
3690
}
3691

    
3692
/****f* interfaces/get_interface_mtu
3693
 * NAME
3694
 *   get_interface_mtu - Return the mtu of an interface
3695
 * RESULT
3696
 *   $tmp       - Returns the mtu of an interface
3697
 ******/
3698
function get_interface_mtu($interface) {
3699
        $mtu = pfSense_get_interface_addresses($interface);
3700
        return $mtu['mtu'];
3701
}
3702

    
3703
function get_interface_mac($interface) {
3704

    
3705
	$macinfo = pfSense_get_interface_addresses($interface);
3706
	return $macinfo["macaddr"];
3707
}
3708

    
3709
/****f* pfsense-utils/generate_random_mac_address
3710
 * NAME
3711
 *   generate_random_mac - generates a random mac address
3712
 * INPUTS
3713
 *   none
3714
 * RESULT
3715
 *   $mac - a random mac address
3716
 ******/
3717
function generate_random_mac_address() {
3718
        $mac = "02";
3719
        for($x=0; $x<5; $x++)
3720
                $mac .= ":" . dechex(rand(16, 255));
3721
        return $mac;
3722
}
3723

    
3724
/****f* interfaces/is_jumbo_capable
3725
 * NAME
3726
 *   is_jumbo_capable - Test if interface is jumbo frame capable.  Useful for determining VLAN capability.
3727
 * INPUTS
3728
 *   $int             - string containing interface name
3729
 * RESULT
3730
 *   boolean          - true or false
3731
 ******/
3732
function is_jumbo_capable($iface) {
3733

    
3734
	$iface = trim($iface);
3735
	$capable = pfSense_get_interface_addresses($iface);
3736
	if (isset($capable['caps']['vlanmtu']))
3737
                return true;
3738

    
3739
	return false;
3740
}
3741

    
3742
function setup_pppoe_reset_file($pppif, $iface="") {
3743
	global $g;
3744
	$cron_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
3745

    
3746
	if(!empty($iface) && !empty($pppif)){
3747
		$cron_cmd = <<<EOD
3748
#!/bin/sh
3749
/usr/local/sbin/pfSctl -c 'interface reload {$iface}'
3750
/usr/bin/logger -t pppoe{$iface} "PPPoE periodic reset executed on {$iface}"
3751

    
3752
EOD;
3753

    
3754
		file_put_contents($cron_file, $cron_cmd);
3755
		chmod($cron_file, 0700);
3756
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
3757
	} else
3758
		unlink_if_exists($cron_file);
3759
}
3760

    
3761
function get_interface_default_mtu($type = "ethernet") {
3762
	switch ($type) {
3763
	case "gre":
3764
		return 1476;
3765
		break;
3766
	case "gif":
3767
		return 1280;
3768
		break;
3769
	case "tun":
3770
	case "vlan":
3771
	case "tap":
3772
	case "ethernet":
3773
	default:
3774
		return 1500;
3775
		break;
3776
	}
3777

    
3778
	/* Never reached */
3779
	return 1500;
3780
}
3781

    
3782
function get_vip_descr($ipaddress) {
3783
	global $config;
3784

    
3785
	foreach ($config['virtualip']['vip'] as $vip) {
3786
		if ($vip['subnet'] == $ipaddress) {
3787
			return ($vip['descr']);
3788
		}
3789
	}
3790
	return "";
3791
}
3792

    
3793
function interfaces_staticarp_configure($if) {
3794
	global $config, $g;
3795
	if(isset($config['system']['developerspew'])) {
3796
		$mt = microtime();
3797
		echo "interfaces_staticarp_configure($if) being called $mt\n";
3798
	}
3799

    
3800
	$ifcfg = $config['interfaces'][$if];
3801

    
3802
	if (empty($if) || empty($ifcfg['if']))
3803
		return 0;
3804

    
3805
	/* Enable staticarp, if enabled */
3806
	if(isset($config['dhcpd'][$if]['staticarp'])) {
3807
		mwexec("/sbin/ifconfig " . escapeshellarg($ifcfg['if']) . " staticarp " );
3808
		mwexec("/usr/sbin/arp -d -i " . escapeshellarg($ifcfg['if']) . " -a > /dev/null 2>&1 ");
3809
		if (is_array($config['dhcpd'][$if]['staticmap'])) {
3810

    
3811
			foreach ($config['dhcpd'][$if]['staticmap'] as $arpent) {
3812
				mwexec("/usr/sbin/arp -s " . escapeshellarg($arpent['ipaddr']) . " " . escapeshellarg($arpent['mac']));
3813

    
3814
			}
3815

    
3816
		}
3817
	} else {
3818
		mwexec("/sbin/ifconfig " . escapeshellarg($ifcfg['if']) . " -staticarp " );
3819
		mwexec("/usr/sbin/arp -d -i " . escapeshellarg($ifcfg['if']) . " -a > /dev/null 2>&1 ");
3820
	}
3821

    
3822
	return 0;
3823
}
3824

    
3825
?>
(25-25/62)