Passed
Push — master ( 75cf8d...706e81 )
by Patrick
02:11
created

Trap::update_oid()   F

Complexity

Conditions 25
Paths 1218

Size

Total Lines 110
Code Lines 69

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 25
eloc 69
nc 1218
nop 9
dl 0
loc 110
rs 0
c 0
b 0
f 0

How to fix   Long Method    Complexity    Many Parameters   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
4
//use FontLib\EOT\File;
5
6
include (dirname(__DIR__).'/library/Trapdirector/Icinga2Api.php');
7
8
use Icinga\Module\Trapdirector\Icinga2API;
9
10
define("ERROR", 1);define("WARN", 2);define("INFO", 3);define("DEBUG", 4);
11
12
class Trap
13
{
14
	// Configuration files a dirs
15
	protected $icingaweb2_etc; //< Icinga etc path	
16
	protected $trap_module_config; //< config.ini of module	
17
	protected $icingaweb2_ressources; //< resources.ini of icingaweb2
18
	// Options from config.ini 
19
	protected $snmptranslate='/usr/bin/snmptranslate';
20
	protected $snmptranslate_dirs='/usr/share/icingaweb2/modules/trapdirector/mibs';
21
	protected $icinga2cmd='/var/run/icinga2/cmd/icinga2.cmd';
22
	protected $db_prefix='traps_';
23
24
	// API
25
	protected $api_use=false;
26
	protected $icinga2api=null;
27
	protected $api_hostname='';
28
	protected $api_port=0;
29
	protected $api_username='';
30
	protected $api_password='';
31
32
	//**** Options from config database
33
	// Logs 
34
	protected $debug_level=2;  // 0=No output 1=critical 2=warning 3=trace 4=ALL
35
	protected $alert_output='display'; // alert type : file, syslog, display
36
	protected $debug_file="/tmp/trapdebug.txt";
37
	protected $debug_text=array("","Error","Warning","Info","Debug");
38
	
39
	//**** End options from database
40
	
41
	//protected $debug_file="php://stdout";	
42
	// Databases
43
	protected $trapDB=null; //< trap database
44
	protected $idoDB=null; //< ido database
45
	protected $trapDBType; //< Type of database for traps (mysql, pgsql)
46
	protected $idoDBType; //< Type of database for ido (mysql, pgsql)
47
	
48
	// Trap received data
49
	protected $receivingHost;
50
	public $trap_data=array(); //< Main trap data (oid, source...)
51
	public $trap_data_ext=array(); //< Additional trap data objects (oid/value).
52
	public $trap_id=null; //< trap_id after sql insert
53
	public $trap_action=null; //< trap action for final write
54
	protected $trap_to_db=true; //< log trap to DB
55
	
56
	// Mib update data
57
	private $dbOidAll; //< All oid in database;
58
	private $dbOidIndex; //< Index of oid in dbOidAll
59
	private $objectsAll; //< output lines of snmptranslate list
60
	private $trapObjectsIndex; //< array of traps objects (as OID)
61
	
62
	function __construct($etc_dir='/etc/icingaweb2')
63
	{
64
		$this->icingaweb2_etc=$etc_dir;
65
		$this->trap_module_config=$this->icingaweb2_etc."/modules/trapdirector/config.ini";		
66
		$this->icingaweb2_ressources=$this->icingaweb2_etc."/resources.ini";
67
		
68
		$this->getOptions();
69
70
		$this->trap_data=array(
71
			'source_ip'	=> 'unknown',
72
			'source_port'	=> 'unknown',
73
			'destination_ip'	=> 'unknown',
74
			'destination_port'	=> 'unknown',
75
			'trap_oid'	=> 'unknown',
76
		);
77
	}
78
	
79
	/**
80
	 * Get option from array of ini file, send message if empty
81
	 * @param string $option_array Array of ini file
82
	 * @param string $option_category category in ini file
83
	 * @param string $option_name name of option in category
84
	 * @param resource $option_var variable to fill if found, left untouched if not found
85
	 * @param integer $log_level default 2 (warning)
86
	 * @param string $message warning message if not found
87
	 * @return boolean true if found, or false
88
	 */
89
	protected function getOptionIfSet($option_array,$option_category,$option_name, &$option_var, $log_level = 2, $message = null)
90
	{
91
	    if (!isset($option_array[$option_category][$option_name]))
92
	    {
93
	        if ($message === null)
94
	        {
95
	            $message='No ' . $option_name . ' in config file: '. $this->trap_module_config;
96
	        }
97
	        $this->trapLog($message,$log_level,'syslog');
98
	        return false;
99
	    }
100
	    else
101
	    {
102
	        $option_var=$option_array[$option_category][$option_name];
103
	        return true;
104
	    }
105
	}
106
	
107
	/** Get options from ini file and database
108
	*/
109
	protected function getOptions()
110
	{
111
		$trap_config=parse_ini_file($this->trap_module_config,true);
112
		if ($trap_config == false) 
113
		{
114
			$this->trapLog("Error reading ini file : ".$this->trap_module_config,ERROR,'syslog'); 
115
		}
116
		// Snmptranslate binary path
117
		$this->getOptionIfSet($trap_config,'config','snmptranslate', $this->snmptranslate);
118
119
		// mibs path
120
		$this->getOptionIfSet($trap_config,'config','snmptranslate_dirs', $this->snmptranslate_dirs);
121
122
		// icinga2cmd path
123
		$this->getOptionIfSet($trap_config,'config','icingacmd', $this->icinga2cmd);
124
		
125
		// table prefix
126
		$this->getOptionIfSet($trap_config,'config','database_prefix', $this->db_prefix);
127
128
		// API options
129
		if ($this->getOptionIfSet($trap_config,'config','icingaAPI_host', $this->api_hostname))
130
		{
131
		    $this->api_use=true;
132
		    $this->getOptionIfSet($trap_config,'config','icingaAPI_port', $this->api_port);
133
		    $this->getOptionIfSet($trap_config,'config','icingaAPI_user', $this->api_username);
134
		    $this->getOptionIfSet($trap_config,'config','icingaAPI_password', $this->api_password);
135
		}
136
				
137
		/***** Database options :  ***/
138
		$this->getDBConfigIfSet('log_level',$this->debug_level);
139
		$this->getDBConfigIfSet('log_destination',$this->alert_output);
140
		$this->getDBConfigIfSet('log_file',$this->debug_file);
141
		$this->getAPI();
142
	}
143
144
	protected function getDBConfigIfSet($element,&$variable)
145
	{
146
		$value=$this->getDBConfig($element);
147
		if ($value != 'null') $variable=$value;
148
	}
149
	
150
	/** Get data from db_config
151
	*	@param $element string name of param
152
	*	@return mixed : value (or null)
153
	*/	
154
	protected function getDBConfig($element)
155
	{
156
		$db_conn=$this->db_connect_trap();
157
		$sql='SELECT value from '.$this->db_prefix.'db_config WHERE ( name=\''.$element.'\' )';
158
		if (($ret_code=$db_conn->query($sql)) == FALSE) {
159
			$this->trapLog('No result in query : ' . $sql,WARN,'');
160
			return null;
161
		}
162
		$value=$ret_code->fetch();
163
		if ($value != null && isset($value['value']))
164
		{
165
			return $value['value'];
166
		}
167
		return null;
168
	}
169
	
170
	/** Send log. Throws exception on critical error
171
	*	@param	string $message Message to log
172
	*	@param	int $level 1=critical 2=warning 3=trace 4=debug
173
	*	@param  string $destination file/syslog/display
174
	*	@return void
175
	**/	
176
	public function trapLog( $message, $level, $destination ='')
177
	{	
178
		if ($this->debug_level >= $level) 
179
		{
180
			$message = '['.  date("Y/m/d H:i:s") . '] ' .
181
				'['. basename(__FILE__) . '] ['.$this->debug_text[$level].']: ' .$message . "\n";
182
			
183
			if ( $destination != '' ) $output=$destination;
184
			else $output=$this->alert_output;
185
			switch ($output)
186
			{
187
				case 'file':
188
					file_put_contents ($this->debug_file, $message , FILE_APPEND);
189
					break;
190
				case 'syslog':
191
					switch($level)
192
					{
193
						case 1 : $prio = LOG_ERR;break;
194
						case 2 : $prio = LOG_WARNING;break;
195
						case 3 : $prio = LOG_INFO;break;
196
						case 4 : $prio = LOG_DEBUG;break;
197
						default: $prio = LOG_ERR;
198
					}
199
					syslog($prio,$message);
200
					break;
201
				case 'display':
202
					echo $message;
203
					break;
204
				default : // nothing we can do at this point
205
					throw new Exception($message);
206
			}
207
		}
208
		if ($level == 1)
209
		{
210
			throw new Exception($message);
211
		}
212
	}
213
	
214
	public function setLogging($debug_lvl,$output_type,$output_option=null)
215
	{
216
		$this->debug_level=$debug_lvl;
217
		switch ($output_type)
218
		{
219
			case 'file':
220
			    if ($output_option == null) throw new Exception("File logging without file !");
221
				$this->debug_file=$output_option;
222
				$this->alert_output='file';
223
				break;
224
			case 'syslog':
225
				$this->alert_output='syslog';
226
				break;
227
			case 'display':
228
				$this->alert_output='display';
229
				break;
230
			default : // syslog should always work....
231
				$this->trapLog("Error in log output : ".$output_type,ERROR,'syslog');
232
		}
233
	}
234
	
235
	protected function getAPI()
236
	{
237
	    if ($this->icinga2api == null)
238
	    {
239
	        $this->icinga2api = new Icinga2API($this->api_hostname,$this->api_port);
240
	    }
241
	    return $this->icinga2api;
242
	}
243
244
	/** Connects to trapdb 
245
	*	@return mixed : PDO connection or null
246
	*/
247
	public function db_connect_trap() 
248
	{
249
		if ($this->trapDB != null) {
250
		    // Check if connection is still alive
251
		    try {
252
		        $this->trapDB->query('select 1')->fetchColumn();
253
		        return $this->trapDB;
254
		    } catch (Exception $e) {
255
		        // select 1 failed, try to reconnect.
256
		        $this->trapDB=null;
257
				$this->trapDB=$this->db_connect('traps');
258
		        $this->trapLog('Database connection lost, reconnecting',WARN,'');
259
				return $this->trapDB;
260
		    }
261
		     
262
		}
263
		$this->trapDB=$this->db_connect('traps');
264
		return $this->trapDB;
265
	}
266
	
267
268
	/** Connects to idodb 
269
	*	@return PDO connection
270
	*/
271
	public function db_connect_ido() 
272
	{
273
		if ($this->idoDB != null) { return $this->idoDB; }
274
		$this->idoDB=$this->db_connect('ido');
275
		return $this->idoDB;
276
	}	
277
	
278
	/** connects to database named by parameter
279
	*	@param $database string : 'traps' for traps database, 'ido' for ido database
280
	*	@return PDO connection
281
	**/
282
	protected function db_connect($database) {
283
		$confarray=$this->get_database($database);
284
		//	$dsn = 'mysql:dbname=traps;host=127.0.0.1';
285
		$dsn= $confarray[0].':dbname='.$confarray[2].';host='.$confarray[1];
286
		$user = $confarray[3];
287
		$password = $confarray[4];
288
		$this->trapLog('DSN : '.$dsn,3);
289
		try {
290
			$dbh = new PDO($dsn, $user, $password);
291
		} catch (PDOException $e) {
292
			$this->trapLog('Connection failed : ' . $e->getMessage(),ERROR,'');
293
		}
294
		return $dbh;
295
	}
296
297
	/** Get database connexion options
298
	*	@param string $database : 'traps' for traps database, 'ido' for ido database
299
	*	@return mixed : null or array( DB type (mysql, pgsql.) , db_host, database name , db_user, db_pass)
300
	**/
301
	protected function get_database($database) {
302
303
		$trap_config=parse_ini_file($this->trap_module_config,true);
304
		if ($trap_config == false) 
305
		{
306
			$this->trapLog("Error reading ini file : ".$this->trap_module_config,ERROR,''); 
307
		}
308
		if ($database == 'traps')
309
		{
310
			if (!isset($trap_config['config']['database'])) 
311
			{
312
				$this->trapLog("No Config/database in config file: ".$this->trap_module_config,ERROR,''); 
313
			}
314
			$db_name=$trap_config['config']['database'];
315
		} 
316
		else if ($database == 'ido')
317
		{
318
			if (!isset($trap_config['config']['IDOdatabase'])) 
319
			{
320
				$this->trapLog("No Config/IDOdatabase in config file: ".$this->trap_module_config,ERROR,''); 
321
			}
322
			$db_name=$trap_config['config']['IDOdatabase'];		
323
		}
324
		else
325
		{
326
			$this->trapLog("Unknown database type : ".$database,ERROR,'');
327
			return null;
328
		}	
329
		$this->trapLog("Found database in config file: ".$db_name,3,''); 
330
		$db_config=parse_ini_file($this->icingaweb2_ressources,true);
331
		if ($db_config == false) 
332
		{
333
			$this->trapLog("Error reading ini file : ".$this->icingaweb2_ressources,ERROR,''); 
334
		}
335
		if (!isset($db_config[$db_name])) 
336
		{
337
			$this->trapLog("No Config/database in config file: ".$this->icingaweb2_ressources,ERROR,''); 
338
		}
339
		$db_type=$db_config[$db_name]['db'];
340
		$db_host=$db_config[$db_name]['host'];
341
		$db_sql_name=$db_config[$db_name]['dbname'];
342
		$db_user=$db_config[$db_name]['username'];
343
		$db_pass=$db_config[$db_name]['password'];
344
		if ($database == 'traps') $this->trapDBType = $db_type;
345
		if ($database == 'ido') $this->idoDBType = $db_type;
346
		
347
		$this->trapLog( "DB selected : $db_type $db_host $db_sql_name $db_user",3,''); 
348
		return array($db_type,$db_host,$db_sql_name,$db_user,$db_pass);
349
	}	
350
	
351
	/** read data from stream
352
	*	@param $stream string input stream, defaults to "php://stdin"
353
	*	@return mixed array trap data or exception with error
354
	*/
355
	public function read_trap($stream='php://stdin')
356
	{
357
		//Read data from snmptrapd from stdin
358
		$input_stream=fopen($stream, 'r');
359
360
		if ($input_stream==FALSE)
361
		{
362
		    $this->writeTrapErrorToDB("Error reading trap (code 1/Stdin)");
363
			$this->trapLog("Error reading stdin !",ERROR,'');
364
			return null; // note : exception thrown by traplog
365
		}
366
367
		// line 1 : host
368
		$this->receivingHost=chop(fgets($input_stream));
369
		if ($this->receivingHost === false)
370
		{
371
		    $this->writeTrapErrorToDB("Error reading trap (code 1/Line Host)");
372
			$this->trapLog("Error reading Host !",ERROR,''); 
373
		}
374
		// line 2 IP:port=>IP:port
375
		$IP=chop(fgets($input_stream));
376
		if ($IP === false)
377
		{
378
		    $this->writeTrapErrorToDB("Error reading trap (code 1/Line IP)");
379
			$this->trapLog("Error reading IP !",ERROR,''); 
380
		}
381
		$matches=array();
382
		$ret_code=preg_match('/.DP: \[(.*)\]:(.*)->\[(.*)\]:(.*)/',$IP,$matches);
383
		if ($ret_code===0 || $ret_code===false) 
384
		{
385
		    $this->writeTrapErrorToDB("Error parsing trap (code 2/IP)");
386
			$this->trapLog('Error parsing IP : '.$IP,ERROR,'');
387
		} 
388
		else 
389
		{		
390
			$this->trap_data['source_ip']=$matches[1];
391
			$this->trap_data['destination_ip']=$matches[3];
392
			$this->trap_data['source_port']=$matches[2];
393
			$this->trap_data['destination_port']=$matches[4];
394
		}
395
396
		while (($vars=fgets($input_stream)) !==false)
397
		{
398
			$vars=chop($vars);
399
			$ret_code=preg_match('/^([^ ]+) (.*)$/',$vars,$matches);
400
			if ($ret_code===0 || $ret_code===false) 
401
			{
402
				$this->trapLog('No match on trap data : '.$vars,WARN,'');
403
			}
404
			else 
405
			{
406
			    if (($matches[1]=='.1.3.6.1.6.3.1.1.4.1.0') || ($matches[1]=='.1.3.6.1.6.3.1.1.4.1'))
407
				{
408
					$this->trap_data['trap_oid']=$matches[2];				
409
				}
410
				else
411
				{
412
					$object= new stdClass;
413
					$object->oid =$matches[1];
414
					$object->value = $matches[2];
415
					array_push($this->trap_data_ext,$object);
416
				}
417
			}
418
		}
419
420
		if ($this->trap_data['trap_oid']=='unknown') 
421
		{
422
		    $this->writeTrapErrorToDB("No trap oid found : check snmptrapd configuration (code 3/OID)",$this->trap_data['source_ip']);
423
			$this->trapLog('no trap oid found',ERROR,'');
424
		} 
425
426
		// Translate oids.
427
		
428
		$retArray=$this->translateOID($this->trap_data['trap_oid']);
429
		if ($retArray != null)
430
		{
431
			$this->trap_data['trap_name']=$retArray['trap_name'];
432
			$this->trap_data['trap_name_mib']=$retArray['trap_name_mib'];
433
		}
434
		foreach ($this->trap_data_ext as $key => $val)
435
		{
436
			$retArray=$this->translateOID($val->oid);
437
			if ($retArray != null)
438
			{
439
				$this->trap_data_ext[$key]->oid_name=$retArray['trap_name'];
440
				$this->trap_data_ext[$key]->oid_name_mib=$retArray['trap_name_mib'];
441
			}			
442
		}
443
		
444
445
		$this->trap_data['status']= 'waiting';
446
		
447
		return $this->trap_data;
448
	}
449
450
	/** Translate oid into array(MIB,Name)
451
	* @param $oid string oid to translate
452
	* @return mixed : null if not found or array(MIB,Name)
453
	*/
454
	public function translateOID($oid)
455
	{
456
		// try from database
457
		$db_conn=$this->db_connect_trap();
458
		
459
		$sql='SELECT mib,name from '.$this->db_prefix.'mib_cache WHERE oid=\''.$oid.'\';';
460
		$this->trapLog('SQL query : '.$sql,4,'');
461
		if (($ret_code=$db_conn->query($sql)) == FALSE) {
462
			$this->trapLog('No result in query : ' . $sql,ERROR,'');
463
		}
464
		$name=$ret_code->fetch();
465
		if ($name['name'] != null)
466
		{
467
			return array('trap_name_mib'=>$name['mib'],'trap_name'=>$name['name']);
468
		}
469
		
470
		// Also check if it is an instance of OID
471
		$oid_instance=preg_replace('/\.[0-9]+$/','',$oid);
472
		
473
		$sql='SELECT mib,name from '.$this->db_prefix.'mib_cache WHERE oid=\''.$oid_instance.'\';';
474
		$this->trapLog('SQL query : '.$sql,4,'');
475
		if (($ret_code=$db_conn->query($sql)) == FALSE) {
476
			$this->trapLog('No result in query : ' . $sql,ERROR,'');
477
		}
478
		$name=$ret_code->fetch();
479
		if ($name['name'] != null)
480
		{
481
			return array('trap_name_mib'=>$name['mib'],'trap_name'=>$name['name']);
482
		}
483
		
484
		// Try to get oid name from snmptranslate
485
		$translate=exec($this->snmptranslate . ' -m ALL -M +'.$this->snmptranslate_dirs.
486
		    ' '.$oid);
487
		$matches=array();
488
		$ret_code=preg_match('/(.*)::(.*)/',$translate,$matches);
489
		if ($ret_code===0 || $ret_code===FALSE) {
490
			return NULL;
491
		} else {
492
			$this->trapLog('Found name with snmptrapd and not in DB for oid='.$oid,INFO,'');
493
			return array('trap_name_mib'=>$matches[1],'trap_name'=>$matches[2]);
494
		}	
495
	}
496
	
497
	/** Erase old trap records 
498
	*	@param integer $days : erase traps when more than $days old
499
	*	@return integer : number of lines deleted
500
	**/
501
	public function eraseOldTraps($days=0)
502
	{
503
		if ($days==0)
504
		{
505
			if (($days=$this->getDBConfig('db_remove_days')) == null)
506
			{
507
				$this->trapLog('No days specified & no db value : no tap erase' ,WARN,'');
508
				return;
509
			}
510
		}
511
		$db_conn=$this->db_connect_trap();
512
		$daysago = strtotime("-".$days." day");
513
		$sql= 'delete from '.$this->db_prefix.'received where date_received < \''.date("Y-m-d H:i:s",$daysago).'\';';
514
		if ($db_conn->query($sql) == FALSE) {
515
			$this->trapLog('Error erasing traps : '.$sql,ERROR,'');
516
		}
517
		$this->trapLog('Erased traps older than '.$days.' day(s) : '.$sql,3);
518
	}
519
520
	/** Write error to received trap database
521
	 */
522
	public function writeTrapErrorToDB($message,$sourceIP=null,$trapoid=null)
523
	{
524
	    
525
	    $db_conn=$this->db_connect_trap();
526
	    
527
	    // add date time
528
	    $insert_col ='date_received,status';
529
	    $insert_val = "'" . date("Y-m-d H:i:s")."','error'";
530
        
531
	    if ($sourceIP !=null)
532
	    {
533
	        $insert_col .=',source_ip';
534
	        $insert_val .=",'". $sourceIP ."'";
535
	    }
536
	    if ($trapoid !=null)
537
	    {
538
	        $insert_col .=',trap_oid';
539
	        $insert_val .=",'". $trapoid ."'";
540
	    }
541
	    $insert_col .=',status_detail';
542
	    $insert_val .=",'". $message ."'";
543
	    
544
	    $sql= 'INSERT INTO '.$this->db_prefix.'received (' . $insert_col . ') VALUES ('.$insert_val.')';
545
	    
546
	    switch ($this->trapDBType)
547
	    {
548
	        case 'pgsql':
549
	            $sql .= ' RETURNING id;';
550
	            $this->trapLog('sql : '.$sql,3,'');
551
	            if (($ret_code=$db_conn->query($sql)) == FALSE) {
552
	                $this->trapLog('Error SQL insert : '.$sql,1,'');
553
	            }
554
	            $this->trapLog('SQL insertion OK',3,'');
555
	            // Get last id to insert oid/values in secondary table
556
	            if (($inserted_id_ret=$ret_code->fetch(PDO::FETCH_ASSOC)) == FALSE) {
557
	                
558
	                $this->trapLog('Erreur recuperation id',1,'');
559
	            }
560
	            if (! isset($inserted_id_ret['id'])) {
561
	                $this->trapLog('Error getting id',1,'');
562
	            }
563
	            $this->trap_id=$inserted_id_ret['id'];
564
	            break;
565
	        case 'mysql':
566
	            $sql .= ';';
567
	            $this->trapLog('sql : '.$sql,3,'');
568
	            if ($db_conn->query($sql) == FALSE) {
569
	                $this->trapLog('Error SQL insert : '.$sql,1,'');
570
	            }
571
	            $this->trapLog('SQL insertion OK',3,'');
572
	            // Get last id to insert oid/values in secondary table
573
	            $sql='SELECT LAST_INSERT_ID();';
574
	            if (($ret_code=$db_conn->query($sql)) == FALSE) {
575
	                $this->trapLog('Erreur recuperation id',1,'');
576
	            }
577
	            
578
	            $inserted_id=$ret_code->fetch(PDO::FETCH_ASSOC)['LAST_INSERT_ID()'];
579
	            if ($inserted_id==false) throw new Exception("Weird SQL error : last_insert_id returned false : open issue");
580
	            $this->trap_id=$inserted_id;
581
	            break;
582
	        default:
583
	            $this->trapLog('Error SQL type  : '.$this->trapDBType,1,'');
584
	    }
585
	    
586
	    $this->trapLog('id found: '. $this->trap_id,3,'');    
587
	}
588
	
589
	/** Write trap data to trap database
590
	*/
591
	public function writeTrapToDB()
592
	{
593
		
594
		// If action is ignore -> don't send t DB
595
		if ($this->trap_to_db === false) return;
596
		
597
		
598
		$db_conn=$this->db_connect_trap();
599
		
600
		$insert_col='';
601
		$insert_val='';
602
		// add date time
603
		$this->trap_data['date_received'] = date("Y-m-d H:i:s");
604
605
		$firstcol=1;
606
		foreach ($this->trap_data as $col => $val)
607
		{
608
			if ($firstcol==0) 
609
			{
610
				$insert_col .=',';
611
				$insert_val .=',';
612
			}
613
			$insert_col .= $col ;
614
			$insert_val .= ($val==null)? 'NULL' : $db_conn->quote($val);
615
			$firstcol=0;
616
		}
617
		
618
		$sql= 'INSERT INTO '.$this->db_prefix.'received (' . $insert_col . ') VALUES ('.$insert_val.')';
619
		switch ($this->trapDBType)
620
		{
621
			case 'pgsql': 
622
				$sql .= ' RETURNING id;';
623
				$this->trapLog('sql : '.$sql,3,'');
624
				if (($ret_code=$db_conn->query($sql)) == FALSE) {
625
					$this->trapLog('Error SQL insert : '.$sql,ERROR,'');
626
				}
627
				$this->trapLog('SQL insertion OK',3,'');
628
				// Get last id to insert oid/values in secondary table
629
				if (($inserted_id_ret=$ret_code->fetch(PDO::FETCH_ASSOC)) == FALSE) {
630
														   
631
					$this->trapLog('Erreur recuperation id',ERROR,'');
632
				}
633
				if (! isset($inserted_id_ret['id'])) {
634
					$this->trapLog('Error getting id',ERROR,'');
635
				}
636
				$this->trap_id=$inserted_id_ret['id'];
637
			break;
638
			case 'mysql': 
639
				$sql .= ';';
640
				$this->trapLog('sql : '.$sql,3,'');
641
				if ($db_conn->query($sql) == FALSE) {
642
					$this->trapLog('Error SQL insert : '.$sql,ERROR,'');
643
				}
644
				$this->trapLog('SQL insertion OK',3,'');
645
				// Get last id to insert oid/values in secondary table
646
				$sql='SELECT LAST_INSERT_ID();';
647
				if (($ret_code=$db_conn->query($sql)) == FALSE) {
648
					$this->trapLog('Erreur recuperation id',ERROR,'');
649
				}
650
651
				$inserted_id=$ret_code->fetch(PDO::FETCH_ASSOC)['LAST_INSERT_ID()'];
652
				if ($inserted_id==false) throw new Exception("Weird SQL error : last_insert_id returned false : open issue");
653
				$this->trap_id=$inserted_id;
654
			break;
655
			default: 
656
				$this->trapLog('Error SQL type  : '.$this->trapDBType,ERROR,'');
657
		}
658
		$this->trapLog('id found: '.$this->trap_id,3,'');
659
		
660
		// Fill trap extended data table
661
		foreach ($this->trap_data_ext as $value) {			
662
			// TODO : detect if trap value is encoded and decode it to UTF-8 for database
663
			$firstcol=1;
664
			$value->trap_id = $this->trap_id;
665
			$insert_col='';
666
			$insert_val='';
667
			foreach ($value as $col => $val)
668
			{
669
				if ($firstcol==0) 
670
				{
671
					$insert_col .=',';
672
					$insert_val .=',';
673
				}
674
				$insert_col .= $col;
675
				$insert_val .= ($val==null)? 'NULL' : $db_conn->quote($val);
676
				$firstcol=0;
677
			}
678
679
			$sql= 'INSERT INTO '.$this->db_prefix.'received_data (' . $insert_col . ') VALUES ('.$insert_val.');';			
680
681
			if (($ret_code=$db_conn->query($sql)) == FALSE) {
682
				$this->trapLog('Erreur insertion data : ' . $sql,WARN,'');
683
			}	
684
		}	
685
	}
686
687
	/** Get rules from rule database with ip and oid
688
	*	@param $ip string ipv4 or ipv6
689
	*	@param $oid string oid in numeric
690
	*	@return mixed : PDO object or false
691
	*/	
692
	protected function getRules($ip,$oid)
693
	{
694
		$db_conn=$this->db_connect_trap();
695
		// fetch rules based on IP in rule and OID
696
		$sql='SELECT * from '.$this->db_prefix.'rules WHERE trap_oid=\''.$oid.'\' ';
697
		$this->trapLog('SQL query : '.$sql,4,'');
698
		if (($ret_code=$db_conn->query($sql)) == FALSE) {
699
			$this->trapLog('No result in query : ' . $sql,WARN,'');
700
			return false;
701
		}
702
		$rules_all=$ret_code->fetchAll();
703
		//echo "rule all :\n";print_r($rules_all);echo "\n";
704
		$rules_ret=array();
705
		$rule_ret_key=0;
706
		foreach ($rules_all as $key => $rule)
707
		{
708
			if ($rule['ip4']==$ip || $rule['ip6']==$ip)
709
			{
710
				$rules_ret[$rule_ret_key]=$rules_all[$key];
711
				//TODO : get host name by API (and check if correct in rule).
712
				$rule_ret_key++;
713
				continue;
714
			}
715
			// TODO : get hosts IP by API
716
			if (isset($rule['host_group_name']) && $rule['host_group_name']!=null)
717
			{ // get ips of group members by oid
718
				$db_conn2=$this->db_connect_ido();
719
				$sql="SELECT m.host_object_id, a.address as ip4, a.address6 as ip6, b.name1 as host_name
720
						FROM icinga_objects as o
721
						LEFT JOIN icinga_hostgroups as h ON o.object_id=h.hostgroup_object_id
722
						LEFT JOIN icinga_hostgroup_members as m ON h.hostgroup_id=m.hostgroup_id
723
						LEFT JOIN icinga_hosts as a ON a.host_object_id = m.host_object_id
724
						LEFT JOIN icinga_objects as b ON b.object_id = a.host_object_id
725
						WHERE o.name1='".$rule['host_group_name']."';";
726
				if (($ret_code2=$db_conn2->query($sql)) == FALSE) {
727
					$this->trapLog('No result in query : ' . $sql,WARN,'');
728
					continue;
729
				}
730
				$grouphosts=$ret_code2->fetchAll();
731
				//echo "rule grp :\n";print_r($grouphosts);echo "\n";
732
				foreach ( $grouphosts as $host)
733
				{
734
					//echo $host['ip4']."\n";
735
					if ($host['ip4']==$ip || $host['ip6']==$ip)
736
					{
737
						//echo "Rule added \n";
738
						$rules_ret[$rule_ret_key]=$rules_all[$key];
739
						$rules_ret[$rule_ret_key]['host_name']=$host['host_name'];
740
						$rule_ret_key++;
741
					}	
742
				}
743
			}
744
		}
745
		//echo "rule rest :\n";print_r($rules_ret);echo "\n";exit(0);
746
		return $rules_ret;
747
	}
748
749
	/** Add rule match to rule
750
	*	@param id int : rule id
751
	*   @param set int : value to set
752
	*/
753
	protected function add_rule_match($id, $set)
754
	{
755
		$db_conn=$this->db_connect_trap();
756
		$sql="UPDATE ".$this->db_prefix."rules SET num_match = '".$set."' WHERE (id = '".$id."');";
757
		if ($db_conn->query($sql) === false) {
758
			$this->trapLog('Error in update query : ' . $sql,WARN,'');
759
		}
760
	}
761
	
762
	/** Send SERVICE_CHECK_RESULT with icinga2cmd or API
763
	 * 
764
	 * @param string $host
765
	 * @param string $service
766
	 * @param integer $state numerical staus 
767
	 * @param string $display
768
	 * @returnn bool true is service check was sent without error
769
	*/
770
	public function serviceCheckResult($host,$service,$state,$display)
771
	{
772
	    if ($this->api_use === false)
773
	    {
774
    		$send = '[' . date('U') .'] PROCESS_SERVICE_CHECK_RESULT;' .
775
    			$host.';' .$service .';' . $state . ';'.$display;
776
    		$this->trapLog( $send." : to : " .$this->icinga2cmd,3,'');
777
    		
778
    		// TODO : file_put_contents & fopen (,'w' or 'a') does not work. See why. Or not as using API will be by default....
779
    		exec('echo "'.$send.'" > ' .$this->icinga2cmd);
780
    		return true;
781
	    }
782
	    else
783
	    {
784
	        $api = $this->getAPI();
785
	        $api->setCredentials($this->api_username, $this->api_password);
786
	        list($retcode,$retmessage)=$api->serviceCheckResult($host,$service,$state,$display);
787
	        if ($retcode == false)
788
	        {
789
	            $this->trapLog( "Error sending result : " .$retmessage,WARN,'');
790
	            return false;
791
	        }
792
	        else 
793
	        {
794
	            $this->trapLog( "Sent result : " .$retmessage,3,'');
795
	            return true;
796
	        }
797
	    }
798
	}
799
	
800
	public function getHostByIP($ip)
801
	{
802
	    $api = $this->getAPI();
803
	    $api->setCredentials($this->api_username, $this->api_password);
804
	    return $api->getHostByIP($ip);
805
	}
806
	
807
	/** Resolve display. 
808
	*	Changes OID(<oid>) to value if found or text "<not in trap>"
809
	*	@param $display string
810
	*	@return string display
811
	*/
812
	protected function applyDisplay($display)
813
	{
814
	    $matches=array();
815
	    while (preg_match('/_OID\(([0-9\.]+)\)/',$display,$matches) == 1)
816
		{
817
			$oid=$matches[1];
818
			$found=0;
819
			foreach($this->trap_data_ext as $val)
820
			{
821
				if ($oid == $val->oid)
822
				{
823
					$val->value=preg_replace('/"/','',$val->value);
824
					$rep=0;
825
					$display=preg_replace('/_OID\('.$oid.'\)/',$val->value,$display,-1,$rep);
826
					if ($rep==0)
827
					{
828
						$this->trapLog("Error in display",WARN,'');
829
						return $display;
830
					}
831
					$found=1;
832
					break;
833
				}
834
			}
835
			if ($found==0)
836
			{
837
				$display=preg_replace('/_OID\('.$oid.'\)/','<not in trap>',$display,-1,$rep);
838
				if ($rep==0)
839
				{
840
					$this->trapLog("Error in display",WARN,'');
841
					return $display;
842
				}				
843
			}
844
		}
845
		return $display;
846
	}
847
848
	
849
	/***************** Eval & tokenizer functions ****************/
850
	protected function eval_getElement($rule,&$item)
851
	{
852
		while ($rule[$item]==' ') $item++;
853
		if (preg_match('/[0-9\.]/',$rule[$item]))
854
		{ // number
855
	
856
			$item2=$item+1; 
857
			while (($item2!=strlen($rule)) && (preg_match('/[0-9\.]/',$rule[$item2]))) { $item2++ ;}
858
			$val=substr($rule,$item,$item2-$item);
859
			$item=$item2;
860
			//echo "number ".$val."\n";
861
			return array(0,$val);
862
		}
863
		if ($rule[$item] == '"')
864
		{ // string
865
			$item++;
866
			$item2=$this->eval_getNext($rule,$item,'"');
867
			$val=substr($rule,$item,$item2-$item-1);
868
			$item=$item2;
869
			//echo "string : ".$val."\n";
870
			return array(1,$val);
871
		}
872
		
873
		if ($rule[$item] == '(')
874
		{ // grouping
875
		    $item++;
876
			$start=$item;
877
			$parenthesis_count=0; 
878
			while (($item < strlen($rule)) // Not end of string AND
879
			      && ( ($rule[$item] != ')' ) || $parenthesis_count > 0) ) // Closing ')' or embeded ()
880
			{ 
881
				if ($rule[$item] == '"' )
882
				{ // pass through string
883
					$item++;
884
					$item=$this->eval_getNext($rule,$item,'"');
885
				} 
886
				else{
887
				    if ($rule[$item] == '(')
888
				    {
889
				        $parenthesis_count++;
890
				    }
891
				    if ($rule[$item] == ')')
892
				    {
893
				        $parenthesis_count--;
894
				    }
895
					$item++;
896
				}
897
			}
898
			
899
			if ($item==strlen($rule)) {throw new Exception("no closing () in ".$rule ." at " .$item);}
900
			$val=substr($rule,$start,$item-$start);
901
			$item++;
902
			$start=0;
903
			//echo "group : ".$val."\n";
904
			// returns evaluation of group as type 2 (boolean)
905
			return array(2,$this->evaluation($val,$start));		
906
		}
907
		throw new Exception("number/string not found in ".$rule ." at " .$item . ' : ' .$rule[$item]);
908
		
909
	}
910
	
911
	protected function eval_getNext($rule,$item,$tok)
912
	{
913
		while (($rule[$item] != $tok ) && ($item < strlen($rule))) { $item++;}
914
		if ($item==strlen($rule)) throw new Exception("closing '".$tok."' not found in ".$rule ." at " .$item);
915
		return $item+1;
916
	}
917
	
918
	protected function eval_getOper($rule,&$item)
919
	{
920
		while ($rule[$item]==' ') $item++;
921
		switch ($rule[$item])
922
		{
923
			case '<':
924
				if ($rule[$item+1]=='=') { $item+=2; return array(0,"<=");}
925
				$item++; return array(0,"<");
926
			case '>':
927
				if ($rule[$item+1]=='=') { $item+=2; return array(0,">=");}
928
				$item++; return array(0,">");
929
			case '=':
930
				$item++; return array(0,"=");	
931
			case '!':
932
				if ($rule[$item+1]=='=') { $item+=2; return array(0,"!=");}
933
				throw new Exception("Erreur in expr - incorrect operator '!'  found in ".$rule ." at " .$item);
934
			case '~':
935
				$item++; return array(0,"~");	
936
			case '|':
937
				$item++; return array(1,"|");	
938
			case '&':
939
				$item++; return array(1,"&");
940
			default	:
941
				throw new Exception("Erreur in expr - operator not found in ".$rule ." at " .$item);
942
		}
943
	}
944
	
945
	/** Evaluation : makes token and evaluate. 
946
	*	Public function for expressions testing
947
	*	accepts : < > = <= >= !=  (typec = 0)
948
	*	operators : & | (typec=1)
949
	*	with : integers/float  (type 0) or strings "" (type 1) or results (type 2)
950
	*   comparison int vs strings will return null (error)
951
	*	return : bool or null on error
952
	*/
953
	public function evaluation($rule,&$item)
954
	{
955
	    //echo "Evaluation of ".substr($rule,$item)."\n";
956
		if ( $rule[$item] == '!') // If '!' found, negate next expression.
957
		{
958
		    $negate=true;
959
		    $item++;
960
		}
961
		else
962
		{
963
		    $negate=false;
964
		}
965
		// First element : number, string or ()
966
		list($type1,$val1) = $this->eval_getElement($rule,$item);
967
		//echo "Elmt1: ".$val1."/".$type1." : ".substr($rule,$item)."\n";
968
		
969
		if ($item==strlen($rule)) // If only element, return value, but only boolean
970
		{
971
		  if ($type1 != 2) throw new Exception("Cannot use num/string as boolean : ".$rule);
972
		  if ($negate === true) $val1= ! $val1;
973
		  return $val1;
974
		}  
975
		
976
		// Second element : operator
977
		list($typec,$comp) = $this->eval_getOper($rule,$item);
978
		//echo "Comp : ".$comp." : ".substr($rule,$item)."\n";
979
        
980
		// Third element : number, string or ()
981
		if ( $rule[$item] == '!') // starts with a ! so evaluate whats next
982
		{
983
		    $item++;
984
		    if ($typec != 1) throw new Exception("Mixing boolean and comparison : ".$rule);
985
		    $val2= ! $this->evaluation($rule,$item);
986
		    $type2=2; // result is a boolean 
987
		}
988
		else 
989
		{
990
		    list($type2,$val2) = $this->eval_getElement($rule,$item);
991
		}
992
		//echo "Elmt2: ".$val2."/".$type2." : ".substr($rule,$item)."\n";
993
		
994
		if ($type1!=$type2)  // cannot compare different types
995
		{ 
996
		    throw new Exception("Cannot compare string & number : ".$rule);
997
		}
998
		if ($typec==1 && $type1 !=2) // cannot use & or | with string/number
999
		{
1000
		    throw new Exception("Cannot use boolean operators with string & number : ".$rule);
1001
		}
1002
		
1003
		switch ($comp){
1004
			case '<':	$retVal= ($val1 < $val2); break;
1005
			case '<=':	$retVal= ($val1 <= $val2); break;
1006
			case '>':	$retVal= ($val1 > $val2); break;
1007
			case '>=':	$retVal= ($val1 >= $val2); break;
1008
			case '=':	$retVal= ($val1 == $val2); break;
1009
			case '!=':	$retVal= ($val1 != $val2); break;
1010
			case '~':	$retVal= (preg_match('/'.preg_replace('/"/','',$val2).'/',$val1)); break;
1011
			case '|':	$retVal= ($val1 || $val2); break;
1012
			case '&':	$retVal= ($val1 && $val2); break;
1013
			default:  throw new Exception("Error in expression - unknown comp : ".$comp);
1014
		}
1015
		if ($negate === true) $retVal = ! $retVal; // Inverse result if negate before expression
1016
		
1017
		if ($item==strlen($rule)) return $retVal; // End of string : return evaluation
1018
		// check for logical operator :
1019
		switch ($rule[$item])
1020
		{
1021
			case '|':	$item++; return ($retVal || $this->evaluation($rule,$item) );
1022
			case '&':	$item++; return ($retVal && $this->evaluation($rule,$item) );
1023
			
1024
			default:  throw new Exception("Erreur in expr - garbadge at end of expression : ".$rule[$item]);
1025
		}
1026
	}
1027
	// Remove all whitespaces (when not quoted)
1028
	public function eval_cleanup($rule)
1029
	{
1030
		$item=0;
1031
		$rule2='';
1032
		while ($item < strlen($rule))
1033
		{
1034
			if ($rule[$item]==' ') { $item++; continue; }
1035
			if ($rule[$item]=='"')
1036
			{
1037
				$rule2.=$rule[$item];
1038
				$item++;
1039
				while (($rule[$item]!='"') && ($item < strlen($rule)))
1040
				{
1041
					$rule2.=$rule[$item];
1042
					$item++;
1043
				}
1044
				if ($item == strlen ($rule)) throw new Exception("closing '\"' not found in ".$rule ." at " .$item);
1045
				$rule2.=$rule[$item];
1046
				$item++;
1047
				continue;
1048
			}
1049
			
1050
			$rule2.=$rule[$item];
1051
			$item++;		
1052
		}
1053
		
1054
		return $rule2;		
1055
	}		
1056
	
1057
	/** Evaluation rule (uses eval_* functions recursively)
1058
	*	@param $rule string rule ( _OID(.1.3.6.1.4.1.8072.2.3.2.1)=_OID(.1.3.6.1.2.1.1.3.0) )
1059
	*	@return bool : true : rule match, false : rule don't match , throw exception on error.
1060
	*/
1061
	
1062
	protected function eval_rule($rule)
1063
	{
1064
		if ($rule==null || $rule == '') // Empty rule is always true
1065
		{
1066
			return true;
1067
		}
1068
		$matches=array();
1069
		while (preg_match('/_OID\(([0-9\.\*]+)\)/',$rule,$matches) == 1)
1070
		{
1071
			$oid=$matches[1];
1072
			$found=0;
1073
			// ** replaced by .*
1074
			$oidR=preg_replace('/\*\*/', '.*', $oid);
1075
			// * replaced by [^.]*  
1076
			$oidR=preg_replace('/\*/', '[0-9]+', $oidR);
1077
			
1078
			// replace * with \* in oid for preg_replace
1079
			$oid=preg_replace('/\*/', '\*', $oid);
1080
			
1081
			$this->trapLog('OID in rule : '.$oid.' / '.$oidR,4,'');
1082
			
1083
			foreach($this->trap_data_ext as $val)
1084
			{
1085
				if (preg_match("/^$oidR$/",$val->oid) == 1)
1086
				{
1087
					if (!preg_match('/^[0-9]*\.?[0-9]+$/',$val->value))
1088
					{ // If not a number, change " to ' and put " around it
1089
						$val->value=preg_replace('/"/',"'",$val->value);
1090
						$val->value='"'.$val->value.'"';
1091
					}
1092
					$rep=0;
1093
					$rule=preg_replace('/_OID\('.$oid.'\)/',$val->value,$rule,-1,$rep);
1094
					if ($rep==0)
1095
					{
1096
						$this->trapLog("Error in rule_eval",WARN,'');
1097
						return false;
1098
					}
1099
					$found=1;
1100
					break;
1101
				}
1102
			}
1103
			if ($found==0)
1104
			{	// OID not found : throw error
1105
			    throw new Exception('OID '.$oid.' not found in trap');
1106
			}
1107
		}
1108
		$item=0;
1109
		$rule=$this->eval_cleanup($rule);
1110
		$this->trapLog('Rule after clenup: '.$rule,3,'');
1111
		
1112
		return  $this->evaluation($rule,$item);
1113
	}
1114
	
1115
	/** Match rules for current trap and do action
1116
	*/
1117
	public function applyRules()
1118
	{
1119
		$rules = $this->getRules($this->trap_data['source_ip'],$this->trap_data['trap_oid']);
1120
		
1121
		if ($rules===false || count($rules)==0)
1122
		{
1123
			$this->trapLog('No rules found for this trap',3,'');
1124
			$this->trap_data['status']='unknown';
1125
			$this->trap_to_db=true;
1126
			return;
1127
		}
1128
		//print_r($rules);
1129
		// Evaluate all rules in sequence
1130
		$this->trap_action=null;
1131
		foreach ($rules as $rule)
1132
		{
1133
			
1134
			$host_name=$rule['host_name'];
1135
			$service_name=$rule['service_name'];
1136
			
1137
			$display=$this->applyDisplay($rule['display']);
1138
			$this->trap_action = ($this->trap_action==null)? '' : $this->trap_action . ', ';
1139
			try
1140
			{
1141
				$this->trapLog('Rule to eval : '.$rule['rule'],3,'');
1142
				$evalr=$this->eval_rule($rule['rule']);
1143
				
1144
				if ($evalr == true)
1145
				{
1146
					//$this->trapLog('rules OOK: '.print_r($rule),3,'');
1147
					$action=$rule['action_match'];
1148
					$this->trapLog('action OK : '.$action,3,'');
1149
					if ($action >= 0)
1150
					{
1151
						if ($this->serviceCheckResult($host_name,$service_name,$action,$display) == false)
1152
						{
1153
						    $this->trap_action.='Error sending status : check cmd/API';
1154
						}
1155
						else
1156
						{
1157
						    $this->add_rule_match($rule['id'],$rule['num_match']+1);
1158
						    $this->trap_action.='Status '.$action.' to '.$host_name.'/'.$service_name;
1159
						}
1160
					}
1161
					else
1162
					{
1163
						$this->add_rule_match($rule['id'],$rule['num_match']+1);
1164
					}
1165
					$this->trap_to_db=($action==-2)?false:true;
1166
				}
1167
				else
1168
				{
1169
					//$this->trapLog('rules KOO : '.print_r($rule),3,'');
1170
					
1171
					$action=$rule['action_nomatch'];
1172
					$this->trapLog('action NOK : '.$action,3,'');
1173
					if ($action >= 0)
1174
					{
1175
					    if ($this->serviceCheckResult($host_name,$service_name,$action,$display)==false)
1176
					    {
1177
					        $this->trap_action.='Error sending status : check cmd/API';
1178
					    }
1179
					    else
1180
					    {
1181
    						$this->add_rule_match($rule['id'],$rule['num_match']+1);
1182
    						$this->trap_action.='Status '.$action.' to '.$host_name.'/'.$service_name;
1183
					    }
1184
					}
1185
					else
1186
					{
1187
						$this->add_rule_match($rule['id'],$rule['num_match']+1);
1188
					}
1189
					$this->trap_to_db=($action==-2)?false:true;					
1190
				}
1191
				// Put name in source_name
1192
				if (!isset($this->trap_data['source_name']))
1193
				{
1194
					$this->trap_data['source_name']=$rule['host_name'];
1195
				}
1196
				else
1197
				{
1198
					if (!preg_match('/'.$rule['host_name'].'/',$this->trap_data['source_name']))
1199
					{ // only add if not present
1200
						$this->trap_data['source_name'].=','.$rule['host_name'];
1201
					}
1202
				}
1203
			}
1204
			catch (Exception $e) 
1205
			{ 
1206
			    $this->trapLog('Error in rule eval : '.$e->getMessage(),WARN,'');
1207
			    $this->trap_action.=' ERR : '.$e->getMessage();
1208
			    $this->trap_data['status']='error';
1209
			}
1210
			
1211
		}
1212
		if ($this->trap_data['status']=='error')
1213
		{
1214
		  $this->trap_to_db=true; // Always put errors in DB for the use can see
1215
		}
1216
		else
1217
		{
1218
		  $this->trap_data['status']='done';
1219
		}
1220
	}
1221
1222
	/** Add Time a action to rule
1223
	*	@param string $time : time to process to insert in SQL
1224
	*/
1225
	public function add_rule_final($time)
1226
	{
1227
		$db_conn=$this->db_connect_trap();
1228
		if ($this->trap_action==null) 
1229
		{
1230
			$this->trap_action='No action';
1231
		}
1232
		$sql="UPDATE ".$this->db_prefix."received SET process_time = '".$time."' , status_detail='".$this->trap_action."'  WHERE (id = '".$this->trap_id."');";
1233
		if ($db_conn->query($sql) == FALSE) {
1234
			$this->trapLog('Error in update query : ' . $sql,WARN,'');
1235
		}
1236
	}
1237
	
1238
	/*********** UTILITIES *********************/
1239
	
1240
	/** Create database schema 
1241
	*	@param $schema_file	string File to read schema from
1242
	*	@param $table_prefix string to replace #PREFIX# in schema file by this
1243
	*/
1244
	public function create_schema($schema_file,$table_prefix)
1245
	{
1246
		//Read data from snmptrapd from stdin
1247
		$input_stream=fopen($schema_file, 'r');
1248
1249
		if ($input_stream==FALSE)
1250
		{
1251
			$this->trapLog("Error reading schema !",ERROR,''); 
1252
			return;
1253
		}
1254
		$newline='';
1255
		$cur_table='';
1256
		$cur_table_array=array();
1257
		$db_conn=$this->db_connect_trap();
1258
		
1259
		while (($line=fgets($input_stream)) !== false)
1260
		{
1261
			$newline.=chop(preg_replace('/#PREFIX#/',$table_prefix,$line));
1262
			if (preg_match('/; *$/', $newline)) 
1263
            {
1264
                $sql= $newline;
1265
                if ($db_conn->query($sql) == FALSE) {
1266
                    $this->trapLog('Error create schema : '.$sql,ERROR,'');
1267
                }
1268
                if (preg_match('/^ *CREATE TABLE ([^ ]+)/',$newline,$cur_table_array))
1269
                {
1270
                    $cur_table='table '.$cur_table_array[1];
1271
                }
1272
                else
1273
                {
1274
                    $cur_table='secret SQL stuff :-)';
1275
                }
1276
                $this->trapLog('Creating : ' . $cur_table, 3,'');
1277
                $newline='';
1278
            }
1279
		}
1280
		
1281
		$sql= $newline;
1282
		if ($sql != '')
1283
		{
1284
    		if ($db_conn->query($sql) == FALSE) {
1285
    			$this->trapLog('Error create schema : '.$sql,ERROR,'');
1286
    		}
1287
		}
1288
		$this->trapLog('Schema created',3);		
1289
	}
1290
1291
	/** 
1292
	 * Update database schema from current (as set in db) to $target_version
1293
	 *     @param $prefix string file prefix of sql update File
1294
	 *     @param $target_version int target db version number
1295
	 *     @param $table_prefix string to replace #PREFIX# in schema file by this
1296
	 *     @param bool $getmsg : only get messages from version upgrades
1297
	 *     @return string : if $getmsg=true, return messages.
1298
	 */
1299
	public function update_schema($prefix,$target_version,$table_prefix,$getmsg=false)
1300
	{
1301
	    // Get current db number
1302
	    $db_conn=$this->db_connect_trap();
1303
	    $sql='SELECT id,value from '.$this->db_prefix.'db_config WHERE name=\'db_version\' ';
1304
	    $this->trapLog('SQL query : '.$sql,4,'');
1305
	    if (($ret_code=$db_conn->query($sql)) == FALSE) {
1306
	        $this->trapLog('Cannot get db version. Query : ' . $sql,2,'');
1307
	        return;
1308
	    }
1309
	    $version=$ret_code->fetchAll();
1310
	    $cur_version=$version[0]['value'];
1311
	    $db_version_id=$version[0]['id'];
1312
	    
1313
	    if ($this->trapDBType == 'pgsql')
1314
	    {
1315
	        $prefix .= 'update_pgsql/schema_';
1316
	    }
1317
	    else
1318
	    {
1319
	        $prefix .= 'update_sql/schema_';
1320
	    }
1321
	    //echo "version all :\n";print_r($version);echo " \n $cur_ver \n";
1322
	    if ($getmsg === true)
1323
	    {
1324
	        $message='';
1325
	        $this->trapLog('getting message for upgrade',4,'');
1326
	        while($cur_version<$target_version)
1327
	        {
1328
	            $cur_version++;
1329
	            $updateFile=$prefix.'v'.($cur_version-1).'_v'.$cur_version.'.sql';
1330
	            $input_stream=fopen($updateFile, 'r');
1331
	            if ($input_stream==FALSE)
1332
	            {
1333
	                $this->trapLog("Error reading update file ". $updateFile,2,'');
1334
	                return;
1335
	            }
1336
	            do { $line=fgets($input_stream); }
1337
	            while ($line !== false && !preg_match('/#MESSAGE/',$line));
1338
	            if ($line === false)
1339
	            {
1340
	                $this->trapLog("No message in file ". $updateFile,2,'');
1341
	                return;
1342
	            }
1343
	            $message .= ($cur_version-1) . '->' . $cur_version. ' : ' . preg_replace('/#MESSAGE : /','',$line)."\n";
1344
	        }
1345
	        return $message;
1346
	    }
1347
	    while($cur_version<$target_version)
1348
	    { // tODO : execute pre & post scripts
1349
	       $cur_version++;
1350
	       $this->trapLog('Updating to version : ' .$cur_version ,3,'');
1351
	       $updateFile=$prefix.'v'.($cur_version-1).'_v'.$cur_version.'.sql';
1352
	       $input_stream=fopen($updateFile, 'r');
1353
	       if ($input_stream==FALSE)
1354
	       {
1355
	           $this->trapLog("Error reading update file ". $updateFile,2,'');
1356
	           return;
1357
	       }
1358
	       $newline='';
1359
	       $db_conn=$this->db_connect_trap();
1360
	       $db_conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
1361
	       while (($line=fgets($input_stream)) !== false)
1362
	       {
1363
	           if (preg_match('/^#/', $line)) continue; // ignore comment lines
1364
	           $newline.=chop(preg_replace('/#PREFIX#/',$table_prefix,$line));
1365
	           if (preg_match('/; *$/', $newline))
1366
	           {
1367
	               $sql_req=$db_conn->prepare($newline);
1368
	               if ($sql_req->execute() === false) {
1369
	                   $this->trapLog('Error create schema : '.$newline,1,'');
1370
	               }
1371
	               $cur_table_array=array();
1372
	               if (preg_match('/^ *([^ ]+) TABLE ([^ ]+)/',$newline,$cur_table_array))
1373
	               {
1374
	                   $cur_table=$cur_table_array[1] . ' SQL table '.$cur_table_array[2];
1375
	               }
1376
	               else
1377
	               {
1378
	                   $cur_table='secret SQL stuff :-)';
1379
	                   //$cur_table=$newline;
1380
	               }
1381
	               $this->trapLog('Doing : ' . $cur_table, 3,'');
1382
	               
1383
	               $newline='';
1384
	           }
1385
	       }
1386
	       fclose($input_stream);
1387
	       
1388
	       //$sql= $newline;
1389
	       //if ($db_conn->query($sql) == FALSE) {
1390
	       //    $this->trapLog('Error updating schema : '.$sql,1,'');
1391
	       //}
1392
	       
1393
	       $sql='UPDATE '.$this->db_prefix.'db_config SET value='.$cur_version.' WHERE ( id = '.$db_version_id.' )';
1394
	       $this->trapLog('SQL query : '.$sql,4,'');
1395
	       if (($db_conn->query($sql) === false) {
1396
	           $this->trapLog('Cannot update db version. Query : ' . $sql,2,'');
0 ignored issues
show
Bug introduced by
A parse error occurred: Syntax error, unexpected ';' on line 1396 at column 76
Loading history...
1397
	           return;
1398
	       }
1399
	       
1400
	       $this->trapLog('Schema updated to version : '.$cur_version ,3);
1401
	    }
1402
	}
1403
	
1404
	/** reset service to OK after time defined in rule
1405
	*	TODO logic is : get all service in error + all rules, see if getting all rules then select services is better 
1406
	*	@return : like a plugin : status code (0->3) <message> | <perfdata>
1407
	**/
1408
	public function reset_services()
1409
	{
1410
		// Get all services not in 'ok' state
1411
		$sql_query="SELECT s.service_object_id,
1412
	 UNIX_TIMESTAMP(s.last_check) AS last_check,
1413
	s.current_state as state,
1414
	v.name1 as host_name,
1415
    v.name2 as service_name
1416
	FROM icinga_servicestatus AS s 
1417
    LEFT JOIN icinga_objects as v ON s.service_object_id=v.object_id
1418
    WHERE s.current_state != 0;";
1419
		$db_conn=$this->db_connect_ido();
1420
		if (($services_db=$db_conn->query($sql_query)) == FALSE) { // set err to 1 to throw exception.
1421
			$this->trapLog('No result in query : ' . $sql_query,ERROR,'');
1422
		}
1423
		$services=$services_db->fetchAll();
1424
		
1425
		// Get all rules
1426
		$sql_query="SELECT host_name, service_name, revert_ok FROM ".$this->db_prefix."rules where revert_ok != 0;";
1427
		$db_conn2=$this->db_connect_trap();
1428
		if (($rules_db=$db_conn2->query($sql_query)) == FALSE) {
1429
			$this->trapLog('No result in query : ' . $sql_query,ERROR,''); 
1430
		}
1431
		$rules=$rules_db->fetchAll();
1432
		
1433
		$now=date('U');
1434
		
1435
		$numreset=0;
1436
		foreach ($rules as $rule)
1437
		{
1438
			foreach ($services as $service)
1439
			{
1440
				if ($service['service_name'] == $rule['service_name'] &&
1441
					$service['host_name'] == $rule['host_name'] &&
1442
					($service['last_check'] + $rule['revert_ok']) < $now)
1443
				{
1444
					$this->serviceCheckResult($service['host_name'],$service['service_name'],0,'Reset service to OK after '.$rule['revert_ok'].' seconds');
1445
					$numreset++;
1446
				}
1447
			}
1448
		}
1449
		echo "\n";
1450
		echo $numreset . " service(s) reset to OK\n";
1451
		return 0;
1452
		
1453
	}
1454
1455
	
1456
	/*********** MIB cache update functions *********************/
1457
	
1458
	/**
1459
	 * Update or add an OID to database uses $this->dbOidIndex for mem cache
1460
	 * @param string $oid
1461
	 * @param string $mib
1462
	 * @param string $name
1463
	 * @param string $type
1464
	 * @param string $textConv
1465
	 * @param string $dispHint
1466
	 * @param string $syntax
1467
	 * @param string $type_enum
1468
	 * @param string $description
1469
	 * @return number : 0=unchanged, 1 = changed, 2=created
1470
	 */
1471
	public function update_oid($oid,$mib,$name,$type,$textConv,$dispHint,$syntax,$type_enum,$description=NULL)
1472
	{
1473
		$db_conn=$this->db_connect_trap();
1474
		$description=$db_conn->quote($description);
1475
		if (isset($this->dbOidIndex[$oid]))
1476
		{
1477
		    if ($this->dbOidIndex[$oid]['key'] == -1)
1478
		    { // newly created.
1479
		        return 0;
1480
		    }
1481
			if ( $name != $this->dbOidAll[$this->dbOidIndex[$oid]['key']]['name'] ||
1482
			    $mib != $this->dbOidAll[$this->dbOidIndex[$oid]['key']]['mib'] ||
1483
			    $type != $this->dbOidAll[$this->dbOidIndex[$oid]['key']]['type'] //||
1484
			    //$textConv != $this->dbOidAll[$this->dbOidIndex[$oid]['key']]['textual_convention'] //||
1485
			    //$dispHint != $this->dbOidAll[$this->dbOidIndex[$oid]['key']]['display_hint'] ||
1486
			    //$syntax != $this->dbOidAll[$this->dbOidIndex[$oid]['key']]['syntax'] ||
1487
			    //$type_enum != $this->dbOidAll[$this->dbOidIndex[$oid]['key']]['type_enum'] ||
1488
			    //$description != $this->dbOidAll[$this->dbOidIndex[$oid]['key']]['description']
1489
			    )
1490
			{ // Do update
1491
			    $sql='UPDATE '.$this->db_prefix.'mib_cache SET '.
1492
 			    'name = :name , type = :type , mib = :mib , textual_convention = :tc , display_hint = :display_hint'. 
1493
 			    ', syntax = :syntax, type_enum = :type_enum, description = :description '.
1494
 			    ' WHERE id= :id';
1495
			    $sqlQuery=$db_conn->prepare($sql);
1496
			    
1497
			    $sqlParam=array(
1498
			        ':name' => $name,
1499
			        ':type' => $type, 
1500
			        ':mib' => $mib, 
1501
			        ':tc' =>  ($textConv==null)?'null':$textConv , 
1502
			        ':display_hint' => ($dispHint==null)?'null':$dispHint ,
1503
			        ':syntax' => ($syntax==null)?'null':$syntax,
1504
			        ':type_enum' => ($type_enum==null)?'null':$type_enum, 
1505
			        ':description' => ($description==null)?'null':$description,
1506
			        ':id' => $this->dbOidAll[$this->dbOidIndex[$oid]['id']]
1507
			    );
1508
			    
1509
			    if ($sqlQuery->execute($sqlParam) === false) {
1510
			        $this->trapLog('Error in query : ' . $sql,ERROR,'');
1511
			    }
1512
			    $this->trapLog('Trap updated : '.$name . ' / OID : '.$oid,4,'');
1513
				return 1;
1514
			}
1515
			else
1516
			{
1517
			    $this->trapLog('Trap unchanged : '.$name . ' / OID : '.$oid,4,'');
1518
			    return 0;
1519
			}
1520
		}
1521
        // create new OID.
1522
			
1523
		// Insert data
1524
1525
		$sql='INSERT INTO '.$this->db_prefix.'mib_cache '.
1526
		      '(oid, name, type , mib, textual_convention, display_hint '.
1527
              ', syntax, type_enum , description ) ' . 
1528
              'values (:oid, :name , :type ,:mib ,:tc , :display_hint'.
1529
              ', :syntax, :type_enum, :description )';
1530
        
1531
		if ($this->trapDBType == 'pgsql') $sql .= 'RETURNING id';
1532
		
1533
		$sqlQuery=$db_conn->prepare($sql);
1534
		
1535
		$sqlParam=array(
1536
		    ':oid' => $oid,
1537
		    ':name' => $name,
1538
		    ':type' => $type,
1539
		    ':mib' => $mib,
1540
		    ':tc' =>  ($textConv==null)?'null':$textConv ,
1541
		    ':display_hint' => ($dispHint==null)?'null':$dispHint ,
1542
		    ':syntax' => ($syntax==null)?'null':$syntax,
1543
		    ':type_enum' => ($type_enum==null)?'null':$type_enum,
1544
		    ':description' => ($description==null)?'null':$description
1545
		);
1546
		
1547
		if ($sqlQuery->execute($sqlParam) === false) {
1548
		    $this->trapLog('Error in query : ' . $sql,1,'');
1549
		}
1550
		
1551
		switch ($this->trapDBType)
1552
		{
1553
		    case 'pgsql':
1554
		        // Get last id to insert oid/values in secondary table
1555
		        if (($inserted_id_ret=$sqlQuery->fetch(PDO::FETCH_ASSOC)) == FALSE) {		            
1556
		            $this->trapLog('Error getting id - pgsql - ',1,'');
1557
		        }
1558
		        if (! isset($inserted_id_ret['id'])) {
1559
		            $this->trapLog('Error getting id - pgsql - empty.',1,'');
1560
		        }
1561
		        $this->dbOidIndex[$oid]['id']=$inserted_id_ret['id'];
1562
		        break;
1563
		    case 'mysql':
1564
		        // Get last id to insert oid/values in secondary table
1565
		        $sql='SELECT LAST_INSERT_ID();';
1566
		        if (($ret_code=$db_conn->query($sql)) == FALSE) {
1567
		            $this->trapLog('Erreur getting id - mysql - ',1,'');
1568
		        }
1569
		        
1570
		        $inserted_id=$ret_code->fetch(PDO::FETCH_ASSOC)['LAST_INSERT_ID()'];
1571
		        if ($inserted_id==false) throw new Exception("Weird SQL error : last_insert_id returned false : open issue");
1572
		        $this->dbOidIndex[$oid]['id']=$inserted_id;
1573
		        break;
1574
		    default:
1575
		        $this->trapLog('Error SQL type  : '.$this->trapDBType,1,'');
1576
		}
1577
1578
		// Set as newly created.
1579
		$this->dbOidIndex[$oid]['key']=-1;
1580
		return 2;
1581
	}
1582
1583
    /**
1584
     * create or update (with check_existing = true) objects of trap
1585
     * @param string $trapOID : trap oid
1586
     * @param string $trapmib : mib of trap
1587
     * @param array $objects : array of objects name (without MIB)
1588
     * @param bool $check_existing : check instead of create
1589
     */
1590
	public function trap_objects($trapOID,$trapmib,$objects,$check_existing)
1591
	{
1592
	    $dbObjects=null; // cache of objects for trap in db
1593
	    $db_conn=$this->db_connect_trap();
1594
	    
1595
	    // Get id of trapmib.
1596
1597
	    $trapId = $this->dbOidIndex[$trapOID]['id'];
1598
	    if ($check_existing === true)
1599
	    {
1600
	        // Get all objects
1601
	        $sql='SELECT * FROM '.$this->db_prefix.'mib_cache_trap_object where trap_id='.$trapId.';';
1602
	        $this->trapLog('SQL query get all traps: '.$sql,4,'');
1603
	        if (($ret_code=$db_conn->query($sql)) == FALSE) {
1604
	            $this->trapLog('No result in query : ' . $sql,1,'');
1605
	        }
1606
	        $dbObjectsRaw=$ret_code->fetchAll();
1607
	        
1608
	        foreach ($dbObjectsRaw as $val)
1609
	        {
1610
	            $dbObjects[$val['object_id']]=1;
1611
	        }
1612
	    }
1613
	    foreach ($objects as $object)
1614
	    {
1615
	        $match=$snmptrans=array();
1616
	        $retVal=0;
1617
	        $objOid=$objTc=$objDispHint=$objSyntax=$objDesc=$objEnum=NULL;
1618
	        $tmpdesc='';$indesc=false;
1619
	        
1620
	        $objMib=$trapmib;
1621
	        exec($this->snmptranslate . ' -m ALL -M +'.$this->snmptranslate_dirs.
1622
	            ' -On -Td '.$objMib.'::'.$object . ' 2>/dev/null',$snmptrans,$retVal);
1623
	        if ($retVal!=0)
1624
	        {
1625
	            // Maybe not trap mib, search with IR
1626
	            exec($this->snmptranslate . ' -m ALL -M +'.$this->snmptranslate_dirs.
1627
	                ' -IR '.$object . ' 2>/dev/null',$snmptrans,$retVal);
1628
	            if ($retVal != 0 || !preg_match('/(.*)::(.*)/',$snmptrans[0],$match))
1629
	            { // Not found -> continue with warning
1630
	               $this->trapLog('Error finding trap object : '.$trapmib.'::'.$object,2,'');
1631
	               continue;
1632
	            }
1633
	            $objMib=$match[1];
1634
	            
1635
	            // Do the snmptranslate again.
1636
	            exec($this->snmptranslate . ' -m ALL -M +'.$this->snmptranslate_dirs.
1637
	                ' -On -Td '.$objMib.'::'.$object,$snmptrans,$retVal);
1638
	            if ($retVal!=0) {
1639
	                $this->trapLog('Error finding trap object : '.$objMib.'::'.$object,2,'');
1640
	            }
1641
	            
1642
	        }
1643
	        foreach ($snmptrans as $line)
1644
	        {
1645
	            if ($indesc===true)
1646
	            {
1647
	                $line=preg_replace('/[\t ]+/',' ',$line);
1648
	                if (preg_match('/(.*)"$/', $line,$match))
1649
	                {
1650
	                    $objDesc = $tmpdesc . $match[1];
1651
	                    $indesc=false;
1652
	                }
1653
	                $tmpdesc.=$line;
1654
	                continue;
1655
	            }
1656
	            if (preg_match('/^\.[0-9\.]+$/', $line))
1657
	            {
1658
	                $objOid=$line;
1659
	                continue;
1660
	            }
1661
	            if (preg_match('/^[\t ]+SYNTAX[\t ]+([^{]*) \{(.*)\}/',$line,$match))
1662
	            {
1663
	                $objSyntax=$match[1];
1664
                    $objEnum=$match[2];
1665
	                continue;
1666
	            }
1667
	            if (preg_match('/^[\t ]+SYNTAX[\t ]+(.*)/',$line,$match))
1668
	            {
1669
	                $objSyntax=$match[1];
1670
	                continue;
1671
	            }
1672
	            if (preg_match('/^[\t ]+DISPLAY-HINT[\t ]+"(.*)"/',$line,$match))
1673
	            {
1674
	                $objDispHint=$match[1];
1675
	                continue;
1676
	            }
1677
	            if (preg_match('/^[\t ]+DESCRIPTION[\t ]+"(.*)"/',$line,$match))
1678
	            {
1679
	                $objDesc=$match[1];
1680
	                continue;
1681
	            }
1682
	            if (preg_match('/^[\t ]+DESCRIPTION[\t ]+"(.*)/',$line,$match))
1683
	            {
1684
	                $tmpdesc=$match[1];
1685
	                $indesc=true;
1686
	                continue;
1687
	            }
1688
	            if (preg_match('/^[\t ]+-- TEXTUAL CONVENTION[\t ]+(.*)/',$line,$match))
1689
	            {
1690
	                $objTc=$match[1];
1691
	                continue;
1692
	            }
1693
	        }
1694
	        $this->trapLog("Adding trap $object : $objOid / $objSyntax / $objEnum / $objDispHint / $objTc",4,'');
1695
	        //echo "$object : $objOid / $objSyntax / $objEnum / $objDispHint / $objTc / $objDesc\n";
1696
	        // Update 
1697
	        $this->update_oid($objOid, $objMib, $object, '3', $objTc, $objDispHint, $objSyntax, $objEnum,$objDesc);
1698
            
1699
	        if (isset($dbObjects[$this->dbOidIndex[$objOid]['id']]))
1700
	        {   // if link exists, continue
1701
	            $dbObjects[$this->dbOidIndex[$objOid]['id']]=2;
1702
	            continue;
1703
	        }
1704
	        if ($check_existing === true) 
1705
	        {
1706
	            // TODO : check link trap - objects exists, mark them.
1707
	        }
1708
	        // Associate in object table
1709
	        $sql='INSERT INTO '.$this->db_prefix.'mib_cache_trap_object (trap_id,object_id) '.
1710
	   	        'values (:trap_id, :object_id)';	        
1711
	        $sqlQuery=$db_conn->prepare($sql);	        
1712
	        $sqlParam=array(
1713
	            ':trap_id' => $trapId,
1714
	            ':object_id' => $this->dbOidIndex[$objOid]['id'],
1715
	        );
1716
	        
1717
	        if ($sqlQuery->execute($sqlParam) === false) {
1718
	            $this->trapLog('Error adding trap object : ' . $sql . ' / ' . $trapId . '/'. $this->dbOidIndex[$objOid]['id'] ,1,'');
1719
	        }
1720
	    }
1721
	    if ($check_existing === true)
1722
	    {
1723
	        // TODO : remove link trap - objects that wasn't marked.
1724
	    }
1725
	    
1726
	}
1727
	
1728
	/** 
1729
	 * Cache mib in database
1730
	 * @param boolean $display_progress : Display progress on standard output
1731
	 * @param boolean $check_change : Force check of trap params & objects
1732
	 * @param boolean $onlyTraps : only cache traps and objects (true) or all (false)
1733
	 * @param string $startOID : only cache under startOID (NOT IMPLEMENTED)
1734
	*/	
1735
	public function update_mib_database($display_progress=false,$check_change=false,$onlyTraps=true,$startOID='.1')
1736
	{
1737
		// Timing 
1738
		$timeTaken = microtime(true);
1739
		$retVal=0;
1740
		// Get all mib objects from all mibs
1741
		$snmpCommand=$this->snmptranslate . ' -m ALL -M +'.$this->snmptranslate_dirs.' -On -Tto 2>/dev/null';
1742
		$this->trapLog('Getting all traps : '.$snmpCommand,4,'');
1743
		unset($this->objectsAll);
1744
		exec($snmpCommand,$this->objectsAll,$retVal);		
1745
		if ($retVal!=0)
1746
		{
1747
			$this->trapLog('error executing snmptranslate',ERROR,'');
1748
		}
1749
		
1750
		// Get all mibs from databse to have a memory index
1751
		
1752
		$db_conn=$this->db_connect_trap();
1753
		
1754
		$sql='SELECT * from '.$this->db_prefix.'mib_cache;';
1755
		$this->trapLog('SQL query : '.$sql,4,'');
1756
		if (($ret_code=$db_conn->query($sql)) == FALSE) {
1757
			$this->trapLog('No result in query : ' . $sql,ERROR,'');
1758
		}
1759
		$this->dbOidAll=$ret_code->fetchAll();
1760
		$this->dbOidIndex=array();
1761
		// Create the index for db;
1762
		foreach($this->dbOidAll as $key=>$val)
1763
		{
1764
			$this->dbOidIndex[$val['oid']]['key']=$key;
1765
			$this->dbOidIndex[$val['oid']]['id']=$val['id'];
1766
		}
1767
		
1768
		// Count elements to show progress
1769
		$numElements=count($this->objectsAll);
1770
		$this->trapLog('Total snmp objects returned by snmptranslate : '.$numElements,3,'');
1771
		
1772
		$step=$basestep=$numElements/10; // output display of % done
1773
		$num_step=0;
1774
		$timeFiveSec = microtime(true); // Used for display a '.' every <n> seconds
1775
		
1776
		// Create index for trap objects
1777
		$this->trapObjectsIndex=array();
1778
		
1779
		// detailed timing (time_* vars)
1780
		$time_parse1=$time_check1=$time_check2=$time_check3=$time_update=$time_objects=0;
1781
		$time_parse1N=$time_check1N=$time_check2N=$time_check3N=$time_updateN=$time_objectsN=0;
1782
		$time_num_traps=0;
1783
		
1784
		for ($curElement=0;$curElement < $numElements;$curElement++)
1785
		{
1786
		    $time_1= microtime(true);
1787
			if ((microtime(true)-$timeFiveSec) > 2 && $display_progress)
1788
			{ // echo a . every 2 sec
1789
				echo '.';
1790
				$timeFiveSec = microtime(true);
1791
			}
1792
			if ($curElement>$step) 
1793
			{ // display progress
1794
				$num_step++;
1795
				$step+=$basestep;
1796
				if ($display_progress)
1797
				{				
1798
					echo "\n" . ($num_step*10). '% : ';
1799
				}
1800
			}
1801
			// Get oid or pass if not found
1802
			if (!preg_match('/^\.[0-9\.]+$/',$this->objectsAll[$curElement]))
1803
			{
1804
			    $time_parse1 += microtime(true) - $time_1;
1805
			    $time_parse1N ++;
1806
				continue;
1807
			}
1808
			$oid=$this->objectsAll[$curElement];
1809
			
1810
			// get next line 
1811
			$curElement++;
1812
			$match=$snmptrans=array();
1813
			if (!preg_match('/ +([^\(]+)\(.+\) type=([0-9]+)( tc=([0-9]+))?( hint=(.+))?/',
1814
						$this->objectsAll[$curElement],$match))
1815
			{
1816
			    $time_check1 += microtime(true) - $time_1;
1817
				$time_check1N++;
1818
				continue;
1819
			}
1820
			
1821
			$name=$match[1]; // Name 
1822
			$type=$match[2]; // type (21=trap, 0: may be trap, else : not trap
1823
			
1824
			if ($type==0) // object type=0 : check if v1 trap
1825
			{
1826
				// Check if next is suboid -> in that case is cannot be a trap
1827
				if (preg_match("/^$oid/",$this->objectsAll[$curElement+1]))
1828
				{
1829
				    $time_check2 += microtime(true) - $time_1;
1830
				    $time_check2N++;
1831
					continue;
1832
				}		
1833
				unset($snmptrans);
1834
				exec($this->snmptranslate . ' -m ALL -M +'.$this->snmptranslate_dirs.
1835
					' -Td '.$oid . ' | grep OBJECTS ',$snmptrans,$retVal);
1836
				if ($retVal!=0)
1837
				{
1838
				    $time_check2 += microtime(true) - $time_1;
1839
				    $time_check2N++;
1840
					continue;
1841
				}
1842
				//echo "\n v1 trap found : $oid \n";
1843
				// Force as trap.
1844
				$type=21;
1845
			}
1846
			if ($onlyTraps===true && $type!=21) // if only traps and not a trap, continue
1847
			{
1848
			    $time_check3 += microtime(true) - $time_1;
1849
				$time_check3N++;
1850
				continue;
1851
			}
1852
			
1853
			$time_num_traps++;
1854
			
1855
			$this->trapLog('Found trap : '.$match[1] . ' / OID : '.$oid,3,'');
1856
			if ($display_progress) echo '#'; // echo a # when trap found
1857
				
1858
			// get trap objects & source MIB
1859
			unset($snmptrans);
1860
			exec($this->snmptranslate . ' -m ALL -M +'.$this->snmptranslate_dirs.
1861
					' -Td '.$oid,$snmptrans,$retVal);
1862
			if ($retVal!=0)
1863
			{
1864
				$this->trapLog('error executing snmptranslate',ERROR,'');
1865
			}
1866
			
1867
			if (!preg_match('/^(.*)::/',$snmptrans[0],$match))
1868
			{
1869
			    $this->trapLog('Error getting mib from trap '.$oid.' : ' . $snmptrans[0],1,'');
1870
			}
1871
			$trapMib=$match[1];
1872
			
1873
			$numLine=1;$trapDesc='';
1874
			while (isset($snmptrans[$numLine]) && !preg_match('/^[\t ]+DESCRIPTION[\t ]+"(.*)/',$snmptrans[$numLine],$match)) $numLine++;
1875
			if (isset($snmptrans[$numLine]))
1876
			{
1877
			    $snmptrans[$numLine] = preg_replace('/^[\t ]+DESCRIPTION[\t ]+"/','',$snmptrans[$numLine]);
1878
1879
			    while (isset($snmptrans[$numLine]) && !preg_match('/"/',$snmptrans[$numLine]))
1880
			    {
1881
			        $trapDesc.=preg_replace('/[\t ]+/',' ',$snmptrans[$numLine]);
1882
			        $numLine++;
1883
			    }
1884
			    if (isset($snmptrans[$numLine])) {
1885
			        $trapDesc.=preg_replace('/".*/','',$snmptrans[$numLine]);
1886
			        $trapDesc=preg_replace('/[\t ]+/',' ',$trapDesc);
1887
			    }
1888
1889
			}
1890
			$update=$this->update_oid($oid,$trapMib,$name,$type,NULL,NULL,NULL,NULL,$trapDesc);
1891
			$time_update += microtime(true) - $time_1; $time_1= microtime(true);
1892
			
1893
			if (($update==0) && ($check_change===false))
1894
			{ // Trapd didn't change & force check disabled
1895
			    $time_objects += microtime(true) - $time_1;
1896
			    if ($display_progress) echo "C";
1897
			    continue;
1898
			}
1899
			
1900
			$synt=null;
1901
			foreach ($snmptrans as $line)
1902
			{	
1903
    			if (preg_match('/OBJECTS.*\{([^\}]+)\}/',$line,$match))
1904
    				{
1905
    					$synt=$match[1];
1906
    				}
1907
			}
1908
			if ($synt == null) 
1909
			{
1910
				//echo "No objects for $trapOID\n";
1911
			    $time_objects += microtime(true) - $time_1;
1912
				continue;
1913
			}
1914
			//echo "$synt \n";
1915
			$trapObjects=array();
1916
			while (preg_match('/ *([^ ,]+) *,* */',$synt,$match))
1917
			{
1918
				array_push($trapObjects,$match[1]);
1919
				$synt=preg_replace('/'.$match[0].'/','',$synt);
1920
			}
1921
			
1922
			$this->trap_objects($oid, $trapMib, $trapObjects, false);
1923
			
1924
			$time_objects += microtime(true) - $time_1;
1925
			$time_objectsN++;
1926
		}
1927
		
1928
		if ($display_progress)
1929
		{
1930
    		echo "\nNumber of processed traps : $time_num_traps \n";
1931
    		echo "\nParsing : " . number_format($time_parse1+$time_check1,1) ." sec / " . ($time_parse1N+ $time_check1N)  . " occurences\n";
1932
    		echo "Detecting traps : " . number_format($time_check2+$time_check3,1) . " sec / " . ($time_check2N+$time_check3N) ." occurences\n";
1933
    		echo "Trap processing ($time_updateN): ".number_format($time_update,1)." sec , ";
1934
    		echo "Objects processing ($time_objectsN) : ".number_format($time_objects,1)." sec \n";
1935
		}
1936
		
1937
		// Timing ends
1938
		$timeTaken=microtime(true) - $timeTaken;
1939
		if ($display_progress)
1940
		{
1941
		    echo "Global time : ".round($timeTaken)." seconds\n";
1942
		}
1943
		
1944
	}
1945
	
1946
}
1947
1948
?>
1949