/*
* Copyright 2010 NCHOVY
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.krakenapps.snmp;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Vector;
import org.krakenapps.api.Script;
import org.krakenapps.api.ScriptContext;
import org.krakenapps.api.ScriptUsage;
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.OID;
import org.snmp4j.smi.OctetString;
import org.snmp4j.smi.UdpAddress;
import org.snmp4j.smi.VariableBinding;
import org.snmp4j.transport.DefaultUdpTransportMapping;
public class SnmpScript implements Script {
private SnmpTrapService trap;
private ScriptContext context;
public SnmpScript(SnmpTrapService trap) {
this.trap = trap;
}
@Override
public void setScriptContext(ScriptContext context) {
this.context = context;
}
public void trapbindings(String[] args) {
context.println("Trap Bindings");
context.println("---------------");
for (String name : trap.getBindingNames())
context.println(name + " => " + trap.getBinding(name));
}
@ScriptUsage(description = "trace snmp trap packet")
public void trace(String[] args) {
Map<String, String> filters = new HashMap<String, String>();
for (String arg : args) {
int p = arg.indexOf("=");
String key = arg.substring(0, p);
String value = arg.substring(p + 1);
filters.put(key, value);
context.println("applying filter " + key + " => " + value);
}
context.println("press ctrl-c to stop");
context.println("----------------------");
Tracer tracer = new Tracer(filters);
trap.addReceiver(tracer);
try {
while (true) {
context.readLine();
}
} catch (InterruptedException e) {
context.println("interrupted");
} finally {
trap.removeReceiver(tracer);
}
}
private class Tracer implements SnmpTrapReceiver {
private Map<String, String> filters;
public Tracer(Map<String, String> filters) {
this.filters = filters;
}
@Override
public void handle(SnmpTrap trap) {
String remote = trap.getRemoteAddress().getAddress().getHostAddress() + ":" + trap.getRemoteAddress().getPort();
if (filters != null && !checkFilter(trap))
return;
context.println(remote + " " + trap.getVariableBindings());
}
private boolean checkFilter(SnmpTrap trap) {
for (String key : filters.keySet()) {
String expected = filters.get(key);
Object value = trap.getVariableBindings().get(key);
String actual = null;
if (value != null)
actual = value.toString();
if ((expected == null || expected.isEmpty())) {
if (actual == null)
continue;
else
return false;
}
if (actual == null)
return false;
if (!expected.equals(actual))
return false;
}
return true;
}
}
public void get(String[] args) {
Map<String, String> options = parseOptions(args);
String version = options.get("-v");
String community = options.get("-c");
String host = options.get("-h");
String port = options.get("-p");
String oid = args[args.length - 1];
// .1.3.6.1.2.1.25.1.1.0
if (version.equals("2c")) {
getV2(host, port, community, oid);
}
}
private static HashMap<String, Integer> methodMap = new HashMap<String, Integer>();
static {
methodMap.put("GET", PDU.GET);
methodMap.put("GETNEXT", PDU.GETNEXT);
methodMap.put("GETBULK", PDU.GETBULK);
}
private int getMethod(String method) {
Integer ret = methodMap.get(method.toUpperCase());
if (ret != null) {
return ret;
} else {
return -1;
}
}
public void getsubtree(String[] args) {
Map<String, String> options = parseOptions(args);
String community = options.get("-c");
String host = options.get("-h");
String port = options.get("-p");
String oid = args[args.length - 1];
Snmp snmp = null;
TransportMapping transport = null;
try {
CommunityTarget commTarget = new CommunityTarget();
commTarget.setCommunity(new OctetString(community));
commTarget.setVersion(SnmpConstants.version2c);
commTarget.setAddress(new UdpAddress(host + "/" + port));
commTarget.setRetries(2);
commTarget.setTimeout(3000);
transport = new DefaultUdpTransportMapping();
transport.listen();
snmp = new Snmp(transport);
PDU pdu = new PDU();
pdu.add(new VariableBinding(new OID(oid)));
pdu.setType(PDU.GETBULK);
pdu.setMaxRepetitions(10);
ArrayList<VariableBinding> results = new ArrayList<VariableBinding>();
OID ifEntryOid = new OID(oid);
while (true) {
ResponseEvent response = null;
response = snmp.getBulk(pdu, commTarget);
PDU responsePdu = response.getResponse();
if (responsePdu == null) {
throw new RuntimeException(response.getError());
}
@SuppressWarnings("unchecked")
Vector<VariableBinding> variableBindings = responsePdu.getVariableBindings();
VariableBinding lastElement = variableBindings.lastElement();
if (lastElement != null && lastElement.getOid().startsWith(ifEntryOid)) {
results.addAll(variableBindings);
pdu.remove(0);
pdu.add(new VariableBinding(lastElement.getOid()));
// continue to retrieve next bulk
continue;
} else {
// break loop.
// find last element startsWith ifEntryOid
for (VariableBinding vb : variableBindings) {
if (vb.getOid().startsWith(ifEntryOid))
results.add(vb);
else {
break;
}
}
// break while loop
break;
}
}
for (VariableBinding vb : results) {
context.println(vb.toString());
}
} catch (Exception e) {
context.println(e.getMessage());
} finally {
if (transport != null) {
try {
transport.close();
} catch (IOException e) {
}
}
if (snmp != null) {
try {
snmp.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public void getv2c(String[] args) {
Map<String, String> options = parseOptions(args);
String methodStr = options.get("-m");
String community = options.get("-c");
String host = options.get("-h");
String port = options.get("-p");
String bulkNumber = options.get("-n");
int method = getMethod(methodStr);
if (method == -1)
throw new RuntimeException("not supported method: " + methodStr);
String oid = args[args.length - 1];
Snmp snmp = null;
TransportMapping transport = null;
try {
CommunityTarget target = new CommunityTarget();
target.setCommunity(new OctetString(community));
target.setVersion(SnmpConstants.version2c);
target.setAddress(new UdpAddress(host + "/" + port));
target.setRetries(2);
target.setTimeout(3000);
PDU pdu = new PDU();
pdu.add(new VariableBinding(new OID(oid)));
pdu.setType(method);
if (pdu.getType() == PDU.GETBULK)
pdu.setMaxRepetitions(Integer.parseInt(bulkNumber));
transport = new DefaultUdpTransportMapping();
transport.listen();
snmp = new Snmp(transport);
ResponseEvent response = null;
switch (method) {
case PDU.GETNEXT:
response = snmp.getNext(pdu, target);
break;
case PDU.GETBULK:
response = snmp.getBulk(pdu, target);
break;
default:
response = snmp.get(pdu, target);
}
PDU responsePdu = response.getResponse();
if (responsePdu == null) {
context.println("request timeout.");
return;
}
Iterator<?> it = responsePdu.getVariableBindings().iterator();
while (it.hasNext()) {
context.println(it.next().toString());
}
} catch (Exception e) {
context.println(e.getMessage());
} finally {
if (transport != null) {
try {
transport.close();
} catch (IOException e) {
}
}
if (snmp != null) {
try {
snmp.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
private void getV2(String host, String port, String community, String oid) {
Snmp snmp = null;
TransportMapping transport = null;
try {
CommunityTarget target = new CommunityTarget();
target.setCommunity(new OctetString(community));
target.setVersion(SnmpConstants.version2c);
target.setAddress(new UdpAddress(host + "/" + port));
target.setRetries(2);
target.setTimeout(3000);
PDU pdu = new PDU();
pdu.add(new VariableBinding(new OID(oid)));
pdu.setType(PDU.GET);
transport = new DefaultUdpTransportMapping();
transport.listen();
snmp = new Snmp(transport);
ResponseEvent response = snmp.get(pdu, target);
PDU responsePdu = response.getResponse();
if (responsePdu == null) {
context.println("request timeout.");
return;
}
Iterator<?> it = responsePdu.getVariableBindings().iterator();
while (it.hasNext()) {
context.println(it.next().toString());
}
} catch (Exception e) {
context.println(e.getMessage());
} finally {
if (transport != null) {
try {
transport.close();
} catch (IOException e) {
}
}
if (snmp != null) {
try {
snmp.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
private Map<String, String> parseOptions(String[] args) {
Map<String, String> options = new HashMap<String, String>();
for (int i = 0; i < args.length; ++i) {
if (args[i].charAt(0) == '-') {
if (i + 1 < args.length)
options.put(args[i], args[++i]);
}
}
return options;
}
}