Witam,
Obecnie jestem na etapie pisania programu klienta SNMP do pracy dyplomowej. W tym celu korzystam z biblioteki SNMP4J. Z opinii ludzi słyszałem, że jest to dobre narzędzie i sprawdza się w takich zadaniach. Problem polega jednak na tym, że potrzebuję ściągnąć całą gałąź statystyk. Mój kod pozwala jedynie na odczytanie końcowego elementu w drzewie MIB (końcowego "liścia" w całej gałęzi). Lepiej to wyjaśnię na przykładzie:
Moim zadaniem jest ściąganie statystyk ruchu przechodzącego przez router CISCO z uaktywnioną usługą NBAR. I tak np: jeżeli chcę sprawdzić jakie protokoły są monitorowane wywołuję w programie OID równe 1.3.6.1.4.1.9.9.244.1.2.1.1.2.2.1 w wyniku czego otrzymuję nazwę protokołu - w tym przypadku ftp.
RESPONSE[requestID=393169313, errorStatus=Success(0), errorIndex=0, VBS[1.3.6.1.4.1.9.9.244.1.2.1.1.2.2.1 = ftp]]
Chciałbym jednak by mój kod potrafił zareagować na "mniej szczegółowy" OID. Chcąc pobrać całe drzewo statystyk NBAR powinienem wpisać identyfikator równy 1.3.6.1.4.1.9.9.244.1.2.1.1 co odpowiada MIB - cnpdAllStatsEntry. Niestety program wtedy zwraca jedynie poniższy komunikat:
RESPONSE[requestID=1579941146, errorStatus=Success(0), errorIndex=0, VBS[1.3.6.1.4.1.9.9.244.1.2.1.1 = noSuchObject]]
Wiem, że rozwiązanie pobierania całej gałęzi jest możliwe. Analizowałem inne przeglądarki OID i badałem nimi mój router. Wszystkie potrafiły po wpisaniu pierwszych cyfr OID pobrać całą gałąź z wpisami.
Pod spodem prezentuje kod omawianego wyżej programu:
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.snmp4j.CommunityTarget;
import org.snmp4j.PDU;
import org.snmp4j.Snmp;
import org.snmp4j.Target;
import org.snmp4j.TransportMapping;
import org.snmp4j.event.ResponseEvent;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.smi.Address;
import org.snmp4j.smi.GenericAddress;
import org.snmp4j.smi.OID;
import org.snmp4j.smi.OctetString;
import org.snmp4j.smi.VariableBinding;
import org.snmp4j.transport.DefaultUdpTransportMapping;
import org.snmp4j.util.DefaultPDUFactory;
import org.snmp4j.util.TableEvent;
import org.snmp4j.util.TableUtils;
public class SnmpClient {
private String address;
private Snmp snmp;
public SnmpClient(String address) {
super();
this.address = address;
try {
start();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public void stop() throws IOException {
snmp.close();
}
private void start() throws IOException {
TransportMapping transport = new DefaultUdpTransportMapping();
snmp = new Snmp(transport);
// Do not forget this line!
System.out.println(transport.getListenAddress());
transport.listen();
}
public void getAsString(OID oid) throws IOException {
ResponseEvent event = get(new OID[]{oid});
System.out.println(event.getResponse());
}
public ResponseEvent get(OID oids[]) throws IOException {
PDU pdu = new PDU();
for (OID oid : oids) {
pdu.add(new VariableBinding(oid));
}
pdu.setType(PDU.GET);
ResponseEvent event = snmp.send(pdu, getTarget(), null);
if(event != null) {
return event;
}
throw new RuntimeException("GET timed out");
}
private Target getTarget() {
Address targetAddress = GenericAddress.parse(address);
CommunityTarget target = new CommunityTarget();
target.setCommunity(new OctetString("public"));
target.setAddress(targetAddress);
target.setRetries(2);
target.setTimeout(1500);
target.setVersion(SnmpConstants.version2c);
return target;
}
/**
* Normally this would return domain objects or something else than this...
*/
public List<List<String>> getTableAsStrings(OID[] oids) {
TableUtils tUtils = new TableUtils(snmp, new DefaultPDUFactory());
@SuppressWarnings("unchecked")
List<TableEvent> events = tUtils.getTable(getTarget(), oids, null, null);
List<List<String>> list = new ArrayList<List<String>>();
for (TableEvent event : events) {
if(event.isError()) {
throw new RuntimeException(event.getErrorMessage());
}
List<String> strList = new ArrayList<String>();
list.add(strList);
for(VariableBinding vb: event.getColumns()) {
strList.add(vb.getVariable().toString());
}
}
return list;
}
}
oraz jego wywołanie:
public class SnmpTest {
public static void main(String[] args) throws IOException {
SnmpClient client = new SnmpClient("udp:192.168.1.100/161");
client.getAsString(new OID("1.3.6.1.2.1.4.20.1.1.192.168.1.100"));
client.getAsString(new OID("1.3.6.1.4.1.9.9.244.0"));
client.getAsString(new OID("1.3.6.1.2.1.4.3.0"));
client.getAsString(new OID("1.3.6.1.2.1.1.1.0"));
//działający OID z końcową wartością w gałęzi
client.getAsString(new OID("1.3.6.1.4.1.9.9.244.1.2.1.1.2.2.1"));
//nie działający OID
//client.getAsString(new OID("1.3.6.1.4.1.9.9.244.1.2.1.1"));
}
}
W programie powyżej dopisałem też funkcję, której kod znalazłem w necie - getTableAsStrings. Nie rozumiem jednak dlaczego w argumencie przyjmuje tablice OID. Czy nie można podać jednego OID i pobierze korzeń z wszystkimi jego potomkami?
Proszę o pomoc. Mam nadzieję, że ktoś miał do czynienia z SNMP4J.
Pozdrawiam