File: autodiscovery_network.php

package info (click to toggle)
jffnms 0.8.3dfsg.1-2.1etch1
  • links: PTS
  • area: main
  • in suites: etch
  • size: 4,928 kB
  • ctags: 5,050
  • sloc: php: 19,981; sh: 266; makefile: 91; perl: 52
file content (603 lines) | stat: -rw-r--r-- 19,286 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
<?
/* Network Autodiscovery. This file is part of JFFNMS
 * Copyright (C) <2004-2005> Javier Szyszlican <javier@szysz.com>
 * This program is licensed under the GNU GPL, full terms in the LICENSE file
 */

    $launcher_function = "discovery_network";
    $launcher_item_source = "nad_core";
    $launcher_init = "nad_init";
    $launcher_child_status ="nad_status";
    $launcher_status = "show_networks";

    $launcher_param_managed_handler = "nad_params_managed";
    
    $refresh_items = true;
    $refresh_time = 10;
    
    $timeout = 60*4;
    //$launcher_detach = false;

    require ("launcher.inc.php");

//-=-=-=-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
    function nad_load_ips() {    

	$query_ips = "SELECT ip, type FROM nad_ips WHERE id > 1";
	$result_ips = db_query ($query_ips) or die ("Query Error - ".db_error());
    
	$ips = array();
	
	while ($rip = db_fetch_array ($result_ips)) 
	    $ips[$rip["ip"]] = $rip["type"];
    
	return $ips;
    }

    function ip_to_str2 ($ip_ip) {
	$ip_bin = decbin($ip_ip);
	$ip_bin = str_pad($ip_bin,32,"0",STR_PAD_LEFT);
	$parte1 = substr($ip_bin,0,8);
        $parte2 = substr($ip_bin,8,8);
	$parte3 = substr($ip_bin,16,8);
        $parte4 = substr($ip_bin,24,8);
	$string = bindec($parte1).".".bindec($parte2).".".bindec($parte3).".".bindec($parte4);
	return $string;
    }

    function str_to_ip ($strIP){
        $Arr = explode (".",$strIP);
	return ($Arr[3] + $Arr[2] * pow(2,8) + $Arr[1] * pow(2,16) + $Arr[0] * pow(2,24));
    }

    function ip_to_bitsmask ($mask){
	$r = pow(2,32) - $mask;
        $ret = round (32 - (log($r + 1)/log(2)));
	return $ret;
    }
    
    function bitsmask_to_mask ($bmask) {
	$b = round(pow(2,32) - pow(2,32 - $bmask));
	$b = ip_to_str2 ($b);
	return $b;
    }
    
    function ip_same_network ($ip1, $ip2, $mask) {
	$mask_bit = str_to_ip($mask);
    
	$ip1_bit = str_to_ip($ip1);
	$ip2_bit = str_to_ip($ip2);

	$net1_bit = $ip1_bit & $mask_bit;
	$net2_bit = $ip2_bit & $mask_bit;
    
	if ($net1_bit == $net2_bit) return true;
	
	return false;
    }

    function nad_private_net ($ip) {
	$private_nets = array("10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16", "127.0.0.0/8", "192.169.0.0/16");
	
	foreach ($private_nets as $priv) {
	    list ($private_net, $private_mask) = explode ("/", $priv);
	    list ($net, $net_mask) = explode ("/", $ip);
	    
	    if  (
		(ip_same_network($net, $private_net, bitsmask_to_mask($private_mask))) ||	// base net is the same network as a private net
		(ip_same_network($net, "0.0.0.0", bitsmask_to_mask($net_mask)))	||		// base net is 0.0.0.0
		(ip_same_network($net, "0.0.0.0", bitsmask_to_mask(24)))			// base net is 0.0.0.0
		)
		return true;
	}
	
	return false;
    }

    function nmap_pipe ($target, $data) {
    
	if (!is_array($data[$target])) {
    	    $data[$target]["res"] = proc_open(
		get_config_option("nmap_executable"). " -sP -PB --randomize_hosts -T3 -iL - -oG -",
                array(0=>array("pipe","r"), 1=>array("pipe","w"), 2=>array("pipe","r")), $data[$target]["pipes"]);

	    fwrite($data[$target]["pipes"][0], $target."\n");
	    fclose($data[$target]["pipes"][0]);
	}
	
	if (false !== ($ret = fgets($data[$target]["pipes"][1]))) 
	    if ($ret != "# Nmap run completed")
		return rtrim($ret,"\n");

	return false;
    }

    function discovery_network ($network, $output = true) {

	$nad_time_start = time();
	$hosts_up = 0;
	$hosts_unique = 0;
	
	$net_data = current(nad_load_networks($network));
	
	if (!$output) ob_start();
	
	logger ("N ".str_pad($net_data["id"], 4)." : ".
		"Scanning Network ".$network.", deep ".$net_data["deep"]."\n");	
	
	nad_network_status ($net_data["id"], 2); //Running

	while ($line = nmap_pipe($network, &$nmap_data)) 
	    if (preg_match ("/Host\: (.*) \((.*)\).*Status\: (.*)/", $line ,$parts)) {

		if (!$output) launcher_heartbeat(); 

		$host_ip = trim($parts[1]);
		$host_name = $parts[2];
		    
		$log =  "N ".str_pad($net_data["id"], 4)." : Scanning Host ".$host_ip;
		
		$host_ip_parts = explode(".",$host_ip);
		
		if (($host_ip_parts[3]!=0) && ($host_ip_parts[3]!=255)) {
		    if ($parts[3]=="Up") {
			$hosts_up++;
			
			if (array_key_exists($host_ip, nad_load_ips())==false) {

			    $host_id = nad_add_host ();
			    $hosts_unique++;

			    logger ($log." Responded to Ping added as H $host_id\n");
		
			    $ip_id = nad_add_ip ($host_ip);
			
			    $ips_found = discovery_host ($host_id, $host_ip, $net_data["communities"], $net_data, $ip_id);
		    
			    if (!$ips_found)
				nad_update_ip ($ip_id, $host_name, $host_id, $net_data["id"]);
			
			} else
			    logger ($log." Already Added\n");
		    } else
			logger ($log." Down\n");
		} else
		    logger ($log." Invalid\n");
	    }

	nad_network_status ($net_data["id"], 3); //done
	
	ob_end_clean();
	
	return array("OK", $hosts_up, $hosts_unique, time()-$nad_time_start);
    }

    function discovery_host ($host_id, $host_ip, $communities, $net, $host_ip_id) {

	$system_description_oid = ".1.3.6.1.2.1.1.1.0";
	$system_name_oid 	= ".1.3.6.1.2.1.1.5.0";
        $ipadent_oid = ".1.3.6.1.2.1.4.20.1.1";
	$ipadentmask_oid = ".1.3.6.1.2.1.4.20.1.3";
        $ipadentint_oid = ".1.3.6.1.2.1.4.20.1.2";
	$inttype_oid = ".1.3.6.1.2.1.2.2.1.3";
	$ipforwarding_oid = ".1.3.6.1.2.1.4.1.0";
	$ipnettomedia_oid = ".1.3.6.1.2.1.4.22.1.2";
	$intstatus_oid = ".1.3.6.1.2.1.2.2.1.8";

	$invalid_ips = array("127.0.0.1","0.0.0.0");
	if (!is_array($communities)) $communities = array();
	
	$result = false;

	while ((list (, $comm) = each ($communities)) && (!$snmp_name))
	    
	    if (($snmp_name = snmp_get($host_ip, $comm, $system_name_oid, 1))!==false) {
		
		$log =  "N ".str_pad($net["id"], 4)." : H ".str_pad($host_id,3)." : ";
		logger ($log." Has SNMP $comm - $snmp_name\n");

		$snmp_ips_data = snmp_walk ($host_ip, $comm, $ipadent_oid);

		if ($snmp_ips_data!==false) {

		    $host_ips = array();

		    // Create IPs Table
		    foreach ($snmp_ips_data as $key=>$aux_ip) {
			$aux_ip = trim($aux_ip);
			
			if (strpos(" ", $aux_ip)!==false)
			    list(,$aux_ip) = explode (" ",$aux_ip);
			
			if (!in_array($aux_ip,$invalid_ips)) {

			    if ($aux_ip!=$host_ip) 					// If IP is different than the host IP
				$ip_id = nad_add_ip($aux_ip);				// Add IP to DB
			    else
				$ip_id = $host_ip_id;					// Use ID of the Already added IP
				
			    $host_ips[$aux_ip] = array("ip_id"=>$ip_id , "pos"=>$key); 	//add IP to the Array
			}
		    }
		    unset ($snmp_ips_data);

		    // Do other SNMP reads
		    $snmp_mask_data = snmp_walk ($host_ip, $comm, $ipadentmask_oid);
		    $snmp_int_data  = snmp_walk ($host_ip, $comm, $ipadentint_oid);

		    // Populate the IPs table with Mask and Type data
		    foreach ($host_ips as $aux_ip=>$ipd) {
	
			if (strpos(" ", $aux_mask)!==false)
			    list(,$aux_mask) = explode (" ",$snmp_mask_data[$ipd["pos"]]);
			else
			    $aux_mask = $snmp_mask_data[$ipd["pos"]];
			    
			if (empty($aux_mask)) $aux_mask = "255.255.255.0"; // Fix for broken IP-MIB implementations
					
			$if_index = $snmp_int_data[$ipd["pos"]];
			list(,$if_status) = split("[()]",snmp_get($host_ip, $comm, $intstatus_oid.".".$if_index));
			
			//$if_status = 1;
			if ($if_status == 1) { // Its UP
			    unset ($if_type);
			    list(,$if_type) = split("[()]",snmp_get($host_ip, $comm, $inttype_oid.".".$if_index));
			    
			    $host_ips[$aux_ip]["mask"] = $aux_mask;
			    $host_ips[$aux_ip]["type"] = $if_type;
			
			} else {	// Its Down
			
			    nad_del_ip($host_ips[$aux_ip]["ip_id"]);  	// Delete the IP from the DB
			    unset ($host_ips[$aux_ip]);			// remove it from the list used to add networks
			}
		    }
		    unset ($snmp_mask_data);
		    unset ($snmp_int_data);

		    // Add other IP addresses based on the ARP table (mine not remote)
		    $snmp_physical  = snmp_walk ($host_ip, $comm, $ipnettomedia_oid, 1);

		    if ($snmp_physical != false) {
			
			$snmp_net_to_media = array();	
		    
		        // Make Net-To-Media Table
			foreach ($snmp_physical as $k=>$aux_mac) {
			    $k = explode (".",$k);
			    $aux_ip = join(".",array_slice($k,count($k)-4,4));
			    $snmp_net_to_media[$aux_ip]=$aux_mac;
			    $snmp_media_to_net[$aux_mac][]=$aux_ip;
		        }
			unset ($snmp_physical_data);
		    
			// Find out if there are others ips on the same network with my IP's MAC address (more than 1 IP on the same network)
		        // And add it to the IPs list
			foreach ($host_ips as $ip=>$ipd)
			    if (array_key_exists($ip, $snmp_net_to_media))
				foreach ($snmp_media_to_net[$snmp_net_to_media[$ip]] as $new_ip) 
				    if (!array_key_exists($new_ip,$host_ips) && ip_same_network($ip, $new_ip, $ipd["mask"])) {
					
					$host_ips[$new_ip] = $ipd; 				//copy the other type and mask
					$host_ips[$new_ip]["ip_id"] = nad_add_ip ($new_ip);	//put in my own IP id
				    }
				    
			unset ($snmp_net_to_media);
			unset ($snmp_media_to_net);
		    }
		    
		    foreach ($host_ips as $ip=>$ipd) {
		    
		    	$ipd["dns"] = gethostbyaddr($ip);		// Resolve Reverse DNS for this IP
			if ($ipd["dns"]==$ip) unset ($ipd["dns"]); 	// Do not add the DNS if this IP doesn't have a reverse

			logger ($log." Has IP $ip - ".$ipd["mask"]." - ".$ipd["dns"]."\n");
			
			$new_net_id = nad_add_network ($ip, $ipd["mask"], $net["deep"]+1, $net["id"], $net["seed"]);

			if (!is_numeric($new_net_id)) $new_net_id = $net["id"];
			    
			nad_update_ip ($ipd["ip_id"], $ipd["dns"], $host_id, $new_net_id, $ipd["type"]);	// Update the IP DB

			$result = true; //we found some ip's
		    }
		}	

		// Get Description
		$snmp_description = snmp_get ($host_ip, $comm, $system_description_oid);

		// Findout if the Host has IP Forwarding (Router) Enabled
		list(,$host_forwarding) = split("[()]",snmp_get($host_ip, $comm, $ipforwarding_oid));
	
		if ($host_forwarding==2) $host_forwarding = 0;
		
		// Update Host information
		nad_update_host ($host_id, array("description"=>$snmp_description, "snmp_name"=>$snmp_name,
			"snmp_community"=>$comm, "forwarding"=>$host_forwarding));
	    }

	return $result;
    }


    function nad_add_network ($ip, $mask, $deep, $parent_net, $seed_id, $id=NULL) {

	if (empty($mask)) { // /24
	    list($ip, $bitmask) = explode("/",$ip);
	    $mask = bitsmask_to_mask ($bitmask);
	}
    
	    $ip_bit = str_to_ip($ip);
	    $mask_bit = str_to_ip($mask);

	    $net_bit = $ip_bit & $mask_bit;
	    $net = ip_to_str2 ($net_bit);

	    if (($net != "127.0.0.0") && ($net!="0.0.0.0")) {
		$oper_status = 0;

		$mask_prefix = ip_to_bitsmask ($mask_bit);
	    
		if ($mask_prefix < 22) $mask_prefix = 22;
		
		if ($mask_prefix == 31) $mask_prefix = 32;
	
		if (($mask_prefix == 32) && ($parent_net!=1)) $oper_status = 3;
	    
		$aux ="$net/$mask_prefix";
	
		$networks = nad_load_networks();
		
		/*
		logger ("***** Trying to add Path to network $aux ".
		    (isset($networks["aux"])?"(Alredy added as ".$networks["aux"]["id"].") ":"").
		    "via NET_ID $parent_net, Deep $deep\n");
		*/
		
		if (!isset($networks[$aux])) {
		
		    $fields = array("network"=>$aux, "deep"=>$deep, "parent"=>$parent_net, 
			"oper_status"=>$oper_status, "seed"=>$seed_id, "oper_status_changed"=>time());

		    if ($id!==NULL) $fields["id"] = $id;
	
		    return db_insert("nad_networks",$fields);
		} else
		    return $networks[$aux]["id"];	// return the network id
	    }
    }

    function nad_load_networks($network="") {    

	$query_networks = "
	    SELECT nad_networks.*, zones.max_deep, zones.communities, zones.admin_status, zones.refresh, zones.allow_private
	    FROM nad_networks, zones
	    WHERE nad_networks.id > 1 AND nad_networks.seed = zones.id ".(!empty($network)?" AND network = '$network'":"");
	$result_networks = db_query ($query_networks) or die ("Query Error - ".db_error());
    
	$networks = array();
	
	while ($rnet = db_fetch_array ($result_networks))
	    $networks[$rnet["network"]] = array ("deep"=>$rnet["deep"], 
		"oper_status"=>$rnet["oper_status"], "admin_status"=>$rnet["admin_status"], "parent"=>$rnet["parent"],
		"id"=>$rnet["id"], "communities"=>explode(",",$rnet["communities"]), "max_deep"=>$rnet["max_deep"],
		"seed"=>$rnet["seed"], "oper_status_changed"=>$rnet["oper_status_changed"], "refresh"=>$rnet["refresh"],
		"allow_private"=>$rnet["allow_private"]);

	return $networks;
    }

    function nad_add_ip ($ip, $dns = "", $host = 1, $network = 1, $type = 1) {
	$data = compact("ip","dns","host","type","network");
	return db_insert ("nad_ips",$data);
    }

    function nad_update_ip ($ip_id, $dns, $host, $network, $type = 1) {
	$data = compact("ip","dns","host","type","network");
	return db_update ("nad_ips",$ip_id, $data);
    }

    function nad_del_ip ($ip_id) {
	return db_delete ("nad_ips",$ip_id);
    }

    function nad_add_host () {
	return db_insert ("nad_hosts",array("date_added"=>time()));
    }	

    function nad_update_host ($host_id, $host_data) {
	return db_update("nad_hosts", $host_id, $host_data);
    }

    function nad_network_status($net_id, $status) {
	return db_update("nad_networks",$net_id, array("oper_status"=>$status, "oper_status_changed"=>time()));
    }

    function nad_cleanup_network ($net_id) {
	$hosts_query = "
	    SELECT nad_hosts.id 
	    FROM nad_hosts, nad_ips 
	    WHERE nad_ips.host = nad_hosts.id AND nad_ips.network = ".$net_id;
	$hosts_result = db_query ($hosts_query) or die ("Query Error - ".db_error());

	$hosts = array();
	while ($rhost = db_fetch_array($hosts_result))
	    $hosts[]=$rhost["id"];
    
	if (count($hosts) > 0) {
	    $hosts_query = "DELETE FROM nad_hosts WHERE id = ".join(" OR id = ",$hosts);
	    $hosts_result = db_query ($hosts_query) or die ("Query Error - Hosts Delete - ".db_error());
	}
	
	$ips_query = "DELETE FROM nad_ips WHERE network = ".$net_id;
	$ips_result = db_query ($ips_query) or die ("Query Error - IPs Delete - ".db_error());

	$net_query = "DELETE FROM nad_networks WHERE id = ".$net_id;
	$net_result = db_query ($net_query) or die ("Query Error - Net Delete - ".db_error());

	db_repair("nad_networks");
	db_repair("nad_hosts");
	db_repair("nad_ips");

	return ($ips_result && $hosts_result && $net_query);
    }

    function nad_params_managed($params) {
	$params[1] = false;
	return $params;
    }

    function nad_load_seeds ($networks = array()) {

	$seeds_query = "SELECT id, seeds, refresh FROM zones where id > 1 and seeds != '' and admin_status = 1";
	$seeds_result = db_query ($seeds_query) or die ("Query Error - ".db_error());

	$something_changed = false;

	while ($rseed = db_fetch_array($seeds_result)) { 	//read each seed
	    $seeds = explode (",",$rseed["seeds"]);

	    foreach ($seeds as $seed) {				//foreach seed
		$seed = trim($seed);

		$total_seeds++;
		
		if (!isset($networks[$seed])) {			//if its not already in the networks list
		    nad_add_network($seed,"",1,1,$rseed["id"]);	//its new, then add it to the DB.
		    $something_changed = true;			//tell the caller that something has changed
		} 
	    }
	}

	if ($total_seeds==0) $something_changed = true;
	
	return $something_changed;	
    }

    function nad_init () {

	db_repair("nad_networks");
	db_repair("nad_hosts");
	db_repair("nad_ips");

	nad_load_seeds(nad_load_networks());
	
	return true;
    }

    function nad_status ($child, $result) {
    
	list (,$status, $hosts_total, $hosts_new, $time) = explode (" ", $result);
	
	$ok = $status=="OK"?true:false;
	
	logger (
	    "NAD ".$child["pid"]." ".
	    ($ok
	    ?"finished discovering network ".$child["item"]." in ".time_hms($time).", Hosts $hosts_new/$hosts_total"
	    :"failed when discovering network ".$child["item"].": ".$result)
	.".\n");

	return $ok;
    }

    function show_networks () {
    
	$network_admin_status=array(0=>"stopped","started");

	$network_oper_status=array(0=>"pending",1=>"starting",2=>"running",3=>"done", 4=>"other path", 5=>"error");
	
	$networks = nad_load_networks();
	
	logger ("Number      Network          Deep/Max         Status       Changed           IDs\n");

	foreach ($networks as $network=>$net_data) {
	    logger (
		str_pad(++$i,5," ",STR_PAD_LEFT).
		"\t".str_pad($network,18).
		"\t".str_pad($net_data["deep"]."/".$net_data["max_deep"],7).
		str_pad($network_admin_status[$net_data["admin_status"]].
		"/".$network_oper_status[$net_data["oper_status"]],16).
		" ".str_pad((time()-$net_data["oper_status_changed"])." secs ago",15," ",STR_PAD_LEFT).
		"\tNID ".str_pad($net_data["id"],5).
		"PID ".$net_data["parent"].
		"\n");
	}

	logger(str_repeat("=-",45)."\n");
    }
    
    function nad_core () {
    	global $pending_items, $timeout;

	$pending = array();
	$nets = nad_load_networks();

	while (list($network, $net_data) = each ($nets)) {

	    if (($net_data["admin_status"]==1) &&					// admin up 
		($net_data["deep"] <= $net_data["max_deep"]))	{			// deep is less than max deep

		// First Start
		if ($net_data["oper_status"]==0)				// oper status pending
		    if (($net_data["allow_private"]==1) || !nad_private_net($network)) {// seed allows private or this IP is not private

	    	        nad_network_status ($net_data["id"], 1); 			// mark it as Starting
    
			logger("Changing Network ".$network." status to Starting.\n");

		        $pending[]=$network;

		    } else {								//Private IP

			nad_network_status ($net_data["id"], 5); 			// mark it as error
		        logger("Discarded Network $network, because its private space.\n");
		    }	

		// Hanged Starting
		if (($net_data["oper_status"] == 1) && 					// oper starting
		    (time()-$net_data["oper_status_changed"] > $timeout)) {		// it didn't start correctly 

		    nad_network_status ($net_data["id"], 0); 				// mark it as Pending
		    logger("Changed Network $network to Pending, because it was hanged starting\n");
		} 

		// Hanged Running
		if (($net_data["oper_status"] == 2) && 					// if its Running
		    !isset($pending_items[$network])) {					// and its not in the pending list
		
		    //nad_network_status ($net_data["id"], 5); 				// mark it as error
		    logger("Changed Network $network to Error, because it was hanged running\n");
		}

		// Refresh
		if (($net_data["oper_status"] >= 3) && 					// oper done or error
		    (time()-$net_data["oper_status_changed"] > $net_data["refresh"])) {	// and has been for more time than refresh
	
		    logger ("Cleaning Network ".$network."\n");
		    nad_cleanup_network ($net_data["id"]);				// Cleanup this network data
		
		    logger("Reloading Network ".$network."\n");
		    nad_add_network ($network, "", $net_data["deep"], $net_data["parent"], $net_data["seed"], $net_data["id"]);

		    $net_data["oper_status"] = 0;					// do not count as done now
		}
	    } else 								// Admin Down or Max Deep	
		if ($net_data["oper_status"] != 5) {				// Not already Error

    		    nad_network_status ($net_data["id"], 5); 			// mark it as error
		    logger("Discarded Network $network, because its admin/down or out of reach because of deep.\n");
		}	
	
	    // Done or Error
	    if (($net_data["oper_status"] == 3) || ($net_data["oper_status"] == 5))	// if its Done or Error
		$done_networks++;
	}
	
	if ((count($pending)==0) && ($done_networks==count($nets)))			// Nothing else to do
	    $GLOBALS["refresh_items"] = false;						// stop refreshing the list/exit

	return $pending; 
    }

?>