Project

General

Profile

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

    
8
	originally part of m0n0wall (http://m0n0.ch/wall)
9
	Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>.
10
	All rights reserved.
11

    
12
	Redistribution and use in source and binary forms, with or without
13
	modification, are permitted provided that the following conditions are met:
14

    
15
	1. Redistributions of source code must retain the above copyright notice,
16
	   this list of conditions and the following disclaimer.
17

    
18
	2. Redistributions in binary form must reproduce the above copyright
19
	   notice, this list of conditions and the following disclaimer in the
20
	   documentation and/or other materials provided with the distribution.
21

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

    
34
/* include all configuration functions */
35
require_once("functions.inc");
36

    
37
if(!is_numeric($bridges_total)) $bridges_total=0;
38

    
39
function interfaces_loopback_configure() {
40
	mwexec("/sbin/ifconfig lo0 127.0.0.1");
41

    
42
	return 0;
43
}
44

    
45
function interfaces_vlan_configure() {
46
	global $config;
47

    
48
	if (is_array($config['vlans']['vlan']) && count($config['vlans']['vlan'])) {
49

    
50
		/* devices with native VLAN support */
51
		$vlan_native_supp = explode(" ", "bge em gx nge ti txp");
52

    
53
		/* devices with long frame support */
54
		$vlan_long_supp = explode(" ", "dc fxp sis ste tl tx xl");
55

    
56
		$i = 0;
57

    
58
		foreach ($config['vlans']['vlan'] as $vlan) {
59

    
60
			$cmd = "/sbin/ifconfig vlan{$i} create vlan " .
61
				escapeshellarg($vlan['tag']) . " vlandev " .
62
				escapeshellarg($vlan['if']);
63

    
64
			/* get driver name */
65
			for ($j = 0; $j < strlen($vlan['if']); $j++) {
66
				if ($vlan['if'][$j] >= '0' && $vlan['if'][$j] <= '9')
67
					break;
68
			}
69
			$drvname = substr($vlan['if'], 0, $j);
70

    
71
			if (in_array($drvname, $vlan_native_supp))
72
				$cmd .= " link0";
73
			else if (in_array($drvname, $vlan_long_supp))
74
				$cmd .= " mtu 1500";
75

    
76
			mwexec($cmd);
77

    
78
			/* make sure the parent interface is up */
79
			mwexec("/sbin/ifconfig " . escapeshellarg($vlan['if']) . " up");
80

    
81
			$i++;
82
		}
83
	}
84

    
85
	return 0;
86
}
87

    
88
function interfaces_lan_configure() {
89
	global $config, $g, $bridges_total;
90

    
91
	$lancfg = $config['interfaces']['lan'];
92

    
93
	/* wireless configuration? */
94
	if (is_array($lancfg['wireless']))
95
		interfaces_wireless_configure($lancfg['if'], $lancfg['wireless']);
96

    
97
	/* MAC spoofing? */
98
	if ($lancfg['spoofmac']) {
99
		mwexec("/sbin/ifconfig " . escapeshellarg($lancfg['if']) .
100
			" link " . escapeshellarg($lancfg['spoofmac']));
101
	} else {
102
		$mac = get_interface_mac_address($lancfg['if']);
103
		if($mac == "ff:ff:ff:ff:ff:ff") {
104
			/*   this is not a valid mac address.  generate a
105
			 *   temporary mac address so the machine can get online.
106
			 */
107
			echo "Generating new MAC address.";
108
			$random_mac = generate_random_mac_address();
109
			mwexec("/sbin/ifconfig " . escapeshellarg($lancfg['if']) .
110
				" link " . escapeshellarg($random_mac));
111
			$lancfg['spoofmac'] = $random_mac;
112
			write_config();
113
			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");
114
		}
115
	}	
116

    
117
	/* bridged? */
118
	
119
	if ($lancfg['bridge']) {
120
		// mwexec("/sbin/ifconfig " . escapeshellarg($lancfg['if']) . " delete up");
121
		/* use open/netBSD style bridge */
122
		mwexec("/sbin/ifconfig bridge{$bridges_total} create");
123
		mwexec("/sbin/ifconfig bridge{$bridges_total} addm {$lancfg['if']} addm {$config['interfaces'][$lancfg['bridge']]['if']} up");
124
		mwexec("/sbin/ifconfig bridge{$bridges_total} stp {$lancfg['if']} add {$config['interfaces'][$lancfg['bridge']]['if']}");
125
		
126
		$fd = fopen("{$g['tmp_path']}/bridge_config_{$lancfg['if']}", "w");
127
		fwrite($fd, "/sbin/ifconfig bridge{$bridges_total} create\n");
128
		fwrite($fd, "/sbin/ifconfig bridge{$bridges_total} addm {$lancfg['if']} addm {$config['interfaces'][$lancfg['bridge']]['if']} up\n");
129
		fwrite($fd, "/sbin/ifconfig bridge{$bridges_total} stp {$lancfg['if']} add {$config['interfaces'][$lancfg['bridge']]['if']}\n");
130
		fclose($fd);
131
		
132
		/* lets keep track of the amount of bridges initialized */
133
		$bridges_total++;
134
	}
135
	
136
	/* media */
137
	if ($lancfg['media'] || $lancfg['mediaopt']) {
138
		$cmd = "/sbin/ifconfig " . escapeshellarg($lancfg['if']);
139
		if ($lancfg['media'])
140
			$cmd .= " media " . escapeshellarg($lancfg['media']);
141
		if ($lancfg['mediaopt'])
142
			$cmd .= " mediaopt " . escapeshellarg($lancfg['mediaopt']);
143
		mwexec($cmd);
144
	}
145

    
146
	mwexec("/sbin/ifconfig " . escapeshellarg($lancfg['if']) . " " .
147
		escapeshellarg($lancfg['ipaddr'] . "/" . $lancfg['subnet']));
148

    
149
	if (!$g['booting']) {
150
		/* make new hosts file */
151
		system_hosts_generate();
152

    
153
		/* reconfigure static routes (kernel may have deleted them) */
154
		system_routing_configure();
155

    
156
		/* set the reload filter dity flag */
157
		touch("{$g['tmp_path']}/filter_dirty");
158

    
159
		/* reload IPsec tunnels */
160
		vpn_ipsec_configure();
161

    
162
		/* reload dhcpd (gateway may have changed) */
163
		services_dhcpd_configure();
164

    
165
		/* reload dnsmasq */
166
		services_dnsmasq_configure();
167

    
168
		/* reload webgui */
169
		system_webgui_start();
170

    
171
		/* reload captive portal */
172
		captiveportal_configure();
173
	}
174

    
175
	return 0;
176
}
177

    
178
function interfaces_optional_configure() {
179
	global $config, $g;
180
	global $bridgeconfig;
181

    
182
	/* Reset bridge configuration.	Interfaces will add to it. */
183
	$bridgeconfig = "";
184

    
185
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++) {
186
		interfaces_optional_configure_if($i);
187
	}
188

    
189
	if (!$g['booting']) {
190
		/* reconfigure static routes (kernel may have deleted them) */
191
		system_routing_configure();
192

    
193
		/* reload IPsec tunnels */
194
		vpn_ipsec_configure();
195

    
196
		/* reload dhcpd (interface enabled/disabled/bridged status may have changed) */
197
		services_dhcpd_configure();
198

    
199
		/* restart dnsmasq */
200
		services_dnsmasq_configure();
201

    
202
		/* set the reload filter dity flag */
203
		touch("{$g['tmp_path']}/filter_dirty");				
204
	}
205

    
206
	return 0;
207
}
208

    
209
function interfaces_optional_configure_if($opti) {
210
	global $config, $g;
211
	global $bridgeconfig;
212
	global $bridges_total;
213

    
214
	$optcfg = $config['interfaces']['opt' . $opti];
215

    
216
	if ($g['booting']) {
217
		$optdescr = "";
218
		if ($optcfg['descr'])
219
			$optdescr = " ({$optcfg['descr']})";
220
		print "\tOPT{$opti}{$optdescr}... ";
221
		mute_kernel_msgs();
222
	}
223

    
224
	if (isset($optcfg['enable'])) {
225
		/* wireless configuration? */
226
		if (is_array($optcfg['wireless']))
227
			interfaces_wireless_configure($optcfg['if'], $optcfg['wireless']);
228

    
229
		/* MAC spoofing? */
230
		if ($optcfg['spoofmac']) {
231
			mwexec("/sbin/ifconfig " . escapeshellarg($optcfg['if']) .
232
				" link " . escapeshellarg($optcfg['spoofmac']));
233
		} else {
234
			$mac = get_interface_mac_address($optcfg['if']);
235
			if($mac == "ff:ff:ff:ff:ff:ff") {
236
				/*   this is not a valid mac address.  generate a
237
				 *   temporary mac address so the machine can get online.
238
				 */
239
				echo "Generating new MAC address.";
240
				$random_mac = generate_random_mac_address();
241
				mwexec("/sbin/ifconfig " . escapeshellarg($optcfg['if']) .
242
					" link " . escapeshellarg($random_mac));
243
				$optcfg['spoofmac'] = $random_mac;
244
				write_config();
245
				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");
246
			}
247
		}
248

    
249
		/* media */
250
		if ($optcfg['media'] || $optcfg['mediaopt']) {
251
			$cmd = "/sbin/ifconfig " . escapeshellarg($optcfg['if']);
252
			if ($optcfg['media'])
253
				$cmd .= " media " . escapeshellarg($optcfg['media']);
254
			if ($optcfg['mediaopt'])
255
				$cmd .= " mediaopt " . escapeshellarg($optcfg['mediaopt']);
256
			mwexec($cmd);
257
		}
258

    
259
		/* OpenVPN configuration? */
260
 		if (isset($optcfg['ovpn'])) {
261
 			if (strstr($optcfg['if'], "tap"))
262
 				ovpn_link_tap();
263
 		}
264

    
265
		/* bridged? */
266
		if ($optcfg['bridge']) {
267
			mwexec("/sbin/ifconfig " . escapeshellarg($optcfg['if']) . " delete up");
268
                        /* use open/netBSD style bridge */
269
			mwexec("/sbin/ifconfig bridge{$bridges_total} create");
270
                        mwexec("/sbin/ifconfig bridge{$bridges_total} addm {$optcfg['if']} addm {$config['interfaces'][$optcfg['bridge']]['if']} up");
271
			mwexec("/sbin/ifconfig bridge{$bridges_total} stp {$optcfg['if']} add {$config['interfaces'][$optcfg['bridge']]['if']}");
272
			
273
			$fd = fopen("{$g['tmp_path']}/bridge_config_{$optcfg['if']}", "w");
274
			fwrite($fd, "/sbin/ifconfig bridge{$bridges_total} create\n");
275
			fwrite($fd, "/sbin/ifconfig bridge{$bridges_total} addm {$optcfg['if']} addm {$config['interfaces'][$optcfg['bridge']]['if']} up\n");
276
			fwrite($fd, "/sbin/ifconfig bridge{$bridges_total} stp {$optcfg['if']} add {$config['interfaces'][$optcfg['bridge']]['if']}\n");
277
			fclose($fd);
278
			
279
			/* lets keep track of the amount of bridges initialized */
280
			$bridges_total++;
281
		} else {
282
			/* if user has selected DHCP type then act accordingly */
283
			if($optcfg['ipaddr'] == "dhcp") {
284
				interfaces_opt_dhcp_configure("opt{$opti}");
285
			} else {			
286
				mwexec("/sbin/ifconfig " . escapeshellarg($optcfg['if']) . " " .
287
				escapeshellarg($optcfg['ipaddr'] . "/" . $optcfg['subnet']));
288
			}
289
		}
290
	} else {
291
		mwexec("/sbin/ifconfig " . escapeshellarg($optcfg['if']) . " delete down");
292
	}
293

    
294
	return 0;
295
}
296

    
297
function interfaces_carp_configure() {
298
	global $g, $config;
299
	if ($g['booting']) {
300
		echo "Configuring CARP interfaces...";
301
		mute_kernel_msgs();
302
	}
303
	unlink_if_exists("/usr/local/etc/rc.d/carp.sh");
304
	unlink_if_exists("/usr/local/pkg/pf/carp.sh");
305
	unlink_if_exists("/usr/local/pkg/pf/carp_rules.sh");
306
	$carp_instances_counter = 0;
307
	$pfsync_instances_counter = 0;
308
	$total_carp_interfaces_defined = find_number_of_created_carp_interfaces();
309
	if (is_array($config['virtualip']['vip'])) {
310
		if(is_array($config['installedpackages']['carpsettings']['config'])) {
311
			foreach($config['installedpackages']['carpsettings']['config'] as $carp)
312
			if($carp['pfsyncenabled'] != "") {
313
				if($carp['premption'] != "")
314
				mwexec("/sbin/sysctl net.inet.carp.preempt=1");
315
				if($carp['balancing'] != "")
316
				mwexec("/sbin/sysctl net.inet.arpbalance=1");
317
				$carp_sync_int = convert_friendly_interface_to_real_interface_name($carp['pfsyncinterface']);
318
				mwexec("/sbin/ifconfig pfsync0 create");
319
				mwexec("/sbin/ifconfig pfsync0 syncdev " . $carp_sync_int);
320
				mwexec("/sbin/ifconfig pfsync0 syncif " . $carp_sync_int);
321
				mwexec("/sbin/ifconfig {$carp_sync_int} up");
322
				mwexec("/sbin/ifconfig pfsync0 up");
323
				if($g['booting']) {
324
					/* install rules to alllow pfsync to sync up during boot
325
					* carp interfaces will remain down until the bootup sequence finishes
326
					*/
327
					exec("echo pass quick proto carp all keep state > /tmp/rules.boot");
328
					exec("echo pass quick proto pfsync all >> /tmp/rules.boot");
329
					exec("echo pass out proto { tcp, udp } from any to any port 53 keep state >> /tmp/rules.boot");
330
					exec("/sbin/pfctl -f /tmp/rules.boot");
331
				}
332
				$pfsync_instances_counter++;
333
			}
334
		}
335
		$viparr = &$config['virtualip']['vip'];
336
		foreach ($viparr as $vip) {
337
			if ($vip['mode'] == "carp") {
338
				/*
339
				*  create the carp interface
340
				*/
341
				mwexec("/sbin/ifconfig carp" . $carp_instances_counter . " create");
342
				mwexec("/sbin/ifconfig carp" . $carp_instances_counter . " down");
343
				$broadcast_address = gen_subnet_max($vip['subnet'], $vip['subnet_bits']);
344
				if($vip['password'] != "") {
345
					$password = " pass " . $vip['password'];
346
				}
347
				/* XXX: billm - carpdev not in our build?
348
				$carpdev = "";
349
				if(isset($vip['interface']) && ($vip['interface'] != "AUTO" && $vip['interface'] != "")) {
350
					$ci = filter_opt_interface_to_real($vip['interface']);
351
					$carpdev = " carpdev {$ci} ";
352
				}
353
				*/
354
				mwexec("/sbin/ifconfig carp" . $carp_instances_counter . " " . $vip['subnet'] . "/" . $vip['subnet_bits'] . " broadcast " . $broadcast_address . " vhid " . $vip['vhid'] . "{$carpdev} advskew " . $vip['advskew'] . $password);
355
				$carp_instances_counter++;
356
			}
357
		}
358
	} else {
359
		/* hush little pfsync, don't say a word.  GeekGod's gonna
360
		   buy you a mocking bird. */
361
		mwexec("/sbin/ifconfig pfsync0 syncdev lo0 up");
362
	}	
363
	/* remove any dangling carp references */
364
	for($x=$carp_instances_counter; $x<$total_carp_interfaces_defined; $x++) {
365
		mwexec("/sbin/ifconfig carp{$x} down");
366
		mwexec("/sbin/ifconfig carp{$x} destroy");
367
	}
368
	unmute_kernel_msgs();
369
	if ($g['booting']) {
370
		unmute_kernel_msgs();
371
		echo "done.\n";
372
	}
373
}
374

    
375
function interfaces_carp_bringup() {
376
	global $g;
377
	/* lets bring the carp interfaces up now */
378
	if ($g['booting'])
379
		sleep(1);
380
	$carp_ints = find_number_of_created_carp_interfaces();
381
	for($x=0; $x<$carp_ints; $x++)
382
		mwexec("/sbin/ifconfig carp{$x} up");	
383
}
384

    
385
function interfaces_wireless_configure($if, $wlcfg) {
386
        global $config, $g;
387
	
388
	/*   set wireless channel value.  if we're using 0 then
389
	 *   convert the channel to -
390
	 */
391
	$channel = escapeshellarg($wlcfg['channel']);
392
	if($channel == "") 
393
		$channel = "";
394

    
395
        /* wireless configuration */
396
        $ifcargs = escapeshellarg($if) .
397
                " ssid " . escapeshellarg($wlcfg['ssid']) . " channel {$channel} ";
398

    
399
        if ($wlcfg['stationname'])
400
                $ifcargs .= "stationname " . escapeshellarg($wlcfg['stationname']) . " ";
401
	
402
	if(!$wlcfg['mode']) {
403
		if (isset($wlcfg['wpa']['enable'])) {
404
		
405
	$wpa .= <<<EOD
406
	
407
ctrl_interface_group=0
408
eapol_version=1
409
ap_scan=1
410
fast_reauth=1
411

    
412
network={
413
	ssid="{$wlcfg['ssid']}"
414
	key_mgmt="{$wlcfg['wpapsk']}"
415
	psk="{$wlcfg['passphrase']}"
416
	
417
}
418

    
419
EOD;
420

    
421
		$fd = fopen("{$g['etc_path']}/ifconfig_{$if}", "w");
422
		fwrite($fd, "{$wpa}");
423
		fclose($fd);
424
		mwexec_bg("wpa_supplicant -i {$if} -c /etc/wpa_supplicant.conf");
425

    
426
		}
427
	}
428

    
429
        if (isset($wlcfg['wep']['enable']) && is_array($wlcfg['wep']['key'])) {
430
                $ifcargs .= "wepmode on ";
431

    
432
                $i = 1;
433
                foreach ($wlcfg['wep']['key'] as $wepkey) {
434
                        $ifcargs .= "wepkey " . escapeshellarg("{$i}:{$wepkey['value']}") . " ";
435
                        if (isset($wepkey['txkey'])) {
436
                                $ifcargs .= "weptxkey {$i} ";
437
                        }
438
                        $i++;
439
                }
440
        } else {
441
                $ifcargs .= "wepmode off ";
442
        }
443

    
444
	if(isset($wlcfg['pureg'])) {
445
		$ifcargs .= "mode 11g ";
446
	} else {
447
		if (preg_match($g['wireless_regex'], $if)) {
448
			if ($wlcfg['standard'])
449
				$ifcargs .= "mode {$wlcfg['standard']} ";
450
		}
451
	}
452

    
453
        switch ($wlcfg['mode']) {
454
                case 'hostap':
455
                        if (preg_match($g['wireless_regex'], $if)) 
456
                                $ifcargs .= "-mediaopt adhoc mediaopt hostap ";
457
                        else if (strstr($if, "wi"))
458
                                $ifcargs .= "-mediaopt ibss mediaopt hostap ";
459
				if (isset($wlcfg['wpa']['enable'])) {
460
$wpa .= <<<EOD
461

    
462
interface={$if}
463
driver=bsd
464
logger_syslog=-1
465
logger_syslog_level=0
466
logger_stdout=-1
467
logger_stdout_level=0
468
debug=4
469
dump_file=/tmp/hostapd.dump
470
ctrl_interface=/var/run/hostapd
471
ctrl_interface_group=wheel
472
ssid={$wlcfg['ssid']}
473
macaddr_acl=1
474
auth_algs=3
475
eapol_key_index_workaround=0
476
wpa=1
477
wpa_key_mgmt={$wlcfg['wpapsk']}
478
wpa_pairwise=CCMP
479
wpa_group_rekey=60
480
wpa_gmk_rekey=3600
481
wpa_passphrase={$wlcfg['passphrase']}
482

    
483
EOD;
484
					$fd = fopen("{$g['etc_path']}/hostapd_{$if}.conf", "w");
485
					fwrite($fd, "{$wpa}");
486
					fclose($fd);
487
					if(is_process_running("hostapd")) {
488
						mwexec("/usr/bin/killall -HUP hostapd");
489
					} else {
490
						mwexec("/usr/sbin/hostapd -B {$g['etc_path']}/hostapd_{$if}.conf");
491
					}
492
				}				
493
				
494
                        break;
495
                case 'ibss':
496
                case 'IBSS':
497
                        if (preg_match($g['wireless_regex'], $if)) 
498
                                $ifcargs .= "-mediaopt hostap mediaopt adhoc ";
499
                        else if (strstr($if, "wi"))
500
                                $ifcargs .= "-mediaopt hostap mediaopt ibss ";
501
                        else if (strstr($if, "an"))
502
                                $ifcargs .= "mediaopt adhoc ";
503
                        break;
504
                case 'bss':
505
                case 'BSS':
506
                        if (preg_match($g['wireless_regex'], $if)) 
507
                                $ifcargs .= "-mediaopt hostap -mediaopt adhoc ";
508
                        else if (strstr($if, "wi"))
509
                                $ifcargs .= "-mediaopt hostap -mediaopt ibss ";
510
                        else if (strstr($if, "an"))
511
                                $ifcargs .= "-mediaopt adhoc ";
512
                        break;
513
        }
514
	
515
	/*   extra options during hostap mode
516
	 */
517
	if($wlcfg['mode'] == "hostap") {
518
		/* handle hide ssid option */
519
		if(isset($wlcfg['hidessid']))
520
			$ifcargs .= "hidessid ";
521
		else
522
			$ifcargs .= "-hidessid ";
523
		/* handle pureg (802.11g) only option */
524
		if(isset($wlcfg['pureg']))
525
			$ifcargs .= "pureg ";
526
		else
527
			$ifcargs .= "-pureg ";
528
	}
529

    
530
        $ifcargs .= "up";
531

    
532
        mwexec("/sbin/ifconfig " . $ifcargs);
533

    
534
	$fd = fopen("{$g['tmp_path']}/ifconfig_wireless", "w");
535
	fwrite($fd, "/sbin/ifconfig {$ifcargs}");
536
	fclose($fd);
537
	
538
	if($wlcfg['txpower'] <> "")
539
		mwexec("/sbin/ifconfig {$ifcargs} txpower {$wlcfg['txpower']}");
540
	
541
	if(isset($wlcfg['useolsr']))
542
		setup_wireless_olsr(escapeshellarg($if));
543
	
544
        return 0;
545

    
546
}
547

    
548
function find_dhclient_process($interface) {
549
	if(filter_translate_type_to_real_interface($interface) <> "")
550
        	$realinterface = filter_translate_type_to_real_interface($interface);
551
	$pid = `ps ax | grep "[d]hclient" | grep {$realinterface} | awk -F" " '{print $1}'`;
552
	return $pid;
553
}
554

    
555
function interfaces_wan_configure() {
556
	global $config, $g;
557

    
558
	$wancfg = $config['interfaces']['wan'];
559

    
560
	if(!$g['booting']) {
561
		mute_kernel_msgs();
562

    
563
		/* find dhclient process for wan and kill it */
564
		killbypid(find_dhclient_process("wan"));
565

    
566
		/* kill PPPoE client (mpd) */
567
		killbypid("{$g['varrun_path']}/mpd.pid");
568

    
569
		/* wait for processes to die */
570
		sleep(1);
571

    
572
		unlink_if_exists("{$g['varetc_path']}/dhclient_wan.conf");
573
		unlink_if_exists("{$g['varetc_path']}/mpd.conf");
574
		unlink_if_exists("{$g['varetc_path']}/mpd.links");
575
		unlink_if_exists("{$g['vardb_path']}/wanip");
576
		unlink_if_exists("{$g['varetc_path']}/nameservers.conf");
577
	}
578

    
579
	/* remove all addresses first */
580
	while (mwexec("/sbin/ifconfig " . escapeshellarg($wancfg['if']) . " -alias") == 0);
581
	mwexec("/sbin/ifconfig " . escapeshellarg($wancfg['if']) . " down");
582

    
583
	/* wireless configuration? */
584
	if (is_array($wancfg['wireless']))
585
		interfaces_wireless_configure($wancfg['if'], $wancfg['wireless']);
586

    
587
	if ($wancfg['spoofmac']) {
588
		mwexec("/sbin/ifconfig " . escapeshellarg($wancfg['if']) .
589
			" link " . escapeshellarg($wancfg['spoofmac']));
590
	}  else {
591
		$mac = get_interface_mac_address($wancfg['if']);
592
		if($mac == "ff:ff:ff:ff:ff:ff") {
593
			/*   this is not a valid mac address.  generate a
594
			 *   temporary mac address so the machine can get online.
595
			 */
596
			echo "Generating new MAC address.";
597
			$random_mac = generate_random_mac_address();
598
			mwexec("/sbin/ifconfig " . escapeshellarg($wancfg['if']) .
599
				" link " . escapeshellarg($random_mac));
600
			$wancfg['spoofmac'] = $random_mac;
601
			write_config();
602
			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");
603
		}
604
	}
605

    
606
	/* media */
607
	if ($wancfg['media'] || $wancfg['mediaopt']) {
608
		$cmd = "/sbin/ifconfig " . escapeshellarg($wancfg['if']);
609
		if ($wancfg['media'])
610
			$cmd .= " media " . escapeshellarg($wancfg['media']);
611
		if ($wancfg['mediaopt'])
612
			$cmd .= " mediaopt " . escapeshellarg($wancfg['mediaopt']);
613
		mwexec($cmd);
614
	}
615

    
616
	switch ($wancfg['ipaddr']) {
617

    
618
		case 'dhcp':
619
			interfaces_wan_dhcp_configure();
620
			break;
621

    
622
		case 'pppoe':
623
			interfaces_wan_pppoe_configure();
624
			break;
625

    
626
		case 'pptp':
627
			interfaces_wan_pptp_configure();
628
			break;
629

    
630
		case 'bigpond':
631
			/* just configure DHCP for now; fire up bpalogin when we've got the lease */
632
			interfaces_wan_dhcp_configure();
633
			break;
634

    
635
		default:
636
			if (isset($wancfg['ispointtopoint']) && $wancfg['pointtopoint']) {
637
				mwexec("/sbin/ifconfig " . escapeshellarg($wancfg['if']) . " " .
638
					escapeshellarg($wancfg['ipaddr'] . "/" . $wancfg['subnet']) .
639
					" " . escapeshellarg($wancfg['pointtopoint']) . " up");
640
			} else {
641
				mwexec("/sbin/ifconfig " . escapeshellarg($wancfg['if']) . " " .
642
					escapeshellarg($wancfg['ipaddr'] . "/" . $wancfg['subnet']));
643
			}
644
			/* install default route */
645
			mwexec("/sbin/route delete default");
646
			mwexec("/sbin/route add default " . escapeshellarg($config['system']['gateway']));
647

    
648
			/* resync pf (done automatically for DHCP/PPPoE/PPTP) */
649
			filter_configure();
650
	}
651

    
652
	if (!$g['booting']) {
653
		/* reconfigure static routes (kernel may have deleted them) */
654
		system_routing_configure();
655

    
656
		/* set the reload filter dity flag */
657
		touch("{$g['tmp_path']}/filter_dirty");
658

    
659
		/* reload ipsec tunnels */
660
		vpn_ipsec_configure();
661

    
662
		/* restart ez-ipupdate */
663
		services_dyndns_configure();
664

    
665
		/* force DNS update */
666
		services_dnsupdate_process();
667

    
668
		/* restart dnsmasq */
669
		services_dnsmasq_configure();
670
	}
671

    
672
	unmute_kernel_msgs();
673

    
674
	return 0;
675
}
676

    
677
function interfaces_opt_dhcp_configure($interface) {
678
	global $config, $g;
679

    
680
	$optcfg = $config['interfaces'][$interface];
681
	$optif = $optcfg['if'];
682

    
683
	/* generate dhclient_wan.conf */
684
	$fd = fopen("{$g['varetc_path']}/dhclient_{$optif}.conf", "w");
685
	if (!$fd) {
686
		printf("Error: cannot open dhclient_{$optif}.conf in interfaces_opt_dhcp_configure({$optif}) for writing.\n");
687
		return 1;
688
	}
689

    
690
	if ($optcfg['dhcphostname']) {
691
		$dhclientconf_hostname = "send dhcp-client-identifier \"{$optcfg['dhcphostname']}\";\n";
692
		$dhclientconf_hostname = "	send dhcp-client-identifier \"{$optcfg['dhcphostname']}\";\n";
693
	} else {
694
		$dhclientconf_hostname = "";
695
	}
696

    
697
 	$dhclientconf = "";
698

    
699
	$dhclientconf .= <<<EOD
700
interface "{$optif}" {
701
	send host-name "{$optcfg['dhcphostname']}";
702
	script "/sbin/dhclient-script";
703
	{$dhclientconf_hostname}
704
}
705

    
706
EOD;
707

    
708
	fwrite($fd, $dhclientconf);
709
	fclose($fd);
710

    
711
        /* bring interface up before starting dhclient */
712
        mwexec("/sbin/ifconfig {$optif} up");
713

    
714
        /* fire up dhclient */
715
        mwexec_bg("/sbin/dhclient -d -c {$g['varetc_path']}/dhclient_{$optif}.conf {$optif}");
716

    
717
	return 0;
718
}
719

    
720
function interfaces_dhcp_configure($interface) {
721
	global $config, $g;
722

    
723
	if(filter_translate_type_to_real_interface($interface) <> "")
724
        	$realinterface = filter_translate_type_to_real_interface($interface);
725

    
726
	$optcfg = $config['interfaces'][$interface];
727

    
728
	/* generate dhclient_$interface.conf */
729
	$fd = fopen("{$g['varetc_path']}/dhclient_{$interface}.conf", "w");
730
	if (!$fd) {
731
		printf("Error: cannot open dhclient_{$interface}.conf in interfaces_dhcp_configure({$$interface}) for writing.\n");
732
		return 1;
733
	}
734

    
735
	if ($optcfg['dhcphostname']) {
736
		$dhclientconf_hostname = "send dhcp-client-identifier \"{$optcfg['dhcphostname']}\";\n";
737
		$dhclientconf_hostname = "	send dhcp-client-identifier \"{$optcfg['dhcphostname']}\";\n";
738
	} else {
739
		$dhclientconf_hostname = "";
740
	}
741

    
742
 	$dhclientconf = "";
743

    
744
	$dhclientconf .= <<<EOD
745
interface "{$realinterface}" {
746
	script "/sbin/dhclient-script";
747
	{$dhclientconf_hostname}
748
}
749

    
750
EOD;
751

    
752
	fwrite($fd, $dhclientconf);
753
	fclose($fd);
754
	
755
	$optif = $optcfg['if'];
756
	
757
        /* bring wan interface up before starting dhclient */
758
        mwexec("/sbin/ifconfig {$optif} up");
759

    
760
        /* fire up dhclient */
761
        mwexec_bg("/sbin/dhclient -d -c {$g['varetc_path']}/dhclient_{$optif}.conf {$optif} >/tmp/{$optif}_output >/tmp/{$optif}_error_output");
762

    
763
	$fout = fopen("/tmp/ifconfig_{$optif}","w");
764
	fwrite($fout, "/sbin/dhclient -d -c {$g['varetc_path']}/dhclient_{$optif}.conf {$optif}");
765
	fclose($fout);
766

    
767
	return 0;
768
}
769

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

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

    
775
	/* generate dhclient_wan.conf */
776
	$fd = fopen("{$g['varetc_path']}/dhclient_wan.conf", "w");
777
	if (!$fd) {
778
		printf("Error: cannot open dhclient_wan.conf in interfaces_wan_dhcp_configure() for writing.\n");
779
		return 1;
780
	}
781
	
782
	if ($wancfg['dhcphostname']) {
783
		$dhclientconf_hostname = "send dhcp-client-identifier \"{$wancfg['dhcphostname']}\";\n";
784
		$dhclientconf_hostname = "	send dhcp-client-identifier \"{$wancfg['dhcphostname']}\";\n";
785
	} else {
786
		$dhclientconf_hostname = "";
787
	}
788

    
789
 	$dhclientconf = "";
790

    
791
	$dhclientconf .= <<<EOD
792
interface "{$wancfg['if']}" {
793
	script "/sbin/dhclient-script";
794
	{$dhclientconf_hostname}
795
}
796

    
797
EOD;
798

    
799
	fwrite($fd, $dhclientconf);
800
	fclose($fd);
801
	
802
	$wanif = $wancfg['if'];
803
	
804
        /* bring wan interface up before starting dhclient */
805
        mwexec("/sbin/ifconfig {$wanif} up");
806

    
807
        /* fire up dhclient */
808
        mwexec_bg("/sbin/dhclient -d -c {$g['varetc_path']}/dhclient_wan.conf {$wanif} >/tmp/{$wanif}_output >/tmp/{$wanif}_error_output");
809

    
810
	$fout = fopen("/tmp/ifconfig_{$wanif}","w");
811
	fwrite($fout, "/sbin/dhclient -d -c {$g['varetc_path']}/dhclient_wan.conf {$wanif}");
812
	fclose($fout);
813

    
814
	return 0;
815
}
816

    
817
function interfaces_wan_dhcp_down() {
818
	global $config;
819
	$wancfg = $config['interfaces']['wan'];
820
	$wanif = $wancfg['if'];
821
	mwexec("/sbin/ifconfig {$wanif} delete");
822
	sleep(1);
823
}
824

    
825
function interfaces_dhcp_down($interface) {
826
	global $config;
827
	if(filter_translate_type_to_real_interface($interface) <> "")
828
		$realinterface = filter_translate_type_to_real_interface($interface);
829
	mwexec("/sbin/ifconfig {$realinterface} down");
830
	sleep(1);
831
	$pid = find_dhclient_process($interface);
832
	if($pid)
833
		mwexec("kill {$pid}");
834
}
835

    
836
function interfaces_dhcp_up($interface) {
837
	interfaces_dhcp_configure($interface);
838
	sleep(1);
839
}
840

    
841
function interfaces_wan_dhcp_up() {
842
	interfaces_wan_dhcp_configure();
843
	sleep(1);
844
}
845

    
846
function interfaces_wan_pppoe_configure() {
847
	global $config, $g;
848

    
849
	$wancfg = $config['interfaces']['wan'];
850
	$pppoecfg = $config['pppoe'];
851

    
852
	/* generate mpd.conf */
853
	$fd = fopen("{$g['varetc_path']}/mpd.conf", "w");
854
	if (!$fd) {
855
		printf("Error: cannot open mpd.conf in interfaces_wan_pppoe_configure().\n");
856
		return 1;
857
	}
858

    
859
	$idle = 0;
860

    
861
	if (isset($pppoecfg['ondemand'])) {
862
		$ondemand = "enable";
863
		if ($pppoecfg['timeout'])
864
			$idle = $pppoecfg['timeout'];
865
	} else {
866
		$ondemand = "disable";
867
	}
868

    
869
	$mpdconf = <<<EOD
870
pppoe:
871
	new -i ng0 pppoe pppoe
872
	set iface route default
873
	set iface {$ondemand} on-demand
874
	set iface idle {$idle}
875
	set iface up-script /usr/local/sbin/ppp-linkup
876

    
877
EOD;
878

    
879
	if (isset($pppoecfg['ondemand'])) {
880
		$mpdconf .= <<<EOD
881
	set iface addrs 10.0.0.1 10.0.0.2
882

    
883
EOD;
884
	}
885

    
886
	$mpdconf .= <<<EOD
887
	set bundle disable multilink
888
	set bundle authname "{$pppoecfg['username']}"
889
	set bundle password "{$pppoecfg['password']}"
890
	set link keep-alive 10 60
891
	set link max-redial 0
892
	set link no acfcomp protocomp
893
	set link disable pap chap
894
	set link accept chap
895
	set link mtu 1492
896
	set ipcp yes vjcomp
897
	set ipcp ranges 0.0.0.0/0 0.0.0.0/0
898

    
899
EOD;
900

    
901
	if (isset($config['system']['dnsallowoverride'])) {
902
		$mpdconf .= <<<EOD
903
	set ipcp enable req-pri-dns
904

    
905
EOD;
906
	}
907

    
908
	$mpdconf .= <<<EOD
909
	open iface
910

    
911
EOD;
912

    
913
	fwrite($fd, $mpdconf);
914
	fclose($fd);
915

    
916
	/* generate mpd.links */
917
	$fd = fopen("{$g['varetc_path']}/mpd.links", "w");
918
	if (!$fd) {
919
		printf("Error: cannot open mpd.links in interfaces_wan_pppoe_configure().\n");
920
		return 1;
921
	}
922

    
923
	$mpdconf = <<<EOD
924
pppoe:
925
	set link type pppoe
926
	set pppoe iface {$wancfg['if']}
927
	set pppoe service "{$pppoecfg['provider']}"
928
	set pppoe enable originate
929
	set pppoe disable incoming
930

    
931
EOD;
932

    
933
	fwrite($fd, $mpdconf);
934
	fclose($fd);
935

    
936
	/* if mpd is active, lets take it down */
937
	if(file_exists("{$g['varrun_path']}/mpd.pid")) {
938
		killbypid(file_get_contents("{$g['varrun_path']}/mpd.pid"));
939
		sleep(3);
940
	}
941

    
942
	/* fire up mpd */
943
	mwexec("/usr/local/sbin/mpd -b -d {$g['varetc_path']} -p {$g['varrun_path']}/mpd.pid pppoe");
944

    
945
	return 0;
946
}
947

    
948
function interfaces_wan_pppoe_down() {
949
	global $g;
950
	sigkillbypid("{$g['varrun_path']}/mpd.pid", "SIGUSR2");
951
	sleep(1);
952
}
953

    
954
function interfaces_wan_pppoe_up() {
955
	global $g;
956
	sigkillbypid("{$g['varrun_path']}/mpd.pid", "SIGUSR1");
957
	sleep(1);
958
}
959

    
960
function interfaces_wan_pptp_configure() {
961
	global $config, $g;
962

    
963
	$wancfg = $config['interfaces']['wan'];
964
	$pptpcfg = $config['pptp'];
965

    
966
	/* generate mpd.conf */
967
	$fd = fopen("{$g['varetc_path']}/mpd.conf", "w");
968
	if (!$fd) {
969
		printf("Error: cannot open mpd.conf in interfaces_wan_pptp_configure().\n");
970
		return 1;
971
	}
972

    
973
	$idle = 0;
974

    
975
	if (isset($pptpcfg['ondemand'])) {
976
		$ondemand = "enable";
977
		if ($pptpcfg['timeout'])
978
			$idle = $pptpcfg['timeout'];
979
	} else {
980
		$ondemand = "disable";
981
	}
982

    
983
	$mpdconf = <<<EOD
984
pptp:
985
	new -i ng0 pptp pptp
986
	set iface route default
987
	set iface {$ondemand} on-demand
988
	set iface idle {$idle}
989
	set iface up-script /usr/local/sbin/ppp-linkup
990

    
991
EOD;
992

    
993
	if (isset($pptpcfg['ondemand'])) {
994
		$mpdconf .= <<<EOD
995
	set iface addrs 10.0.0.1 10.0.0.2
996

    
997
EOD;
998
	}
999

    
1000
	$mpdconf .= <<<EOD
1001
	set bundle disable multilink
1002
	set bundle authname "{$pptpcfg['username']}"
1003
	set bundle password "{$pptpcfg['password']}"
1004
	set link keep-alive 10 60
1005
	set link max-redial 0
1006
	set link no acfcomp protocomp
1007
	set link disable pap chap
1008
	set link accept chap
1009
	set ipcp no vjcomp
1010
	set ipcp ranges 0.0.0.0/0 0.0.0.0/0
1011

    
1012
EOD;
1013

    
1014
	if (isset($config['system']['dnsallowoverride'])) {
1015
		$mpdconf .= <<<EOD
1016
	set ipcp enable req-pri-dns
1017

    
1018
EOD;
1019
	}
1020

    
1021
	$mpdconf .= <<<EOD
1022
	open
1023

    
1024
EOD;
1025

    
1026
	fwrite($fd, $mpdconf);
1027
	fclose($fd);
1028

    
1029
	/* generate mpd.links */
1030
	$fd = fopen("{$g['varetc_path']}/mpd.links", "w");
1031
	if (!$fd) {
1032
		printf("Error: cannot open mpd.links in interfaces_wan_pptp_configure().\n");
1033
		return 1;
1034
	}
1035

    
1036
	$mpdconf = <<<EOD
1037
pptp:
1038
	set link type pptp
1039
	set pptp enable originate outcall
1040
	set pptp disable windowing
1041
	set pptp self {$pptpcfg['local']}
1042
	set pptp peer {$pptpcfg['remote']}
1043

    
1044
EOD;
1045

    
1046
	fwrite($fd, $mpdconf);
1047
	fclose($fd);
1048

    
1049
	/* configure interface */
1050
	mwexec("/sbin/ifconfig " . escapeshellarg($wancfg['if']) . " " .
1051
		escapeshellarg($pptpcfg['local'] . "/" . $pptpcfg['subnet']));
1052

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

    
1056
	return 0;
1057
}
1058

    
1059
function interfaces_wan_pptp_down() {
1060
	global $g;
1061
	sigkillbypid("{$g['varrun_path']}/mpd.pid", "SIGUSR2");
1062
	sleep(1);
1063
}
1064

    
1065
function interfaces_wan_pptp_up() {
1066
	global $g;
1067
	sigkillbypid("{$g['varrun_path']}/mpd.pid", "SIGUSR1");
1068
	sleep(1);
1069
}
1070

    
1071
function interfaces_wan_bigpond_configure($curwanip) {
1072
	global $config, $g;
1073

    
1074
	$bpcfg = $config['bigpond'];
1075

    
1076
	if (!$curwanip) {
1077
		/* IP address not configured yet, exit */
1078
		return 0;
1079
	}
1080

    
1081
	/* kill bpalogin */
1082
	killbyname("bpalogin");
1083

    
1084
	/* wait a moment */
1085
	sleep(1);
1086

    
1087
	/* get the default domain */
1088
	$nfd = @fopen("{$g['varetc_path']}/defaultdomain.conf", "r");
1089
	if ($nfd) {
1090
		$defaultdomain = trim(fgets($nfd));
1091
		fclose($nfd);
1092
	}
1093

    
1094
	/* generate bpalogin.conf */
1095
	$fd = fopen("{$g['varetc_path']}/bpalogin.conf", "w");
1096
	if (!$fd) {
1097
		printf("Error: cannot open bpalogin.conf in interfaces_wan_bigpond_configure().\n");
1098
		return 1;
1099
	}
1100

    
1101
	if (!$bpcfg['authserver'])
1102
		$bpcfg['authserver'] = "dce-server";
1103
	if (!$bpcfg['authdomain'])
1104
		$bpcfg['authdomain'] = $defaultdomain;
1105

    
1106
	$bpconf = <<<EOD
1107
username {$bpcfg['username']}
1108
password {$bpcfg['password']}
1109
authserver {$bpcfg['authserver']}
1110
authdomain {$bpcfg['authdomain']}
1111
localport 5050
1112

    
1113
EOD;
1114

    
1115
	if ($bpcfg['minheartbeatinterval'])
1116
		$bpconf .= "minheartbeatinterval {$bpcfg['minheartbeatinterval']}\n";
1117

    
1118
	fwrite($fd, $bpconf);
1119
	fclose($fd);
1120

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

    
1124
	return 0;
1125
}
1126

    
1127
function get_real_wan_interface() {
1128
	global $config, $g;
1129

    
1130
	$wancfg = $config['interfaces']['wan'];
1131

    
1132
	$wanif = $wancfg['if'];
1133
	if (($wancfg['ipaddr'] == "pppoe") || ($wancfg['ipaddr'] == "pptp")) {
1134
		$wanif = $g['pppoe_interface'];
1135
	}
1136

    
1137
	return $wanif;
1138
}
1139

    
1140
function get_current_wan_address() {
1141
	global $config, $g;
1142

    
1143
	$wancfg = $config['interfaces']['wan'];
1144

    
1145
	if (in_array($wancfg['ipaddr'], array('pppoe','dhcp','pptp','bigpond'))) {
1146
		/* dynamic WAN IP address, find out which one */
1147
		$wanif = get_real_wan_interface();
1148

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

    
1152
		if (isset($ifinfo[1])) {
1153
			$aif = preg_split("/\s+/", $ifinfo[1]);
1154
			$curwanip = chop($aif[3]);
1155

    
1156
			if ($curwanip && is_ipaddr($curwanip) && ($curwanip != "0.0.0.0"))
1157
				return $curwanip;
1158
		}
1159

    
1160
		return null;
1161
	} else {
1162
		/* static WAN IP address */
1163
		return $wancfg['ipaddr'];
1164
	}
1165
}
1166

    
1167
/****f* interfaces/is_jumbo_capable
1168
 * NAME
1169
 *   is_jumbo_capable - Test if interface is jumbo frame capable.  Useful for determining VLAN capability.
1170
 * INPUTS
1171
 *   $int             - string containing interface name
1172
 * RESULT
1173
 *   boolean          - true or false
1174
 ******/
1175

    
1176
function is_jumbo_capable($int) {
1177
	/* Per:
1178
	 * http://www.freebsd.org/cgi/man.cgi?query=vlan&manpath=FreeBSD+6.0-current&format=html
1179
	 * Only the following drivers support large frames
1180
	 */
1181
	$capable = array("bfe", "dc", "de", "fxp", "hme", "rl", "sis", "ste",
1182
		"tl", "tx", "xl");
1183
	
1184
	$int_family = preg_split("/[0-9]+/", $int);
1185

    
1186
	if (in_array($int_family[0], $capable))
1187
		return true;
1188
	else
1189
		return false;
1190
}
1191

    
1192
/****f* interfaces/is_altq_capable
1193
 * NAME
1194
 *   is_altq_capable - Test if interface is capable of using ALTQ
1195
 * INPUTS
1196
 *   $int            - string containing interface name
1197
 * RESULT
1198
 *   boolean         - true or false
1199
 ******/
1200

    
1201
function is_altq_capable($int) {
1202
        /* Per:
1203
         * http://www.freebsd.org/cgi/man.cgi?query=altq&manpath=FreeBSD+6.0-current&format=html
1204
         * Only the following drivers have ALTQ support
1205
         */
1206
        $capable = array("an", "ath", "awi", "bfe", "bge", "dc", "de", "ed",
1207
		"em", "fxp", "hme", "lnc", "ndis", "rl", "sf", "sis", "sk",
1208
		"tun", "vr", "wi", "xl");
1209

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

    
1212
        if (in_array($int_family[0], $capable))
1213
                return true;
1214
        else
1215
                return false;
1216
}
1217

    
1218

    
1219
?>
(8-8/23)