Project

General

Profile

Download (119 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_BUILDER_BINARIES:	/usr/local/sbin/dhcp6c
41
	pfSense_MODULE:	interfaces
42

    
43
*/
44

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

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

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

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

    
68
        return $interface_arr_cache;
69
}
70

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

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

    
88
/*
89
 * does_vip_exist($vip): return true or false if a vip is
90
 * configured.
91
 */
92
function does_vip_exist($vip) {
93
	global $config;
94
	
95
	if(!$vip)
96
		return false;
97

    
98

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

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

    
125
	return false;
126
}
127

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

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

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

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

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

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

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

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

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

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

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

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

    
264
	interfaces_bring_up($vlanif);
265

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

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

    
272
	return $vlanif;
273
}
274

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

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

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

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

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

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

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

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

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

    
342
        return $vlanif;
343
}
344

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

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

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

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

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

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

    
385
        return $vlanif;
386
}
387

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

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

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

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

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

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

    
434
	if (empty($bridge['members'])) {
435
		log_error(sprintf(gettext("No members found on %s"), $bridge['bridgeif']));
436
		return -1;
437
	}
438

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

    
443
	$checklist = get_configured_interface_list();
444

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

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

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

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

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

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

    
616
	return $bridgeif;
617
}
618

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
731
	interfaces_bring_up($laggif);
732

    
733
	return $laggif;
734
}
735

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

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

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

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

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

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

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

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

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

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

    
795
	return $greif;
796
}
797

    
798
function interfaces_gif_configure($checkparent = 0) {
799
	global $config;
800

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

    
815
/* NOTE: $gifkey is not used but useful for passing this function to array_walk. */
816
function interface_gif_configure(&$gif, $gifkey = "") {
817
	global $config, $g;
818

    
819
	if (!is_array($gif))
820
		return -1;
821

    
822
	$realif = get_real_interface($gif['if']);
823
	$realifip = get_interface_ip($gif['if']);
824

    
825
	/* make sure the parent interface is up */
826
	if($realif)
827
		interfaces_bring_up($realif);
828
	else 
829
		log_error(gettext("could not bring realif up -- variable not defined -- interface_gif_configure()"));
830

    
831
	if ($g['booting'] || !(empty($gif['gifif']))) {
832
		pfSense_interface_destroy($gif['gifif']);
833
		pfSense_interface_create($gif['gifif']);
834
		$gifif = $gif['gifif'];
835
	} else
836
		$gifif = pfSense_interface_create("gif");
837

    
838
	/* Do not change the order here for more see gif(4) NOTES section. */
839
	mwexec("/sbin/ifconfig {$gifif} tunnel {$realifip} {$gif['remote-addr']}");
840
	if((is_ipaddrv6($gif['tunnel-local-addr'])) || (is_ipaddrv6($gif['tunnel-remote-addr']))) {
841
		mwexec("/sbin/ifconfig {$gifif} inet6 {$gif['tunnel-local-addr']} {$gif['tunnel-remote-addr']} prefixlen {$gif['tunnel-remote-net']} ");
842
	} else {
843
		mwexec("/sbin/ifconfig {$gifif} {$gif['tunnel-local-addr']} {$gif['tunnel-remote-addr']} netmask " . gen_subnet_mask($gif['tunnel-remote-net']));
844
	}
845
	if (isset($gif['link0']) && $gif['link0'])
846
		pfSense_interface_flags($gifif, IFF_LINK0);
847
	if (isset($gif['link1']) && $gif['link1'])
848
		pfSense_interface_flags($gifif, IFF_LINK1);
849
	if($gifif)
850
		interfaces_bring_up($gifif);
851
	else
852
		log_error(gettext("could not bring gifif up -- variable not defined"));
853

    
854
	$iflist = get_configured_interface_list();
855
	foreach($iflist as $ifname) {
856
		if($config['interfaces'][$ifname]['if'] == $gifif) {
857
			if(get_interface_gateway($ifname)) {
858
				system_routing_configure($ifname);
859
				break;
860
			}
861
			if(get_interface_gateway_v6($ifname)) {
862
				system_routing_configure($ifname);
863
				break;
864
			}
865
		}
866
	}
867

    
868
	if(is_ipaddrv4($gif['tunnel-remote-addr']))
869
		file_put_contents("{$g['tmp_path']}/{$gifif}_router", $gif['tunnel-remote-addr']);
870
	if(is_ipaddrv6($gif['tunnel-remote-addr']))
871
		file_put_contents("{$g['tmp_path']}/{$gifif}_routerv6", $gif['tunnel-remote-addr']);
872

    
873
	return $gifif;
874
}
875

    
876
function interfaces_configure() {
877
	global $config, $g;
878

    
879
	/* Set up our loopback interface */
880
	interfaces_loopback_configure();
881

    
882
	/* set up LAGG virtual interfaces */
883
	interfaces_lagg_configure();
884

    
885
	/* set up VLAN virtual interfaces */
886
	interfaces_vlan_configure();
887

    
888
	interfaces_qinq_configure();
889

    
890
	$iflist = get_configured_interface_with_descr();
891
	$delayed_list = array();
892
	$bridge_list = array();
893
	
894
	/* This is needed to speedup interfaces on bootup. */
895
	$reload = false;
896
	if ($g['booting'])
897
		$reload = true;
898

    
899
	foreach($iflist as $if => $ifname) {
900
		$realif = $config['interfaces'][$if]['if'];
901
		if (strstr($realif, "bridge")) 
902
			$bridge_list[$if] = $ifname;
903
		else if (strstr($realif, "gre"))
904
			$delayed_list[$if] = $ifname;
905
		else if (strstr($realif, "gif"))
906
			$delayed_list[$if] = $ifname;
907
		else if (strstr($realif, "ovpn")) {
908
			//echo "Delaying OpenVPN interface configuration...done.\n";
909
			continue;
910
		} else {
911
			if ($g['booting'])
912
				printf(gettext("Configuring %s interface..."), $ifname);
913
			if($g['debug'])
914
				log_error(sprintf(gettext("Configuring %s"), $ifname));
915
			interface_configure($if, $reload);
916
			if ($g['booting']) 
917
				echo gettext( "done.") . "\n";
918
		}
919
	}
920

    
921
	/* create the unconfigured wireless clones */
922
	interfaces_create_wireless_clones();
923

    
924
	/*
925
	 * NOTE: The following function parameter consists of
926
	 *	1 - Do not load gre/gif/bridge with parent/member as vip
927
	 *	2 - Do load gre/gif/bridge with parent/member as vip
928
	 */
929

    
930
	/* set up GRE virtual interfaces */
931
	interfaces_gre_configure(1);
932

    
933
	/* set up GIF virtual interfaces */
934
	interfaces_gif_configure(1);
935

    
936
	/* set up BRIDGe virtual interfaces */
937
	interfaces_bridge_configure(1);
938

    
939
	/* bring up vip interfaces */
940
	interfaces_vips_configure();
941

    
942
	/* set up GRE virtual interfaces */
943
	interfaces_gre_configure(2);
944

    
945
	/* set up GIF virtual interfaces */
946
	interfaces_gif_configure(2);
947

    
948
	foreach ($delayed_list as $if => $ifname) {
949
		if ($g['booting'])
950
			printf(gettext("Configuring %s interface..."), $ifname);
951
        	if ($g['debug'])
952
        		log_error(sprintf(gettext("Configuring %s"), $ifname));
953

    
954
		interface_configure($if, $reload);
955

    
956
		if ($g['booting'])
957
			echo gettext("done.") . "\n";
958
	}
959

    
960
	/* set up BRIDGe virtual interfaces */
961
	interfaces_bridge_configure(2);
962

    
963
	foreach ($bridge_list as $if => $ifname) {
964
		if ($g['booting'])
965
			printf(gettext("Configuring %s interface..."), $ifname);
966
		if($g['debug'])
967
			log_error(sprintf(gettext("Configuring %s"), $ifname));
968

    
969
		interface_configure($if, $reload);
970

    
971
		if ($g['booting'])
972
			echo gettext("done.") . "\n";
973
	}
974

    
975
	/* configure interface groups */
976
	interfaces_group_setup();
977

    
978
	if (!$g['booting']) {
979
		/* reconfigure static routes (kernel may have deleted them) */
980
		system_routing_configure();
981

    
982
		/* reload IPsec tunnels */
983
		vpn_ipsec_configure();
984

    
985
		/* reload dhcpd (interface enabled/disabled status may have changed) */
986
		services_dhcpd_configure();
987

    
988
		/* restart dnsmasq */
989
		services_dnsmasq_configure();
990

    
991
		/* reload captive portal */
992
		captiveportal_init_rules();
993
	}
994

    
995
	return 0;
996
}
997

    
998
function interface_reconfigure($interface = "wan", $reloadall = false) {
999
	interface_bring_down($interface);
1000
	interface_configure($interface, $reloadall);
1001
}
1002

    
1003
function interface_vip_bring_down($vip) {
1004
	global $g;
1005

    
1006
	switch ($vip['mode']) {
1007
	case "proxyarp":
1008
		$vipif = get_real_interface($vip['interface']);
1009
		if (file_exists("{$g['varrun_path']}/choparp_{$vipif}.pid"))
1010
			killbypid("{$g['varrun_path']}/choparp_{$vipif}.pid");
1011
		break;
1012
	case "ipalias":
1013
		$vipif = get_real_interface($vip['interface']);
1014
		if(does_interface_exist($vipif))
1015
			pfSense_interface_deladdress($vipif, $vip['subnet']);
1016
		break;
1017
	case "carp":
1018
		$vipif = "vip" . $vip['vhid'];
1019
		if(does_interface_exist($vipif)) 
1020
			pfSense_interface_destroy($vipif);
1021
		break;
1022
	case "carpdev-dhcp":
1023
		$vipif = "vip" . $vip['vhid'];
1024
		if(does_interface_exist($vipif)) 
1025
			pfSense_interface_destroy($vipif);
1026
		break;
1027
	}
1028
}
1029

    
1030
function interface_bring_down($interface = "wan", $destroy = false) {
1031
	global $config, $g;
1032

    
1033
	if (!isset($config['interfaces'][$interface]))
1034
		return; 
1035

    
1036
	$ifcfg = $config['interfaces'][$interface];
1037

    
1038
	$realif = get_real_interface($interface);
1039

    
1040
	switch ($ifcfg['ipaddr']) {
1041
	case "ppp":
1042
	case "pppoe":
1043
	case "pptp":
1044
	case "l2tp":
1045
		if (is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) {
1046
			foreach ($config['ppps']['ppp'] as $pppid => $ppp) {
1047
				if ($realif == $ppp['if']) {
1048
					if (isset($ppp['ondemand']) && !$destroy){
1049
						send_event("interface reconfigure {$interface}");
1050
						break;
1051
					}
1052
					if (file_exists("{$g['varrun_path']}/{$ppp['type']}_{$interface}.pid")) {
1053
						killbypid("{$g['varrun_path']}/{$ppp['type']}_{$interface}.pid");
1054
						sleep(2);
1055
					}
1056
					unlink_if_exists("{$g['varetc_path']}/mpd_{$interface}.conf");
1057
					break;
1058
				}
1059
			}
1060
		}
1061
		break;
1062
	case "carpdev-dhcp":
1063
		/* 
1064
		 * NB: When carpdev gets enabled it would be better to be handled as all
1065
		 *	   other interfaces! 
1066
		 */
1067
	case "dhcp":
1068
		$pid = find_dhclient_process($realif);
1069
		if($pid)
1070
			mwexec("/bin/kill {$pid}");
1071
		$pidv6 = find_dhcp6c_process($realif);
1072
		if($pidv6)
1073
			mwexec("/bin/kill {$pidv6}");
1074
		sleep(1);
1075
		unlink_if_exists("{$g['varetc_path']}/dhclient_{$interface}.conf");
1076
		unlink_if_exists("{$g['varetc_path']}/dhcp6c_{$interface}.conf");
1077
		if(does_interface_exist("$realif")) {
1078
			mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete", true);
1079
			if ($destroy == true)
1080
				pfSense_interface_flags($realif, -IFF_UP);
1081
			mwexec("/usr/sbin/arp -d -i {$realif} -a");
1082
		}
1083
		break;
1084
	default:
1085
		if(does_interface_exist("$realif")) {
1086
			mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " delete", true);
1087
			if ($destroy == true)
1088
				pfSense_interface_flags($realif, -IFF_UP);
1089
			mwexec("/usr/sbin/arp -d -i {$realif} -a");
1090
		}
1091
		break;
1092
	}
1093

    
1094
	/* remove interface up file if it exists */
1095
	unlink_if_exists("{$g['tmp_path']}/{$realif}up");
1096
	unlink_if_exists("{$g['vardb_path']}/{$interface}ip");
1097
	unlink_if_exists("{$g['vardb_path']}/{$interface}ipv6");
1098
	unlink_if_exists("{$g['tmp_path']}/{$realif}_router");
1099
	unlink_if_exists("{$g['tmp_path']}/{$realif}_routerv6");
1100
	unlink_if_exists("{$g['varetc_path']}/nameserver_{$realif}");
1101
	unlink_if_exists("{$g['varetc_path']}/searchdomain_{$realif}");
1102
	
1103
	/* hostapd and wpa_supplicant do not need to be running when the interface is down.
1104
	 * They will also use 100% CPU if running after the wireless clone gets deleted. */
1105
	if (is_array($ifcfg['wireless'])) {
1106
		mwexec(kill_hostapd($realif));
1107
		mwexec(kill_wpasupplicant($realif));
1108
	}
1109

    
1110
	if ($destroy == true) {
1111
		if (preg_match("/^vip|^tun|^ovpn|^gif|^gre|^lagg|^bridge|vlan/i", $realif))
1112
			pfSense_interface_destroy($realif);
1113
	}	
1114

    
1115
	return;
1116
}
1117

    
1118
function interfaces_ptpid_used($ptpid) {
1119
	global $config;
1120

    
1121
	if (is_array($config['ppps']['ppp']))
1122
		foreach ($config['ppps']['ppp'] as & $settings)
1123
			if ($ptpid == $settings['ptpid'])
1124
				return true;
1125

    
1126
	return false;
1127
}
1128

    
1129
function interfaces_ptpid_next() {
1130

    
1131
	$ptpid = 0;
1132
	while(interfaces_ptpid_used($ptpid))
1133
		$ptpid++;
1134

    
1135
	return $ptpid;
1136
}
1137

    
1138
function getMPDCRONSettings($pppif_) {
1139
	global $config;
1140
	$cron_cmd_file = "{$g['varetc_path']}/pppoe_restart_";
1141
	if (is_array($config['cron']['item'])) {
1142
		for ($i = 0; $i < count($config['cron']['item']); $i++) {
1143
			$item = $config['cron']['item'][$i];
1144
			if (strpos($item['command'], $cron_cmd_file.$pppif_) !== false) {
1145
				return array("ID" => $i, "ITEM" => $item);
1146
			}
1147
		}
1148
	}
1149
	return NULL;
1150
}
1151

    
1152
function handle_pppoe_reset($post_array) {
1153
	global $config, $g;
1154

    
1155
	$cron_cmd_file = "{$g['varetc_path']}/pppoe_restart_";
1156

    
1157
	$pppif = $post_array['type'].$post_array['ptpid'];
1158
	if (!is_array($config['cron']['item'])) 
1159
		$config['cron']['item'] = array(); 
1160
	$itemhash = getMPDCRONSettings($pppif);
1161
	$item = $itemhash['ITEM'];
1162
	
1163
	// reset cron items if necessary and return
1164
	if (empty($post_array['pppoe-reset-type'])) {
1165
		if (isset($item))
1166
			unset($config['cron']['item'][$itemhash['ID']]);
1167
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
1168
		return;
1169
	}
1170

    
1171
	if (empty($item)) 
1172
		$item = array();
1173
	if (isset($post_array['pppoe-reset-type']) && $post_array['pppoe-reset-type'] == "custom") {
1174
		$item['minute'] = $post_array['pppoe_resetminute'];
1175
		$item['hour'] = $post_array['pppoe_resethour'];
1176
		if (isset($post_array['pppoe_resetdate']) && $post_array['pppoe_resetdate'] <> "") {
1177
			$date = explode("/", $post_array['pppoe_resetdate']);
1178
			$item['mday'] = $date[1];
1179
			$item['month'] = $date[0];
1180
		} else {
1181
			$item['mday'] = "*";
1182
			$item['month'] = "*";
1183
		}
1184
		$item['wday'] = "*";
1185
		$item['who'] = "root";
1186
		$item['command'] = $cron_cmd_file.$pppif;
1187
	} else if (isset($post_array['pppoe-reset-type']) && $post_array['pppoe-reset-type'] == "preset") {
1188
		switch ($post_array['pppoe_pr_preset_val']) {
1189
			case "monthly":
1190
				$item['minute'] = "0";
1191
				$item['hour'] = "0";
1192
				$item['mday'] = "1";
1193
				$item['month'] = "*";
1194
				$item['wday'] = "*";
1195
				$item['who'] = "root";
1196
				$item['command'] = $cron_cmd_file.$pppif;
1197
				break;
1198
	        case "weekly":
1199
				$item['minute'] = "0";
1200
				$item['hour'] = "0";
1201
				$item['mday'] = "*";
1202
				$item['month'] = "*";
1203
				$item['wday'] = "0";
1204
				$item['who'] = "root";
1205
				$item['command'] = $cron_cmd_file.$pppif;
1206
				break;
1207
			case "daily":
1208
				$item['minute'] = "0";
1209
				$item['hour'] = "0";
1210
				$item['mday'] = "*";
1211
				$item['month'] = "*";
1212
				$item['wday'] = "*";
1213
				$item['who'] = "root";
1214
				$item['command'] = $cron_cmd_file.$pppif;
1215
				break;
1216
			case "hourly":
1217
				$item['minute'] = "0";
1218
				$item['hour'] = "*";
1219
				$item['mday'] = "*";
1220
				$item['month'] = "*";
1221
				$item['wday'] = "*";
1222
				$item['who'] = "root";
1223
				$item['command'] = $cron_cmd_file.$pppif;
1224
				break;
1225
		} // end switch
1226
	} else {
1227
		/* test whether a cron item exists and unset() it if necessary */
1228
		$itemhash = getMPDCRONSettings($pppif);
1229
		$item = $itemhash['ITEM'];
1230
		if (isset($item))
1231
			unset($config['cron']['item'][$itemhash['ID']]); 
1232
	}// end if
1233
	if (isset($itemhash['ID'])) 
1234
		$config['cron']['item'][$itemhash['ID']] = $item;
1235
	else 
1236
		$config['cron']['item'][] = $item;
1237
}
1238

    
1239
/*	This function can configure PPPoE, MLPPP (PPPoE), PPTP.
1240
*	It writes the mpd config file to /var/etc every time the link is opened.
1241
*/
1242

    
1243
function interface_ppps_configure($interface) {
1244
	global $config, $g;
1245

    
1246
	/* Return for unassigned interfaces. This is a minimum requirement. */
1247
	if (empty($config['interfaces'][$interface]))
1248
		return 0;
1249
	$ifcfg = $config['interfaces'][$interface];
1250
	if (!isset($ifcfg['enable']))
1251
		return 0;
1252

    
1253
	// mpd5 requires a /var/spool/lock directory for PPP modem links.
1254
	if(!is_dir("/var/spool/lock")) {
1255
		exec("/bin/mkdir -p /var/spool/lock");
1256
		exec("/bin/chmod a+rw /var/spool/lock/.");
1257
	}
1258
	// mpd5 modem chat script expected in the same directory as the mpd_xxx.conf files	
1259
	if (!file_exists("{$g['varetc_path']}/mpd.script"))
1260
		mwexec("/bin/ln -s /usr/local/sbin/mpd.script {$g['varetc_path']}/.");
1261

    
1262
	if (is_array($config['ppps']['ppp']) && count($config['ppps']['ppp'])) {
1263
		foreach ($config['ppps']['ppp'] as $pppid => $ppp) {
1264
			if ($ifcfg['if'] == $ppp['if'])
1265
				break;
1266
		}
1267
	}
1268
	if (!$ppp || $ifcfg['if'] != $ppp['if']){
1269
		log_error(sprintf(gettext("Can't find PPP config for %s in interface_ppps_configure()."), $ifcfg['if']));
1270
		return 0;
1271
	}
1272
	$pppif = $ifcfg['if'];
1273
	if ($ppp['type'] == "ppp")
1274
		$type = "modem";
1275
	else
1276
		$type = $ppp['type'];
1277
	$upper_type = strtoupper($ppp['type']);	
1278

    
1279
	if($g['booting']) {
1280
		$descr = isset($ifcfg['descr']) ? $ifcfg['descr'] : strtoupper($interface);
1281
		echo "starting {$pppif} link...";
1282
		// Do not re-configure the interface if we are booting and it's already been started
1283
		if(file_exists("{$g['varrun_path']}/{$ppp['type']}_{$interface}.pid"))
1284
			return 0;
1285
	}
1286

    
1287
	$ports = explode(',',$ppp['ports']);
1288
	if ($type != "modem") {
1289
		foreach ($ports as $pid => $port)
1290
			$ports[$pid] = get_real_interface($port);
1291
	}
1292
	$localips = explode(',',$ppp['localip']);
1293
	$gateways = explode(',',$ppp['gateway']);
1294
	$subnets = explode(',',$ppp['subnet']);
1295

    
1296
	/* We bring up the parent interface first because if DHCP is configured on the parent we need
1297
	 * to obtain an address first so we can write it in the mpd .conf file for PPTP and L2TP configs
1298
	 */
1299
	foreach($ports as $pid => $port){
1300
		switch ($ppp['type']) {
1301
			case "pppoe": 
1302
				/* Bring the parent interface up */
1303
				interfaces_bring_up($port);
1304
				pfSense_ngctl_attach(".", $port);
1305
				break;
1306
			case "pptp":
1307
			case "l2tp":
1308
				/* configure interface */
1309
				if(is_ipaddr($localips[$pid])){
1310
					// Manually configure interface IP/subnet
1311
					pfSense_interface_setaddress($port, "{$localips[$pid]}/{$subnets[$pid]}");
1312
					interfaces_bring_up($port);
1313
				} else if (empty($localips[$pid]))
1314
					$localips[$pid] = get_interface_ip($port); // try to get the interface IP from the port
1315
				
1316
				if(!is_ipaddr($localips[$pid])){
1317
					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!");
1318
					$localips[$pid] = "0.0.0.0";
1319
				}
1320
				/* XXX: This needs to go away soon! [It's commented out!] */
1321
				/* Configure the gateway (remote IP ) */
1322
				if (!$g['booting'] && !is_ipaddr($gateways[$pid]) && is_hostname($gateways[$pid])) {
1323
					/* XXX: Fix later 
1324
					$gateways[$pid] = gethostbyname($gateways[$pid]);
1325
					if(!is_ipaddr($gateways[$pid])) {
1326
						log_error("Could not get a valid Gateway IP from {$port} via DNS in interfaces_ppps_configure.");
1327
						return 0;
1328
					}
1329
					*/
1330
				}
1331
				if(!is_ipaddr($gateways[$pid])){
1332
					log_error(sprintf(gettext('Could not get a PPTP/L2TP Remote IP address from %1$s for %2$s in interfaces_ppps_configure.'), $dhcp_gateway, $gway));
1333
					return 0;
1334
				}
1335
				pfSense_ngctl_attach(".", $port);
1336
				break;
1337
			case "ppp":
1338
				if (!file_exists("{$port}")) {
1339
					log_error(sprintf(gettext("Device %s does not exist. PPP link cannot start without the modem device."), $port));
1340
					return 0;
1341
				}
1342
				break;
1343
			default:
1344
				log_error(sprintf(gettext("Unkown %s configured as ppp interface."), $type));
1345
				break;
1346
		}
1347
	}
1348
	
1349
	if (is_array($ports) && count($ports) > 1)
1350
		$multilink = "enable";
1351
	else
1352
		$multilink = "disable";
1353
	
1354
	if ($type == "modem"){
1355
		if (is_ipaddr($ppp['localip']))
1356
			$localip = $ppp['localip'];
1357
		else
1358
			$localip = '0.0.0.0';
1359

    
1360
		if (is_ipaddr($ppp['gateway']))
1361
			$gateway = $ppp['gateway'];
1362
		else
1363
			$gateway = "10.64.64.{$pppid}";
1364
		$ranges = "{$localip}/0 {$gateway}/0";
1365
		
1366
		if (empty($ppp['apnum']))	
1367
			$ppp['apnum'] = 1;
1368
	} else
1369
		$ranges = "0.0.0.0/0 0.0.0.0/0";
1370

    
1371
	if (isset($ppp['ondemand'])) 
1372
		$ondemand = "enable";
1373
	else
1374
		$ondemand = "disable";
1375
	if (!isset($ppp['idletimeout']))
1376
		$ppp['idletimeout'] = 0;
1377

    
1378
	if (empty($ppp['username']) && $type == "modem"){
1379
		$ppp['username'] = "user";
1380
		$ppp['password'] = "none";
1381
	}
1382
	if (empty($ppp['password']) && $type == "modem")
1383
		$passwd = "none";
1384
	else
1385
		$passwd = base64_decode($ppp['password']);
1386

    
1387
	$bandwidths = explode(',',$ppp['bandwidth']);
1388
	$mtus = explode(',',$ppp['mtu']);
1389
	$mrus = explode(',',$ppp['mru']);
1390

    
1391
	if (isset($ppp['mrru']))
1392
		$mrrus = explode(',',$ppp['mrru']);
1393

    
1394
	// Construct the mpd.conf file
1395
	$mpdconf = <<<EOD
1396
startup:
1397
	# configure the console
1398
	set console close
1399
	# configure the web server
1400
	set web close
1401

    
1402
default:
1403
{$ppp['type']}client:
1404
	create bundle static {$interface}
1405
	set bundle enable ipv6cp
1406
	set iface name {$pppif}
1407

    
1408
EOD;
1409
	$setdefaultgw = false;
1410
	$founddefaultgw = false;
1411
	if (is_array($config['gateways']['gateway_item'])) {
1412
		foreach($config['gateways']['gateway_item'] as $gateway) {
1413
			if($interface == $gateway['interface'] && isset($gateway['defaultgw'])) {
1414
				$setdefaultgw = true;
1415
				break;
1416
			} else if (isset($gateway['defaultgw']) && !empty($gateway['interface'])) {
1417
				$founddefaultgw = true;
1418
				break;
1419
			}
1420
		}
1421
	}
1422
	
1423
	if (($interface == "wan" && $founddefaultgw == false) || $setdefaultgw == true){
1424
		$setdefaultgw = true;
1425
		$mpdconf .= <<<EOD
1426
	set iface route default
1427

    
1428
EOD;
1429
	}
1430
	$mpdconf .= <<<EOD
1431
	set iface {$ondemand} on-demand
1432
	set iface idle {$ppp['idletimeout']}
1433

    
1434
EOD;
1435

    
1436
	if (isset($ppp['ondemand']))
1437
		$mpdconf .= <<<EOD
1438
	set iface addrs 10.10.1.1 10.10.1.2
1439

    
1440
EOD;
1441
	
1442
	if (isset($ppp['tcpmssfix']))
1443
		$tcpmss = "disable";
1444
	else
1445
		$tcpmss = "enable";
1446
		$mpdconf .= <<<EOD
1447
	set iface {$tcpmss} tcpmssfix
1448

    
1449
EOD;
1450

    
1451
	$mpdconf .= <<<EOD
1452
	set iface up-script /usr/local/sbin/ppp-linkup
1453
	set iface down-script /usr/local/sbin/ppp-linkdown
1454
	set ipcp ranges {$ranges}
1455

    
1456
EOD;
1457
	if (isset($ppp['vjcomp']))
1458
		$mpdconf .= <<<EOD
1459
	set ipcp no vjcomp
1460

    
1461
EOD;
1462

    
1463
	if (isset($config['system']['dnsallowoverride']))
1464
		$mpdconf .= <<<EOD
1465
	set ipcp enable req-pri-dns
1466
	set ipcp enable req-sec-dns
1467

    
1468
EOD;
1469
	if (!isset($ppp['verbose_log']))
1470
		$mpdconf .= <<<EOD
1471
	#log -bund -ccp -chat -iface -ipcp -lcp -link
1472

    
1473
EOD;
1474
	foreach($ports as $pid => $port){
1475
		$port = get_real_interface($port);
1476
		$mpdconf .= <<<EOD
1477

    
1478
	create link static {$interface}_link{$pid} {$type}
1479
	set link action bundle {$interface}
1480
	set link {$multilink} multilink
1481
	set link keep-alive 10 60
1482
	set link max-redial 0
1483

    
1484
EOD;
1485
		if (isset($ppp['shortseq']))
1486
			$mpdconf .= <<<EOD
1487
	set link no shortseq
1488

    
1489
EOD;
1490

    
1491
		if (isset($ppp['acfcomp']))
1492
			$mpdconf .= <<<EOD
1493
	set link no acfcomp
1494

    
1495
EOD;
1496

    
1497
		if (isset($ppp['protocomp']))
1498
			$mpdconf .= <<<EOD
1499
	set link no protocomp
1500

    
1501
EOD;
1502

    
1503
		$mpdconf .= <<<EOD
1504
	set link disable chap pap
1505
	set link accept chap pap eap
1506
	set link disable incoming
1507

    
1508
EOD;
1509

    
1510

    
1511
		if (!empty($bandwidths[$pid]))
1512
			$mpdconf .= <<<EOD
1513
	set link bandwidth {$bandwidths[$pid]}
1514

    
1515
EOD;
1516

    
1517
		if (empty($mtus[$pid]))
1518
			$mtus[$pid] = "1492";
1519
			$mpdconf .= <<<EOD
1520
	set link mtu {$mtus[$pid]}
1521

    
1522
EOD;
1523

    
1524
		if (!empty($mrus[$pid]))
1525
			$mpdconf .= <<<EOD
1526
	set link mru {$mrus[$pid]}
1527

    
1528
EOD;
1529

    
1530
		if (!empty($mrrus[$pid]))
1531
			$mpdconf .= <<<EOD
1532
	set link mrru {$mrrus[$pid]}
1533

    
1534
EOD;
1535

    
1536
		$mpdconf .= <<<EOD
1537
	set auth authname "{$ppp['username']}"
1538
	set auth password {$passwd}
1539

    
1540
EOD;
1541
		if ($type == "modem") {
1542
			$mpdconf .= <<<EOD
1543
	set modem device {$ppp['ports']}
1544
	set modem script DialPeer
1545
	set modem idle-script Ringback
1546
	set modem watch -cd
1547
	set modem var \$DialPrefix "DT"
1548
	set modem var \$Telephone "{$ppp['phone']}"
1549

    
1550
EOD;
1551
		}
1552
		if (isset($ppp['connect-timeout']) && $type == "modem") {
1553
			$mpdconf .= <<<EOD
1554
	set modem var \$ConnectTimeout "{$ppp['connect-timeout']}"
1555

    
1556
EOD;
1557
		}
1558
		if (isset($ppp['initstr']) && $type == "modem") {
1559
			$initstr = base64_decode($ppp['initstr']);
1560
			$mpdconf .= <<<EOD
1561
	set modem var \$InitString "{$initstr}"
1562

    
1563
EOD;
1564
		}
1565
		if (isset($ppp['simpin']) && $type == "modem") {
1566
			$mpdconf .= <<<EOD
1567
	set modem var \$SimPin "{$ppp['simpin']}"
1568
	set modem var \$PinWait "{$ppp['pin-wait']}"
1569

    
1570
EOD;
1571
		}
1572
		if (isset($ppp['apn']) && $type == "modem") {
1573
			$mpdconf .= <<<EOD
1574
	set modem var \$APN "{$ppp['apn']}"
1575
	set modem var \$APNum "{$ppp['apnum']}"
1576

    
1577
EOD;
1578
		}
1579
		if ($type == "pppoe") {
1580
			// Send a null service name if none is set.
1581
			$provider = isset($ppp['provider']) ? $ppp['provider'] : "";
1582
			$mpdconf .= <<<EOD
1583
	set pppoe service "{$provider}"
1584

    
1585
EOD;
1586
		}
1587
		if ($type == "pppoe")
1588
			$mpdconf .= <<<EOD
1589
	set pppoe iface {$port}
1590

    
1591
EOD;
1592

    
1593
		if ($type == "pptp" || $type == "l2tp") {
1594
			$mpdconf .= <<<EOD
1595
	set {$type} self {$localips[$pid]}
1596
	set {$type} peer {$gateways[$pid]}
1597

    
1598
EOD;
1599
		}
1600
		
1601
		$mpdconf .= "\topen\r\n";
1602
	} //end foreach($port)
1603

    
1604

    
1605
	/* Generate mpd.conf. If mpd_[interface].conf exists in the conf path, then link to it instead of generating a fresh conf file. */
1606
	if (file_exists("{$g['conf_path']}/mpd_{$interface}.conf"))
1607
		mwexec("/bin/ln -s {$g['conf_path']}/mpd_{$interface}.conf {$g['varetc_path']}/.");
1608
	else {
1609
		$fd = fopen("{$g['varetc_path']}/mpd_{$interface}.conf", "w");
1610
		if (!$fd) {
1611
			log_error(sprintf(gettext("Error: cannot open mpd_%s.conf in interface_ppps_configure().%s"), $interface, "\n"));
1612
			return 0;
1613
		}
1614
		// Write out mpd_ppp.conf
1615
		fwrite($fd, $mpdconf);
1616
		fclose($fd);
1617
	}
1618

    
1619
	// Create the uptime log if requested and if it doesn't exist already, or delete it if it is no longer requested.
1620
	if (isset($ppp['uptime'])) {
1621
		if (!file_exists("/conf/{$pppif}.log")) {
1622
			conf_mount_rw();
1623
			mwexec("echo /dev/null > /conf/{$pppif}.log");
1624
			conf_mount_ro();
1625
		}
1626
	} else {
1627
		if (file_exists("/conf/{$pppif}.log")) {
1628
			conf_mount_rw();
1629
			mwexec("rm -f /conf/{$pppif}.log");
1630
			conf_mount_ro();
1631
		}
1632
	}
1633

    
1634
	/* fire up mpd */
1635
	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");
1636

    
1637
	// Check for PPPoE periodic reset request 
1638
	if ($type == "pppoe") {
1639
		if (isset($ppp['pppoe-reset-type']))
1640
			setup_pppoe_reset_file($ppp['if'], $interface);
1641
		else
1642
			setup_pppoe_reset_file($ppp['if']);
1643
	}
1644

    
1645
	return 1;
1646
}
1647

    
1648
function interfaces_carp_setup() {
1649
	global $g, $config;
1650

    
1651
	$balanacing = "";
1652
	$pfsyncinterface = "";
1653
	$pfsyncenabled = "";
1654
	if(isset($config['system']['developerspew'])) {
1655
		$mt = microtime();
1656
		echo "interfaces_carp_setup() being called $mt\n";
1657
	}
1658

    
1659
	// Prepare CmdCHAIN that will be used to execute commands.
1660
	$cmdchain = new CmdCHAIN();	
1661

    
1662
	if ($g['booting']) {
1663
		echo gettext("Configuring CARP settings...");
1664
		mute_kernel_msgs();
1665
	}
1666

    
1667
	/* suck in configuration items */
1668
	if($config['installedpackages']['carpsettings']) {
1669
		if($config['installedpackages']['carpsettings']['config']) {
1670
			foreach($config['installedpackages']['carpsettings']['config'] as $carp) {
1671
				$pfsyncenabled = $carp['pfsyncenabled'];
1672
				$balanacing = $carp['balancing'];
1673
				$pfsyncinterface = $carp['pfsyncinterface'];
1674
				$pfsyncpeerip = $carp['pfsyncpeerip'];
1675
			}
1676
		}
1677
	} else {
1678
		unset($pfsyncinterface);
1679
		unset($balanacing);
1680
		unset($pfsyncenabled);
1681
	}
1682

    
1683
	if($balanacing) {
1684
		$cmdchain->add(gettext("Enable CARP ARP-balancing"), "/sbin/sysctl net.inet.carp.arpbalance=1", true);
1685
		$cmdchain->add(gettext("Disallow CARP preemption"), "/sbin/sysctl net.inet.carp.preempt=0", true);
1686
	} else
1687
		$cmdchain->add(gettext("Enable CARP preemption"), "/sbin/sysctl net.inet.carp.preempt=1", true);		
1688

    
1689
	$cmdchain->add(gettext("Enable CARP logging"), "/sbin/sysctl net.inet.carp.log=1", true);
1690
	if (!empty($pfsyncinterface))
1691
		$carp_sync_int = get_real_interface($pfsyncinterface);
1692

    
1693
	if($g['booting']) {
1694
		/*    install rules to alllow pfsync to sync up during boot
1695
		 *    carp interfaces will remain down until the bootup sequence finishes
1696
		 */
1697
		$fd = fopen("{$g['tmp_path']}/rules.boot", "w");
1698
		if ($fd) {
1699
			fwrite($fd, "block quick proto carp \n");
1700
			fwrite($fd, "block quick proto pfsync \n");
1701
			fwrite($fd, "pass out quick from any to any keep state\n");
1702
			fclose($fd);
1703
			mwexec("/sbin/pfctl -f {$g['tmp_path']}/rules.boot");
1704
		} else
1705
			log_error(gettext("Could not create rules.boot file!"));
1706
	}
1707

    
1708
	/* setup pfsync interface */
1709
	if($carp_sync_int and $pfsyncenabled) {
1710
		if (is_ipaddr($pfsyncpeerip))
1711
			$cmdchain->add(gettext("Bring up pfsync0 syncpeer"), "/sbin/ifconfig pfsync0 syncdev {$carp_sync_int} syncpeer {$pfsyncpeerip} up", false);						
1712
		else
1713
			$cmdchain->add(gettext("Bring up pfsync0 syncdev"), "/sbin/ifconfig pfsync0 syncdev {$carp_sync_int} up", false);			
1714
	} else
1715
		$cmdchain->add(gettext("Bring up pfsync0"), "/sbin/ifconfig pfsync0 syncdev lo0 up", false);						
1716

    
1717
	sleep(1);
1718

    
1719
	/* 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
1720
	 * for exiting sessions.
1721
	 */
1722
	$i = 0;
1723
	while (intval(trim(`/sbin/ifconfig pfsync0 | /usr/bin/grep 'syncok: 0' | /usr/bin/grep -v grep | /usr/bin/wc -l`)) == 0 && $i < 30) {
1724
		$i++;
1725
		sleep(1);
1726
	}
1727

    
1728
	if($config['virtualip']['vip'])
1729
		$cmdchain->add(gettext("Allow CARP."), "/sbin/sysctl net.inet.carp.allow=1", true);				
1730
	else
1731
		$cmdchain->add(gettext("Disallow CARP."), "/sbin/sysctl net.inet.carp.allow=0", true);		
1732
	
1733
	if($g['debug'])
1734
		$cmdchain->setdebug(); // optional for verbose logging
1735

    
1736
	$cmdchain->execute();
1737
	$cmdchain->clear();
1738

    
1739
	if ($g['booting']) {
1740
		unmute_kernel_msgs();
1741
		echo gettext("done.") . "\n";
1742
	}
1743
}
1744

    
1745
function interface_proxyarp_configure($interface = "") {
1746
	global $config, $g;
1747
	if(isset($config['system']['developerspew'])) {
1748
		$mt = microtime();
1749
		echo "interface_proxyarp_configure() being called $mt\n";
1750
	}
1751

    
1752
	/* kill any running choparp */
1753
	if (empty($interface))
1754
		killbyname("choparp");
1755
	else {
1756
		$vipif = get_real_interface($interface);
1757
		if (file_exists("{$g['varrun_path']}/choparp_{$vipif}.pid"))
1758
			killbypid("{$g['varrun_path']}/choparp_{$vipif}.pid");
1759
	}
1760

    
1761
	$paa = array();
1762
	if (!empty($config['virtualip']) && is_array($config['virtualip']['vip'])) {
1763

    
1764
		/* group by interface */
1765
		foreach ($config['virtualip']['vip'] as $vipent) {
1766
			if ($vipent['mode'] === "proxyarp") {
1767
				if ($vipent['interface'])
1768
					$proxyif = $vipent['interface'];
1769
				else
1770
					$proxyif = "wan";
1771
				
1772
				if (!empty($interface) && $interface != $proxyif)
1773
					continue;
1774

    
1775
				if (!is_array($paa[$proxyif]))
1776
					$paa[$proxyif] = array();
1777

    
1778
				$paa[$proxyif][] = $vipent;
1779
			}
1780
		}
1781
	}
1782

    
1783
	if (!empty($interface)) {
1784
		if (is_array($paa[$interface])) {
1785
			$paaifip = get_interface_ip($interface);
1786
                        if (!is_ipaddr($paaifip))
1787
                                return;
1788
                        $args = get_real_interface($interface) . " auto";
1789
                        foreach ($paa[$interface] as $paent) {
1790
                                if (isset($paent['subnet']))
1791
                                        $args .= " " . escapeshellarg("{$paent['subnet']}/{$paent['subnet_bits']}");
1792
                                else if (isset($paent['range']))
1793
                                        $args .= " " . escapeshellarg($paent['range']['from'] . "-" . $paent['range']['to']);
1794
                        }
1795
                        mwexec_bg("/usr/local/sbin/choparp " . $args);	
1796
		}
1797
	} else if (count($paa) > 0) {
1798
		foreach ($paa as $paif => $paents)  {
1799
			$paaifip = get_interface_ip($paif);
1800
			if (!is_ipaddr($paaifip))
1801
				continue;
1802
			$args = get_real_interface($paif) . " auto";
1803
			foreach ($paents as $paent) {
1804
				if (isset($paent['subnet']))
1805
					$args .= " " . escapeshellarg("{$paent['subnet']}/{$paent['subnet_bits']}");
1806
				else if (isset($paent['range']))
1807
					$args .= " " . escapeshellarg($paent['range']['from'] . "-" . $paent['range']['to']);
1808
			}
1809
			mwexec_bg("/usr/local/sbin/choparp " . $args);
1810
		}
1811
	}
1812
}
1813

    
1814
function interfaces_vips_configure($interface = "") {
1815
	global $g, $config;
1816
	if(isset($config['system']['developerspew'])) {
1817
		$mt = microtime();
1818
		echo "interfaces_vips_configure() being called $mt\n";
1819
	}
1820
	$paa = array();
1821
	if(is_array($config['virtualip']['vip'])) {
1822
		$carp_setuped = false;
1823
		$anyproxyarp = false;
1824
		foreach ($config['virtualip']['vip'] as $vip) {
1825
			switch ($vip['mode']) {
1826
			case "proxyarp":
1827
				/* nothing it is handled on interface_proxyarp_configure() */
1828
				if ($interface <> "" && $vip['interface'] <> $interface)
1829
					continue;
1830
				$anyproxyarp = true;
1831
				break;
1832
			case "ipalias":
1833
				if ($interface <> "" && $vip['interface'] <> $interface)
1834
					continue;
1835
				interface_ipalias_configure(&$vip);
1836
				break;
1837
			case "carp":
1838
				if ($interface <> "" && $vip['interface'] <> $interface)
1839
					continue;
1840
				if ($carp_setuped == false)
1841
					$carp_setuped = true;
1842
				interface_carp_configure($vip);
1843
				break;
1844
			case "carpdev-dhcp":
1845
				if ($interface <> "" && $vip['interface'] <> $interface)
1846
					continue;
1847
				interface_carpdev_configure($vip);
1848
				break;
1849
			}
1850
		}
1851
		if ($carp_setuped == true)
1852
			interfaces_carp_setup();
1853
		if ($anyproxyarp == true)
1854
			interface_proxyarp_configure();
1855
	}
1856
}
1857

    
1858
function interface_ipalias_configure(&$vip) {
1859

    
1860
	if ($vip['mode'] == "ipalias") {
1861
		$if = get_real_interface($vip['interface']);
1862
		mwexec("/sbin/ifconfig " . escapeshellarg($if) . " " . $vip['subnet'] . "/" . escapeshellarg($vip['subnet_bits']) . " alias");
1863
	}
1864
}
1865

    
1866
function interface_reload_carps($cif) {
1867
	global $config;
1868

    
1869
	$carpifs = link_ip_to_carp_interface(find_interface_ip($cif));
1870
	if (empty($carpifs))
1871
		return;
1872

    
1873
	$carps = explode(" ", $carpifs);
1874
	if(is_array($config['virtualip']['vip'])) {
1875
		$viparr = &$config['virtualip']['vip'];
1876
		foreach ($viparr as $vip) {
1877
			if (in_array($vip['carpif'], $carps)) {
1878
				switch ($vip['mode']) {
1879
				case "carp":
1880
					interface_vip_bring_down($vip);
1881
					sleep(1);
1882
					interface_carp_configure($vip);
1883
					break;
1884
				case "carpdev-dhcp":
1885
					interface_vip_bring_down($vip);
1886
					sleep(1);
1887
					interface_carpdev_configure($vip);
1888
					break;
1889
				case "ipalias":
1890
					interface_vip_bring_down($vip);
1891
					sleep(1);
1892
					interface_ipalias_configure($vip);
1893
					break;
1894
				}
1895
			}
1896
		}
1897
	}
1898
}
1899

    
1900
function interface_carp_configure(&$vip) {
1901
	global $config, $g;
1902
	if(isset($config['system']['developerspew'])) {
1903
		$mt = microtime();
1904
		echo "interface_carp_configure() being called $mt\n";
1905
	}
1906

    
1907
	if ($vip['mode'] != "carp")
1908
		return;
1909

    
1910
	$vip_password = $vip['password'];
1911
	$vip_password = escapeshellarg(addslashes(str_replace(" ", "", $vip_password)));
1912
	if ($vip['password'] != "")
1913
		$password = " pass {$vip_password}";
1914

    
1915
	// set the vip interface to the vhid
1916
	$vipif = "vip{$vip['vhid']}";
1917

    
1918
	/*
1919
	 * ensure the interface containing the VIP really exists
1920
 	 * prevents a panic if the interface is missing or invalid
1921
	 */
1922
	$realif = get_real_interface($vip['interface']);
1923
	if (!does_interface_exist($realif)) {
1924
		file_notice("CARP", sprintf(gettext("Interface specified for the virtual IP address %s does not exist. Skipping this VIP."), $vip['subnet']), "Firewall: Virtual IP", "");
1925
		return;
1926
	}
1927

    
1928
	if(is_ipaddrv4($vip['subnet'])) {
1929
		/* Ensure CARP IP really exists prior to loading up. */
1930
		$ww_subnet_ip = find_interface_ip($realif);
1931
		$ww_subnet_bits = find_interface_subnet($realif);
1932
		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'])) {
1933
			file_notice("CARP", sprintf(gettext("Sorry but we could not find a matching real interface subnet for the virtual IP address %s."), $vip['subnet']), "Firewall: Virtual IP", "");
1934
			return;
1935
		}
1936
	}
1937
	if(is_ipaddrv6($vip['subnet'])) {
1938
		/* Ensure CARP IP really exists prior to loading up. */
1939
		$ww_subnet_ip = find_interface_ipv6($realif);
1940
		$ww_subnet_bits = find_interface_subnetv6($realif);
1941
		if (!ip_in_subnet($vip['subnet'], gen_subnetv6($ww_subnet_ip, $ww_subnet_bits) . "/" . $ww_subnet_bits) && !ip_in_interface_alias_subnet($vip['interface'], $vip['subnet'])) {
1942
			file_notice("CARP", sprintf(gettext("Sorry but we could not find a matching real interface subnet for the virtual IPv6 address %s."), $vip['subnet']), "Firewall: Virtual IP", "");
1943
			return;
1944
		}
1945
	}
1946

    
1947
	/* create the carp interface and setup */
1948
	if (does_interface_exist($vipif)) {
1949
		pfSense_interface_flags($vipif, -IFF_UP);
1950
	} else {
1951
		$carpif = pfSense_interface_create("carp");
1952
		pfSense_interface_rename($carpif, $vipif);
1953
		pfSense_ngctl_name("{$carpif}:", $vipif);
1954
	}
1955

    
1956
	/* invalidate interface cache */
1957
	get_interface_arr(true);
1958

    
1959
	$advbase = "";
1960
	if (!empty($vip['advbase']))
1961
		$advbase = "advbase {$vip['advbase']}";
1962

    
1963
	if(is_ipaddrv4($vip['subnet'])) {
1964
		$broadcast_address = gen_subnet_max($vip['subnet'], $vip['subnet_bits']);
1965
		mwexec("/sbin/ifconfig {$vipif} {$vip['subnet']}/{$vip['subnet_bits']} vhid {$vip['vhid']} advskew {$vip['advskew']} {$advbase} {$password}");
1966
	}
1967
	if(is_ipaddrv6($vip['subnet'])) {
1968
		$broadcast_address = gen_subnet_max($vip['subnet'], $vip['subnet_bits']);
1969
		mwexec("/sbin/ifconfig {$vipif} inet6 {$vip['subnet']} prefixlen {$vip['subnet_bits']} vhid {$vip['vhid']} advskew {$vip['advskew']} {$advbase} {$password}");
1970
	}
1971

    
1972
	interfaces_bring_up($vipif);
1973
	
1974
	return $vipif;
1975
}
1976

    
1977
function interface_carpdev_configure(&$vip) {
1978
	global $g;
1979

    
1980
	if ($vip['mode'] != "carpdev-dhcp")
1981
		return;
1982

    
1983
	$vip_password = $vip['password'];
1984
	$vip_password = str_replace(" ", "", $vip_password);
1985
	if($vip['password'] != "")
1986
		$password = " pass \"" . $vip_password . "\"";
1987

    
1988
	if (empty($vip['interface']))
1989
		return;
1990

    
1991
	$vipif = "vip" . $vip['vhid'];
1992
	$realif = get_real_interface($vip['interface']);
1993
	interfaces_bring_up($realif);
1994
	/*
1995
	 * ensure the interface containing the VIP really exists
1996
	 * prevents a panic if the interface is missing or invalid
1997
	 */
1998
	if (!does_interface_exist($realif)) {
1999
		file_notice("CARP", sprintf(gettext("Interface specified for the virtual IP address %s does not exist. Skipping this VIP."), $vip['subnet']), "Firewall: Virtual IP", "");
2000
		return;
2001
	}
2002

    
2003
	if (does_interface_exist($vipif)) {
2004
		interface_bring_down($vipif);
2005
	} else {
2006
		$carpdevif = exec("/sbin/ifconfig carp create");
2007
		mwexec("/sbin/ifconfig {$carpdevif} name {$vipif}");
2008
		pfSense_ngctl_name("{$carpdevif}:", $vipif);
2009
	}
2010

    
2011
	mwexec("/sbin/ifconfig {$vipif} carpdev {$realif} vhid {$vip['vhid']} advskew {$vip['advskew']} advbase {$vip['advbase']} {$password}");
2012
	interfaces_bring_up($vipif);
2013

    
2014
	/*
2015
	 * XXX: BIG HACK but carpdev needs ip services active
2016
	 *      before even starting something as dhclient.
2017
	 *      I do not know if this is a feature or a bug
2018
	 *      but better than track it make it work ;) .
2019
	 */
2020
	//$fakeiptouse = "10.254.254." . ($carp_instances_counter+1);
2021
	//$cmdchain->add("CarpDEV hack", "/sbin/ifconfig {$carpint} inet {$fakeiptouse}", false);
2022

    
2023
	/* generate dhclient_wan.conf */
2024
	$fd = fopen("{$g['varetc_path']}/dhclient_{$vipif}.conf", "w");
2025
	if ($fd) {
2026
		$dhclientconf = "";
2027

    
2028
		$dhclientconf .= <<<EOD
2029
interface "{$vipif}" {
2030
timeout 60;
2031
retry 1;
2032
select-timeout 0;
2033
initial-interval 1;
2034
script "/sbin/dhclient-script";
2035
}
2036

    
2037
EOD;
2038

    
2039
		fwrite($fd, $dhclientconf);
2040
		fclose($fd);
2041

    
2042
		/* fire up dhclient */
2043
		mwexec("/sbin/dhclient -c {$g['varetc_path']}/dhclient_{$vipif}.conf {$vipif} >{$g['tmp_path']}/{$vipif}_output 2>{$g['tmp_path']}/{$vipif}_error_output", false);
2044
	} else {
2045
		log_error(sprintf(gettext("Error: cannot open dhclient_%s.conf in interfaces_carpdev_configure() for writing.%s"), $vipif, "\n"));
2046
		mwexec("/sbin/dhclient -b {$vipif}");
2047
	}
2048

    
2049
	return $vipif;
2050
}
2051

    
2052
function interface_wireless_clone($realif, $wlcfg) {
2053
	global $config, $g;
2054
	/*   Check to see if interface has been cloned as of yet.  
2055
	 *   If it has not been cloned then go ahead and clone it.
2056
	 */
2057
	$needs_clone = false;
2058
	if(is_array($wlcfg['wireless']))
2059
		$wlcfg_mode = $wlcfg['wireless']['mode'];
2060
	else
2061
		$wlcfg_mode = $wlcfg['mode'];
2062
	switch($wlcfg_mode) {
2063
		 case "hostap":
2064
			$mode = "wlanmode hostap";
2065
			break;
2066
		 case "adhoc":
2067
			$mode = "wlanmode adhoc";
2068
			break;
2069
		 default:
2070
			$mode = "";
2071
			break;
2072
	}
2073
	$baseif = interface_get_wireless_base($wlcfg['if']);
2074
	if(does_interface_exist($realif)) {
2075
		exec("/sbin/ifconfig {$realif}", $output, $ret);
2076
		$ifconfig_str = implode($output);
2077
		if(($wlcfg_mode == "hostap") && (! preg_match("/hostap/si", $ifconfig_str))) {
2078
			log_error(sprintf(gettext("Interface %s changed to hostap mode"), $realif));
2079
			$needs_clone = true;
2080
		}
2081
		if(($wlcfg_mode == "adhoc") && (! preg_match("/adhoc/si", $ifconfig_str))) {
2082
			log_error(sprintf(gettext("Interface %s changed to adhoc mode"), $realif));
2083
			$needs_clone = true;
2084
		}
2085
		if(($wlcfg_mode == "bss") && (preg_match("/hostap|adhoc/si", $ifconfig_str))) {
2086
			log_error(sprintf(gettext("Interface %s changed to infrastructure mode"), $realif));
2087
			$needs_clone = true;
2088
		}
2089
	} else {
2090
		$needs_clone = true;
2091
	}
2092

    
2093
	if($needs_clone == true) {
2094
		/* remove previous instance if it exists */
2095
		if(does_interface_exist($realif))
2096
			pfSense_interface_destroy($realif);
2097

    
2098
		log_error(sprintf(gettext("Cloning new wireless interface %s"), $realif));
2099
		// Create the new wlan interface. FreeBSD returns the new interface name.
2100
		// example:  wlan2
2101
		exec("/sbin/ifconfig wlan create wlandev {$baseif} {$mode} bssid 2>&1", $out, $ret);
2102
		if($ret <> 0) {
2103
			log_error(sprintf(gettext('Failed to clone interface %1$s with error code %2$s, output %3$s'), $baseif, $ret, $out[0]));
2104
			return false;
2105
		}
2106
		$newif = trim($out[0]);
2107
		// Rename the interface to {$parentnic}_wlan{$number}#: EX: ath0_wlan0
2108
		pfSense_interface_rename($newif, $realif);
2109
		// FIXME: not sure what ngctl is for. Doesn't work.
2110
		// mwexec("/usr/sbin/ngctl name {$newif}: {$realif}", false);
2111
		file_put_contents("{$g['tmp_path']}/{$realif}_oldmac", get_interface_mac($realif));
2112
	}
2113
	return true;
2114
}
2115

    
2116
function interface_sync_wireless_clones(&$ifcfg, $sync_changes = false) {
2117
	global $config, $g;
2118

    
2119
	$shared_settings = array('standard', 'turbo', 'protmode', 'txpower', 'channel',
2120
	                         'diversity', 'txantenna', 'rxantenna', 'distance',
2121
	                         'regdomain', 'regcountry', 'reglocation');
2122

    
2123
	if(!is_interface_wireless($ifcfg['if']))
2124
		return;
2125

    
2126
	$baseif = interface_get_wireless_base($ifcfg['if']);
2127

    
2128
	// Sync shared settings for assigned clones
2129
	$iflist = get_configured_interface_list(false, true);
2130
	foreach ($iflist as $if) {
2131
		if ($baseif == interface_get_wireless_base($config['interfaces'][$if]['if']) && $ifcfg['if'] != $config['interfaces'][$if]['if']) {
2132
			if (isset($config['interfaces'][$if]['wireless']['standard']) || $sync_changes) {
2133
				foreach ($shared_settings as $setting) {
2134
					if ($sync_changes) {
2135
						if (isset($ifcfg['wireless'][$setting]))
2136
							$config['interfaces'][$if]['wireless'][$setting] = $ifcfg['wireless'][$setting];
2137
						else if (isset($config['interfaces'][$if]['wireless'][$setting]))
2138
							unset($config['interfaces'][$if]['wireless'][$setting]);
2139
					} else {
2140
						if (isset($config['interfaces'][$if]['wireless'][$setting]))
2141
							$ifcfg['wireless'][$setting] = $config['interfaces'][$if]['wireless'][$setting];
2142
						else if (isset($ifcfg['wireless'][$setting]))
2143
							unset($ifcfg['wireless'][$setting]);
2144
					}
2145
				}
2146
				if (!$sync_changes)
2147
					break;
2148
			}
2149
		}
2150
	}
2151

    
2152
	// Read or write settings at shared area
2153
	if (isset($config['wireless']['interfaces'][$baseif])) {
2154
		foreach ($shared_settings as $setting) {
2155
			if ($sync_changes) {
2156
				if (isset($ifcfg['wireless'][$setting]))
2157
					$config['wireless']['interfaces'][$baseif][$setting] = $ifcfg['wireless'][$setting];
2158
				else if (isset($config['wireless']['interfaces'][$baseif][$setting]))
2159
					unset($config['wireless']['interfaces'][$baseif][$setting]);
2160
			} else if (isset($config['wireless']['interfaces'][$baseif][$setting])) {
2161
				if (isset($config['wireless']['interfaces'][$baseif][$setting]))
2162
					$ifcfg['wireless'][$setting] = $config['wireless']['interfaces'][$baseif][$setting];
2163
				else if (isset($ifcfg['wireless'][$setting]))
2164
					unset($ifcfg['wireless'][$setting]);
2165
			}
2166
		}
2167
	}
2168

    
2169
	// Sync the mode on the clone creation page with the configured mode on the interface
2170
	if (interface_is_wireless_clone($ifcfg['if'])) {
2171
		foreach ($config['wireless']['clone'] as &$clone) {
2172
			if ($clone['cloneif'] == $ifcfg['if']) {
2173
				if ($sync_changes) {
2174
					$clone['mode'] = $ifcfg['wireless']['mode'];
2175
				} else {
2176
					$ifcfg['wireless']['mode'] = $clone['mode'];
2177
				}
2178
				break;
2179
			}
2180
		}
2181
		unset($clone);
2182
	}
2183
}
2184

    
2185
function interface_wireless_configure($if, &$wl, &$wlcfg) {
2186
	global $config, $g;
2187

    
2188
	/*    open up a shell script that will be used to output the commands.
2189
	 *    since wireless is changing a lot, these series of commands are fragile
2190
     *    and will sometimes need to be verified by a operator by executing the command
2191
     *    and returning the output of the command to the developers for inspection.  please
2192
     *    do not change this routine from a shell script to individul exec commands.  -sullrich
2193
	 */
2194

    
2195
	// Remove script file
2196
	unlink_if_exists("{$g['tmp_path']}/{$if}_setup.sh");
2197

    
2198
	// Clone wireless nic if needed.
2199
	interface_wireless_clone($if, $wl);
2200

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

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

    
2208
	/* set values for /path/program */
2209
	$hostapd = "/usr/sbin/hostapd";
2210
	$wpa_supplicant = "/usr/sbin/wpa_supplicant";
2211
	$ifconfig = "/sbin/ifconfig";
2212
	$sysctl = "/sbin/sysctl";
2213
	$killall = "/usr/bin/killall";
2214

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

    
2217
	$wlcmd = array();
2218
	$wl_sysctl = array();
2219
	/* Make sure it's up */
2220
	$wlcmd[] = "up";
2221
	/* Set a/b/g standard */
2222
	$standard = str_replace(" Turbo", "", $wlcfg['standard']);
2223
	$wlcmd[] = "mode " . escapeshellarg($standard);
2224

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

    
2230
	/* Set ssid */
2231
	if($wlcfg['ssid'])
2232
		$wlcmd[] = "ssid " .escapeshellarg($wlcfg['ssid']);
2233

    
2234
	/* Set 802.11g protection mode */
2235
	$wlcmd[] = "protmode " . escapeshellarg($wlcfg['protmode']);
2236

    
2237
	/* set wireless channel value */
2238
	if(isset($wlcfg['channel'])) {
2239
		if($wlcfg['channel'] == "0") {
2240
			$wlcmd[] = "channel any";
2241
		} else {
2242
			$wlcmd[] = "channel " . escapeshellarg($wlcfg['channel']);
2243
		}
2244
	}
2245

    
2246
	/* Set antenna diversity value */
2247
	if(isset($wlcfg['diversity']))
2248
		$wl_sysctl[] = "diversity=" . escapeshellarg($wlcfg['diversity']);
2249

    
2250
	/* Set txantenna value */
2251
	if(isset($wlcfg['txantenna']))
2252
		$wl_sysctl[] = "txantenna=" . escapeshellarg($wlcfg['txantenna']);
2253

    
2254
	/* Set rxantenna value */
2255
	if(isset($wlcfg['rxantenna']))
2256
		$wl_sysctl[] = "rxantenna=" . escapeshellarg($wlcfg['rxantenna']);
2257

    
2258
	/* set Distance value */
2259
	if($wlcfg['distance'])
2260
		$distance = escapeshellarg($wlcfg['distance']);
2261

    
2262
	/* Set wireless hostap mode */
2263
	if ($wlcfg['mode'] == "hostap") {
2264
		$wlcmd[] = "mediaopt hostap";
2265
	} else {
2266
		$wlcmd[] = "-mediaopt hostap";
2267
	}
2268

    
2269
	/* Set wireless adhoc mode */
2270
	if ($wlcfg['mode'] == "adhoc") {
2271
		$wlcmd[] = "mediaopt adhoc";
2272
	} else {
2273
		$wlcmd[] = "-mediaopt adhoc";
2274
	}
2275

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

    
2278
	/* handle hide ssid option */
2279
	if(isset($wlcfg['hidessid']['enable'])) {
2280
		$wlcmd[] = "hidessid";
2281
	} else {
2282
		$wlcmd[] = "-hidessid";
2283
	}
2284

    
2285
	/* handle pureg (802.11g) only option */
2286
	if(isset($wlcfg['pureg']['enable'])) {
2287
		$wlcmd[] = "mode 11g pureg";
2288
	} else {
2289
		$wlcmd[] = "-pureg";
2290
	}
2291

    
2292
	/* handle puren (802.11n) only option */
2293
	if(isset($wlcfg['puren']['enable'])) {
2294
		$wlcmd[] = "puren";
2295
	} else {
2296
		$wlcmd[] = "-puren";
2297
	}
2298

    
2299
	/* enable apbridge option */
2300
	if(isset($wlcfg['apbridge']['enable'])) {
2301
		$wlcmd[] = "apbridge";
2302
	} else {
2303
		$wlcmd[] = "-apbridge";
2304
	}
2305

    
2306
	/* handle turbo option */
2307
	if(isset($wlcfg['turbo']['enable'])) {
2308
		$wlcmd[] = "mediaopt turbo";
2309
	} else {
2310
		$wlcmd[] = "-mediaopt turbo";
2311
	}
2312

    
2313
	/* handle txpower setting */
2314
	/* if($wlcfg['txpower'] <> "")
2315
		$wlcmd[] = "txpower " . escapeshellarg($wlcfg['txpower']);
2316
	*/
2317
	/* handle wme option */
2318
	if(isset($wlcfg['wme']['enable'])) {
2319
		$wlcmd[] = "wme";
2320
	} else {
2321
		$wlcmd[] = "-wme";
2322
	}
2323

    
2324
	/* set up wep if enabled */
2325
	$wepset = "";
2326
	if (isset($wlcfg['wep']['enable']) && is_array($wlcfg['wep']['key'])) {
2327
		switch($wlcfg['wpa']['auth_algs']) {
2328
			case "1":
2329
				$wepset .= "authmode open wepmode on ";
2330
				break;
2331
			case "2":
2332
				$wepset .= "authmode shared wepmode on ";
2333
				break;
2334
			case "3":
2335
				$wepset .= "authmode mixed wepmode on ";
2336
		}
2337
		$i = 1;
2338
		foreach ($wlcfg['wep']['key'] as $wepkey) {
2339
			$wepset .= "wepkey " . escapeshellarg("{$i}:{$wepkey['value']}") . " ";
2340
			if (isset($wepkey['txkey'])) {
2341
				$wlcmd[] = "weptxkey {$i} ";
2342
			}
2343
			$i++;
2344
		}
2345
		$wlcmd[] = $wepset;
2346
	} else {
2347
		$wlcmd[] = "authmode open wepmode off ";
2348
	}
2349

    
2350
	mwexec(kill_hostapd("{$if}"));
2351
	mwexec(kill_wpasupplicant("{$if}"));
2352

    
2353
	/* generate wpa_supplicant/hostap config if wpa is enabled */
2354
	conf_mount_rw();
2355

    
2356
	switch ($wlcfg['mode']) {
2357
		case 'bss':
2358
			if (isset($wlcfg['wpa']['enable'])) {
2359
				$wpa .= <<<EOD
2360
ctrl_interface={$g['varrun_path']}/wpa_supplicant
2361
ctrl_interface_group=0
2362
ap_scan=1
2363
#fast_reauth=1
2364
network={
2365
ssid="{$wlcfg['ssid']}"
2366
scan_ssid=1
2367
priority=5
2368
key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
2369
psk="{$wlcfg['wpa']['passphrase']}"
2370
pairwise={$wlcfg['wpa']['wpa_pairwise']}
2371
group={$wlcfg['wpa']['wpa_pairwise']}
2372
}
2373
EOD;
2374

    
2375
				$fd = fopen("{$g['varetc_path']}/wpa_supplicant_{$if}.conf", "w");
2376
				fwrite($fd, "{$wpa}");
2377
				fclose($fd);
2378
			}
2379
			break;
2380
		case 'hostap':
2381
			if($wlcfg['wpa']['passphrase']) 
2382
				$wpa_passphrase = "wpa_passphrase={$wlcfg['wpa']['passphrase']}\n";
2383
			else 
2384
				$wpa_passphrase = "";
2385
			if (isset($wlcfg['wpa']['enable'])) {
2386
				$wpa .= <<<EOD
2387
interface={$if}
2388
driver=bsd
2389
logger_syslog=-1
2390
logger_syslog_level=0
2391
logger_stdout=-1
2392
logger_stdout_level=0
2393
dump_file={$g['tmp_path']}/hostapd_{$if}.dump
2394
ctrl_interface={$g['varrun_path']}/hostapd
2395
ctrl_interface_group=wheel
2396
#accept_mac_file={$g['tmp_path']}/hostapd_{$if}.accept
2397
#deny_mac_file={$g['tmp_path']}/hostapd_{$if}.deny
2398
#macaddr_acl={$wlcfg['wpa']['macaddr_acl']}
2399
ssid={$wlcfg['ssid']}
2400
debug={$wlcfg['wpa']['debug_mode']}
2401
auth_algs={$wlcfg['wpa']['auth_algs']}
2402
wpa={$wlcfg['wpa']['wpa_mode']}
2403
wpa_key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
2404
wpa_pairwise={$wlcfg['wpa']['wpa_pairwise']}
2405
wpa_group_rekey={$wlcfg['wpa']['wpa_group_rekey']}
2406
wpa_gmk_rekey={$wlcfg['wpa']['wpa_gmk_rekey']}
2407
wpa_strict_rekey={$wlcfg['wpa']['wpa_strict_rekey']}
2408
{$wpa_passphrase}
2409

    
2410
EOD;
2411

    
2412
if (isset($wlcfg['wpa']['rsn_preauth'])) {
2413
	$wpa .= <<<EOD
2414
# Enable the next lines for preauth when roaming. Interface = wired or wireless interface talking to the AP you want to roam from/to
2415
rsn_preauth=1
2416
rsn_preauth_interfaces={$if}
2417

    
2418
EOD;
2419

    
2420
}
2421
				if($wlcfg['auth_server_addr'] && $wlcfg['auth_server_shared_secret']) {
2422
					$auth_server_port = "1812";
2423
					if($wlcfg['auth_server_port']) 
2424
						$auth_server_port = $wlcfg['auth_server_port'];
2425
					$wpa .= <<<EOD
2426

    
2427
ieee8021x=1
2428
auth_server_addr={$wlcfg['auth_server_addr']}
2429
auth_server_port={$auth_server_port}
2430
auth_server_shared_secret={$wlcfg['auth_server_shared_secret']}
2431

    
2432
EOD;
2433
				} else {
2434
					$wpa .= "ieee8021x={$wlcfg['wpa']['ieee8021x']}\n";
2435
				}
2436

    
2437
				$fd = fopen("{$g['varetc_path']}/hostapd_{$if}.conf", "w");
2438
				fwrite($fd, "{$wpa}");
2439
				fclose($fd);
2440

    
2441
			}
2442
			break;
2443
	}
2444

    
2445
	/*
2446
	 *    all variables are set, lets start up everything
2447
	 */
2448

    
2449
	$baseif = interface_get_wireless_base($if);
2450
	preg_match("/^(.*?)([0-9]*)$/", $baseif, $baseif_split);
2451
	$wl_sysctl_prefix = 'dev.' . $baseif_split[1] . '.' . $baseif_split[2];
2452

    
2453
	/* set sysctls for the wireless interface */
2454
	if (!empty($wl_sysctl)) {
2455
		fwrite($fd_set, "# sysctls for {$baseif}\n");
2456
		foreach ($wl_sysctl as $wl_sysctl_line) {
2457
			fwrite($fd_set, "{$sysctl} {$wl_sysctl_prefix}.{$wl_sysctl_line}\n");
2458
		}
2459
	}
2460

    
2461
	/* set ack timers according to users preference (if he/she has any) */
2462
	if($distance) {
2463
		fwrite($fd_set, "# Enable ATH distance settings\n");
2464
		fwrite($fd_set, "/sbin/athctrl.sh -i {$baseif} -d {$distance}\n");
2465
	}
2466

    
2467
	if (isset($wlcfg['wpa']['enable'])) {
2468
		if ($wlcfg['mode'] == "bss") {
2469
			fwrite($fd_set, "{$wpa_supplicant} -B -i {$if} -c {$g['varetc_path']}/wpa_supplicant_{$if}.conf\n");
2470
		}
2471
		if ($wlcfg['mode'] == "hostap") {
2472
			/* add line to script to restore old mac to make hostapd happy */
2473
			if (file_exists("{$g['tmp_path']}/{$if}_oldmac")) {
2474
				$if_oldmac = file_get_contents("{$g['tmp_path']}/{$if}_oldmac");
2475
				if (is_macaddr($if_oldmac))
2476
					fwrite($fd_set, "{$ifconfig} " . escapeshellarg($if) .
2477
						" link " . escapeshellarg($if_oldmac) . "\n");
2478
			}
2479

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

    
2482
			/* add line to script to restore spoofed mac after running hostapd */
2483
			if (file_exists("{$g['tmp_path']}/{$if}_oldmac")) {
2484
				if ($wl['spoofmac'])
2485
					$if_curmac = $wl['spoofmac'];
2486
				else
2487
					$if_curmac = get_interface_mac($if);
2488
				if (is_macaddr($if_curmac))
2489
					fwrite($fd_set, "{$ifconfig} " . escapeshellarg($if) .
2490
						" link " . escapeshellarg($if_curmac) . "\n");
2491
			}
2492
		}
2493
	}
2494

    
2495
	fclose($fd_set);
2496
	conf_mount_ro();
2497

    
2498
	/* Making sure regulatory settings have actually changed
2499
	 * before applying, because changing them requires bringing
2500
	 * down all wireless networks on the interface. */
2501
	exec("{$ifconfig} " . escapeshellarg($if), $output);
2502
	$ifconfig_str = implode($output);
2503
	unset($output);
2504
	$reg_changing = false;
2505

    
2506
	/* special case for the debug country code */
2507
	if ($wlcfg['regcountry'] == 'DEBUG' && !preg_match("/\sregdomain\s+DEBUG\s/si", $ifconfig_str))
2508
		$reg_changing = true;
2509
	else if ($wlcfg['regdomain'] && !preg_match("/\sregdomain\s+{$wlcfg['regdomain']}\s/si", $ifconfig_str))
2510
		$reg_changing = true;
2511
	else if ($wlcfg['regcountry'] && !preg_match("/\scountry\s+{$wlcfg['regcountry']}\s/si", $ifconfig_str))
2512
		$reg_changing = true;
2513
	else if ($wlcfg['reglocation'] == 'anywhere' && preg_match("/\s(indoor|outdoor)\s/si", $ifconfig_str))
2514
		$reg_changing = true;
2515
	else if ($wlcfg['reglocation'] && $wlcfg['reglocation'] != 'anywhere' && !preg_match("/\s{$wlcfg['reglocation']}\s/si", $ifconfig_str))
2516
		$reg_changing = true;
2517

    
2518
	if ($reg_changing) {
2519
		/* set regulatory domain */
2520
		if($wlcfg['regdomain'])
2521
			$wlregcmd[] = "regdomain " . escapeshellarg($wlcfg['regdomain']);
2522

    
2523
		/* set country */
2524
		if($wlcfg['regcountry'])
2525
			$wlregcmd[] = "country " . escapeshellarg($wlcfg['regcountry']);
2526

    
2527
		/* set location */
2528
		if($wlcfg['reglocation'])
2529
			$wlregcmd[] = escapeshellarg($wlcfg['reglocation']);
2530

    
2531
		$wlregcmd_args = implode(" ", $wlregcmd);
2532

    
2533
		/* build a complete list of the wireless clones for this interface */
2534
		$clone_list = array();
2535
		if (does_interface_exist(interface_get_wireless_clone($baseif)))
2536
			$clone_list[] = interface_get_wireless_clone($baseif);
2537
		if (is_array($config['wireless']['clone'])) {
2538
			foreach ($config['wireless']['clone'] as $clone) {
2539
				if ($clone['if'] == $baseif)
2540
					$clone_list[] = $clone['cloneif'];
2541
			}
2542
		}
2543

    
2544
		/* find which clones are up and bring them down */
2545
		$clones_up = array();
2546
		foreach ($clone_list as $clone_if) {
2547
			$clone_status = pfSense_get_interface_addresses($clone_if);
2548
			if ($clone_status['status'] == 'up') {
2549
				$clones_up[] = $clone_if;
2550
				mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " down");
2551
			}
2552
		}
2553

    
2554
		/* apply the regulatory settings */
2555
		mwexec("{$ifconfig} " . escapeshellarg($if) . " {$wlregcmd_args}");
2556

    
2557
		/* bring the clones back up that were previously up */
2558
		foreach ($clones_up as $clone_if) {
2559
			mwexec("{$ifconfig} " . escapeshellarg($clone_if) . " up");
2560

    
2561
			/*
2562
			 * Rerun the setup script for the interface if it isn't this interface, the interface
2563
			 * is in infrastructure mode, and WPA is enabled.
2564
			 * This can be removed if wpa_supplicant stops dying when you bring the interface down.
2565
			 */
2566
			if ($clone_if != $if) {
2567
				$friendly_if = convert_real_interface_to_friendly_interface_name($clone_if);
2568
				if ( !empty($friendly_if)
2569
				    && $config['interfaces'][$friendly_if]['wireless']['mode'] == "bss"
2570
				    && isset($config['interfaces'][$friendly_if]['wireless']['wpa']['enable']) ) {
2571
					mwexec("/bin/sh {$g['tmp_path']}/{$clone_if}_setup.sh");
2572
				}
2573
			}
2574
		}
2575
	}
2576

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

    
2581
	/* configure wireless */
2582
	$wlcmd_args = implode(" ", $wlcmd);
2583
	mwexec("/sbin/ifconfig {$if} $wlcmd_args", false);
2584

    
2585
	
2586
	sleep(1);
2587
	/* execute hostapd and wpa_supplicant if required in shell */
2588
	mwexec("/bin/sh {$g['tmp_path']}/{$if}_setup.sh");
2589

    
2590
	return 0;
2591

    
2592
}
2593

    
2594
function kill_hostapd($interface) {
2595
	return "/bin/pkill -f \"hostapd .*{$interface}\"\n";
2596
}
2597

    
2598
function kill_wpasupplicant($interface) {
2599
	return "/bin/pkill -f \"wpa_supplicant .*{$interface}\"\n";
2600
}
2601

    
2602
function find_dhclient_process($interface) {
2603
	if ($interface)
2604
		$pid = `/bin/pgrep -axf "dhclient: {$interface}"`;
2605
	else
2606
		$pid = 0;
2607

    
2608
	return intval($pid);
2609
}
2610

    
2611
function find_dhcp6c_process($interface) {
2612
	if ($interface)
2613
		$pid = `/bin/ps auxw|grep "dhcp6c" |grep "{$interface}"|awk '{print $2}'`;
2614
	else
2615
		$pid = 0;
2616

    
2617
	return intval($pid);
2618
}
2619

    
2620
function interface_configure($interface = "wan", $reloadall = false, $linkupevent = false) {
2621
	global $config, $g;
2622
	global $interface_sn_arr_cache, $interface_ip_arr_cache;
2623
	global $interface_snv6_arr_cache, $interface_ipv6_arr_cache;
2624

    
2625
	$wancfg = $config['interfaces'][$interface];
2626

    
2627
	$realif = get_real_interface($interface);
2628
	$realhwif_array = get_parent_interface($interface);
2629
	// Need code to handle MLPPP if we ever use $realhwif for MLPPP handling
2630
	$realhwif = $realhwif_array[0];
2631

    
2632
			
2633
	if (!$g['booting'] && !substr($realif, 0, 4) == "ovpn") {
2634
		/* remove all IPv4 and IPv6 addresses */
2635
		while (mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " -alias", true) == 0);
2636
		while (mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 -alias", true) == 0);
2637
		/* Disable Accepting router advertisements unless specifically requested */
2638
		while (mwexec("/sbin/ifconfig " . escapeshellarg($realif) . " inet6 -accept_rtadv") == 0);
2639

    
2640
		switch ($wancfg['ipaddr']) {
2641
			case 'pppoe':
2642
			case 'l2tp':
2643
			case 'pptp':
2644
			case 'ppp':
2645
				break;
2646
			default:
2647
				interface_bring_down($interface);
2648
				break;
2649
		}
2650
	}
2651

    
2652
	/* wireless configuration? */
2653
	if (is_array($wancfg['wireless']))
2654
		interface_wireless_configure($realif, $wancfg, $wancfg['wireless']);
2655

    
2656
	if ($wancfg['spoofmac']) {
2657
		mwexec("/sbin/ifconfig " . escapeshellarg($realhwif) .
2658
			" link " . escapeshellarg($wancfg['spoofmac']));
2659

    
2660
                /*
2661
                 * All vlans need to spoof their parent mac address, too.  see
2662
                 * ticket #1514: http://cvstrac.pfsense.com/tktview?tn=1514,33
2663
                 */
2664
                if (is_array($config['vlans']['vlan'])) {
2665
                        foreach ($config['vlans']['vlan'] as $vlan) {
2666
                                if ($vlan['if'] == $realhwif)
2667
                                        mwexec("/sbin/ifconfig " . escapeshellarg($vlan['vlanif']) .
2668
                                                " link " . escapeshellarg($wancfg['spoofmac']));
2669
                        }
2670
                }
2671
	}  else {
2672
		$mac = get_interface_mac($realhwif);
2673
		if ($mac == "ff:ff:ff:ff:ff:ff") {
2674
			/*   this is not a valid mac address.  generate a
2675
			 *   temporary mac address so the machine can get online.
2676
			 */
2677
			echo gettext("Generating new MAC address.");
2678
			$random_mac = generate_random_mac_address();
2679
			mwexec("/sbin/ifconfig " . escapeshellarg($realhwif) .
2680
				" link " . escapeshellarg($random_mac));
2681
			$wancfg['spoofmac'] = $random_mac;
2682
			write_config();
2683
			file_notice("MAC Address altered", sprintf(gettext('The INVALID MAC address (ff:ff:ff:ff:ff:ff) on interface %1$s has been automatically replaced with %2$s'), $realif, $random_mac), "Interfaces");
2684
		}
2685
	}
2686

    
2687
	/* media */
2688
	if ($wancfg['media'] || $wancfg['mediaopt']) {
2689
		$cmd = "/sbin/ifconfig " . escapeshellarg($realhwif);
2690
		if ($wancfg['media'])
2691
			$cmd .= " media " . escapeshellarg($wancfg['media']);
2692
		if ($wancfg['mediaopt'])
2693
			$cmd .= " mediaopt " . escapeshellarg($wancfg['mediaopt']);
2694
		mwexec($cmd);
2695
	}
2696
	if (!empty($wancfg['mtu']))
2697
		pfSense_interface_mtu($realhwif, $wancfg['mtu']);
2698
	else {
2699
		$mtu = get_interface_default_mtu(remove_numbers($realhwif));
2700
		if ($mtu != get_interface_mtu($realhwif))
2701
			pfSense_interface_mtu($realhwif, $mtu);
2702
	}
2703

    
2704
	$options = pfSense_get_interface_addresses($realhwif);
2705
	if (is_array($options) && isset($options['caps']['polling'])) {
2706
		if (isset($config['system']['polling']))
2707
			pfSense_interface_capabilities($realif, IFCAP_POLLING);
2708
		else
2709
			pfSense_interface_capabilities($realif, -IFCAP_POLLING);
2710
	}
2711

    
2712
	/* skip vlans for checksumming and polling */
2713
        if (!stristr($realhwif, "vlan") && is_array($options)) {
2714
		$flags = 0;
2715
		if(isset($config['system']['disablechecksumoffloading'])) {
2716
			if (isset($options['encaps']['txcsum']))
2717
				$flags |= IFCAP_TXCSUM;
2718
			if (isset($options['encaps']['rxcsum']))
2719
				$flags |= IFCAP_RXCSUM;
2720
        	} else {
2721
 			if (!isset($options['caps']['txcsum']))
2722
				$flags |= IFCAP_TXCSUM;
2723
			if (!isset($options['caps']['rxcsum']))
2724
				$flags |= IFCAP_RXCSUM;
2725
        	}
2726

    
2727
        	if(isset($config['system']['disablesegmentationoffloading'])) {
2728
                	if (isset($options['encaps']['tso4']))
2729
				$flags |= IFCAP_TSO;
2730
                	if (isset($options['encaps']['tso6']))
2731
				$flags |= IFCAP_TSO;
2732
        	} else {
2733
                	if (!isset($options['caps']['tso4']))
2734
				$flags |= IFCAP_TSO;
2735
                	if (!isset($options['caps']['tso6']))
2736
				$flags |= IFCAP_TSO;
2737
        	}
2738

    
2739
        	if(isset($config['system']['disablelargereceiveoffloading'])) {
2740
                	if (isset($options['encaps']['lro']))
2741
				$flags |= IFCAP_LRO;
2742
        	} else {
2743
                	if (!isset($options['caps']['lro']))
2744
				$flags |= IFCAP_LRO;
2745
        	}
2746

    
2747
        	/* if the NIC supports polling *AND* it is enabled in the GUI */
2748
        	if (!isset($config['system']['polling']) || !isset($options['caps']['polling'])) {
2749
			$flags |= IFCAP_POLLING;
2750
		}
2751
               	pfSense_interface_capabilities($realhwif, -$flags);
2752
	}
2753

    
2754
	/* invalidate interface/ip/sn cache */
2755
	get_interface_arr(true);
2756
	unset($interface_ip_arr_cache[$realif]);
2757
	unset($interface_sn_arr_cache[$realif]);
2758
	unset($interface_ipv6_arr_cache[$realif]);
2759
	unset($interface_snv6_arr_cache[$realif]);
2760

    
2761
	switch ($wancfg['ipaddr']) {
2762
		case 'carpdev-dhcp':
2763
			interface_carpdev_dhcp_configure($interface);
2764
			break;
2765
		case 'dhcp':
2766
			interface_dhcp_configure($interface);
2767
			break;
2768
		case 'pppoe':
2769
		case 'l2tp':
2770
		case 'pptp':
2771
		case 'ppp':
2772
			interface_ppps_configure($interface);
2773
			break;
2774
		default:
2775
			if ($wancfg['ipaddr'] <> "" && $wancfg['subnet'] <> "") {
2776
				pfSense_interface_setaddress($realif, "{$wancfg['ipaddr']}/{$wancfg['subnet']}");
2777
			} else if (substr($realif, 0, 3) == "gre") {
2778
				if (is_array($config['gres']['gre'])) {
2779
					foreach ($config['gres']['gre'] as $gre)
2780
						if ($gre['greif'] == $realif)
2781
							interface_gre_configure($gre);
2782
				}
2783
			} else if (substr($realif, 0, 3) == "gif") {
2784
				 if (is_array($config['gifs']['gif'])) {
2785
					foreach ($config['gifs']['gif'] as $gif)
2786
						if($gif['gifif'] == $realif)
2787
							interface_gif_configure($gif);
2788
				}
2789
			} else if (substr($realif, 0, 4) == "ovpn") {
2790
				/* XXX: Should be done anything?! */
2791
			}
2792
			break;
2793
	}
2794

    
2795
	switch ($wancfg['ipaddrv6']) {
2796
		default:
2797
			if ($wancfg['ipaddrv6'] <> "" && $wancfg['subnetv6'] <> "") {
2798
				pfSense_interface_setaddress($realif, "{$wancfg['ipaddrv6']}/{$wancfg['subnetv6']}");
2799
				// FIXME: Add IPv6 Support to the pfSense module
2800
				mwexec("/sbin/ifconfig {$realif} inet6 {$wancfg['ipaddrv6']} prefixlen {$wancfg['subnetv6']} ");
2801
			}
2802
			break;
2803
	}
2804

    
2805
	if(does_interface_exist($wancfg['if']))
2806
		interfaces_bring_up($wancfg['if']);
2807

    
2808
	interface_netgraph_needed($interface);
2809
 	
2810
	if (!$g['booting']) {
2811
		link_interface_to_vips($interface, "update");
2812

    
2813
		unset($gre);
2814
		$gre = link_interface_to_gre($interface);
2815
		if (!empty($gre))
2816
			array_walk($gre, 'interface_gre_configure');
2817

    
2818
		unset($gif);
2819
		$gif = link_interface_to_gif($interface);
2820
		if (!empty($gif))
2821
                       	array_walk($gif, 'interface_gif_configure');
2822

    
2823
		if ($linkupevent == false || substr($realif, 0, 4) == "ovpn") {
2824
			unset($bridgetmp);
2825
			$bridgetmp = link_interface_to_bridge($interface);
2826
			if (!empty($bridgetmp))
2827
				interface_bridge_add_member($bridgetmp, $realif);
2828
		}
2829

    
2830
		$grouptmp = link_interface_to_group($interface);
2831
		if (!empty($grouptmp))
2832
			array_walk($grouptmp, 'interface_group_add_member');
2833

    
2834
		if ($interface == "lan")
2835
			/* make new hosts file */
2836
			system_hosts_generate();
2837

    
2838
		if ($reloadall == true) {
2839

    
2840
			/* reconfigure static routes (kernel may have deleted them) */
2841
			system_routing_configure($interface);
2842

    
2843
			/* reload ipsec tunnels */
2844
			vpn_ipsec_configure();
2845

    
2846
			/* restart dnsmasq */
2847
			services_dnsmasq_configure();
2848

    
2849
			/* update dyndns */
2850
			send_event("service reload dyndns {$interface}");
2851

    
2852
			/* reload captive portal */
2853
			captiveportal_init_rules();
2854
		}
2855
	}
2856

    
2857
	return 0;
2858
}
2859

    
2860
function interface_carpdev_dhcp_configure($interface = "wan") {
2861
	global $config, $g;
2862

    
2863
	$wancfg = $config['interfaces'][$interface];
2864
	$wanif = $wancfg['if'];
2865
	/* bring wan interface up before starting dhclient */
2866
	if($wanif)
2867
		interfaces_bring_up($wanif);
2868
	else 
2869
		log_error(gettext("Could not bring wanif up in terface_carpdev_dhcp_configure()"));
2870

    
2871
	return 0;
2872
}
2873

    
2874
function interface_dhcp_configure($interface = "wan") {
2875
	global $config, $g;
2876

    
2877
	$wancfg = $config['interfaces'][$interface];
2878
	$wanif = $wancfg['if'];
2879
	if (empty($wancfg))
2880
		$wancfg = array();
2881

    
2882
	$wanif = get_real_interface($interface);
2883
	/* bring wan interface up before starting dhclient */
2884
	if($wanif)
2885
		interfaces_bring_up($wanif);
2886
	else 
2887
		log_error("Could not bring up {$wanif} interface in interface_dhcp_configure()");
2888

    
2889
	/* launch v6 before v4, dhclient can hold up the execution if no dhcp4 is available */
2890
	interface_dhcpv6_configure($interface);
2891
	interface_dhcpv4_configure($interface);
2892

    
2893
	return 0;
2894

    
2895
}
2896

    
2897
function interface_dhcpv6_configure($interface = "wan") {
2898
	global $config, $g;
2899
	$iflist = get_configured_interface_with_descr(false, true);
2900

    
2901
	$wancfg = $config['interfaces'][$interface];
2902
	$wanif = $wancfg['if'];
2903
	if (empty($wancfg))
2904
		$wancfg = array();
2905

    
2906
	$wanif = get_real_interface($interface);
2907

    
2908
	/* Add IPv6 dhclient here, only wide-dhcp6c works for now. */
2909
	$fd = fopen("{$g['varetc_path']}/dhcp6c_{$interface}.conf", "w");
2910
	if (!$fd) {
2911
		printf("Error: cannot open dhcp6c_{$interface}.conf in interfaces_wan_dhcp_configure() for writing.\n");
2912
		return 1;
2913
	}
2914

    
2915
	$dhcp6cconf = "";
2916
 	$dhcp6cconf .= "interface {$wanif} {\n";
2917
	$dhcp6cconf .= " 	send ia-na 0;	# request stateful address\n";
2918
	if(is_numeric($wancfg['dhcp6-ia-pd-len'])) {
2919
		$dhcp6cconf .= " 	send ia-pd 0;	# request prefix delegation\n";
2920
	}
2921
	$dhcp6cconf .= "request domain-name-servers;\n";
2922
	$dhcp6cconf .= "request domain-name;\n";
2923
	$dhcp6cconf .= "script \"/etc/rc.newwanipv6\";	# we'd like some nameservers please\n";
2924

    
2925
	$dhcp6cconf .= "};\n";
2926
	$dhcp6cconf .= "id-assoc na 0 { };\n";
2927
	if(is_numeric($wancfg['dhcp6-ia-pd-len'])) {
2928
		/* Setup the prefix delegation */
2929
		$dhcp6cconf .= "	id-assoc pd 0 {\n";
2930
		foreach($iflist as $friendly => $pdinterface) {
2931
			// log_error("setting up $friendly - $pdinterface - {$pdinterface['dhcp6-pd-sla-id']}");
2932
			if(is_numeric($config['interfaces'][$friendly]['dhcp6-pd-sla-id'])) {
2933
				$realif = get_real_interface($friendly);
2934
				$dhcp6cconf .= "	prefix-interface {$realif} {\n";
2935
				$dhcp6cconf .= "		sla-id {$config['interfaces'][$friendly]['dhcp6-pd-sla-id']};\n";
2936
				$dhcp6cconf .= "		sla-len {$wancfg['dhcp6-ia-pd-len']};\n";
2937
				$dhcp6cconf .= "	};\n";
2938
			}
2939
		}
2940
		$dhcp6cconf .= "};\n";
2941
	}
2942

    
2943
	fwrite($fd, $dhcp6cconf);
2944
	fclose($fd);
2945

    
2946
	/* accept router advertisements for this interface */
2947
	// mwexec("/sbin/sysctl -w net.inet6.ip6.accept_rtadv=1");
2948
	mwexec("/sbin/ifconfig {$wanif} inet6 accept_rtadv");
2949
	/* fire up dhcp6c for IPv6 first, this backgrounds immediately */
2950
	mwexec("/usr/local/sbin/dhcp6c -d -c {$g['varetc_path']}/dhcp6c_{$interface}.conf {$wanif}");
2951

    
2952
	return 0;
2953
}
2954

    
2955
function interface_dhcpv4_configure($interface = "wan") {
2956
	global $config, $g;
2957

    
2958
	$wancfg = $config['interfaces'][$interface];
2959
	$wanif = $wancfg['if'];
2960
	if (empty($wancfg))
2961
		$wancfg = array();
2962

    
2963
	/* generate dhclient_wan.conf */
2964
	$fd = fopen("{$g['varetc_path']}/dhclient_{$interface}.conf", "w");
2965
	if (!$fd) {
2966
		printf(printf(gettext("Error: cannot open dhclient_%s.conf in interfaces_wan_dhcp_configure() for writing.%s"), $interface, "\n"));
2967
		return 1;
2968
	}
2969

    
2970
	if ($wancfg['dhcphostname']) {
2971
		$dhclientconf_hostname = "send dhcp-client-identifier \"{$wancfg['dhcphostname']}\";\n";
2972
		$dhclientconf_hostname .= "\tsend host-name \"{$wancfg['dhcphostname']}\";\n";
2973
	} else {
2974
		$dhclientconf_hostname = "";
2975
	}
2976

    
2977
	$wanif = get_real_interface($interface);
2978
	if (empty($wanif)) {
2979
		log_error(sprintf(gettext("Invalid interface \"%s\" in interface_dhcp_configure()"), $interface));
2980
		return 0;
2981
	}
2982
 	$dhclientconf = "";
2983
	
2984
	$dhclientconf .= <<<EOD
2985
interface "{$wanif}" {
2986
timeout 60;
2987
retry 1;
2988
select-timeout 0;
2989
initial-interval 1;
2990
	{$dhclientconf_hostname}
2991
	script "/sbin/dhclient-script";
2992
}
2993

    
2994
EOD;
2995

    
2996
if(is_ipaddr($wancfg['alias-address'])) {
2997
	$subnetmask = gen_subnet_mask($wancfg['alias-subnet']);
2998
	$dhclientconf .= <<<EOD
2999
alias {
3000
	interface  "{$wanif}";
3001
	fixed-address {$wancfg['alias-address']};
3002
	option subnet-mask {$subnetmask};
3003
}
3004

    
3005
EOD;
3006
}
3007
	fwrite($fd, $dhclientconf);
3008
	fclose($fd);
3009

    
3010
	/* bring wan interface up before starting dhclient */
3011
	if($wanif)
3012
		interfaces_bring_up($wanif);
3013
	else 
3014
		log_error(printf(gettext("Could not bring up %s interface in interface_dhcp_configure()"), $wanif));
3015

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

    
3019
	return 0;
3020
}
3021

    
3022
function interfaces_group_setup() {
3023
	global $config;
3024

    
3025
	if (!is_array($config['ifgroups']['ifgroupentry']))
3026
		return;
3027

    
3028
	foreach ($config['ifgroups']['ifgroupentry'] as $groupar)
3029
		interface_group_setup($groupar);
3030

    
3031
	return;
3032
}
3033

    
3034
function interface_group_setup(&$groupname /* The parameter is an array */) {
3035
	global $config;
3036

    
3037
	if (!is_array($groupname))
3038
		return;
3039
	$members = explode(" ", $groupname['members']);
3040
	foreach($members as $ifs) {
3041
		$realif = get_real_interface($ifs);
3042
		if ($realif)
3043
			mwexec("/sbin/ifconfig {$realif} group {$groupname['ifname']}");
3044
	}
3045

    
3046
	return;
3047
}
3048

    
3049
function interface_group_add_member($interface, $groupname) {
3050
	$interface = get_real_interface($interface);
3051
	mwexec("/sbin/ifconfig {$interface} group {$groupname}", true);
3052
}
3053
 
3054
/* COMPAT Function */
3055
function convert_friendly_interface_to_real_interface_name($interface) {
3056
	return get_real_interface($interface);
3057
}
3058

    
3059
/* COMPAT Function */
3060
function get_real_wan_interface($interface = "wan") {
3061
	return get_real_interface($interface);
3062
}
3063

    
3064
/* COMPAT Function */
3065
function get_current_wan_address($interface = "wan") {
3066
	return get_interface_ip($interface);
3067
}
3068

    
3069
/*
3070
 * convert_real_interface_to_friendly_interface_name($interface): convert fxp0 -> wan, etc.
3071
 */
3072
function convert_real_interface_to_friendly_interface_name($interface = "wan") {
3073
        global $config;
3074

    
3075
	if (stristr($interface, "vip")) {
3076
                $index = intval(substr($interface, 3));
3077
                foreach ($config['virtualip']['vip'] as $counter => $vip) {
3078
                        if ($vip['mode'] == "carpdev-dhcp" || $vip['mode'] == "carp")  {
3079
                                if ($index == $vip['vhid'])
3080
                                        return $vip['interface'];
3081
                        }
3082
                }
3083
        }
3084

    
3085
        /* XXX: For speed reasons reference directly the interface array */
3086
	$ifdescrs = &$config['interfaces'];
3087
        //$ifdescrs = get_configured_interface_list(false, true);
3088

    
3089
        foreach ($ifdescrs as $if => $ifname) {
3090
                if ($config['interfaces'][$if]['if'] == $interface)
3091
                        return $if;
3092

    
3093
                if (stristr($interface, "_wlan0") && $config['interfaces'][$if]['if'] == interface_get_wireless_base($interface))
3094
                        return $if;
3095

    
3096
		// XXX: This case doesn't work anymore (segfaults - recursion?) - should be replaced with something else or just removed.
3097
		//      Not to be replaced with get_real_interface - causes slow interface listings here because of recursion!
3098
		/*
3099
                $int = get_parent_interface($if);
3100
                if ($int[0] == $interface)
3101
                        return $ifname;
3102
		*/
3103
        }
3104
        return NULL;
3105
}
3106

    
3107
/* attempt to resolve interface to friendly descr */
3108
function convert_friendly_interface_to_friendly_descr($interface) {
3109
        global $config;
3110

    
3111
        switch ($interface) {
3112
        case "l2tp":
3113
        	$ifdesc = "L2TP";
3114
                break;
3115
	case "pptp":
3116
		$ifdesc = "PPTP";
3117
		break;
3118
	case "pppoe":
3119
		$ifdesc = "PPPoE";
3120
		break;
3121
	case "openvpn":
3122
		$ifdesc = "OpenVPN";
3123
		break;
3124
	case "enc0":
3125
	case "ipsec":
3126
		$ifdesc = "IPsec";
3127
		break;
3128
        default:
3129
                if (isset($config['interfaces'][$interface])) {
3130
                        if (empty($config['interfaces'][$interface]['descr']))
3131
                                $ifdesc = strtoupper($interface);
3132
                        else
3133
                                $ifdesc = strtoupper($config['interfaces'][$interface]['descr']);
3134
			break;
3135
		} else if (substr($interface, 0, 3) == "vip") {
3136
			if (is_array($config['virtualip']['vip'])) {
3137
				foreach ($config['virtualip']['vip'] as $counter => $vip) {
3138
					if ($vip['mode'] == "carpdev-dhcp" || $vip['mode'] == "carp")  {
3139
						if ($interface == "vip{$vip['vhid']}")
3140
							return "{$vip['subnet']} - {$vip['descr']}";
3141
					}
3142
				}
3143
                        }
3144
                } else {
3145
			/* if list */
3146
			$ifdescrs = get_configured_interface_with_descr(false, true);
3147
			foreach ($ifdescrs as $if => $ifname) {
3148
					if ($if == $interface || $ifname == $interface)
3149
						return $ifname;
3150
			}
3151
		}
3152
                break;
3153
        }
3154

    
3155
        return $ifdesc;
3156
}
3157

    
3158
function convert_real_interface_to_friendly_descr($interface) {
3159
        global $config;
3160

    
3161
        $ifdesc = convert_real_interface_to_friendly_interface_name("{$interface}");
3162

    
3163
        if ($ifdesc) {
3164
                $iflist = get_configured_interface_with_descr(false, true);
3165
                return $iflist[$ifdesc];
3166
        }
3167

    
3168
        return $interface;
3169
}
3170

    
3171
/*
3172
 *  get_parent_interface($interface):
3173
 *			--returns the (real or virtual) parent interface(s) array for a given interface friendly name (i.e. wan)
3174
 *				or virtual interface (i.e. vlan)
3175
 *				(We need array because MLPPP and bridge interfaces have more than one parent.)
3176
 *			-- returns $interface passed in if $interface parent is not found
3177
 *			-- returns empty array if an invalid interface is passed
3178
 *	(Only handles ppps and vlans now.)
3179
 */
3180
function get_parent_interface($interface) {
3181
	global $config;
3182

    
3183
	$parents = array();
3184
	//Check that we got a valid interface passed
3185
	$realif = get_real_interface($interface);
3186
	if ($realif == NULL)
3187
		return $parents;
3188

    
3189
	// If we got a real interface, find it's friendly assigned name
3190
	$interface = convert_real_interface_to_friendly_interface_name($interface);
3191
		
3192
	if (!empty($interface) && isset($config['interfaces'][$interface])) {
3193
		$ifcfg = $config['interfaces'][$interface];
3194
		switch ($ifcfg['ipaddr']) {
3195
			case "ppp":
3196
			case "pppoe":
3197
			case "pptp":
3198
			case "l2tp":
3199
				if (empty($parents))
3200
					if (is_array($config['ppps']['ppp']))
3201
						foreach ($config['ppps']['ppp'] as $pppidx => $ppp) {
3202
							if ($ppp_if == $ppp['if']) {
3203
								$ports = explode(',', $ppp['ports']);
3204
								foreach ($ports as $pid => $parent_if) 
3205
									$parents[$pid] = get_real_interface($parent_if);
3206
								break;
3207
							}
3208
						}
3209
				break;
3210
			case "dhcp":
3211
			case "static":
3212
			default:
3213
				// Handle _vlans
3214
				if (strstr($realif,"_vlan"))
3215
					if (is_array($config['vlans']['vlan'])) 
3216
						foreach ($config['vlans']['vlan'] as $vlanidx => $vlan)
3217
							if ($ifcfg['if'] == $vlan['vlanif']){
3218
								$parents[0] = $vlan['if'];
3219
								break;
3220
							}
3221
				break;
3222
		}
3223
	}
3224
	
3225
	if (empty($parents))
3226
		$parents[0] = $realif;
3227
	
3228
	return $parents;
3229
}
3230

    
3231
function interface_is_wireless_clone($wlif) {
3232
	if(!stristr($wlif, "_wlan")) {
3233
		return false;
3234
	} else {
3235
		return true;
3236
	}
3237
}
3238

    
3239
function interface_get_wireless_base($wlif) {
3240
	if(!stristr($wlif, "_wlan")) {
3241
		return $wlif;
3242
	} else {
3243
		return substr($wlif, 0, stripos($wlif, "_wlan"));
3244
	}
3245
}
3246

    
3247
function interface_get_wireless_clone($wlif) {
3248
	if(!stristr($wlif, "_wlan")) {
3249
		return $wlif . "_wlan0";
3250
	} else {
3251
		return $wlif;
3252
	}
3253
}
3254

    
3255
function get_real_interface($interface = "wan") {
3256
    global $config;
3257

    
3258
	$wanif = NULL;
3259

    
3260
	switch ($interface) {
3261
	case "l2tp":
3262
		$wanif = "l2tp";
3263
		break;
3264
	case "pptp":
3265
		$wanif = "pptp";
3266
		break;
3267
	case "pppoe":
3268
		$wanif = "pppoe";
3269
		break;
3270
	case "openvpn":
3271
		$wanif = "openvpn";
3272
		break;
3273
	case "ipsec":
3274
	case "enc0":
3275
		$wanif = "enc0";
3276
		break;
3277
	case "ppp":
3278
		$wanif = "ppp";
3279
		break;
3280
	default:
3281
		// If a real interface was alread passed simply
3282
		// pass the real interface back.  This encourages
3283
		// the usage of this function in more cases so that
3284
		// we can combine logic for more flexibility.
3285
		if(does_interface_exist($interface)) {
3286
			$wanif = $interface;
3287
			break;
3288
		}
3289
		if (empty($config['interfaces'][$interface]))
3290
			break;
3291

    
3292
		$cfg = &$config['interfaces'][$interface];
3293

    
3294
		// Wireless cloned NIC support (FreeBSD 8+)
3295
		// interface name format: $parentnic_wlanparentnic#
3296
		// example: ath0_wlan0
3297
		if (is_interface_wireless($cfg['if'])) {
3298
			$wanif = interface_get_wireless_clone($cfg['if']);
3299
			break;
3300
		}
3301
		/*
3302
		if (empty($cfg['if'])) {
3303
			$wancfg = $cfg['if'];
3304
			break;
3305
		}
3306
		*/
3307

    
3308
		switch ($cfg['ipaddr']) {
3309
			case "carpdev-dhcp":
3310
				$viparr = &$config['virtualip']['vip'];
3311
				if(is_array($viparr))
3312
				foreach ($viparr as $counter => $vip) {
3313
					if ($vip['mode'] == "carpdev-dhcp") {
3314
						if($vip['interface'] == $interface) {
3315
							$wanif = "carp{$counter}";
3316
							break;
3317
						}
3318
					}
3319
				}
3320
				break;
3321
			case "pppoe": 
3322
			case "pptp": 
3323
			case "l2tp": 
3324
			case "ppp":
3325
				$wanif = $cfg['if'];
3326
				break;
3327
			default:
3328
				$wanif = $cfg['if'];
3329
				break;
3330
		}
3331
		break;
3332
	}
3333

    
3334
    return $wanif;
3335
}
3336

    
3337
/* Guess the physical interface by providing a IP address */
3338
function guess_interface_from_ip($ipaddress) {
3339
	if(! is_ipaddr($ipaddress)) {
3340
		return false;
3341
	}
3342
	if(is_ipaddrv4($ipaddress)) {
3343
		/* create a route table we can search */
3344
		exec("netstat -rnWf inet", $output, $ret);
3345
		foreach($output as $line) {
3346
			if(preg_match("/^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\/[0-9]+[ ]+link[#]/", $line)) {
3347
				$fields = preg_split("/[ ]+/", $line);
3348
				if(ip_in_subnet($ipaddress, $fields[0])) {
3349
					return $fields[6];
3350
				}
3351
			}
3352
		}
3353
	}
3354
	/* FIXME: This works from cursory testing, regexp might need fine tuning */
3355
	if(is_ipaddrv6($ipaddress)) {
3356
		/* create a route table we can search */
3357
		exec("netstat -rnWf inet6", $output, $ret);
3358
		foreach($output as $line) {
3359
			if(preg_match("/[0-9a-f]+[:]+[0-9a-f]+[:]+[\/][0-9]+/", $line)) {
3360
				$fields = preg_split("/[ ]+/", $line);
3361
				if(ip_in_subnet($ipaddress, $fields[0])) {
3362
					return $fields[6];
3363
				}
3364
			}
3365
		}
3366
	}
3367
	$ret = exec_command("/sbin/route -n get {$ipaddress} | /usr/bin/awk '/interface/ { print \$2; };'");
3368
	if(empty($ret)) {
3369
        	return false;
3370
	}
3371
	return $ret;
3372
}
3373

    
3374
/*
3375
 * find_ip_interface($ip): return the interface where an ip is defined
3376
 */
3377
function find_ip_interface($ip)
3378
{
3379
        /* if list */
3380
        $ifdescrs = get_configured_interface_list();
3381

    
3382
        foreach ($ifdescrs as $ifdescr => $ifname) {
3383
		if ($ip == get_interface_ip($ifname)) {
3384
                	$int = get_real_interface($ifname);
3385
			return $int;
3386
		}
3387
        }
3388
        return false;
3389
}
3390

    
3391
/*
3392
 *   find_number_of_created_carp_interfaces: return the number of carp interfaces
3393
 */
3394
function find_number_of_created_carp_interfaces() {
3395
	return `/sbin/ifconfig | grep "carp:" | wc -l`;
3396
}
3397

    
3398
function get_all_carp_interfaces() {
3399
	$ints = str_replace("\n", " ", `ifconfig | grep "carp:" -B2 | grep ": flag" | cut -d: -f1`);
3400
	$ints = explode(" ", $ints);
3401
	return $ints;
3402
}
3403

    
3404
/*
3405
 * find_carp_interface($ip): return the carp interface where an ip is defined
3406
 */
3407
function find_carp_interface($ip) {
3408
	global $config;
3409
	if (is_array($config['virtualip']['vip'])) {
3410
		foreach ($config['virtualip']['vip'] as $vip) {
3411
			if ($vip['mode'] == "carp" || $vip['mode'] == "carpdev") {
3412
				if(is_ipaddrv4($ip)) {
3413
					$carp_ip = get_interface_ip($vip['interface']);
3414
				}
3415
				if(is_ipaddrv6($ip)) {
3416
					$carp_ip = get_interface_ipv6($vip['interface']);
3417
				}
3418
				exec("/sbin/ifconfig", $output, $return);
3419
				foreach($output as $line) {
3420
					$elements = preg_split("/[ ]+/i", $line);
3421
					if(strstr($elements[0], "vip"))
3422
						$curif = str_replace(":", "", $elements[0]);
3423
					if(stristr($line, $ip)) {
3424
						$if = $curif;
3425
						continue;
3426
					}
3427
				}
3428
				if ($if)
3429
					return $if;
3430
			}
3431
		}
3432
	}
3433
}
3434

    
3435
function link_carp_interface_to_parent($interface) {
3436
        global $config;
3437

    
3438
        if ($interface == "")
3439
                return;
3440

    
3441
        $carp_ip = get_interface_ip($interface);
3442
        if (!is_ipaddr($carp_ip))
3443
                return;
3444

    
3445
        /* if list */
3446
        $ifdescrs = get_configured_interface_list();
3447
        foreach ($ifdescrs as $ifdescr => $ifname) {
3448
                $interfaceip = get_interface_ip($ifname);
3449
                $subnet_bits = get_interface_subnet($ifname);
3450
                $subnet_ip = gen_subnet("{$interfaceip}", "{$subnet_bits}");
3451
                if(ip_in_subnet($carp_ip, "{$subnet_ip}/{$subnet_bits}"))
3452
                        return $ifname;
3453
        }
3454

    
3455
        return "";
3456
}
3457

    
3458
/****f* interfaces/link_ip_to_carp_interface
3459
 * NAME
3460
 *   link_ip_to_carp_interface - Find where a CARP interface links to.
3461
 * INPUTS
3462
 *   $ip
3463
 * RESULT
3464
 *   $carp_ints
3465
 ******/
3466
function link_ip_to_carp_interface($ip) {
3467
        global $config;
3468

    
3469
        if (!is_ipaddr($ip))
3470
                return;
3471

    
3472
        $carp_ints = "";
3473
        if (is_array($config['virtualip']['vip'])) {
3474
		$first = 0;
3475
		$carp_int = array();
3476
                foreach ($config['virtualip']['vip'] as $vip) {
3477
                        if ($vip['mode'] == "carp" || $vip['mode'] == "carpdev") {
3478
                                $carp_ip = $vip['subnet'];
3479
                                $carp_sn = $vip['subnet_bits'];
3480
                                $carp_nw = gen_subnet($carp_ip, $carp_sn);
3481
                                if (ip_in_subnet($ip, "{$carp_nw}/{$carp_sn}"))
3482
					$carp_int[] = "vip{$vip['vhid']}";
3483
                        }
3484
                }
3485
		if (!empty($carp_int))
3486
			$carp_ints = implode(" ", array_unique($carp_int));
3487
        }
3488

    
3489
        return $carp_ints;
3490
}
3491

    
3492
function link_interface_to_vlans($int, $action = "") {
3493
	global $config;
3494

    
3495
	if (empty($int))
3496
		return;
3497

    
3498
	if (is_array($config['vlans']['vlan'])) {
3499
                foreach ($config['vlans']['vlan'] as $vlan) {
3500
			if ($int == $vlan['if']) {
3501
				if ($action == "update") {
3502
					interfaces_bring_up($int);
3503
				} else if ($action == "")
3504
					return $vlan;
3505
			}
3506
		}
3507
	}
3508
}
3509

    
3510
function link_interface_to_vips($int, $action = "") {
3511
        global $config;
3512

    
3513
        if (is_array($config['virtualip']['vip'])) {
3514
		foreach ($config['virtualip']['vip'] as $vip) {
3515
			if ($int == $vip['interface']) {
3516
				if ($action == "update") {
3517
					if ($vip['mode'] == "carp" && !does_interface_exist("vip{$vip['vhid']}"))
3518
						interfaces_vips_configure($int);
3519
					else {
3520
						interface_vip_bring_down($vip);
3521
						interfaces_vips_configure($int);
3522
					}
3523
				} else
3524
					return $vip;
3525
			}
3526
		}
3527
	}
3528
}
3529

    
3530
/****f* interfaces/link_interface_to_bridge
3531
 * NAME
3532
 *   link_interface_to_bridge - Finds out a bridge group for an interface
3533
 * INPUTS
3534
 *   $ip
3535
 * RESULT
3536
 *   bridge[0-99]
3537
 ******/
3538
function link_interface_to_bridge($int) {
3539
        global $config;
3540

    
3541
        if (is_array($config['bridges']['bridged'])) {
3542
                foreach ($config['bridges']['bridged'] as $bridge) {
3543
			if (in_array($int, explode(',', $bridge['members'])))
3544
                                return "{$bridge['bridgeif']}";
3545
		}
3546
	}
3547
}
3548

    
3549
function link_interface_to_group($int) {
3550
        global $config;
3551

    
3552
	$result = array();
3553

    
3554
        if (is_array($config['ifgroups']['ifgroupentry'])) {
3555
                foreach ($config['ifgroups']['ifgroupentry'] as $group) {
3556
			if (in_array($int, explode(" ", $group['members'])))
3557
				$result[$group['ifname']] = $int;
3558
		}
3559
	}
3560

    
3561
	return $result;
3562
}
3563

    
3564
function link_interface_to_gre($interface) {
3565
        global $config;
3566

    
3567
	$result = array();
3568

    
3569
        if (is_array($config['gres']['gre'])) {
3570
                foreach ($config['gres']['gre'] as $gre)
3571
                        if($gre['if'] == $interface)
3572
				$result[] = $gre;
3573
	}
3574

    
3575
	return $result;
3576
}
3577

    
3578
function link_interface_to_gif($interface) {
3579
        global $config;
3580

    
3581
	$result = array();
3582

    
3583
        if (is_array($config['gifs']['gif'])) {
3584
                foreach ($config['gifs']['gif'] as $gif)
3585
                        if($gif['if'] == $interface)
3586
                                $result[] = $gif;
3587
	}
3588

    
3589
	return $result;
3590
}
3591

    
3592
/*
3593
 * find_interface_ip($interface): return the interface ip (first found)
3594
 */
3595
function find_interface_ip($interface, $flush = false)
3596
{
3597
	global $interface_ip_arr_cache;
3598
	global $interface_sn_arr_cache;
3599

    
3600
	$interface = str_replace("\n", "", $interface);
3601
	
3602
	if (!does_interface_exist($interface))
3603
		return;
3604

    
3605
	/* Setup IP cache */
3606
	if (!isset($interface_ip_arr_cache[$interface]) or $flush) {
3607
		$ifinfo = pfSense_get_interface_addresses($interface);
3608
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
3609
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
3610
	}
3611

    
3612
	return $interface_ip_arr_cache[$interface];
3613
}
3614

    
3615
/*
3616
 * find_interface_ipv6($interface): return the interface ip (first found)
3617
 */
3618
function find_interface_ipv6($interface, $flush = false)
3619
{
3620
	global $interface_ipv6_arr_cache;
3621
	global $interface_snv6_arr_cache;
3622
	global $config;
3623
	
3624
	$interface = str_replace("\n", "", $interface);
3625
	
3626
	if (!does_interface_exist($interface))
3627
		return;
3628

    
3629
	/* Setup IP cache */
3630
	if (!isset($interface_ipv6_arr_cache[$interface]) or $flush) {
3631
		$ifinfo = pfSense_get_interface_addresses($interface);
3632
		// FIXME: Add IPv6 support to the pfSense module
3633
		exec("/sbin/ifconfig {$interface} inet6", $output);
3634
		foreach($output as $line) {
3635
			if(preg_match("/inet6/", $line)) {
3636
				$parts = explode(" ", $line);
3637
				if(! preg_match("/fe80::/", $parts[1])) {
3638
					$ifinfo['ipaddrv6'] = $parts[1];
3639
					if($parts[2] == "-->") {
3640
						$parts[5] = "126";
3641
						$ifinfo['subnetbitsv6'] = $parts[5];
3642
					} else {
3643
						$ifinfo['subnetbitsv6'] = $parts[3];
3644
					}
3645
				}
3646
			}
3647
		}
3648
		$interface_ipv6_arr_cache[$interface] = $ifinfo['ipaddrv6'];
3649
		$interface_snv6_arr_cache[$interface] = $ifinfo['subnetbitsv6'];
3650
	}
3651

    
3652
	return $interface_ipv6_arr_cache[$interface];
3653
}
3654

    
3655
function find_interface_subnet($interface, $flush = false)
3656
{
3657
	global $interface_sn_arr_cache;
3658
	global $interface_ip_arr_cache;
3659

    
3660
	$interface = str_replace("\n", "", $interface);
3661
	if (does_interface_exist($interface) == false)
3662
		return;
3663

    
3664
	if (!isset($interface_sn_arr_cache[$interface]) or $flush) {
3665
		$ifinfo = pfSense_get_interface_addresses($interface);
3666
		$interface_ip_arr_cache[$interface] = $ifinfo['ipaddr'];
3667
		$interface_sn_arr_cache[$interface] = $ifinfo['subnetbits'];
3668
        }
3669

    
3670
	return $interface_sn_arr_cache[$interface];
3671
}
3672

    
3673
function find_interface_subnetv6($interface, $flush = false)
3674
{
3675
	global $interface_snv6_arr_cache;
3676
	global $interface_ipv6_arr_cache;
3677

    
3678
	$interface = str_replace("\n", "", $interface);
3679
	if (does_interface_exist($interface) == false)
3680
		return;
3681

    
3682
	if (!isset($interface_snv6_arr_cache[$interface]) or $flush) {
3683
		$ifinfo = pfSense_get_interface_addresses($interface);
3684
		// FIXME: Add IPv6 support to the pfSense module
3685
		exec("/sbin/ifconfig {$interface} inet6", $output);
3686
		foreach($output as $line) {
3687
			if(preg_match("/inet6/", $line)) {
3688
				$parts = explode(" ", $line);
3689
				if(! preg_match("/fe80::/", $parts[1])) {
3690
					$ifinfo['ipaddrv6'] = $parts[1];
3691
					if($parts[2] == "-->") {
3692
						$parts[5] = "126";
3693
						$ifinfo['subnetbitsv6'] = $parts[5];
3694
					} else {
3695
						$ifinfo['subnetbitsv6'] = $parts[3];
3696
					}
3697
				}
3698
			}
3699
		}
3700
		$interface_ipv6_arr_cache[$interface] = $ifinfo['ipaddrv6'];
3701
		$interface_snv6_arr_cache[$interface] = $ifinfo['subnetbitsv6'];
3702
        }
3703

    
3704
	return $interface_snv6_arr_cache[$interface];
3705
}
3706

    
3707
function ip_in_interface_alias_subnet($interface, $ipalias) {
3708
	global $config;
3709

    
3710
	if (empty($interface) || !is_ipaddr($ipalias))
3711
		return false;
3712
	if (is_array($config['virtualip']['vip'])) {
3713
                foreach ($config['virtualip']['vip'] as $vip) {
3714
                        switch ($vip['mode']) {
3715
                        case "ipalias":
3716
                                if ($vip['interface'] <> $interface)
3717
                                        break;
3718
				if (ip_in_subnet($ipalias, gen_subnet($vip['subnet'], $vip['subnet_bits']) . "/" . $vip['subnet_bits']))
3719
					return true;
3720
                                break;
3721
                        }
3722
                }
3723
	}
3724

    
3725
	return false;
3726
}
3727

    
3728
function get_interface_ip($interface = "wan")
3729
{
3730
	$realif = get_real_interface($interface);
3731
	if (!$realif) {
3732
		if (preg_match("/^carp/i", $interface))
3733
			$realif = $interface;
3734
		else if (preg_match("/^vip/i", $interface))
3735
			$realif = $interface;
3736
		else
3737
			return null;
3738
	}
3739

    
3740
	$curip = find_interface_ip($realif);
3741
	if ($curip && is_ipaddr($curip) && ($curip != "0.0.0.0"))
3742
		return $curip;
3743
	else
3744
		return null;
3745
}
3746

    
3747
function get_interface_ipv6($interface = "wan")
3748
{
3749
	$realif = get_real_interface($interface);
3750
	if (!$realif) {
3751
		if (preg_match("/^carp/i", $interface))
3752
			$realif = $interface;
3753
		else if (preg_match("/^vip/i", $interface))
3754
			$realif = $interface;
3755
		else
3756
			return null;
3757
	}
3758

    
3759
	$curip = find_interface_ipv6($realif);
3760
	if ($curip && is_ipaddrv6($curip) && ($curip != "::"))
3761
		return $curip;
3762
	else
3763
		return null;
3764
}
3765

    
3766
function get_interface_subnet($interface = "wan")
3767
{
3768
	$realif = get_real_interface($interface);
3769
	if (!$realif) {
3770
                if (preg_match("/^carp/i", $interface))
3771
                        $realif = $interface;
3772
                else if (preg_match("/^vip/i", $interface))
3773
                        $realif = $interface;
3774
                else
3775
                        return null;
3776
        }
3777

    
3778
	$cursn = find_interface_subnet($realif);
3779
	if (!empty($cursn))
3780
		return $cursn;
3781

    
3782
	return null;
3783
}
3784

    
3785
function get_interface_subnetv6($interface = "wan")
3786
{
3787
	$realif = get_real_interface($interface);
3788
	if (!$realif) {
3789
                if (preg_match("/^carp/i", $interface))
3790
                        $realif = $interface;
3791
                else if (preg_match("/^vip/i", $interface))
3792
                        $realif = $interface;
3793
                else
3794
                        return null;
3795
        }
3796

    
3797
	$cursn = find_interface_subnetv6($realif);
3798
	if (!empty($cursn))
3799
		return $cursn;
3800

    
3801
	return null;
3802
}
3803

    
3804
/* return outside interfaces with a gateway */
3805
function get_interfaces_with_gateway() {
3806
	global $config;
3807

    
3808
	$ints = array();
3809

    
3810
	/* loop interfaces, check config for outbound */
3811
	foreach($config['interfaces'] as $ifdescr => $ifname) {
3812
		switch ($ifname['ipaddr']) {
3813
			case "dhcp":
3814
			case "carpdev-dhcp":
3815
			case "ppp";
3816
			case "pppoe":
3817
			case "pptp":
3818
			case "l2tp":
3819
			case "ppp";
3820
				$ints[$ifdescr] = $ifdescr;
3821
			break;
3822
			default:
3823
				if (substr($ifname['if'], 0, 5) ==  "ovpnc" ||
3824
				    !empty($ifname['gateway']))
3825
					$ints[$ifdescr] = $ifdescr;
3826
			break;
3827
		}
3828
	}
3829
	return $ints;
3830
}
3831

    
3832
/* return true if interface has a gateway */
3833
function interface_has_gateway($friendly) {
3834
	global $config;
3835

    
3836
	if (!empty($config['interfaces'][$friendly])) {
3837
		$ifname = &$config['interfaces'][$friendly];
3838
		switch ($ifname['ipaddr']) {
3839
			case "dhcp":
3840
			case "carpdev-dhcp":
3841
			case "pppoe":
3842
			case "pptp":
3843
			case "l2tp":
3844
			case "ppp";
3845
				return true;
3846
			break;
3847
			default:
3848
				if (substr($ifname['if'], 0, 5) ==  "ovpnc")
3849
					return true;
3850
				if (!empty($ifname['gateway']))
3851
					return true;
3852
			break;
3853
		}
3854
	}
3855

    
3856
	return false;
3857
}
3858

    
3859
/****f* interfaces/is_altq_capable
3860
 * NAME
3861
 *   is_altq_capable - Test if interface is capable of using ALTQ
3862
 * INPUTS
3863
 *   $int            - string containing interface name
3864
 * RESULT
3865
 *   boolean         - true or false
3866
 ******/
3867

    
3868
function is_altq_capable($int) {
3869
        /* Per:
3870
         * http://www.freebsd.org/cgi/man.cgi?query=altq&manpath=FreeBSD+7.2-current&format=html
3871
         * Only the following drivers have ALTQ support
3872
         */
3873
	$capable = array("age", "alc", "ale", "an", "ath", "aue", "awi", "bce",
3874
			"bfe", "bge", "bridge", "cas", "dc", "de", "ed", "em", "ep", "fxp", "gem",
3875
			"hme", "igb", "ipw", "iwi", "jme", "le", "lem", "msk", "mxge", "my", "nfe",
3876
			"npe", "nve", "ral", "re", "rl", "rum", "run", "bwn", "sf", "sis", "sk",
3877
			"ste", "stge", "txp", "udav", "ural", "vge", "vr", "wi", "xl",
3878
			"ndis", "tun", "ovpns", "ovpnc", "vlan", "pppoe", "pptp", "ng",
3879
			"l2tp", "ppp");
3880

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

    
3883
        if (in_array($int_family[0], $capable))
3884
                return true;
3885
	else if (stristr($int, "vlan")) /* VLANs are name $parent_$vlan now */
3886
		return true;
3887
	else if (stristr($int, "_wlan")) /* WLANs are name $parent_$wlan now */
3888
		return true;
3889
        else
3890
                return false;
3891
}
3892

    
3893
/****f* interfaces/is_interface_wireless
3894
 * NAME
3895
 *   is_interface_wireless - Returns if an interface is wireless
3896
 * RESULT
3897
 *   $tmp       - Returns if an interface is wireless
3898
 ******/
3899
function is_interface_wireless($interface) {
3900
        global $config, $g;
3901

    
3902
        $friendly = convert_real_interface_to_friendly_interface_name($interface);
3903
        if(!isset($config['interfaces'][$friendly]['wireless'])) {
3904
                if (preg_match($g['wireless_regex'], $interface)) {
3905
                        if (isset($config['interfaces'][$friendly]))
3906
                                $config['interfaces'][$friendly]['wireless'] = array();
3907
                        return true;
3908
                }
3909
                return false;
3910
        } else
3911
                return true;
3912
}
3913

    
3914
function get_wireless_modes($interface) {
3915
	/* return wireless modes and channels */
3916
	$wireless_modes = array();
3917

    
3918
	$cloned_interface = get_real_interface($interface);
3919

    
3920
	if($cloned_interface && is_interface_wireless($cloned_interface)) {
3921
		$chan_list = "/sbin/ifconfig {$cloned_interface} list chan";
3922
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
3923
		$format_list = "/usr/bin/awk '{print \$5 \" \" \$6 \",\" \$1}'";
3924

    
3925
		$interface_channels = "";
3926
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
3927
		$interface_channel_count = count($interface_channels);
3928

    
3929
		$c = 0;
3930
		while ($c < $interface_channel_count)
3931
		{
3932
			$channel_line = explode(",", $interface_channels["$c"]);
3933
			$wireless_mode = trim($channel_line[0]);
3934
			$wireless_channel = trim($channel_line[1]);
3935
			if(trim($wireless_mode) != "") {
3936
				/* if we only have 11g also set 11b channels */
3937
				if($wireless_mode == "11g") {
3938
					if(!isset($wireless_modes["11b"]))
3939
						$wireless_modes["11b"] = array();
3940
				} else if($wireless_mode == "11g ht") {
3941
					if(!isset($wireless_modes["11b"]))
3942
						$wireless_modes["11b"] = array();
3943
					if(!isset($wireless_modes["11g"]))
3944
						$wireless_modes["11g"] = array();
3945
					$wireless_mode = "11ng";
3946
				} else if($wireless_mode == "11a ht") {
3947
					if(!isset($wireless_modes["11a"]))
3948
						$wireless_modes["11a"] = array();
3949
					$wireless_mode = "11na";
3950
				}
3951
				$wireless_modes["$wireless_mode"]["$c"] = $wireless_channel;
3952
			}
3953
			$c++;
3954
		}
3955
	}
3956
	return($wireless_modes);
3957
}
3958

    
3959
/* return channel numbers, frequency, max txpower, and max regulation txpower */
3960
function get_wireless_channel_info($interface) {
3961
	$wireless_channels = array();
3962

    
3963
	$cloned_interface = get_real_interface($interface);
3964

    
3965
	if($cloned_interface && is_interface_wireless($cloned_interface)) {
3966
		$chan_list = "/sbin/ifconfig {$cloned_interface} list txpower";
3967
		$stack_list = "/usr/bin/awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
3968
		$format_list = "/usr/bin/awk '{print \$1 \",\" \$3 \" \" \$4 \",\" \$5 \",\" \$7}'";
3969

    
3970
		$interface_channels = "";
3971
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
3972

    
3973
		foreach ($interface_channels as $channel_line) {
3974
			$channel_line = explode(",", $channel_line);
3975
			if(!isset($wireless_channels[$channel_line[0]]))
3976
				$wireless_channels[$channel_line[0]] = $channel_line;
3977
		}
3978
	}
3979
	return($wireless_channels);
3980
}
3981

    
3982
/****f* interfaces/get_interface_mtu
3983
 * NAME
3984
 *   get_interface_mtu - Return the mtu of an interface
3985
 * RESULT
3986
 *   $tmp       - Returns the mtu of an interface
3987
 ******/
3988
function get_interface_mtu($interface) {
3989
        $mtu = pfSense_get_interface_addresses($interface);
3990
        return $mtu['mtu'];
3991
}
3992

    
3993
function get_interface_mac($interface) {
3994

    
3995
	$macinfo = pfSense_get_interface_addresses($interface);
3996
	return $macinfo["macaddr"];
3997
}
3998

    
3999
/****f* pfsense-utils/generate_random_mac_address
4000
 * NAME
4001
 *   generate_random_mac - generates a random mac address
4002
 * INPUTS
4003
 *   none
4004
 * RESULT
4005
 *   $mac - a random mac address
4006
 ******/
4007
function generate_random_mac_address() {
4008
        $mac = "02";
4009
        for($x=0; $x<5; $x++)
4010
                $mac .= ":" . dechex(rand(16, 255));
4011
        return $mac;
4012
}
4013

    
4014
/****f* interfaces/is_jumbo_capable
4015
 * NAME
4016
 *   is_jumbo_capable - Test if interface is jumbo frame capable.  Useful for determining VLAN capability.
4017
 * INPUTS
4018
 *   $int             - string containing interface name
4019
 * RESULT
4020
 *   boolean          - true or false
4021
 ******/
4022
function is_jumbo_capable($int) {
4023
        global $g;
4024

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

    
4027
        if (in_array($int_family[0], $g['vlan_long_frame']))
4028
                return true;
4029
        else
4030
                return false;
4031
}
4032

    
4033
function setup_pppoe_reset_file($pppif, $iface="") {
4034
	global $g;
4035
	$cron_file = "{$g['varetc_path']}/pppoe_restart_{$pppif}";
4036

    
4037
	if(!empty($iface) && !empty($pppif)){
4038
		$cron_cmd = <<<EOD
4039
#!/bin/sh
4040
/usr/local/sbin/pfSctl -c 'interface reload {$iface}'
4041
/usr/bin/logger -t pppoe{$iface} "PPPoE periodic reset executed on {$iface}"
4042

    
4043
EOD;
4044

    
4045
		file_put_contents($cron_file, $cron_cmd);
4046
		chmod($cron_file, 0700);
4047
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
4048
	} else
4049
		unlink_if_exists($cron_file);
4050
}
4051

    
4052
function get_interface_default_mtu($type = "ethernet") {
4053
	switch ($type) {
4054
	case "gre":
4055
		return 1476;
4056
		break;
4057
	case "gif":
4058
		return 1280;
4059
		break;
4060
	case "tun":
4061
	case "vlan":
4062
	case "tap":
4063
	case "ethernet":
4064
	default:
4065
		return 1500;
4066
		break;
4067
	}
4068

    
4069
	/* Never reached */
4070
	return 1500;
4071
}
4072

    
4073
function get_vip_descr($ipaddress) {
4074
	global $config;
4075

    
4076
	foreach ($config['virtualip']['vip'] as $vip) {
4077
		if ($vip['subnet'] == $ipaddress) {
4078
			return ($vip['descr']);
4079
		}
4080
	}
4081
	return "";
4082
}
4083

    
4084
function interfaces_staticarp_configure($if) {
4085
	global $config, $g;
4086
	if(isset($config['system']['developerspew'])) {
4087
		$mt = microtime();
4088
		echo "interfaces_staticarp_configure($if) being called $mt\n";
4089
	}
4090

    
4091
	$ifcfg = $config['interfaces'][$if];
4092

    
4093
	if (empty($if) || empty($ifcfg['if']))
4094
		return 0;
4095

    
4096
	/* Enable staticarp, if enabled */
4097
	if(isset($config['dhcpd'][$if]['staticarp'])) {
4098
		mwexec("/sbin/ifconfig " . escapeshellarg($ifcfg['if']) . " staticarp " );
4099
		mwexec("/usr/sbin/arp -d -i " . escapeshellarg($ifcfg['if']) . " -a > /dev/null 2>&1 ");
4100
		if (is_array($config['dhcpd'][$if]['staticmap'])) {
4101

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

    
4105
			}
4106

    
4107
		}
4108
	} else {
4109
		mwexec("/sbin/ifconfig " . escapeshellarg($ifcfg['if']) . " -staticarp " );
4110
		mwexec("/usr/sbin/arp -d -i " . escapeshellarg($ifcfg['if']) . " -a > /dev/null 2>&1 ");
4111
	}
4112

    
4113
	return 0;
4114
}
4115

    
4116
?>
(25-25/61)