package ch.rakudave.jnetmap.net;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.Map.Entry;
import org.snmp4j.CommunityTarget;
import org.snmp4j.PDU;
import org.snmp4j.Snmp;
import org.snmp4j.TransportMapping;
import org.snmp4j.event.ResponseEvent;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.smi.Integer32;
import org.snmp4j.smi.OID;
import org.snmp4j.smi.OctetString;
import org.snmp4j.smi.UdpAddress;
import org.snmp4j.smi.VariableBinding;
import org.snmp4j.transport.DefaultUdpTransportMapping;
import ch.rakudave.jnetmap.controller.Scheduler;
import ch.rakudave.jnetmap.model.IF.NetworkIF;
import ch.rakudave.jnetmap.model.IF.PhysicalIF;
import ch.rakudave.jnetmap.model.device.Device;
import ch.rakudave.jnetmap.util.IO;
import ch.rakudave.jnetmap.util.Settings;
import ch.rakudave.jnetmap.util.logging.Logger;
/**
* @author techdive.in
* @author sebehuber
* @author rakudave
*/
public class SNMP {
/**
* This Method returns a HashMap with the description of the SNMP OID as Key
* and the Result from the SNMP Request as Value. The request is sent to the
* InetAddress given by parameter. The request goes over the specified Port
* in the Preferences. The request which get executed are stored in the file
* MIB. Other request can easily be added manually in the MIB file.
*
* @param InetAddress
* address
* @return HashMap
*/
public static HashMap<String, String> getValues(InetAddress address) {
// fail fast
if (address == null || !PortScan.isOpen(address, Settings.getInt("snmp.port", 161))) {
return null;
}
String ipAddress = address.toString();
HashMap<String, String> oid = new HashMap<String, String>();
ResponseEvent response = null;
TransportMapping transport = null;
String oidValue = "0";
//int count = 0;
Properties p = new Properties();
final File f = new File(IO.userDir, "MIB");
String descr;
// read from File MIB the oids to request over SNMP
Logger.debug("Loading MIB");
FileInputStream fis = null;
try {
fis = new FileInputStream(f);
p.load(fis);
} catch (IOException e) {
Logger.error("Failed to open MIB.", e);
} finally {
try {
fis.close();
} catch (Exception e) {
}
}// end reading
try {
transport = new DefaultUdpTransportMapping();
transport.listen();
} catch (IOException e) {
}
// Create Target Address object
CommunityTarget comtarget = new CommunityTarget();
comtarget.setCommunity(new OctetString(Settings.get("snmp.community", "public")));
comtarget.setVersion(SnmpConstants.version1);
comtarget.setAddress(new UdpAddress(ipAddress + "/" + Settings.getInt("snmp.port", 161)));
comtarget.setRetries(2);
comtarget.setTimeout(1000);
// Create the PDU object
// Create Snmp object
Snmp snmp = new Snmp(transport);
// Iterating over map
for (Entry<Object, Object> entry : p.entrySet()) {
oidValue = entry.getValue().toString();
descr = entry.getKey().toString();
PDU pdu = new PDU();
pdu.add(new VariableBinding(new OID(oidValue)));
pdu.setRequestID(new Integer32(1));
pdu.setType(PDU.GET);
try {
response = snmp.get(pdu, comtarget);
} catch (IOException e) {
}
// Process Agent Response
if (response != null) {
PDU responsePDU = response.getResponse();
if (responsePDU != null) {
int errorStatus = responsePDU.getErrorStatus();
int errorIndex = responsePDU.getErrorIndex();
String errorStatusText = responsePDU.getErrorStatusText();
if (errorStatus == PDU.noError) {
String resp = (String) responsePDU.getVariableBindings().toString();
// Split answer into OID and description
String[] helperArray = resp.replaceAll("[\\[|\\]]", "").split(" = ");
if (helperArray.length > 1) {
oid.put(descr, helperArray[1]);
//count++;
} else {
Logger.debug("SNMP: Request failed" + ": Error status = " + errorStatus + ": Error sndex = " + errorIndex + ": Error text = " + errorStatusText);
}
} else {
Logger.debug("SNMP: GetNextResponse PDU is null");
}
} else {
Logger.debug("SNMP: Timeout");
}
}
}
try {
snmp.close();
} catch (IOException e) {
Logger.error("SNMP: couldn't close connection");
}
return oid;
}
public static void inferProperties(final Device d) {
Scheduler.execute(new Runnable() {
@Override
public void run() {
Map<String, String> m = null;
for (NetworkIF nif : d.getInterfaces()) {
m = getValues(nif.getAddress());
if (m != null) {
inferProperties(nif);
break;
}
}
if (m == null) return;
d.setName(m.get("Name"));
d.setDescription(m.get("Descr"));
}
});
}
public static void inferProperties(NetworkIF nif) {
Map<String, String> m = getValues(nif.getAddress());
if (m == null) return;
try {
if (m.get("IF-speed") != null) nif.getConnection().setBandwidth(Double.valueOf(m.get("IF-speed"))/1000000);
} catch (Exception e) {
Logger.warn("Unable to set interface speed", e);
}
if (m.get("MAC-address") != null && nif instanceof PhysicalIF) ((PhysicalIF)nif).setMacAddress(m.get("MAC-address"));
}
}