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

Trap::eval_getElement()   C

Complexity

Conditions 14
Paths 32

Size

Total Lines 58
Code Lines 34

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 14
eloc 34
nc 32
nop 2
dl 0
loc 58
rs 6.2666
c 0
b 0
f 0

How to fix   Long Method    Complexity   

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:

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