1<?php
2
3# Check we have been included via subnet-scan-excute.php and not called directly
4require("subnet-scan-check-included.php");
5
6/*
7 * Discover new hosts with snmp
8 *******************************/
9
10//title
11print "<h5>"._('Scan results').":</h5><hr>";
12
13# scan disabled
14if ($User->settings->enableSNMP!="1")           { $Result->show("danger", _("SNMP module disbled"), true); }
15# subnet check
16$subnet = $Subnets->fetch_subnet ("id", $_POST['subnetId']);
17if ($subnet===false)                            { $Result->show("danger", _("Invalid subnet Id"), true);  }
18
19# verify that user has write permissionss for subnet
20if($Subnets->check_permission ($User->user, $_POST['subnetId']) != 3) 	{ $Result->show("danger", _('You do not have permissions to modify hosts in this subnet')."!", true, true); }
21
22# set class
23$Snmp = new phpipamSNMP ();
24
25// fetch all existing hosts
26$all_subnet_hosts = (array) $Addresses->fetch_subnet_addresses ($_POST['subnetId']);
27// reindex
28if (sizeof($all_subnet_hosts)>0) {
29    foreach ($all_subnet_hosts as $h) {
30        $subnet_ip_addresses[] = $Subnets->transform_address($h->ip_addr, "dotted");
31    }
32}
33
34# set selected address fields array
35$selected_ip_fields = $User->settings->IPfilter;
36$selected_ip_fields = explode(";", $selected_ip_fields);
37
38// no errors
39error_reporting(E_ERROR);
40
41# fetch devices that use get_routing_table query
42$devices_used = $Tools->fetch_multiple_objects ("devices", "snmp_queries", "%get_arp_table%", "id", true, true);
43
44# filter out not in this section
45if ($devices_used !== false) {
46    foreach ($devices_used as $d) {
47        // get possible sections
48        $permitted_sections = explode(";", $d->sections);
49        // check
50        if (in_array($subnet->sectionId, $permitted_sections)) {
51            $permitted_devices[] = $d;
52        }
53    }
54}
55
56// if none set die
57if (!isset($permitted_devices))                 { $Result->show("danger", _("No devices for SNMP ARP query available"), true); }
58
59// ok, we have devices, connect to each device and do query
60foreach ($permitted_devices as $d) {
61    // init
62    $Snmp->set_snmp_device ($d);
63    // fetch arp table
64    try {
65        $res = $Snmp->get_query("get_arp_table");
66        // remove those not in subnet
67        if (is_array($res) && sizeof($res)>0) {
68           // save for debug
69           $debug[$d->hostname]["get_arp_table"] = $res;
70           // check
71           foreach ($res as $kr=>$r) {
72               // if is inside subnet
73               if ($Subnets->is_subnet_inside_subnet ($r['ip']."/32", $Subnets->transform_address($subnet->subnet, "dotted")."/".$subnet->mask)===false) { }
74               // check if host already exists, than remove it
75               elseif (in_array($r['ip'], $subnet_ip_addresses)) { }
76               // save
77               else {
78                   $found[$d->id][] = $r;
79               }
80           }
81        }
82        // get interfaces
83        $res = $Snmp->get_query("get_interfaces_ip");
84        // remove those not in subnet
85        if (is_array($res) && sizeof($res)>0) {
86           // save for debug
87           $debug[$d->hostname]["get_interfaces_ip"] = $res;
88           // check
89           foreach ($res as $kr=>$r) {
90               // if is inside subnet
91               if ($Subnets->is_subnet_inside_subnet ($r['ip']."/32", $Subnets->transform_address($subnet->subnet, "dotted")."/".$subnet->mask)===false) { }
92               // check if host already exists, than remove it
93               elseif (in_array($r['ip'], $subnet_ip_addresses)) { }
94               // save
95               else {
96                   $found[$d->id][] = $r;
97               }
98           }
99        }
100    } catch (Exception $e) {
101       // save for debug
102       $debug[$d->hostname]['get_arp_table'] = $res;
103       $errors[] = $e->getMessage();
104	}
105}
106
107# none and errors
108if(sizeof($found)==0 && isset($errors))          {
109    $Result->show("info", _("No new hosts found"), false);
110    $Result->show("warning", implode("<hr>", $errors), false);
111}
112# none
113elseif(sizeof($found)==0) 	                     { $Result->show("info", _("No new hosts found")."!", false); }
114# ok
115else {
116	// fetch subnet and set nsid
117	$nsid = $subnet===false ? false : $subnet->nameserverId;
118
119    // fetch custom fields and check for required
120    $Tools = new Tools ($Database);
121    $required_fields = $Tools->fetch_custom_fields ('ipaddresses');
122    if($required_fields!==false) {
123        foreach ($required_fields as $k=>$f) {
124            if ($f['Null']!="NO") {
125                unset($required_fields[$k]);
126            }
127        }
128    }
129
130    // calculate colspan
131	$colspan = 5 + sizeof(@$required_fields);
132	// port
133	if(in_array('port', $selected_ip_fields)) { $colspan++; }
134
135
136	//form
137	print "<form name='scan-snmp-arp-form' class='scan-snmp-arp-form'>";
138	print "<input type='hidden' name='csrf_cookie' value='$csrf'>";
139	print "<table class='table table-striped table-top table-condensed'>";
140
141	// titles
142	print "<tr>";
143	print "	<th>"._("IP")."</th>";
144	print "	<th>"._("Description")."</th>";
145	print "	<th>"._("MAC")."</th>";
146	print "	<th>"._("Hostname")."</th>";
147	// port
148	if(in_array('port', $selected_ip_fields)) {
149	print "	<th>"._('Port')."</th>";
150	}
151    // custom
152	if (isset($required_fields)) {
153		foreach ($required_fields as $field) {
154            print "<th>"._($field['name'])."</th>";
155		}
156    }
157	print "	<th></th>";
158	print "</tr>";
159
160	// alive
161	$m=0;
162	foreach($found as $deviceid=>$device) {
163    	foreach ($device as $ip ) {
164            print "<tr class='result$m'>";
165    		//resolve?
166    		$hostname = $DNS->resolve_address($ip['ip'], false, true, $nsid);
167
168    		//ip
169    		print "<td>$ip[ip]</td>";
170    		//description, ip, device
171    		print "<td>";
172    		print "	<input type='text' class='form-control input-sm' name='description$m'>";
173    		print "	<input type='hidden' name='ip$m' value='$ip[ip]'>";
174    		print "	<input type='hidden' name='device$m' value='$deviceid'>";
175    		print "</td>";
176    		// mac
177    		print "<td>";
178    		print "	<input type='text' class='form-control input-sm' name='mac$m' value='$ip[mac]'>";
179    		print "</td>";
180    		//hostname
181    		print "<td>";
182    		print "	<input type='text' class='form-control input-sm' name='hostname$m' value='".@$hostname['name']."'>";
183    		print "</td>";
184    		// port
185    		if(in_array('port', $selected_ip_fields)) {
186    		print "<td>";
187    		print "	<input type='text' class='form-control input-sm' name='port$m' value='".@$ip['port']."'>";
188    		print "</td>";
189    		}
190    		// custom
191    		if (isset($required_fields)) {
192        		foreach ($required_fields as $field) {
193        			# replace spaces with |
194        			$field['nameNew'] = str_replace(" ", "___", $field['name']);
195
196        			print '	<td>'. "\n";
197
198        			//set type
199        			if(substr($field['type'], 0,3) == "set" || substr($field['type'], 0,4) == "enum") {
200        				//parse values
201        				$tmp = substr($field['type'], 0,3)=="set" ? explode(",", str_replace(array("set(", ")", "'"), "", $field['type'])) : explode(",", str_replace(array("enum(", ")", "'"), "", $field['type']));
202        				//null
203        				if($field['Null']!="NO") { array_unshift($tmp, ""); }
204
205        				print "<select name='$field[nameNew]$m' class='form-control input-sm input-w-auto' rel='tooltip' data-placement='right' title='$field[Comment]'>";
206        				foreach($tmp as $v) {
207        					if($v==@$address[$field['name']])	{ print "<option value='$v' selected='selected'>$v</option>"; }
208        					else								{ print "<option value='$v'>$v</option>"; }
209        				}
210        				print "</select>";
211        			}
212        			//date and time picker
213        			elseif($field['type'] == "date" || $field['type'] == "datetime") {
214        				// just for first
215        				if($timeP==0) {
216        					print '<link rel="stylesheet" type="text/css" href="css/bootstrap/bootstrap-datetimepicker.min.css?v='.SCRIPT_PREFIX.'">';
217        					print '<script src="js/bootstrap-datetimepicker.min.js?v='.SCRIPT_PREFIX.'"></script>';
218        					print '<script>';
219        					print '$(document).ready(function() {';
220        					//date only
221        					print '	$(".datepicker").datetimepicker( {pickDate: true, pickTime: false, pickSeconds: false });';
222        					//date + time
223        					print '	$(".datetimepicker").datetimepicker( { pickDate: true, pickTime: true } );';
224
225        					print '})';
226        					print '</script>';
227        				}
228        				$timeP++;
229
230        				//set size
231        				if($field['type'] == "date")	{ $size = 10; $class='datepicker';		$format = "yyyy-MM-dd"; }
232        				else							{ $size = 19; $class='datetimepicker';	$format = "yyyy-MM-dd"; }
233
234        				//field
235        				if(!isset($address[$field['name']]))	{ print ' <input type="text" class="'.$class.' form-control input-sm input-w-auto" data-format="'.$format.'" name="'. $field['nameNew'].$m .'" maxlength="'.$size.'" '.$delete.' rel="tooltip" data-placement="right" title="'.$field['Comment'].'">'. "\n"; }
236        				else									{ print ' <input type="text" class="'.$class.' form-control input-sm input-w-auto" data-format="'.$format.'" name="'. $field['nameNew'].$m .'" maxlength="'.$size.'" value="'. $address[$field['name']]. '" '.$delete.' rel="tooltip" data-placement="right" title="'.$field['Comment'].'">'. "\n"; }
237        			}
238        			//boolean
239        			elseif($field['type'] == "tinyint(1)") {
240        				print "<select name='$field[nameNew]$m' class='form-control input-sm input-w-auto' rel='tooltip' data-placement='right' title='$field[Comment]'>";
241        				$tmp = array(0=>"No",1=>"Yes");
242        				//null
243        				if($field['Null']!="NO") { $tmp[2] = ""; }
244
245        				foreach($tmp as $k=>$v) {
246        					if(strlen(@$address[$field['name']])==0 && $k==2)	{ print "<option value='$k' selected='selected'>"._($v)."</option>"; }
247        					elseif($k==@$address[$field['name']])				{ print "<option value='$k' selected='selected'>"._($v)."</option>"; }
248        					else												{ print "<option value='$k'>"._($v)."</option>"; }
249        				}
250        				print "</select>";
251        			}
252        			//default - input field
253        			else {
254        				print ' <input type="text" class="ip_addr form-control input-sm" name="'. $field['nameNew'].$m .'" placeholder="'. $field['name'] .'" value="'. @$address[$field['name']]. '" size="30" '.$delete.' rel="tooltip" data-placement="right" title="'.$field['Comment'].'">'. "\n";
255        			}
256
257                    print " </td>";
258        		}
259    		}
260    		//remove button
261    		print 	"<td><a href='' class='btn btn-xs btn-danger resultRemove' data-target='result$m'><i class='fa fa-times'></i></a></td>";
262    		print "</tr>";
263
264    		$m++;
265		}
266	}
267
268	//submit
269	print "<tr>";
270	print "	<td colspan='$colspan'>";
271	print "<div id='subnetScanAddResult'></div>";
272	print "		<a href='' class='btn btn-sm btn-success pull-right' id='saveScanResults' data-script='scan-snmp-arp' data-subnetId='".$_POST['subnetId']."'><i class='fa fa-plus'></i> "._("Add discovered hosts")."</a>";
273	print "	</td>";
274	print "</tr>";
275
276	print "</table>";
277	print "</form>";
278
279    // print errors
280    if (isset($errors)) {
281        print "<hr>";
282        foreach ($errors as $e) {
283            print $Result->show ("warning", $e, false);
284        }
285    }
286}
287
288//print scan method
289print "<div class='text-right' style='margin-top:7px;'>";
290print " <span class='muted'>";
291print " Scan method: SNMP ARP<hr>";
292print " Scanned devices: <br>";
293foreach ($debug as $k=>$d) {
294    print "&middot; ".$k."<br>";
295}
296print "</span>";
297print "</div>";
298
299# show debug?
300if($_POST['debug']==1) 				{ print "<pre>"; print_r($debug); print "</pre>"; }