Project

General

Profile

Download (19 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/*
3
  Copyright (C) 2008 Bill Marquette, Seth Mos
4
  Copyright (C) 2010 Ermal Lu?i
5
  All rights reserved.
6

    
7
  Redistribution and use in source and binary forms, with or without
8
  modification, are permitted provided that the following conditions are met:
9

    
10
  1. Redistributions of source code must retain the above copyright notice,
11
  this list of conditions and the following disclaimer.
12

    
13
  2. Redistributions in binary form must reproduce the above copyright
14
  notice, this list of conditions and the following disclaimer in the
15
  documentation and/or other materials provided with the distribution.
16

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

    
28
	pfSense_BUILDER_BINARIES:	/usr/bin/killall	/sbin/route	/usr/local/sbin/apinger
29
	pfSense_MODULE:	routing
30

    
31
 */
32

    
33
/*
34
 * Creates monitoring configuration file and
35
 * adds apropriate static routes.
36
 */
37
function setup_gateways_monitor() {
38
	global $config, $g;
39

    
40
	$gateways_arr = return_gateways_array();
41
	if (!is_array($gateways_arr)) {
42
		log_error("No gateways to monitor. Apinger will not be run.");
43
		killbypid("{$g['varrun_path']}/apinger.pid");
44
		@unlink("{$g['tmp_path']}/apinger.status");
45
		return;
46
	}
47

    
48
	/* Default settings. Probably should move to globals.inc? */
49
	$a_settings = array();
50
	$a_settings['latencylow'] = "200";
51
	$a_settings['latencyhigh'] = "500";
52
	$a_settings['losslow'] = "10";
53
	$a_settings['losshigh'] = "20";
54

    
55
	$fd = fopen("{$g['varetc_path']}/apinger.conf", "w");
56
	$apingerconfig = <<<EOD
57

    
58
# pfSense apinger configuration file. Automatically Generated!
59

    
60
## User and group the pinger should run as
61
user "root"
62
group "wheel"
63

    
64
## Mailer to use (default: "/usr/lib/sendmail -t")
65
#mailer "/var/qmail/bin/qmail-inject" 
66

    
67
## Location of the pid-file (default: "/var/run/apinger.pid")
68
pid_file "{$g['varrun_path']}/apinger.pid"
69

    
70
## Format of timestamp (%s macro) (default: "%b %d %H:%M:%S")
71
#timestamp_format "%Y%m%d%H%M%S"
72

    
73
status {
74
	## File where the status information whould be written to
75
	file "{$g['tmp_path']}/apinger.status"
76
	## Interval between file updates
77
	## when 0 or not set, file is written only when SIGUSR1 is received
78
	interval 5s
79
}
80

    
81
########################################
82
# RRDTool status gathering configuration
83
# Interval between RRD updates
84
rrd interval 60s;
85

    
86
## These parameters can be overriden in a specific alarm configuration
87
alarm default { 
88
	command on "/usr/local/sbin/pfSctl -c 'filter reload'"
89
	command off "/usr/local/sbin/pfSctl -c 'filter reload'"
90
	combine 10s
91
}
92

    
93
## "Down" alarm definition. 
94
## This alarm will be fired when target doesn't respond for 30 seconds.
95
alarm down "down" {
96
	time 10s
97
}
98

    
99
## "Delay" alarm definition. 
100
## This alarm will be fired when responses are delayed more than 200ms
101
## it will be canceled, when the delay drops below 100ms
102
alarm delay "delay" {
103
	delay_low {$a_settings['latencylow']}ms
104
	delay_high {$a_settings['latencyhigh']}ms
105
}
106

    
107
## "Loss" alarm definition. 
108
## This alarm will be fired when packet loss goes over 20%
109
## it will be canceled, when the loss drops below 10%
110
alarm loss "loss" {
111
	percent_low {$a_settings['losslow']}
112
	percent_high {$a_settings['losshigh']}
113
}
114

    
115
target default {
116
	## How often the probe should be sent	
117
	interval 1s
118
	
119
	## How many replies should be used to compute average delay 
120
	## for controlling "delay" alarms
121
	avg_delay_samples 10
122
	
123
	## How many probes should be used to compute average loss
124
	avg_loss_samples 50
125

    
126
	## The delay (in samples) after which loss is computed
127
	## without this delays larger than interval would be treated as loss
128
	avg_loss_delay_samples 20
129

    
130
	## Names of the alarms that may be generated for the target
131
	alarms "down","delay","loss"
132

    
133
	## Location of the RRD
134
	#rrd file "{$g['vardb_path']}/rrd/apinger-%t.rrd"
135
}
136

    
137
EOD;
138

    
139
	foreach($gateways_arr as $name => $gateway) {
140
		if (empty($gateway['monitor']) || !is_ipaddr($gateway['monitor'])) {
141
			if (is_ipaddr($gateway['gateway']))
142
				$gateway['monitor'] = $gateway['gateway'];
143
			else /* No chance to get an ip to monitor skip target. */
144
				continue;
145
		}
146

    
147
		/* Interface ip is needed since apinger will bind a socket to it. */
148
		if (is_ipaddrv4($gateway['gateway'])) {
149
			$gwifip = find_interface_ip($gateway['interface'], true);
150
		}
151
		if (is_ipaddrv6($gateway['gateway'])) {
152
			$gwifip = find_interface_ipv6($gateway['interface'], true);
153
		}
154
		if (!is_ipaddr($gwifip))
155
			continue; //Skip this target
156

    
157
		$apingercfg = "target \"{$gateway['monitor']}\" {\n";
158
		$apingercfg .= "	description \"{$name}\"\n";
159
		$apingercfg .= "	srcip \"{$gwifip}\"\n";
160
		$alarms = "";
161
		$alarmscfg = "";
162
		$override = false;
163
		if (!empty($gateway['lowloss'])) {
164
			$alarmscfg .= "alarm loss \"{$name}loss\" {\n";
165
			$alarmscfg .= "\tpercent_low {$gateway['losslow']}\n";
166
       			$alarmscfg .= "\tpercent_high {$gateway['losshigh']}\n";
167
			$alarmscfg .= "}\n";
168
			$alarms .= "\"{$name}loss\"";
169
			$override = true;
170
		} else {
171
			if ($override == true)
172
				$alarms .= ",";
173
			$alarms .= "\"loss\"";
174
			$override = true;
175
		}
176
		if (!empty($gateway['latencylow'])) {
177
			$alarmscfg .= "alarm delay \"{$name}delay\" {\n";
178
			$alarmscfg .= "\tdelay_low {$gateway['latencylow']}ms\n";
179
			$alarmscfg .= "\tdelay_high {$gateway['latencyhigh']}ms\n";
180
			$alarmscfg .= "}\n";
181
			if ($override == true)
182
				$alarms .= ",";
183
			$alarms .= "\"{$name}delay\"";
184
			$override = true;
185
		} else {
186
			if ($override == true)
187
				$alarms .= ",";
188
			$alarms .= "\"delay\"";
189
			$override = true;
190
		}
191
		if (!empty($gateway['down'])) {
192
			$alarmscfg .= "alarm down \"{$name}down\" {\n";
193
			$alarmscfg .= "\ttime {$gateway['down']}s\n";
194
			$alarmscfg .= "}\n";
195
			if ($override == true)
196
				$alarms .= ",";
197
			$alarms .= "\"{$name}down\"";
198
			$override = true;
199
		} else {
200
			if ($override == true)
201
				$alarms .= ",";
202
			$alarms .= "\"down\"";
203
			$override = true;
204
		}
205
		if ($override == true)
206
			$apingercfg .= "\talarms override {$alarms};\n";
207

    
208
		$apingercfg .= "	rrd file \"{$g['vardb_path']}/rrd/{$gateway['name']}-quality.rrd\"\n";
209
		$apingercfg .= "}\n";
210
		$apingercfg .= "\n";
211
		/*
212
		 * If the gateway is the same as the monitor we do not add a
213
		 * route as this will break the routing table.
214
		 * Add static routes for each gateway with their monitor IP
215
		 * not strictly necessary but is a added level of protection.
216
		 */
217
		if (is_ipaddr($gateway['gateway']) && $gateway['monitor'] != $gateway['gateway']) {
218
			log_error("Removing static route for monitor {$gateway['monitor']} and adding a new route through {$gateway['gateway']}");
219
			mwexec("/sbin/route delete -host " . escapeshellarg($gateway['monitor']), true);
220
			mwexec("/sbin/route add -host " . escapeshellarg($gateway['monitor']) .
221
				" " . escapeshellarg($gateway['gateway']), true);
222
		}
223

    
224
		$apingerconfig .= $alarmscfg;
225
		$apingerconfig .= $apingercfg;
226
	}
227
	fwrite($fd, $apingerconfig);
228
	fclose($fd);
229

    
230
	killbypid("{$g['varrun_path']}/apinger.pid");
231
	if (is_dir("{$g['tmp_path']}"))
232
		chmod("{$g['tmp_path']}", 01777);
233
	if (!is_dir("{$g['vardb_path']}/rrd"))
234
		mkdir("{$g['vardb_path']}/rrd", 0775);
235

    
236
	@chown("{$g['vardb_path']}/rrd", "nobody");
237

    
238
	/* start a new apinger process */
239
	@unlink("{$g['tmp_path']}/apinger.status");
240
	sleep(1);
241
	mwexec_bg("/usr/local/sbin/apinger -c {$g['varetc_path']}/apinger.conf");
242

    
243
	return 0;
244
}
245

    
246
/* return the status of the apinger targets as a array */
247
function return_gateways_status($byname = false) {
248
	global $config, $g;
249

    
250
	$apingerstatus = array();
251
	if (file_exists("{$g['tmp_path']}/apinger.status")) {
252
		$apingerstatus = file("{$g['tmp_path']}/apinger.status");
253
	}
254

    
255
	$status = array();
256
	foreach($apingerstatus as $line) {
257
		$info = explode("|", $line);
258
		if ($byname == false)
259
			$target = $info[0];
260
		else
261
			$target = $info[2];
262
		$status[$target]['monitorip'] = $info[0];
263
		$status[$target]['srcip'] = $info[1];
264
		$status[$target]['name'] = $info[2];
265
		$status[$target]['lastcheck'] = $info[5] ? date('r', $info[5]) : date('r');
266
		$status[$target]['delay'] = empty($info[6]) ? 0 : $info[6];
267
		$status[$target]['loss'] = empty($info[7]) ? "0.0%" : $info[7] . "";
268
		$status[$target]['status'] = trim($info[8]);
269
	}
270

    
271
	return($status);
272
}
273

    
274
/* Return all configured gateways on the system */
275
function return_gateways_array($disabled = false) {
276
	global $config, $g;
277

    
278
	$gateways_arr = array();
279

    
280
	$i = 0;
281
	/* Process/add all the configured gateways. */
282
	if (is_array($config['gateways']['gateway_item'])) {
283
		foreach($config['gateways']['gateway_item'] as $gateway) {
284
			if(empty($gateway['gateway']) || $gateway['gateway'] == "dynamic") {
285
				$gateway['gateway'] = get_interface_gateway($gateway['interface']);
286
				/* no IP address found, set to dynamic */
287
				if(! is_ipaddr($gateway['gateway']))
288
					$gateway['gateway'] = "dynamic";
289
				$gateway['dynamic'] = true;
290
			}
291
			if(empty($gateway['monitor']))
292
				$gateway['monitor'] = $gateway['gateway'];
293

    
294
			$gateway['friendlyiface'] = $gateway['interface'];
295
			$gateway['interface'] = get_real_interface($gateway['interface']);
296
			/* FIXME: Should this be enabled.
297
			 * Some interface like wan might be default but have no info recorded 
298
			 * the config.
299
			if ($gateway['friendlyiface'] == "wan" && !isset($gateway['defaultgw'])) {
300
				if (file_exists("{$g['tmp_path']}/{$gateway['interface']}_defaultgw"))
301
					$gateway['defaultgw'] = true;
302
			}
303
			 */
304
			/* include the gateway index as the attribute */
305
			$gateway['attribute'] = $i;
306

    
307
			$gateways_arr[$gateway['name']] = $gateway;
308
			$i++;
309
		}
310
	} 
311

    
312
	/* Loop through all interfaces with a gateway and add it to a array */
313
	if ($disabled == false)
314
		$iflist = get_configured_interface_with_descr();
315
	else
316
		$iflist = get_configured_interface_with_descr(false, true);
317

    
318
	/* Process/add dynamic gateways. */
319
	foreach($iflist as $ifname => $friendly ) {
320
		if(! interface_has_gateway($ifname))
321
			continue;
322

    
323
		if (empty($config['interfaces'][$ifname]))
324
			continue;
325

    
326
		$ifcfg = &$config['interfaces'][$ifname];
327
		if (!empty($ifcfg['ipaddr']) && is_ipaddr($ifcfg['ipaddr']))
328
			continue;
329

    
330
		$gateway = array();
331
		$gateway['dynamic'] = false;
332
		$gateway['gateway'] = get_interface_gateway($ifname, $gateway['dynamic']);
333
		$gateway['interface'] = get_real_interface($ifname);
334
		$gateway['friendlyiface'] = $ifname;
335
		$gateway['name'] = $friendly;
336
		$gateway['attribute'] = "system";
337
	
338
		if ($gateway['dynamic'] === "default") {
339
			$gateway['defaultgw'] = true;
340
			$gateway['dynamic'] = true;
341
		}
342
		/* Loopback dummy for dynamic interfaces without a IP */
343
		if (!is_ipaddr($gateway['gateway']) && $gateway['dynamic'] == true)
344
			$gateway['gateway'] = "dynamic";
345

    
346
		/* automatically skip known static and dynamic gateways we have a array entry for */
347
		foreach($gateways_arr as $gateway_item) {
348
			if (($ifname == $gateway_item['friendlyiface'] && $friendly == $gateway_item['name']) ||
349
				($ifname == $gateway_item['friendlyiface'] && $gateway_item['dynamic'] == true))
350
					continue 2;
351
		}
352

    
353
		if (is_ipaddr($gateway['gateway']))
354
			$gateway['monitor'] = $gateway['gateway'];
355

    
356
		$gateway['descr'] = "Interface {$friendly} Dynamic Gateway";
357
		$gateways_arr[$friendly] = $gateway;
358
	}
359

    
360
	return($gateways_arr);
361
}
362

    
363
/*
364
 * Return an array with all gateway groups with name as key
365
 * All gateway groups will be processed before returning the array.
366
 */
367
function return_gateway_groups_array() {
368
	global $config, $g;
369

    
370
	/* fetch the current gateways status */
371
	$gateways_status = return_gateways_status(true);
372
	$gateways_arr = return_gateways_array();
373
	$gateway_groups_array = array();
374

    
375
	if (0) {
376
	/* 
377
	 * NOTE: The code below is meant to replace the default gateway when it goes down.
378
	 *	This facilitates services running on pfSense itself and are not handled by a PBR to continue working.
379
	 */
380
	$upgw = "";
381
	$dfltgwdown = false;
382
	$dfltgwfound = false;
383
	foreach ($gateways_arr as $gwname => $gwsttng) {
384
		if (isset($gwsttng['defaultgw'])) {
385
			$dfltgwfound = true;
386
			if (stristr($gateways_status[$gwname]['status'], "down"))
387
				$dfltgwdown = true;
388
		}
389
		/* Keep a record of the last up gateway */
390
		if (empty($upgw) && !stristr($gateways_status[$gwname]['status'], "down"))
391
			$upgw = $gwname;
392
		if ($dfltgwdown == true && !empty($upgw))
393
			break;
394
	}
395
	if ($dfltgwfound == false) {
396
		$gwname = convert_friendly_interface_to_friendly_descr("wan");
397
		if (stristr($gateways_status[$gwname]['status'], "down"))
398
			$dfltgwdown = true;
399
	}
400
	if ($dfltgwdown == true && !empty($upgw)) {
401
		if ($gateways_arr[$upgw]['gateway'] == "dynamic")
402
			$gateways_arr[$upgw]['gateway'] = get_interface_gateway($gateways_arr[$upgw]['friendlyiface']);
403
		if (is_ipaddr($gateways_arr[$upgw]['gateway'])) {
404
			log_error("Default gateway down setting {$upgw} as default!");
405
			mwexec("/sbin/route delete -inet default; /sbin/route add -inet default {$gateways_arr[$upgw]['gateway']}");
406
		}
407
	}
408
	unset($upgw, $dfltgwfound, $dfltgwdown, $gwname, $gwsttng);
409
	}
410

    
411
	if (is_array($config['gateways']['gateway_group'])) {
412
		foreach($config['gateways']['gateway_group'] as $group) {
413
			/* create array with group gateways members seperated by tier */
414
			$tiers = array();
415
			$backupplan = array();
416
			foreach($group['item'] as $item) {
417
				$itemsplit = explode("|", $item);
418
				$tier = $itemsplit[1];
419
				$gwname = $itemsplit[0];
420

    
421
				/* Do it here rather than reiterating again the group in case no member is up. */
422
				$backupplan[$tier][] = $gwname;
423

    
424
				/* check if the gateway is available before adding it to the array */
425
				if (!empty($gateways_status[$gwname])) {
426
					$status = $gateways_status[$gwname];
427
					$gwdown = false;
428
					if (stristr($status['status'], "down")) {
429
						$msg = "MONITOR: {$gwname} is down, removing from routing group";
430
						$gwdown = true;
431
					} else if (stristr($status['status'], "loss") && strstr($group['trigger'], "loss")) {
432
						/* packet loss */
433
						$msg = "MONITOR: {$gwname} has packet loss, removing from routing group";
434
						$gwdown = true;
435
					} else if (stristr($status['status'], "delay") && strstr($group['trigger'] , "latency")) {
436
						/* high latency */
437
						$msg = "MONITOR: {$gwname} has high latency, removing from routing group";
438
						$gwdown = true;
439
					}
440
					if ($gwdown == true) {
441
						log_error($msg);
442
						notify_via_growl($msg);
443
						notify_via_smtp($msg);
444
					} else
445
						/* Online add member */
446
						$tiers[$tier][] = $gwname;
447
				}
448
			}
449
			$tiers_count = count($tiers);
450
			if($tiers_count == 0) {
451
				/* Oh dear, we have no members! Engage Plan B */
452
				if (!$g['booting']) {
453
					$msg = "Gateways status could not be determined, considering all as up/active.";
454
					log_error($msg);
455
					notify_via_growl($msg);
456
					notify_via_smtp($msg);
457
				}
458
				$tiers = $backupplan;
459
			}
460
			/* sort the tiers array by the tier key */
461
			ksort($tiers);
462

    
463
			/* we do not really foreach the tiers as we stop after the first tier */
464
			foreach($tiers as $tier) {
465
				/* process all gateways in this tier */
466
				foreach($tier as $member) {
467
					/* determine interface gateway */
468
					if (isset($gateways_arr[$member])) {
469
						$gateway = $gateways_arr[$member];
470
						$int = $gateway['interface'];
471
						$gatewayip = "";
472
						if(is_ipaddr($gateway['gateway'])) 
473
							$gatewayip = $gateway['gateway'];
474
						else if ($int <> "")
475
							$gatewayip = get_interface_gateway($gateway['friendlyiface']);
476
					
477
						if (($int <> "") && is_ipaddr($gatewayip)) {
478
							$groupmember = array();
479
							$groupmember['int']  = $int;
480
							$groupmember['gwip']  = $gatewayip;
481
							$groupmember['weight']  = isset($gateway['weight']) ? $gateway['weight'] : 1;
482
							$gateway_groups_array[$group['name']][] = $groupmember;
483
						}
484
					}
485
				}
486
				/* we should have the 1st available tier now, exit stage left */
487
				break;
488
			}
489
		}
490
	}
491
	return ($gateway_groups_array);
492
}
493

    
494
/* Update DHCP WAN Interface ip address in gateway group item */
495
function dhclient_update_gateway_groups_defaultroute($interface = "wan") {
496
	global $config, $g;
497
	foreach($config['gateways']['gateway_item'] as & $gw) {	
498
		if($gw['interface'] == $interface) {
499
			$current_gw = get_interface_gateway($interface);
500
			if($gw['gateway'] <> $current_gw) {
501
				$gw['gateway'] = $current_gw;
502
				$changed = true;
503
			}
504
		}
505
	}
506
	if($changed && $current_gw)
507
		write_config("Updating gateway group gateway for $interface - new gateway is $current_gw");
508
}
509

    
510
function lookup_gateway_ip_by_name($name) {
511

    
512
	$gateways_arr = return_gateways_array();
513
        foreach ($gateways_arr as $gname => $gw) {
514
                if ($gw['name'] == $name || $gname == $name)
515
                        return $gw['gateway'];
516
        }
517

    
518
	return false;
519
}
520

    
521
function lookup_gateway_monitor_ip_by_name($name) {
522

    
523
        $gateways_arr = return_gateways_array();
524
	if (!empty($gateways_arr[$name])) {
525
		$gateway = $gateways_arr[$name];
526
		if(!is_ipaddr($gateway['monitor']))
527
			return $gateway['gateway'];
528

    
529
		return $gateway['monitor'];
530
        }
531

    
532
        return (false);
533
}
534

    
535
function lookup_gateway_interface_by_name($name) {
536

    
537
        $gateways_arr = return_gateways_array();
538
	if (!empty($gateways_arr[$name])) {
539
		$interfacegw = $gateway['interface'];
540
		return ($interfacegw);
541
        }
542

    
543
        return (false);
544
}
545

    
546
function get_interface_gateway($interface, &$dynamic = false) {
547
	global $config, $g;
548

    
549
	$gw = NULL;
550

    
551
	$gwcfg = $config['interfaces'][$interface];
552
	if (!empty($gwcfg['gateway']) && is_array($config['gateways']['gateway_item'])) {
553
		foreach($config['gateways']['gateway_item'] as $gateway) {
554
			if(($gateway['name'] == $gwcfg['gateway']) && (is_ipaddrv4($gateway['gateway']))) {
555
				$gw = $gateway['gateway'];
556
				break;
557
			}
558
		}
559
	}
560

    
561
	// for dynamic interfaces we handle them through the $interface_router file.
562
	if (!is_ipaddr($gw) && !is_ipaddr($gwcfg['ipaddr'])) {
563
		$realif = get_real_interface($interface);
564
		if (file_exists("{$g['tmp_path']}/{$realif}_router")) {
565
				$gw = trim(file_get_contents("{$g['tmp_path']}/{$realif}_router"), " \n");
566
			$dynamic = true;
567
		}
568
		if (file_exists("{$g['tmp_path']}/{$realif}_defaultgw"))
569
			$dynamic = "default";
570
			
571
	}
572

    
573
	/* return gateway */
574
	return ($gw);
575
}
576

    
577
function get_interface_gateway_v6($interface, &$dynamic = false) {
578
	global $config, $g;
579

    
580
	$gw = NULL;
581
	$gwcfg = $config['interfaces'][$interface];
582
	if (!empty($gwcfg['gatewayv6']) && is_array($config['gateways']['gateway_item'])) {
583
		foreach($config['gateways']['gateway_item'] as $gateway) {
584
			if(($gateway['name'] == $gwcfg['gatewayv6']) && (is_ipaddrv6($gateway['gateway']))) {
585
				$gw = $gateway['gateway'];
586
				break;
587
			}
588
		}
589
	}
590

    
591
	// for dynamic interfaces we handle them through the $interface_router file.
592
	if (!is_ipaddrv6($gw) && !is_ipaddr($gwcfg['ipaddrv6'])) {
593
			$realif = get_real_interface($interface);
594
			if (file_exists("{$g['tmp_path']}/{$realif}_routerv6")) {
595
				$gw = trim(file_get_contents("{$g['tmp_path']}/{$realif}_routerv6"), " \n");
596
				$dynamic = true;
597
			}
598
			if (file_exists("{$g['tmp_path']}/{$realif}_defaultgwv6"))
599
				$dynamic = "default";
600
			
601
	}
602
	/* return gateway */
603
	return ($gw);
604
}
605

    
606
?>
(24-24/61)