Project

General

Profile

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

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

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

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

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

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

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

    
38
/* include all configuration functions */
39
require_once("functions.inc");
40
require_once("globals.inc");
41

    
42
function interfaces_loopback_configure() {
43
	mwexec("/sbin/ifconfig lo0 127.0.0.1");
44

    
45
	return 0;
46
}
47

    
48
function interfaces_vlan_configure() {
49
	global $config;
50

    
51
	$i = 0;
52
	if (is_array($config['vlans']['vlan']) && count($config['vlans']['vlan'])) {
53
		foreach ($config['vlans']['vlan'] as $vlan) {
54
			if(empty($vlan['vlanif'])) {
55
				$vlan['vlanif'] = "vlan{$i}";
56
			}
57
			/* XXX: Maybe we should report any errors?! */
58
			interface_vlan_configure($vlan['if'], $vlan['tag'], $vlan['vlanif']);
59
			$i++;
60
		}
61
	}
62
}
63

    
64
function interface_vlan_configure($if, $tag, $vlanif = "") {
65
	global $config, $g;
66

    
67
	/* make sure the parent interface is up and enable hw vlan support if available*/
68
	mwexec("/sbin/ifconfig " . escapeshellarg($if) . " up vlanhwtag vlanmtu");
69

    
70
	if ($g['booting'] || !(empty($vlanif))) {
71
		/* before destroying, see if CARP is in use
72
		  If an interface containing an active CARP IP is destroyed,
73
		  the CARP interface will hang in INIT and must be destroyed
74
		  itself before it will function again (which causes a panic).
75
		  Trying to configure a CARP interface stuck in INIT will
76
		  cause a panic as well.  -cmb
77
		*/
78
		$carpcount = find_number_of_needed_carp_interfaces();
79
		/* will continue to destroy VLANs where CARP is not in use
80
		  to retain previous behavior and avoid regressions */
81
		if($carpcount < 1)
82
			mwexec("/sbin/ifconfig {$vlanif} destroy");
83
		mwexec("/sbin/ifconfig {$vlanif} create");
84
	} else 
85
		$vlanif = exec("/sbin/ifconfig vlan create");
86
	
87
	mwexec("/sbin/ifconfig {$vlanif} vlan " .
88
		escapeshellarg($tag) . " vlandev " .
89
		escapeshellarg($if));
90

    
91
	mwexec("/sbin/ifconfig {$vlanif} up");
92

    
93
	/* invalidate interface cache */
94
	get_interface_arr(true);
95

    
96
	/*   all vlans need to spoof their parent mac address, too.  see
97
	 *   ticket #1514: http://cvstrac.pfsense.com/tktview?tn=1514,33
98
	 */
99
	foreach($config['interfaces'] as $interfaces) {
100
		if($interfaces['if'] == $if && $interfaces['spoofmac']) {
101
			mwexec("/sbin/ifconfig " . escapeshellarg($if) .
102
				" link " . escapeshellarg($interfaces['spoofmac']));
103
		}
104
	}
105

    
106
	return $vlanif;
107
}
108

    
109
function interfaces_lan_configure() {
110
	global $config, $g;
111

    
112
	$lancfg = $config['interfaces']['lan'];
113

    
114
	/* if user has removed ip address, clear it*/
115
	if($lancfg['ipaddr'] == "")
116
		mwexec("/sbin/ifconfig {$lancfg['if']} delete");
117

    
118
	/* wireless configuration? */
119
	if (is_array($lancfg['wireless']))
120
		interfaces_wireless_configure($lancfg['if'], $lancfg['wireless']);
121

    
122
	/* MAC spoofing? */
123
	if ($lancfg['spoofmac']) {
124
		mwexec("/sbin/ifconfig " . escapeshellarg($lancfg['if']) .
125
			" link " . escapeshellarg($lancfg['spoofmac']));
126
	} else {
127
		$mac = get_interface_mac_address($lancfg['if']);
128
		if($mac == "ff:ff:ff:ff:ff:ff") {
129
			/*   this is not a valid mac address.  generate a
130
			 *   temporary mac address so the machine can get online.
131
			 */
132
			echo "Generating new MAC address.";
133
			$random_mac = generate_random_mac_address();
134
			mwexec("/sbin/ifconfig " . escapeshellarg($lancfg['if']) .
135
				" link " . escapeshellarg($random_mac));
136
			$lancfg['spoofmac'] = $random_mac;
137
			write_config();
138
			file_notice("MAC Address altered", "The INVALID MAC address (ff:ff:ff:ff:ff:ff) on interface {$lancfg['if']} has been automatically replaced with {$random_mac}", "Interfaces");
139
		}
140
	}
141

    
142
	/* bridged? */
143
	if ($lancfg['bridge']) {
144
		setup_bridge();
145
	}
146

    
147
	/* media */
148
	if ($lancfg['media'] || $lancfg['mediaopt']) {
149
		$cmd = "/sbin/ifconfig " . escapeshellarg($lancfg['if']);
150
		if ($lancfg['media'])
151
			$cmd .= " media " . escapeshellarg($lancfg['media']);
152
		if ($lancfg['mediaopt'])
153
			$cmd .= " mediaopt " . escapeshellarg($lancfg['mediaopt']);
154
		mwexec($cmd);
155
	}
156

    
157
	mwexec("/sbin/ifconfig " . escapeshellarg($lancfg['if']) . " " .
158
		escapeshellarg($lancfg['ipaddr'] . "/" . $lancfg['subnet']));
159

    
160
	if (!$g['booting']) {
161
		/* make new hosts file */
162
		system_hosts_generate();
163

    
164
		/* reconfigure static routes (kernel may have deleted them) */
165
		system_routing_configure();
166

    
167
		/* set the reload filter dity flag */
168
		touch("{$g['tmp_path']}/filter_dirty");
169

    
170
		/* reload IPsec tunnels */
171
		vpn_ipsec_configure();
172

    
173
		/* reload dhcpd (gateway may have changed) */
174
		services_dhcpd_configure();
175

    
176
		/* reload dnsmasq */
177
		services_dnsmasq_configure();
178

    
179
		/* reload captive portal */
180
		captiveportal_configure();
181

    
182
	}
183

    
184
	return 0;
185
}
186

    
187
function interfaces_optional_configure() {
188
	global $config, $g;
189

    
190
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++) {
191
		interfaces_optional_configure_if($i);
192
	}
193

    
194
	if (!$g['booting']) {
195
		/* reconfigure static routes (kernel may have deleted them) */
196
		system_routing_configure();
197

    
198
		/* reload IPsec tunnels */
199
		vpn_ipsec_configure();
200

    
201
		/* reload dhcpd (interface enabled/disabled/bridged status may have changed) */
202
		services_dhcpd_configure();
203

    
204
		/* restart dnsmasq */
205
		services_dnsmasq_configure();
206

    
207
		/* reload captive portal */
208
		captiveportal_configure();
209

    
210
		/* set the reload filter dity flag */
211
		touch("{$g['tmp_path']}/filter_dirty");
212
	}
213

    
214
	return 0;
215
}
216

    
217
function interfaces_optional_configure_if($opti) {
218
	global $config, $g;
219
	global $debugging;
220

    
221
	$optcfg = $config['interfaces']['opt' . $opti];
222

    
223
	if ($g['booting']) {
224
		$optdescr = "";
225
		if ($optcfg['descr'])
226
			$optdescr = " ({$optcfg['descr']})";
227
		print "\tOPT{$opti}{$optdescr}... ";
228
	}
229

    
230
	if(file_exists("/tmp/{$optcfg['if']}_router"))
231
		unlink("/tmp/{$optcfg['if']}_router");
232

    
233
	if (isset($optcfg['enable'])) {
234
		if($optcfg['gateway'])
235
			system("echo " . $optcfg['gateway'] . " > /tmp/" . $optcfg['if'] . "_router");
236

    
237
		/* wireless configuration? */
238
		if (is_array($optcfg['wireless']))
239
			interfaces_wireless_configure($optcfg['if'], $optcfg['wireless']);
240

    
241
		/* MAC spoofing? */
242
		if ($optcfg['spoofmac']) {
243
			mwexec("/sbin/ifconfig " . escapeshellarg($optcfg['if']) .
244
				" link " . escapeshellarg($optcfg['spoofmac']));
245
		} else {
246
			$mac = get_interface_mac_address($optcfg['if']);
247
			if($mac == "ff:ff:ff:ff:ff:ff") {
248
				/*   this is not a valid mac address.  generate a
249
				 *   temporary mac address so the machine can get online.
250
				 */
251
				echo "Generating new MAC address.";
252
				$random_mac = generate_random_mac_address();
253
				mwexec("/sbin/ifconfig " . escapeshellarg($optcfg['if']) .
254
					" link " . escapeshellarg($random_mac));
255
				$optcfg['spoofmac'] = $random_mac;
256
				write_config();
257
				file_notice("MAC Address altered", "The INVALID MAC address (ff:ff:ff:ff:ff:ff) on interface {$optcfg['if']} has been automatically replaced with {$random_mac}", "Interfaces");
258
			}
259
		}
260

    
261
		/* media */
262
		if ($optcfg['media'] || $optcfg['mediaopt']) {
263
			$cmd = "/sbin/ifconfig " . escapeshellarg($optcfg['if']);
264
			if ($optcfg['media'])
265
				$cmd .= " media " . escapeshellarg($optcfg['media']);
266
			if ($optcfg['mediaopt'])
267
				$cmd .= " mediaopt " . escapeshellarg($optcfg['mediaopt']);
268
			mwexec($cmd);
269
		}
270

    
271
		/* bridged? */
272
		if ($optcfg['bridge']) {
273
			setup_bridge();
274
		} else {
275
			/* if user has selected DHCP type then act accordingly */
276
			if($optcfg['ipaddr'] == "dhcp") {
277
				interfaces_opt_dhcp_configure("opt{$opti}");
278
			} elseif ($optcfg['ipaddr'] == "none") {
279
				/* hidden trick for IP-less interfaces */
280
				mwexec("/sbin/ifconfig " . escapeshellarg($optcfg['if']) . " up");
281
			} else {
282
				mwexec("/sbin/ifconfig " . escapeshellarg($optcfg['if']) . " " .
283
				escapeshellarg($optcfg['ipaddr'] . "/" . $optcfg['subnet']));
284
			}
285
		}
286
	} else {
287
		mwexec("/sbin/ifconfig " . escapeshellarg($optcfg['if']) . " delete down");
288
	}
289
	return 0;
290
}
291

    
292
function interfaces_carp_configure() {
293
	global $g, $config, $debugging;
294
	$balanacing = "";
295
	$pfsyncinterface = "";
296
	$pfsyncenabled = "";
297
	if(isset($config['system']['developerspew'])) {
298
		$mt = microtime();
299
		echo "interfaces_carp_configure() being called $mt\n";
300
	}
301
	$carp_instances_counter = 0;
302
	$total_carp_interfaces_defined = find_number_of_created_carp_interfaces();
303
	/* destroy previous interfaces */
304
	for($x=0; $x<$total_carp_interfaces_defined; $x++)
305
		mwexec("/sbin/ifconfig carp{$x} delete");
306
	if ($g['booting']) {
307
		echo "Configuring CARP interfaces...";
308
		mute_kernel_msgs();
309
	}
310
	/* suck in configuration items */
311
	if($config['installedpackages']['carpsettings']['config']) {
312
		foreach($config['installedpackages']['carpsettings']['config'] as $carp) {
313
			$pfsyncenabled = $carp['pfsyncenabled'];
314
			$balanacing = $carp['balancing'];
315
			$pfsyncinterface = $carp['pfsyncinterface'];
316
			$pfsyncpeerip = $carp['pfsyncpeerip'];
317
		}
318
	} else {
319
		unset($pfsyncinterface);
320
		unset($balanacing);
321
		unset($pfsyncenabled);
322
	}
323
	if($balanacing) {
324
		mwexec("/sbin/sysctl net.inet.carp.arpbalance=1");
325
		mwexec("/sbin/sysctl net.inet.carp.preempt=0");
326
	} else {
327
		mwexec("/sbin/sysctl net.inet.carp.preempt=1");
328
	}
329
	mwexec("/sbin/sysctl net.inet.carp.log=2"); // tell syslog about state changes	
330
	$carp_sync_int = convert_friendly_interface_to_real_interface_name($pfsyncinterface);
331
	if($g['booting']) {
332
		/*    install rules to alllow pfsync to sync up during boot
333
		 *    carp interfaces will remain down until the bootup sequence finishes
334
		 */
335
		exec("echo pass quick proto carp all keep state > /tmp/rules.boot");
336
		exec("echo pass quick proto pfsync all >> /tmp/rules.boot");
337
		exec("echo pass out proto { tcp, udp } from any to any port 53 keep state >> /tmp/rules.boot");
338
		exec("/sbin/pfctl -f /tmp/rules.boot");
339
	}
340
	/* setup pfsync interface */
341
	if($carp_sync_int and $pfsyncenabled) {
342
		if($pfsyncpeerip) {
343
			mwexec("/sbin/ifconfig pfsync0 syncdev {$carp_sync_int} syncpeer {$pfsyncpeerip} up");
344
		} else {
345
			mwexec("/sbin/ifconfig pfsync0 syncdev {$carp_sync_int} up");
346
		}
347
	} else {
348
		mwexec("/sbin/ifconfig pfsync0 syncdev lo0 up");
349
	}
350
	$fd = fopen("/tmp/carp.sh", "w");
351
	if($config['virtualip']['vip']) {
352
		$viparr = &$config['virtualip']['vip'];
353
		mwexec("/sbin/sysctl net.inet.carp.allow=1");
354
	} else {
355
		$viparr = array();
356
		mwexec("/sbin/sysctl net.inet.carp.allow=0");
357
	}
358
	foreach ($viparr as $vip) {
359
		if ($vip['mode'] == "carp") {
360
			$vip_password = $vip['password'];
361
			$vip_password = str_replace(" ", "", $vip_password);
362
			
363
			/* ensure CARP IP really exists prior to loading up */
364
			$found = false;
365
			$iflist = array("lan", "wan");
366
			for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++)
367
				$iflist['opt' . $i] = 'opt' . $i;
368
			foreach($iflist as $if) {
369
				/* ignore down or "disabled" interfaces */
370
				if($if <> "lan" and $if <> "wan")
371
					if (!isset($config['interfaces'][$if]['enable'])) 
372
						continue;								
373
				$ww_subnet_ip = $config['interfaces'][$if]['ipaddr'];
374
				$ww_subnet_bits = $config['interfaces'][$if]['subnet'];
375
				if (ip_in_subnet($vip['subnet'], gen_subnet($ww_subnet_ip, $ww_subnet_bits) . "/" . $ww_subnet_bits))
376
					$found = true;
377
			}
378
			if($found == false) {
379
				file_notice("CARP", "Sorry but we could not find a matching real interface subnet for the virtual IP address {$vip['subnet']}.", "Firewall: Virtual IP", "");
380
				continue;
381
			}
382
			/* ensure the interface containing the VIP really exists
383
			  prevents a panic if the interface is missing or invalid
384
			*/
385
			$realif = convert_friendly_interface_to_real_interface_name($vip['interface']);
386
			$intcount = exec("/sbin/ifconfig | grep $realif | wc -l | awk '{print $1}'");
387
			if($intcount < 1) {
388
				file_notice("CARP", "Interface specified for the virtual IP address {$vip['subnet']} does not exist. Skipping this VIP.", "Firewall: Virtual IP", "");
389
				continue;
390
			}
391
			/* create the carp interface and setup */
392
			mwexec("/sbin/ifconfig carp" . $carp_instances_counter . " create");
393
			fwrite($fd, "/sbin/ifconfig carp" . $carp_instances_counter . " create\n");
394

    
395
			/* invalidate interface cache */
396
			get_interface_arr(true);
397

    
398
			$broadcast_address = gen_subnet_max($vip['subnet'], $vip['subnet_bits']);
399
			if($vip['password'] != "")
400
				$password = " pass \"" . $vip_password . "\"";
401
			if($debugging)
402
				echo "Configuring carp{$carp_instances_counter}.\n";
403
			fwrite($fd, "/sbin/ifconfig carp" . $carp_instances_counter . " " . $vip['subnet'] . "/" . $vip['subnet_bits'] . " vhid " . $vip['vhid'] . "{$carpdev} advskew 200 " . $password . "\n");
404
			mwexec("/sbin/ifconfig carp" . $carp_instances_counter . " " . $vip['subnet'] . "/" . $vip['subnet_bits'] . " vhid " . $vip['vhid'] . "{$carpdev} advskew 200 " . $password);
405
			mwexec("/sbin/ifconfig carp" . $carp_instances_counter . " up");
406
			fwrite($fd, "/sbin/ifconfig carp" . $carp_instances_counter . " up\n");
407
			usleep(10);
408
			$carp_instances_counter++;
409
		}
410
	}
411
	fclose($fd);
412
	mwexec("/bin/sh /tmp/carp.sh");
413
	if ($g['booting']) {
414
		unmute_kernel_msgs();
415
		echo "done.\n";
416
	}
417

    
418
	/* update cache */
419
	if ($carp_instances_counter != find_number_of_created_carp_interfaces())
420
		find_number_of_created_carp_interfaces(true);
421
}
422

    
423
function interfaces_carp_bring_up_final() {
424
	global $config, $g, $debugging;
425
	if(isset($config['system']['developerspew'])) {
426
		$mt = microtime();
427
		echo "interfaces_carp_bring_up_final() being called $mt\n";
428
	}
429
	if(!$config['virtualip']['vip'])
430
		return;
431
	$viparr = &$config['virtualip']['vip'];
432
	/* could not locate an array, return */
433
	if(!is_array($viparr))
434
		return;
435
	$havecarp = false;
436
	foreach ($viparr as $vip) {
437
		/* bail if this isn't a carp VIP */
438
		if ($vip['mode'] == "carp")
439
			$havecarp = true;
440
	}		
441
	if($havecarp == false) 
442
		return;
443
	$carp_instances_counter = 0;
444
	$counter = 0;
445
	if($g['booting'])
446
		echo "Waiting for final CARP interface bringup...";
447
	$supress = intval(`/sbin/sysctl net.inet.carp.suppress_preempt | cut -d" " -f2`);
448
	if($g['booting']) {
449
		while($supress > 0) {
450
			sleep(1);
451
			$supress = intval(`/sbin/sysctl net.inet.carp.suppress_preempt | cut -d" " -f2`);
452
			if($counter > 15)
453
				$supress = 0;
454
			$counter++;
455
			echo ".";
456
		}
457
	}
458
	foreach ($viparr as $vip) {
459
		/* bail if this isn't a carp VIP */
460
		if ($vip['mode'] != "carp")
461
			continue;
462
		/* ensure CARP IP really exists prior to loading up */
463
		$found = false;
464
		$iflist = array("lan", "wan");
465
		for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++)
466
			$iflist['opt' . $i] = 'opt' . $i;
467
		foreach($iflist as $if) {
468
			/* ignore down or "disabled" interfaces */
469
			if($if <> "lan" and $if <> "wan")
470
				if (!isset($config['interfaces'][$if]['enable'])) 
471
					continue;								
472
			$ww_subnet_ip = $config['interfaces'][$if]['ipaddr'];
473
			$ww_subnet_bits = $config['interfaces'][$if]['subnet'];
474
			if (ip_in_subnet($vip['subnet'], gen_subnet($ww_subnet_ip, $ww_subnet_bits) . "/" . $ww_subnet_bits))
475
				$found = true;
476
		}
477
		if($found == false) {
478
			file_notice("CARP", "Sorry but we could not find a matching real interface subnet for the virtual IP address {$vip['subnet']}.", "Firewall: Virtual IP", "");
479
			continue;
480
		}
481
		/* ensure the interface containing the VIP really exists
482
		  prevents a panic if the interface is missing or invalid
483
		*/
484
		$realif = convert_friendly_interface_to_real_interface_name($vip['interface']);
485
		$intcount = exec("/sbin/ifconfig | grep $realif | wc -l | awk '{print $1}'");
486
		if($intcount < 1) {
487
			file_notice("CARP", "Interface specified for the virtual IP address {$vip['subnet']} does not exist. Skipping this VIP.", "Firewall: Virtual IP", "");
488
			continue;
489
		}
490
		if($debugging)
491
			echo "Upping interface carp{$carp_instances_counter}.\n";
492
		$broadcast_address = gen_subnet_max($vip['subnet'], $vip['subnet_bits']);
493
		if($vip['password'] != "")
494
			$password = " pass " . $vip['password'];
495
		if($debugging)
496
			echo "/sbin/ifconfig carp" . $carp_instances_counter . " " . $vip['subnet'] . "/" . $vip['subnet_bits'] . " vhid " . $vip['vhid'] . "{$carpdev} advskew " . $vip['advskew'] . $password . "\n";
497
		mwexec("/sbin/ifconfig carp" . $carp_instances_counter . " " . $vip['subnet'] . "/" . $vip['subnet_bits'] . " vhid " . $vip['vhid'] . "{$carpdev} advskew " . $vip['advskew'] . $password);
498
		usleep(100);
499
		mwexec("/sbin/ifconfig carp" . $carp_instances_counter . " up");
500
		$carp_instances_counter++;
501
	}
502
	if($g['booting'])
503
		echo " done.\n";
504
}
505

    
506
function interfaces_wireless_configure($if, $wlcfg) {
507
	global $config, $g;
508

    
509
	/*    open up a shell script that will be used to output the commands.
510
	 *    since wireless is changing a lot, these series of commands are fragile
511
     *    and will sometimes need to be verified by a operator by executing the command
512
     *    and returning the output of the command to the developers for inspection.  please
513
     *    do not change this routine from a shell script to individul exec commands.  -sullrich
514
	 */
515

    
516
	conf_mount_rw();
517

    
518
	unlink_if_exists("{$g['tmp_path']}/{$if}_setup.sh");
519

    
520
	$fd_set = fopen("/tmp/{$if}_setup.sh","w");
521
	fwrite($fd_set, "#!/bin/sh\n");
522
	fwrite($fd_set, "# pfSense wireless configuration script.\n\n");
523

    
524
	fwrite($fd_set, "# enable shell debugging\n");
525
	fwrite($fd_set, "set -x\n");
526

    
527
	/* set values for /path/program */
528
	$hostapd = "/usr/sbin/hostapd";
529
	$wpa_supplicant = "/usr/sbin/wpa_supplicant";
530
	$ifconfig = "/sbin/ifconfig";
531
	$killall = "/usr/bin/killall";
532

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

    
535
	/* Set a/b/g standard */
536
	$standard = "mode " . escapeshellarg($wlcfg['standard']);
537

    
538
	/* Set 802.11g protection mode */
539
	$protmode = "protmode " . escapeshellarg($wlcfg['protmode']);
540

    
541
	/* set wireless channel value */
542
	if(isset($wlcfg['channel']))
543
		if($wlcfg['channel'] == "0")
544
			$channel = "channel any";
545
		else
546
			$channel = "channel " . escapeshellarg($wlcfg['channel']);
547

    
548
	/* set Distance value */
549
	if($wlcfg['distance'])
550
		$distance = escapeshellarg($wlcfg['distance']);
551

    
552
	/* Set ssid */
553
	if($wlcfg['ssid'])
554
		$ssid = "ssid " . escapeshellarg($wlcfg['ssid']);
555

    
556
	/* Set wireless hostap mode */
557
	if ($wlcfg['mode'] == "hostap")
558
		$hostapmode = "mediaopt hostap";
559
	else
560
		$hostapmode = "-mediaopt hostap";
561

    
562
	/* Set wireless adhoc mode */
563
	if ($wlcfg['mode'] == "adhoc")
564
		$adhocmode = "mediaopt adhoc";
565
	else
566
		$adhocmode = "-mediaopt adhoc";
567

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

    
570
	/* handle hide ssid option */
571
	if(isset($wlcfg['hidessid']['enable']))
572
		$hidessid = "hidessid";
573
	else
574
		$hidessid = "-hidessid";
575

    
576
	/* handle pureg (802.11g) only option */
577
	if(isset($wlcfg['pureg']['enable']))
578
		$pureg = "mode 11g pureg";
579
	else
580
		$pureg = "-pureg";
581

    
582
	/* enable apbridge option */
583
	if(isset($wlcfg['apbridge']['enable']))
584
		$apbridge = "apbridge";
585
	else
586
		$apbridge = "-apbridge";
587

    
588
	/* handle turbo option */
589
	if(isset($wlcfg['turbo']['enable']))
590
		$turbo = "mediaopt turbo";
591
	else
592
		$turbo = "-mediaopt turbo";
593

    
594
	/* handle txpower setting */
595
	if($wlcfg['txpower'] <> "")
596
		$txpower = "txpower " . escapeshellarg($wlcfg['txpower']);
597

    
598
	/* handle wme option */
599
	if(isset($wlcfg['wme']['enable']))
600
		$wme = "wme";
601
	else
602
		$wme = "-wme";
603

    
604
	/* set up wep if enabled */
605
    if (isset($wlcfg['wep']['enable']) && is_array($wlcfg['wep']['key'])) {
606
		if($wlcfg['wpa']['auth_algs'] == "1")
607
			$wepset .= "authmode open wepmode on ";
608
		else if($wlcfg['wpa']['auth_algs'] == "2")
609
			$wepset .= "authmode shared wepmode on ";
610
		else if($wlcfg['wpa']['auth_algs'] == "3")
611
			$wepset .= "authmode mixed wepmode on ";
612
		$i = 1;
613
		foreach ($wlcfg['wep']['key'] as $wepkey) {
614
			$wepset .= "wepkey " . escapeshellarg("{$i}:{$wepkey['value']}") . " ";
615
			if (isset($wepkey['txkey']))
616
				$wepset .= "weptxkey {$i} ";
617
			$i++;
618
		}
619
    } else {
620
    	$wepset .= "authmode open wepmode off ";
621
	}
622

    
623
	/* generate wpa_supplicant/hostap config if wpa is enabled */
624

    
625
	switch ($wlcfg['mode']) {
626
		case 'bss':
627
			if (isset($wlcfg['wpa']['enable'])) {
628

    
629
				$wpa .= <<<EOD
630
ctrl_interface={$g['varrun_path']}/wpa_supplicant
631
ctrl_interface_group=0
632
ap_scan=1
633
#fast_reauth=1
634
network={
635
ssid="{$wlcfg['ssid']}"
636
scan_ssid=1
637
priority=5
638
key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
639
psk="{$wlcfg['wpa']['passphrase']}"
640
pairwise={$wlcfg['wpa']['wpa_pairwise']}
641
group={$wlcfg['wpa']['wpa_pairwise']}
642
}
643
EOD;
644

    
645
				$fd = fopen("{$g['varetc_path']}/wpa_supplicant_{$if}.conf", "w");
646
				fwrite($fd, "{$wpa}");
647
				fclose($fd);
648

    
649
				fwrite($fd_set, kill_wpasupplicant($if));
650
			}
651
		break;
652

    
653
		case 'hostap':
654
			if (isset($wlcfg['wpa']['enable'])) {
655
				$wpa .= <<<EOD
656
interface={$if}
657
driver=bsd
658
logger_syslog=-1
659
logger_syslog_level=0
660
logger_stdout=-1
661
logger_stdout_level=0
662
dump_file={$g['tmp_path']}/hostapd_{$if}.dump
663
ctrl_interface={$g['varrun_path']}/hostapd
664
ctrl_interface_group=wheel
665
#accept_mac_file={$g['tmp_path']}/hostapd_{$if}.accept
666
#deny_mac_file={$g['tmp_path']}/hostapd_{$if}.deny
667
#macaddr_acl={$wlcfg['wpa']['macaddr_acl']}
668
ssid={$wlcfg['ssid']}
669
debug={$wlcfg['wpa']['debug_mode']}
670
auth_algs={$wlcfg['wpa']['auth_algs']}
671
wpa={$wlcfg['wpa']['wpa_mode']}
672
wpa_key_mgmt={$wlcfg['wpa']['wpa_key_mgmt']}
673
wpa_pairwise={$wlcfg['wpa']['wpa_pairwise']}
674
wpa_group_rekey={$wlcfg['wpa']['wpa_group_rekey']}
675
wpa_gmk_rekey={$wlcfg['wpa']['wpa_gmk_rekey']}
676
wpa_strict_rekey={$wlcfg['wpa']['wpa_strict_rekey']}
677
wpa_passphrase={$wlcfg['wpa']['passphrase']}
678
ieee8021x={$wlcfg['wpa']['ieee8021x']}
679
#Enable the next lines for preauth when roaming. Interface = wired or wireless interface talking to the AP you want to roam from/to
680
#rsn_preauth=1
681
#rsn_preauth_interfaces=eth0
682
EOD;
683

    
684
				$fd = fopen("{$g['varetc_path']}/hostapd_{$if}.conf", "w");
685
				fwrite($fd, "{$wpa}");
686
				fclose($fd);
687

    
688
				fwrite($fd_set, kill_hostapd($if));
689
			}
690
		break;
691

    
692
		case 'adhoc':
693
			fwrite($fd_set, kill_hostapd($if));
694
			fwrite($fd_set, kill_wpasupplicant($if));
695
		break;
696
	}
697

    
698
	/*
699
	 *    all variables are set, lets start up everything
700
     */
701

    
702
	/* set ack timers according to users preference (if he/she has any) */
703
	if($distance) {
704
		fwrite($fd_set, "# Enable ATH distance settings\n");
705
		fwrite($fd_set, "/sbin/athctrl.sh -i {$if} -d {$distance}\n");
706
	}
707

    
708
	$standard_no_turbo = str_replace(" Turbo", "", $standard);
709

    
710
	$settings = <<<EOD
711

    
712
{$ifconfig} {$if} down
713
{$ifconfig} {$if} {$standard_no_turbo}
714
{$ifconfig} {$if} {$channel}
715
{$ifconfig} {$if} {$turbo}
716
{$ifconfig} {$if} {$ssid}
717
{$ifconfig} {$if} {$hidessid}
718
{$ifconfig} {$if} {$adhocmode}
719
{$ifconfig} {$if} {$protmode}
720
{$ifconfig} {$if} {$pureg}
721
{$ifconfig} {$if} {$apbridge}
722
{$ifconfig} {$if} {$wme}
723
{$ifconfig} {$if} {$wepset}
724
{$ifconfig} {$if} {$txpower}
725
{$ifconfig} {$if} {$hostapmode}
726
{$ifconfig} {$if} mtu 1500
727
{$ifconfig} {$if} up
728

    
729
EOD;
730

    
731
	/* write out above <<EOD stuff */
732
	fwrite($fd_set, $settings);
733

    
734
	if (isset($wlcfg['wpa']['enable'])) {
735
		if ($wlcfg['mode'] == "bss")
736
			fwrite($fd_set, "{$wpa_supplicant} -B -i {$if} -c {$g['varetc_path']}/wpa_supplicant_{$if}.conf\n");
737
		if ($wlcfg['mode'] == "hostap")
738
			fwrite($fd_set, "{$hostapd} -B {$g['varetc_path']}/hostapd_{$if}.conf\n");
739
	}
740

    
741
	fclose($fd_set);
742

    
743
	conf_mount_ro();
744

    
745
	/* execute commands now in shell */
746
	mwexec("/bin/sh /tmp/{$if}_setup.sh");
747
	sleep(2);
748
	mwexec("/bin/sh /tmp/{$if}_setup.sh");
749

    
750
	return 0;
751

    
752
}
753

    
754
function kill_hostapd($interface) {
755
	return "/bin/ps awwuxx | grep hostapd | grep $interface | awk '{ print \$2 }' | xargs kill\n";
756
}
757

    
758
function kill_wpasupplicant($interface) {
759
	return "/bin/ps awwuxx | grep wpa_supplicant | grep $interface | awk '{ print \$2 }' | xargs kill\n";
760
}
761

    
762
function find_dhclient_process($interface) {
763
	if(filter_translate_type_to_real_interface($interface) <> "")
764
        	$realinterface = filter_translate_type_to_real_interface($interface);
765
	$pid = `ps awwwux | grep dhclient | grep -v grep | grep {$realinterface} | awk '{ print \$2 }'`;
766
	return $pid;
767
}
768

    
769
function interfaces_wan_configure() {
770
	
771
	global $config, $g;
772

    
773
	$wancfg = $config['interfaces']['wan'];
774

    
775
	if(file_exists("/tmp/{$config['interfaces']['wan']['if']}_router")) 
776
		unlink("/tmp/{$config['interfaces']['wan']['if']}_router");
777

    
778
	if(!$g['booting']) {
779
		mute_kernel_msgs();
780

    
781
		/* find dhclient process for wan and kill it */
782
		killbypid(find_dhclient_process("wan"));
783

    
784
		/* remove wanup file if it exists */
785
		unlink_if_exists("{$g['tmp_path']}/wanup");
786

    
787
		/* kill PPPoE client (mpd) */
788
		killbypid("{$g['varrun_path']}/mpd.pid");
789

    
790
		/* wait for processes to die */
791
		sleep(3);
792
		unlink_if_exists("{$g['varetc_path']}/dhclient_wan.conf");
793
		unlink_if_exists("{$g['varetc_path']}/mpd.conf");
794
		unlink_if_exists("{$g['varetc_path']}/mpd.links");
795
		unlink_if_exists("{$g['vardb_path']}/wanip");
796
		unlink_if_exists("{$g['varetc_path']}/nameservers.conf");
797
	}
798

    
799
	/* remove all addresses first */
800
	while (mwexec("/sbin/ifconfig " . escapeshellarg($wancfg['if']) . " -alias", true) == 0);
801
	mwexec("/sbin/ifconfig " . escapeshellarg($wancfg['if']) . " down");
802

    
803
	/* wireless configuration? */
804
	if (is_array($wancfg['wireless']))
805
		interfaces_wireless_configure($wancfg['if'], $wancfg['wireless']);
806

    
807
	if ($wancfg['spoofmac']) {
808
		mwexec("/sbin/ifconfig " . escapeshellarg($wancfg['if']) .
809
			" link " . escapeshellarg($wancfg['spoofmac']));
810
	}  else {
811
		$mac = get_interface_mac_address($wancfg['if']);
812
		if($mac == "ff:ff:ff:ff:ff:ff") {
813
			/*   this is not a valid mac address.  generate a
814
			 *   temporary mac address so the machine can get online.
815
			 */
816
			echo "Generating new MAC address.";
817
			$random_mac = generate_random_mac_address();
818
			mwexec("/sbin/ifconfig " . escapeshellarg($wancfg['if']) .
819
				" link " . escapeshellarg($random_mac));
820
			$wancfg['spoofmac'] = $random_mac;
821
			write_config();
822
			file_notice("MAC Address altered", "The INVALID MAC address (ff:ff:ff:ff:ff:ff) on interface {$wancfg['if']} has been automatically replaced with {$random_mac}", "Interfaces");
823
		}
824
	}
825

    
826
	/* media */
827
	if ($wancfg['media'] || $wancfg['mediaopt']) {
828
		$cmd = "/sbin/ifconfig " . escapeshellarg($wancfg['if']);
829
		if ($wancfg['media'])
830
			$cmd .= " media " . escapeshellarg($wancfg['media']);
831
		if ($wancfg['mediaopt'])
832
			$cmd .= " mediaopt " . escapeshellarg($wancfg['mediaopt']);
833
		mwexec($cmd);
834
	}
835

    
836
	switch ($wancfg['ipaddr']) {
837

    
838
		case 'dhcp':
839
			interfaces_wan_dhcp_configure();
840
			break;
841

    
842
		case 'pppoe':
843
			interfaces_wan_pppoe_configure();
844
			break;
845

    
846
		case 'pptp':
847
			interfaces_wan_pptp_configure();
848
			break;
849

    
850
		case 'bigpond':
851
			/* just configure DHCP for now; fire up bpalogin when we've got the lease */
852
			interfaces_wan_dhcp_configure();
853
			break;
854

    
855
		default:
856
			if (isset($wancfg['ispointtopoint']) && $wancfg['pointtopoint']) {
857
				mwexec("/sbin/ifconfig " . escapeshellarg($wancfg['if']) . " " .
858
					escapeshellarg($wancfg['ipaddr'] . "/" . $wancfg['subnet']) .
859
					" " . escapeshellarg($wancfg['pointtopoint']) . " up");
860
			} else {
861
				if($wancfg['ipaddr'] && $wancfg['subnet'])
862
					mwexec("/sbin/ifconfig " . escapeshellarg($wancfg['if']) . " " .
863
						escapeshellarg($wancfg['ipaddr'] . "/" . $wancfg['subnet']));
864
			}
865
			/* install default route */
866
			mwexec("/sbin/route delete default", true);
867

    
868
			$dont_add_route = false;
869
			/* if OLSRD is enabled, allow WAN to house DHCP. */
870
			if($config['installedpackages']['olsrd']) {
871
				foreach($config['installedpackages']['olsrd']['config'] as $olsrd) {
872
						if($olsrd['enabledyngw'] == "on") {
873
							$dont_add_route = true;
874
						}
875
				}
876
			}
877

    
878
			if($dont_add_route == false)
879
				mwexec("/sbin/route add default " . escapeshellarg($config['interfaces']['wan']['gateway']));
880

    
881
			if($config['interfaces']['wan']['gateway'])
882
				system("echo " . $config['interfaces']['wan']['gateway'] . " > /tmp/" . $config['interfaces']['wan']['if'] . "_router");
883

    
884
			/* resync pf (done automatically for DHCP/PPPoE/PPTP) */
885
			filter_configure();
886
	}
887

    
888
	if ($wancfg['bridge']) {
889
		setup_bridge();
890
	}
891

    
892
	if (!$g['booting']) {
893
		/* reconfigure static routes (kernel may have deleted them) */
894
		system_routing_configure();
895

    
896
		/* set the reload filter dity flag */
897
		touch("{$g['tmp_path']}/filter_dirty");
898

    
899
		/* reload ipsec tunnels */
900
		vpn_ipsec_configure();
901

    
902
		/* restart ez-ipupdate */
903
		services_dyndns_configure();
904

    
905
		/* force DNS update */
906
		services_dnsupdate_process();
907

    
908
		/* restart dnsmasq */
909
		services_dnsmasq_configure();
910

    
911
		/* reload captive portal */
912
		captiveportal_configure();
913
	}
914

    
915
	mwexec("/sbin/ifconfig {$wancfg['if']} up");
916

    
917
	unmute_kernel_msgs();
918

    
919
	return 0;
920
}
921

    
922
function interfaces_opt_dhcp_configure($interface) {
923
	global $config, $g;
924

    
925
	$optcfg = $config['interfaces'][$interface];
926
	$optif = $optcfg['if'];
927

    
928
	/* generate dhclient_wan.conf */
929
	$fd = fopen("{$g['varetc_path']}/dhclient_{$optif}.conf", "w");
930
	if (!$fd) {
931
		printf("Error: cannot open dhclient_{$optif}.conf in interfaces_opt_dhcp_configure({$optif}) for writing.\n");
932
		return 1;
933
	}
934

    
935
	if ($optcfg['dhcphostname']) {
936
		$dhclientconf_hostname = "send dhcp-client-identifier \"{$optcfg['dhcphostname']}\";\n";
937
		$dhclientconf_hostname .= "\tsend host-name \"{$optcfg['dhcphostname']}\";\n";
938
	} else {
939
		$dhclientconf_hostname = "";
940
	}
941

    
942
 	$dhclientconf = "";
943

    
944
	$dhclientconf .= <<<EOD
945
timeout 60;
946
retry 1;
947
select-timeout 0;
948
initial-interval 1;
949
interface "{$optif}" {
950
	script "/sbin/dhclient-script";
951
	{$dhclientconf_hostname}
952
}
953

    
954
EOD;
955

    
956
	fwrite($fd, $dhclientconf);
957
	fclose($fd);
958

    
959
        /* bring interface up before starting dhclient */
960
        mwexec("/sbin/ifconfig {$optif} up");
961

    
962
        /* fire up dhclient */
963
        mwexec("/sbin/dhclient -c {$g['varetc_path']}/dhclient_{$optif}.conf {$optif}");
964

    
965
	return 0;
966
}
967

    
968
function interfaces_dhcp_configure($interface) {
969
	global $config, $g;
970

    
971
	if(filter_translate_type_to_real_interface($interface) <> "")
972
        	$realinterface = filter_translate_type_to_real_interface($interface);
973

    
974
	$optcfg = $config['interfaces'][$interface];
975

    
976
	/* generate dhclient_$interface.conf */
977
	$fd = fopen("{$g['varetc_path']}/dhclient_{$interface}.conf", "w");
978
	if (!$fd) {
979
		printf("Error: cannot open dhclient_{$interface}.conf in interfaces_dhcp_configure({$$interface}) for writing.\n");
980
		return 1;
981
	}
982

    
983
	if ($optcfg['dhcphostname']) {
984
		$dhclientconf_hostname =  "send dhcp-client-identifier \"{$optcfg['dhcphostname']}\";\n";
985
		$dhclientconf_hostname .= "\tsend host-name \"{$optcfg['dhcphostname']}\";\n";
986
	} else {
987
		$dhclientconf_hostname = "";
988
	}
989

    
990
 	$dhclientconf = "";
991

    
992
	$dhclientconf .= <<<EOD
993
timeout 60;
994
retry 1;
995
select-timeout 0;
996
initial-interval 1;
997
interface "{$realinterface}" {
998
	{$dhclientconf_hostname}
999
	script "/sbin/dhclient-script";
1000
}
1001

    
1002
EOD;
1003

    
1004
	fwrite($fd, $dhclientconf);
1005
	fclose($fd);
1006

    
1007
	$optif = $optcfg['if'];
1008

    
1009
        /* bring wan interface up before starting dhclient */
1010
        mwexec("/sbin/ifconfig {$optif} up");
1011

    
1012
        /* fire up dhclient */
1013
        mwexec("/sbin/dhclient -c {$g['varetc_path']}/dhclient_{$optif}.conf {$optif} >/tmp/{$optif}_output >/tmp/{$optif}_error_output");
1014

    
1015
	$fout = fopen("/tmp/ifconfig_{$optif}","w");
1016
	fwrite($fout, "/sbin/dhclient -c {$g['varetc_path']}/dhclient_{$optif}.conf {$optif}");
1017
	fclose($fout);
1018

    
1019
	return 0;
1020
}
1021

    
1022
function interfaces_wan_dhcp_configure() {
1023
	global $config, $g;
1024

    
1025
	$wancfg = $config['interfaces']['wan'];
1026

    
1027
	/* generate dhclient_wan.conf */
1028
	$fd = fopen("{$g['varetc_path']}/dhclient_wan.conf", "w");
1029
	if (!$fd) {
1030
		printf("Error: cannot open dhclient_wan.conf in interfaces_wan_dhcp_configure() for writing.\n");
1031
		return 1;
1032
	}
1033

    
1034
	if ($wancfg['dhcphostname']) {
1035
		$dhclientconf_hostname = "send dhcp-client-identifier \"{$wancfg['dhcphostname']}\";\n";
1036
		$dhclientconf_hostname .= "\tsend host-name \"{$wancfg['dhcphostname']}\";\n";
1037
	} else {
1038
		$dhclientconf_hostname = "";
1039
	}
1040

    
1041
 	$dhclientconf = "";
1042

    
1043
	$dhclientconf .= <<<EOD
1044
timeout 60;
1045
retry 1;
1046
select-timeout 0;
1047
initial-interval 1;
1048
interface "{$wancfg['if']}" {
1049
	{$dhclientconf_hostname}
1050
	script "/sbin/dhclient-script";
1051
}
1052

    
1053
EOD;
1054

    
1055
	fwrite($fd, $dhclientconf);
1056
	fclose($fd);
1057

    
1058
	$wanif = $wancfg['if'];
1059

    
1060
        /* bring wan interface up before starting dhclient */
1061
        mwexec("/sbin/ifconfig {$wanif} up");
1062

    
1063
        /* fire up dhclient */
1064
        mwexec("/sbin/dhclient -c {$g['varetc_path']}/dhclient_wan.conf {$wanif} >/tmp/{$wanif}_output >/tmp/{$wanif}_error_output");
1065

    
1066
	$fout = fopen("/tmp/ifconfig_{$wanif}","w");
1067
	fwrite($fout, "/sbin/dhclient -c {$g['varetc_path']}/dhclient_wan.conf {$wanif}");
1068
	fclose($fout);
1069

    
1070
	return 0;
1071
}
1072

    
1073
function interfaces_wan_dhcp_down() {
1074
	global $config;
1075
	$wancfg = $config['interfaces']['wan'];
1076
	$wanif = $wancfg['if'];
1077
	mwexec("/sbin/ifconfig {$wanif} delete");
1078
	sleep(1);
1079
}
1080

    
1081
function interfaces_dhcp_down($interface) {
1082
	global $config;
1083
	if(filter_translate_type_to_real_interface($interface) <> "")
1084
		$realinterface = filter_translate_type_to_real_interface($interface);
1085
	mwexec("/sbin/ifconfig {$realinterface} down");
1086
	sleep(1);
1087
	$pid = find_dhclient_process($interface);
1088
	if($pid)
1089
		mwexec("kill {$pid}");
1090
}
1091

    
1092
function interfaces_dhcp_up($interface) {
1093
	interfaces_dhcp_configure($interface);
1094
	sleep(1);
1095
}
1096

    
1097
function interfaces_wan_dhcp_up() {
1098
	interfaces_wan_dhcp_configure();
1099
	sleep(1);
1100
}
1101

    
1102
function interfaces_wan_pppoe_configure() {
1103
	global $config, $g;
1104

    
1105
	$wancfg = $config['interfaces']['wan'];
1106
	$pppoecfg = $config['pppoe'];
1107

    
1108
	/* generate mpd.conf */
1109
	$fd = fopen("{$g['varetc_path']}/mpd.conf", "w");
1110
	if (!$fd) {
1111
		printf("Error: cannot open mpd.conf in interfaces_wan_pppoe_configure().\n");
1112
		return 1;
1113
	}
1114

    
1115
	$idle = 0;
1116

    
1117
	if (isset($pppoecfg['ondemand'])) {
1118
		$ondemand = "enable";
1119
		if ($pppoecfg['timeout'])
1120
			$idle = $pppoecfg['timeout'];
1121
	} else {
1122
		$ondemand = "disable";
1123
	}
1124

    
1125
	$mpdconf = <<<EOD
1126
pppoe:
1127
	new -i ng0 pppoe pppoe
1128
	set iface route default
1129
	set iface {$ondemand} on-demand
1130
	set iface idle {$idle}
1131
	set iface up-script /usr/local/sbin/ppp-linkup
1132

    
1133
EOD;
1134

    
1135
	/*    Check for ppp-linkdown Script in /usr/local/sbin
1136
	 *    Create reference in mpd.conf
1137
	 */
1138
	if ( file_exists("/usr/local/sbin/ppp-linkdown") ){
1139
		$mpdconf .= <<<EOD
1140
	set iface down-script /usr/local/sbin/ppp-linkdown
1141

    
1142
EOD;
1143
	}
1144

    
1145
	if (isset($pppoecfg['ondemand'])) {
1146
		if (isset($pppoecfg['local-ip']) && isset($pppoecfg['remote-ip'])) {
1147
			$mpdconf .= <<<EOD
1148
	set iface addrs {$pppoecfg['local-ip']} {$pppoecfg['remote-ip']}
1149

    
1150
EOD;
1151
		} else {
1152
			$mpdconf .= <<<EOD
1153
	set iface addrs 192.0.2.112 192.0.2.113
1154

    
1155
EOD;
1156
		}
1157
	}
1158

    
1159
	$mpdconf .= <<<EOD
1160
	set bundle disable multilink
1161
	set bundle authname "{$pppoecfg['username']}"
1162
	set bundle password "{$pppoecfg['password']}"
1163
	set bundle no noretry
1164
	set link keep-alive 10 60
1165
	set link max-redial 0
1166
	set link no acfcomp protocomp
1167
	set link disable pap chap
1168
	set link accept chap
1169
	set link mtu 1492
1170
	set ipcp yes vjcomp
1171
	set ipcp ranges 0.0.0.0/0 0.0.0.0/0
1172

    
1173
EOD;
1174

    
1175
	if (isset($config['system']['dnsallowoverride'])) {
1176
		$mpdconf .= <<<EOD
1177
	set ipcp enable req-pri-dns
1178

    
1179
EOD;
1180
	}
1181

    
1182
	if (!isset($config['pppoe']['dnsnosec'])) {
1183
			$mpdconf .= <<<EOD
1184
	set ipcp enable req-sec-dns
1185

    
1186
EOD;
1187
	}
1188
	
1189
	$mpdconf .= <<<EOD
1190
	open iface
1191

    
1192
EOD;
1193

    
1194
	fwrite($fd, $mpdconf);
1195
	fclose($fd);
1196

    
1197
	/* generate mpd.links */
1198
	$fd = fopen("{$g['varetc_path']}/mpd.links", "w");
1199
	if (!$fd) {
1200
		printf("Error: cannot open mpd.links in interfaces_wan_pppoe_configure().\n");
1201
		return 1;
1202
	}
1203

    
1204
	$mpdconf = <<<EOD
1205
pppoe:
1206
	set link type pppoe
1207
	set pppoe iface {$wancfg['if']}
1208
	set pppoe service "{$pppoecfg['provider']}"
1209
	set pppoe enable originate
1210
	set pppoe disable incoming
1211

    
1212
EOD;
1213

    
1214
	fwrite($fd, $mpdconf);
1215
	fclose($fd);
1216

    
1217
	if(file_exists("{$g['varrun_path']}/mpd.pid") and $g['booting']) {
1218
		/* if we are booting and mpd has already been started then don't start again. */
1219
	} else {
1220
		/* if mpd is active, lets take it down */
1221
		if(file_exists("{$g['varrun_path']}/mpd.pid")) {
1222
			killbypid("{$g['varrun_path']}/mpd.pid");
1223
			sleep(3);
1224
		}
1225
		/* fire up mpd */
1226
		mwexec("/usr/local/sbin/mpd -b -d {$g['varetc_path']} -p {$g['varrun_path']}/mpd.pid pppoe");
1227
	}
1228

    
1229
        /* sleep until wan is up - or 30 seconds, whichever comes first */
1230
	for ($count = 0; $count < 30; $count++) {
1231
		if(file_exists("{$g['tmp_path']}/wanup")) {
1232
			break;
1233
		}
1234
		sleep(1);
1235
	}
1236

    
1237
	unlink_if_exists("{$g['tmp_path']}/wanup");
1238

    
1239
	return 0;
1240
}
1241

    
1242
function interfaces_wan_pppoe_restart() {
1243
	interfaces_wan_pppoe_down();
1244
	sleep(1);
1245
	interfaces_wan_pppoe_up();
1246
}
1247

    
1248
function interfaces_wan_pppoe_down() {
1249
	global $g;
1250
	sigkillbypid("{$g['varrun_path']}/mpd.pid", "SIGUSR2");
1251
	sleep(1);
1252
}
1253

    
1254
function interfaces_wan_pppoe_up() {
1255
	global $g;
1256
	sigkillbypid("{$g['varrun_path']}/mpd.pid", "SIGUSR1");
1257
	sleep(1);
1258
}
1259

    
1260
function interfaces_wan_pptp_configure() {
1261
	global $config, $g;
1262

    
1263
	$wancfg = $config['interfaces']['wan'];
1264
	$pptpcfg = $config['pptp'];
1265

    
1266
	/* generate mpd.conf */
1267
	$fd = fopen("{$g['varetc_path']}/mpd.conf", "w");
1268
	if (!$fd) {
1269
		printf("Error: cannot open mpd.conf in interfaces_wan_pptp_configure().\n");
1270
		return 1;
1271
	}
1272

    
1273
	$idle = 0;
1274

    
1275
	if (isset($pptpcfg['ondemand'])) {
1276
		$ondemand = "enable";
1277
		if ($pptpcfg['timeout'])
1278
			$idle = $pptpcfg['timeout'];
1279
	} else {
1280
		$ondemand = "disable";
1281
	}
1282

    
1283
	$mpdconf = <<<EOD
1284
pptp:
1285
	new -i ng0 pptp pptp
1286
	set iface route default
1287
	set iface {$ondemand} on-demand
1288
	set iface idle {$idle}
1289
	set iface up-script /usr/local/sbin/ppp-linkup
1290

    
1291
EOD;
1292

    
1293
	/*   Check for ppp-linkdown Script in /usr/local/sbin
1294
	 *   Create reference in mpd.conf
1295
	 */
1296
	if ( file_exists("/usr/local/sbin/ppp-linkdown") ){
1297
		$mpdconf .= <<<EOD
1298
	set iface down-script /usr/local/sbin/ppp-linkdown
1299

    
1300
EOD;
1301
	}
1302

    
1303
	if (isset($pptpcfg['ondemand'])) {
1304
		$mpdconf .= <<<EOD
1305
	set iface addrs 10.0.0.1 10.0.0.2
1306

    
1307
EOD;
1308
	}
1309

    
1310
	$mpdconf .= <<<EOD
1311
	set bundle disable multilink
1312
	set bundle authname "{$pptpcfg['username']}"
1313
	set bundle password "{$pptpcfg['password']}"
1314
	set link keep-alive 10 60
1315
	set link max-redial 0
1316
	set link no acfcomp protocomp
1317
	set link disable pap chap
1318
	set link accept chap
1319
	set ipcp no vjcomp
1320
	set ipcp ranges 0.0.0.0/0 0.0.0.0/0
1321

    
1322
EOD;
1323
	if (isset($config['system']['dnsallowoverride'])) {
1324
		$mpdconf .= <<<EOD
1325
	set ipcp enable req-pri-dns
1326

    
1327
EOD;
1328
	}
1329

    
1330
	$mpdconf .= <<<EOD
1331
	open
1332

    
1333
EOD;
1334

    
1335
	fwrite($fd, $mpdconf);
1336
	fclose($fd);
1337

    
1338
	/* generate mpd.links */
1339
	$fd = fopen("{$g['varetc_path']}/mpd.links", "w");
1340
	if (!$fd) {
1341
		printf("Error: cannot open mpd.links in interfaces_wan_pptp_configure().\n");
1342
		return 1;
1343
	}
1344

    
1345
	$mpdconf = <<<EOD
1346
pptp:
1347
	set link type pptp
1348
	set pptp enable originate outcall
1349
	set pptp disable windowing
1350
	set pptp self {$pptpcfg['local']}
1351
	set pptp peer {$pptpcfg['remote']}
1352

    
1353
EOD;
1354

    
1355
	fwrite($fd, $mpdconf);
1356
	fclose($fd);
1357

    
1358
	/* configure interface */
1359
	mwexec("/sbin/ifconfig " . escapeshellarg($wancfg['if']) . " " .
1360
		escapeshellarg($pptpcfg['local'] . "/" . $pptpcfg['subnet']));
1361

    
1362
	/* fire up mpd */
1363
	mwexec("/usr/local/sbin/mpd -b -d {$g['varetc_path']} -p {$g['varrun_path']}/mpd.pid pptp");
1364

    
1365
	return 0;
1366
}
1367

    
1368
function interfaces_wan_pptp_restart() {
1369
	interfaces_wan_pptp_down();
1370
	sleep(1);
1371
	interfaces_wan_pptp_up();
1372
}
1373

    
1374
function interfaces_wan_pptp_down() {
1375
	global $g;
1376
	sigkillbypid("{$g['varrun_path']}/mpd.pid", "SIGUSR2");
1377
	sleep(1);
1378
}
1379

    
1380
function interfaces_wan_pptp_up() {
1381
	global $g;
1382
	sigkillbypid("{$g['varrun_path']}/mpd.pid", "SIGUSR1");
1383
	sleep(1);
1384
}
1385

    
1386
function interfaces_wan_bigpond_configure($curwanip) {
1387
	global $config, $g;
1388

    
1389
	$bpcfg = $config['bigpond'];
1390

    
1391
	if (!$curwanip) {
1392
		/* IP address not configured yet, exit */
1393
		return 0;
1394
	}
1395

    
1396
	/* kill bpalogin */
1397
	killbyname("bpalogin");
1398

    
1399
	/* wait a moment */
1400
	sleep(1);
1401

    
1402
	/* get the default domain */
1403
	$nfd = @fopen("{$g['varetc_path']}/defaultdomain.conf", "r");
1404
	if ($nfd) {
1405
		$defaultdomain = trim(fgets($nfd));
1406
		fclose($nfd);
1407
	}
1408

    
1409
	/* generate bpalogin.conf */
1410
	$fd = fopen("{$g['varetc_path']}/bpalogin.conf", "w");
1411
	if (!$fd) {
1412
		printf("Error: cannot open bpalogin.conf in interfaces_wan_bigpond_configure().\n");
1413
		return 1;
1414
	}
1415

    
1416
	if (!$bpcfg['authserver'])
1417
		$bpcfg['authserver'] = "dce-server";
1418
	if (!$bpcfg['authdomain'])
1419
		$bpcfg['authdomain'] = $defaultdomain;
1420

    
1421
	$bpconf = <<<EOD
1422
username {$bpcfg['username']}
1423
password {$bpcfg['password']}
1424
authserver {$bpcfg['authserver']}
1425
authdomain {$bpcfg['authdomain']}
1426
localport 5050
1427

    
1428
EOD;
1429

    
1430
	if ($bpcfg['minheartbeatinterval'])
1431
		$bpconf .= "minheartbeatinterval {$bpcfg['minheartbeatinterval']}\n";
1432

    
1433
	fwrite($fd, $bpconf);
1434
	fclose($fd);
1435

    
1436
	/* fire up bpalogin */
1437
	mwexec("/usr/local/sbin/bpalogin -c {$g['varetc_path']}/bpalogin.conf");
1438

    
1439
	return 0;
1440
}
1441

    
1442
function get_real_wan_interface() {
1443
	global $config, $g;
1444

    
1445
	$wancfg = $config['interfaces']['wan'];
1446

    
1447
	$wanif = $wancfg['if'];
1448
	if (($wancfg['ipaddr'] == "pppoe") || ($wancfg['ipaddr'] == "pptp")) {
1449
		$wanif = $g['pppoe_interface'];
1450
	}
1451

    
1452
	return $wanif;
1453
}
1454

    
1455
function get_current_wan_address($interface = "wan") {
1456
	global $config, $g;
1457

    
1458
	$wancfg = $config['interfaces'][$interface];
1459

    
1460
	$interface = filter_translate_type_to_real_interface($interface);
1461
	$ifinfo = "";
1462
	if(in_array($wancfg['ipaddr'], array('dhcp'))) {
1463
		/* get interface info with netstat */
1464
		exec("/usr/bin/netstat -nWI " . escapeshellarg($interface) . " -f inet", $ifinfo);
1465

    
1466
		if (isset($ifinfo[1])) {
1467
			$aif = preg_split("/\s+/", $ifinfo[1]);
1468
			$curwanip = chop($aif[3]);
1469

    
1470
			if ($curwanip && is_ipaddr($curwanip) && ($curwanip != "0.0.0.0"))
1471
				return $curwanip;
1472
		}
1473

    
1474
		return null;
1475
	} else if (in_array($wancfg['ipaddr'], array('pppoe','pptp','bigpond'))) {
1476
		/* dynamic WAN IP address, find out which one */
1477
		$wanif = get_real_wan_interface();
1478

    
1479
		/* get interface info with netstat */
1480
		exec("/usr/bin/netstat -nWI " . escapeshellarg($wanif) . " -f inet", $ifinfo);
1481

    
1482
		if (isset($ifinfo[1])) {
1483
			$aif = preg_split("/\s+/", $ifinfo[1]);
1484
			$curwanip = chop($aif[3]);
1485

    
1486
			if ($curwanip && is_ipaddr($curwanip) && ($curwanip != "0.0.0.0"))
1487
				return $curwanip;
1488
		}
1489

    
1490
		return null;
1491
	} else {
1492
		/* static WAN IP address */
1493
		return $wancfg['ipaddr'];
1494
	}
1495
}
1496

    
1497
/****f* interfaces/is_altq_capable
1498
 * NAME
1499
 *   is_altq_capable - Test if interface is capable of using ALTQ
1500
 * INPUTS
1501
 *   $int            - string containing interface name
1502
 * RESULT
1503
 *   boolean         - true or false
1504
 ******/
1505

    
1506
function is_altq_capable($int) {
1507
        /* Per:
1508
         * http://www.freebsd.org/cgi/man.cgi?query=altq&manpath=FreeBSD+6.0-current&format=html
1509
         * Only the following drivers have ALTQ support
1510
         */
1511
     	$capable = array("an", "ath", "awi", "bfe", "bge", "dc", "de", "ed",
1512
			"em", "fxp", "hme", "le", "nve", "re", "rl", "ndis", "sf", "sis", "sk",
1513
			"tun", "vr", "wi", "xl", "vlan", "ste", "aue", "bce", "ep", "gem", "ipw", 
1514
			"iwi", "msk", "mxge", "my", "nfe", "npe", "ral", "rum", "stge", "udav", "ural");
1515

    
1516

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

    
1519
        if (in_array($int_family[0], $capable))
1520
                return true;
1521
        else
1522
                return false;
1523
}
1524

    
1525
function get_number_of_vlan_interfaces() {
1526
        $vlans_total = 0;
1527
        $vlans = split("\n", `/sbin/ifconfig -a | /usr/bin/grep vlan | grep flags`);
1528
        foreach($vlans as $bridge) {
1529
                $match_array = "";
1530
                preg_match_all("/vlan(.*):/",$bridge,$match_array);
1531
                if($match_array[1][0] <> "") {
1532
                        if($match_array[1][0] > $vlans_total)
1533
                                $vlans_total = $match_array[1][0];
1534
                }
1535
        }
1536
        return "{$vlans_total}";
1537
}
1538

    
1539
function get_number_of_bridged_interfaces() {
1540

    
1541
	$bridges = split("\n", `/sbin/ifconfig -a | /usr/bin/grep bridge | grep flags`);
1542
	foreach($bridges as $bridge) {
1543
		$match_array = "";
1544
		preg_match_all("/bridge(.*):/",$bridge,$match_array);
1545
		if($match_array[1][0] <> "") {
1546
			if($match_array[1][0] > $bridges_total)
1547
				$bridges_total = $match_array[1][0];
1548
		}
1549
	}
1550
	return "{$bridges_total}";
1551
}
1552

    
1553
function destroy_bridge($bridge_num) {
1554
	mwexec("/sbin/ifconfig bridge{$bridge_num} down");
1555
	sleep(1);
1556
	mwexec("/sbin/ifconfig bridge{$bridge_num} delete");
1557
	sleep(1);
1558
	mwexec("/sbin/ifconfig bridge{$bridge_num} destroy");
1559
	sleep(1);
1560
	return;
1561
}
1562

    
1563
function setup_bridge() {
1564
	global $config, $g;
1565
	$bridge_if_num = -1;
1566
	$bridgearray = array();
1567
	$iflist = array("lan", "wan");
1568
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++)
1569
		if(isset($config['interfaces']['opt' . $i]['enable']))
1570
			$iflist['opt' . $i] = 'opt' . $i;
1571
	foreach($iflist as $if) {
1572
		// go through all interfaces and check for bridged interfaces
1573
		if ($config['interfaces'][$if]['bridge']) {
1574
			// this interface is bridged
1575
			$bridgefound = false;
1576
			if ($bridge_if_num == -1) {
1577
				// this is the first bridge, create the bridge0 interface
1578
				$bridge_if_num++;
1579
				$bridgearray[$bridge_if_num][] = convert_friendly_interface_to_real_interface_name($if);
1580
				$bridgearray[$bridge_if_num][] = convert_friendly_interface_to_real_interface_name($config['interfaces'][$if]['bridge']);
1581
			} else {
1582
				// additional bridge
1583
				// check if interface exists in another bridge
1584
				// since the same int can't be added to two bridges
1585
				$realif = convert_friendly_interface_to_real_interface_name($if);
1586
				$realifbridge = convert_friendly_interface_to_real_interface_name($config['interfaces'][$if]['bridge']);
1587
				for($x=0; $x <= $bridge_if_num; $x++) {
1588
					if (in_array($realif, $bridgearray[$x])) {
1589
						// the interface is already in this bridge
1590
						$bridgefound = true;
1591
						if (!in_array($realifbridge, $bridgearray[$x])) {
1592
							// bridged interface isn't already in this
1593
							// bridge, add it.
1594
							$bridgearray[$bridge_if_num][] = $realifbridge;
1595
						}
1596
					} else {
1597
						// see if the other member interface of the bridge is in existing bridge
1598
						if (in_array($realifbridge, $bridgearray[$x])) {
1599
							$bridgefound = true;
1600
							if (!in_array($realif, $bridgearray[$x])) {
1601
								// if real interface isn't already in
1602
								// this bridge, add it.
1603
								$bridgearray[$bridge_if_num][] = $realif;
1604
							}
1605
						}
1606
					}
1607
				}
1608
				if (!$bridgefound) {
1609
					// the interfaces of this bridge are not contained
1610
					// in any existing bridge. Add new bridge interface.
1611
					$bridge_if_num++;
1612
					$bridgearray[$bridge_if_num][] = convert_friendly_interface_to_real_interface_name($if);
1613
					$bridgearray[$bridge_if_num][] = convert_friendly_interface_to_real_interface_name($config['interfaces'][$if]['bridge']);
1614
				}
1615
			}
1616
		}
1617
	}
1618
	// at this point, $bridgearray is fully populated for the number of bridges the system requires.
1619
	// time to set them up.
1620
	for($x=0; $x <= $bridge_if_num; $x++) {
1621
		// destroy and create ifbridge interface
1622
		mwexec("/sbin/ifconfig bridge{$x} destroy");
1623
		mwexec("/sbin/ifconfig bridge{$x} create");
1624
		// log commands run for debugging in /tmp
1625
		$fd = fopen("{$g['tmp_path']}/bridge{$x}_config", "w");
1626
		fwrite($fd, "/sbin/ifconfig bridge{$x} destroy \n");
1627
		fwrite($fd, "/sbin/ifconfig bridge{$x} create \n");
1628
		$bridgecmd = "/sbin/ifconfig bridge{$x} ";
1629
		$lowestmtu = "1500";
1630
		$wirelessbridge = false;
1631
		// iterate through and see if any of the involved interfaces are wireless or VLANs
1632
		foreach ($bridgearray[$x] as $bridgeif) {
1633
			$friendlyifname = convert_real_interface_to_friendly_interface_name($bridgeif);
1634
			if(is_interface_wireless($friendlyifname))
1635
				$wirelessbridge = true;
1636
		}
1637

    
1638
		$vfaces = array (
1639
				'bridge',
1640
				'ppp',
1641
				'sl',
1642
				'gif',
1643
				'faith',
1644
				'lo',
1645
				'ng',
1646
				'vlan',
1647
				'pflog',
1648
				'pfsync',
1649
				'enc',
1650
				'tun',
1651
				'tap',
1652
				'carp'
1653
		);
1654
		
1655
		foreach ($bridgearray[$x] as $bridgeif) {
1656
			// iterate through all the interfaces in this bridge
1657
			// append to the bridgecmd for this interface
1658
			// only use STP on Ethernet interfaces, not wireless 
1659
			// nor virtual interfaces
1660
			$trimbridgeif = preg_replace("/[0-9]/","", $bridgeif);
1661
			if($wirelessbridge)
1662
				$bridgecmd .= " addm $bridgeif ";
1663
			elseif(in_array($trimbridgeif, $vfaces)) 
1664
				$bridgecmd .= " addm $bridgeif ";
1665
			else
1666
				$bridgecmd .= " addm $bridgeif stp $bridgeif ";
1667
			// get MTU for this interface
1668
			$mtu = get_interface_mtu($bridgeif);
1669
			if (intval($mtu) == 0) {
1670
				log_error("An error occurred while trying to obtain the MTU setting for $bridgeif.  Using 1500.");
1671
				$mtu = "1500";
1672
			} else {
1673
				if (intval($mtu) < intval($lowestmtu))
1674
					$lowestmtu = $mtu;
1675
			}
1676
		}
1677
		
1678
		// force all bridged interfaces to same MTU, the lowest common denominator
1679
		foreach ($bridgearray[$x] as $bridgeif) {
1680
			mwexec("/sbin/ifconfig {$bridgeif} mtu {$lowestmtu}");
1681
			fwrite($fd, "/sbin/ifconfig {$bridgeif} mtu {$lowestmtu} \n");
1682
		}
1683
		
1684
		// bring up each interface
1685
		foreach ($bridgearray[$x] as $bridgeif) {
1686
			mwexec("/sbin/ifconfig {$bridgeif} up");
1687
			fwrite($fd, "/sbin/ifconfig {$bridgeif} up \n");
1688
		}
1689
		
1690
		// setup the bridge
1691
		$bridgecmd .= " up";
1692
		mwexec("{$bridgecmd}");
1693
		fwrite($fd, "{$bridgecmd} \n");
1694
		
1695
		fclose($fd);
1696
	}
1697
}
1698

    
1699
function discover_bridge($interface1, $interface2) {
1700
	if(!$interface1) return;
1701
	if(!$interface2) return;
1702
	$total_bridges = get_number_of_bridged_interfaces();
1703
	$total_bridges++;
1704
	$interfaces = `/sbin/ifconfig -l`;
1705
	$x=0;
1706
	for($x=0; $x<$total_bridges; $x++) {
1707
		$bridge_text = "NA";
1708
		if(!stristr($interfaces, "bridge{$x}"))
1709
			continue;
1710
		$bridge_text = `/sbin/ifconfig bridge{$x} | grep member`;
1711
		if(stristr($bridge_text, $interface1))
1712
			if(stristr($bridge_text, $interface2))
1713
				return $x;
1714
	}
1715
	return "-1";
1716
}
1717

    
1718
function get_wireless_modes($interface)
1719
{
1720
	/* return wireless modes and channels */
1721
	if(is_interface_wireless($interface)) {
1722
		$wi = 1;
1723
		$ifconfig = "/sbin/ifconfig";
1724
		$awk = "/usr/bin/awk";
1725
		$chan_list = "$ifconfig $interface list chan";
1726
		$stack_list = "$awk -F\"Channel \" '{ gsub(/\\*/, \" \"); print \$2 \"\\\n\" \$3 }'";
1727
		$format_list = "$awk '{print \$5 \" \" \$6 \",\" \$1}'";
1728

    
1729
		$interface_channels = "";
1730
		exec("$chan_list | $stack_list | sort -u | $format_list 2>&1", $interface_channels);
1731
		$interface_channel_count = count($interface_channels);
1732

    
1733
		$c = 0;
1734
		while ($c < $interface_channel_count)
1735
		{
1736
			$channel_line = explode(",", $interface_channels["$c"]);
1737
			$wireless_mode = trim($channel_line[0]);
1738
			$wireless_channel = trim($channel_line[1]);
1739
			if(trim($wireless_mode) != "") {
1740
				/* if we only have 11g also set 11b channels */
1741
				if($wireless_mode == "11g") {
1742
					$wireless_modes["11b"] = array();
1743
				}
1744
				$wireless_modes["$wireless_mode"]["$c"] = $wireless_channel;
1745
			}
1746
			$c++;
1747
		}
1748
	}
1749
	return($wireless_modes);
1750
}
1751

    
1752
function get_interface_mac($interface) {
1753

    
1754
        /* build interface list with netstat */
1755
        $linkinfo = "";
1756
        exec("/usr/bin/netstat -I $interface -nW -f link", $linkinfo);
1757
        array_shift($linkinfo);
1758
        $alink = preg_split("/\s+/", $linkinfo[0]);
1759
        $mac = chop($alink[3]);
1760
        return $mac;
1761
}
1762

    
1763
?>
(10-10/27)