I've hit kind of a brick wall. I got a small system that communicate with DSLAM's by SNMP.
Everything has worked fine for a couple of months, but when I recently added a new DSLAM to the system, I couldn't get an answer from it. Tried the other IP's and didn't have a problem.
After an hour or so, suddenly on of the other DSLAM's stopped answering me too. So now I've got two units without any communication, which kinda sucks. So of course I checked the units, and didn't find a problem. By my MIB-browser, I can reach all of the units... But not via my software. So the error lies somewhere in my software. So I checked Wireshark, and see that the getNext requests are going out, but I don't seem to get an answer. When I do it via the MIB browser, there comes an answer. But the funny thing is: the two requests are identical. So I must not be listening - and yes, it is listening.
Why in the world is this specific to some IP's, and dear Lord why do they contaminate eachother?
Let's look at some code:
public String GetNextValue(String OID, Dslam dslam) throws IOException {
Snmp snmp = new Snmp(new DefaultUdpTransportMapping());
snmp.listen();
CommunityTarget target = initializeTarget(dslam);
PDU request = new PDU();
request.setType(PDU.GETNEXT);
OID oid= new OID(OID);
request.add(new VariableBinding(oid));
PDU responsePDU=null;
ResponseEvent responseEvent;
responseEvent = snmp.send(request, target);
if (responseEvent != null){
System.out.println("resonse event not null..");
responsePDU = responseEvent.getResponse();
if ( responsePDU != null){
System.out.println("pdu not null..");
#SuppressWarnings("unchecked")
Vector <VariableBinding> tmpv = (Vector<VariableBinding>) responsePDU.getVariableBindings();
if(tmpv != null){
System.out.println("tmpv not null..");
VariableBinding vb = (VariableBinding) tmpv.get(0);
if(!vb.isException()){
return vb.getVariable().toString()
}
}
}
}
_errorHandler.criticalError("Response error in DSLAM communication");
return null;
}
And the initializer:
private CommunityTarget initializeTarget(Dslam dslam){
Address addr = new UdpAddress(dslam.getAddress() + "/" + dslam.getManagementPort() );
System.out.println("IP: " + dslam.getAddress() + " port: " + dslam.getManagementPort());
CommunityTarget target = new CommunityTarget(addr, new OctetString("public"));
target.setVersion(SnmpConstants.version2c);
target.setTimeout(3000);
target.setRetries(3);
return target;
}
And if we run a test upon a working DSLAM:
#Test
public void Lowtest() throws IOException{
SnmpController snmpController = SnmpController.GetInstance();
DslamGrabber dslamGrabber = new DslamGrabber();
Dslam dslam = dslamGrabber.getByDslamId("test5xda5");
String result = snmpController.GetNextValue(".1.3.6.1.4.1.637.61.1.39.3.3.1.1.2", dslam);
System.out.println(result);
}
Result:
IP: 195.215.96.135 port: 161
resonse event not null..
pdu not null..
tmpv not null..
OID: 1.3.6.1.4.1.637.61.1.39.3.3.1.1.2.1
BF512_2048
The we try against test5xda9 (the second one to succumb to this hideous disease-like error)
We get 3 retries in Wireshark, and the following output:
IP: 192.215.96.139 port: 161
resonse event not null..
Response error in DSLAM communication
null
I really hope somebody here can help me. I'm a few hours away to either break down in tears or break a DSLAM..
Best regards
Ben
Well, as a friend pointed out 192 does not equal 195.
Related
IMPORTANT
I have been blocked by hotmail services. There is a control mechanism
called spamhaus which kicked me out. I'm stuck right now.
I am trying to detect an email address is valid and if its valid then check if this email address potentially used (I know that its not certain). For example, lets assume that there is a website with domain myimaginarydomain.com. If I run code below, I guess it won't fail because domain address is valid. But nobody can take an email address with that domain.
Is there any way to find out that email address is valid? (In this case its invalid)
I don't want to send confirmation email
Sending ping may be useful?
public class Application {
private static EmailValidator validator = EmailValidator.getInstance();
public static void main(String[] args) {
while (true) {
Scanner scn = new Scanner(System.in);
String email = scn.nextLine();
boolean isValid = validateEmail(email);
System.out.println("Syntax is : " + isValid);
if (isValid) {
String domain = email.split("#")[1];
try {
int test = doLookup(domain);
System.out.println(domain + " has " + test + " mail servers");
} catch (NamingException e) {
System.out.println(domain + " has 0 mail servers");
}
}
}
}
private static boolean validateEmail(String email) {
return validator.isValid(email);
}
static int doLookup(String hostName) throws NamingException {
Hashtable env = new Hashtable();
env.put("java.naming.factory.initial",
"com.sun.jndi.dns.DnsContextFactory");
DirContext ictx = new InitialDirContext(env);
Attributes attrs =
ictx.getAttributes(hostName, new String[]{"MX"});
Attribute attr = attrs.get("MX");
if (attr == null) return (0);
return (attr.size());
}
}
There is no failsafe way to do this in all cases, but, assuming the server uses SMTP then https://www.labnol.org/software/verify-email-address/18220/ gives quite a good tutorial on one method that may work.
The method used in the tutorial relies on OS tools, so you will need to ensure they exist before using them. a ProcessBuilder may help. Alternatively, you can open a socket directly in code and avoid using OS-dependent tools.
Essentially, you find out what the mail servers are (using nslookup), then telnet to one of the mail servers and start writing an email:
3a: Connect to the mail server:
telnet gmail-smtp-in.l.google.com 25
3b: Say hello to the other server
HELO
3c: Identify yourself with some fictitious email address
mail from:<labnol#labnol.org>
3d: Type the recipient’s email address that you are trying to verify:
rcpt to:<billgates#gmail.com>
The server response for rcpt to command will give you an idea whether an email address is valid or not. You’ll get an “OK” if the address exists else a 550 error
There really is no sensible way except trying to send a notification with a token to the address and ask the other party to confirm it, usually by visiting a web-page:
the recipients MX may be unavailable at the moment but come back online later, so you cannot rely on a lookup in real time;
just because the MX accepts the email doesn't mean that the address is valid, the message could bounce later down the pipe (think UUCP);
if this is some kind of registration service, you need to provide some confirmation step anyway as otherwise it'd become too easy to subscribe random strangers on the internet that do not want your service.
I'm trying to develop a simple SNMP GET/SET program in java using SNMP4j. I've followed the following tutorials
http://www.developer-tricks.com/2012/11/how-to-get-started-with-snmp4j.html
https://blog.jayway.com/2010/05/21/introduction-to-snmp4j/
I have also read through the 'Getting started with SNMP4J' stackoverflow thread.
Every tutorial and program I've tried to replicate so far to get me started has resulted in "Error:java: java.lang.UnsupportedOperationException" when I compile. I can't figure out why. I used the exact code in both the tutorials I listed above, and both resulted in the same error as soon as I compile. I've read up on other threads involving the exception, but haven't found anything relevant to SNMP4j, a lot of what I read involved something with lists using the AsList method, which isn't used at all.
The code im trying to run is directly copied from the 'developer-tricks' link I posted earlier. The only difference is I changed the OID and IP address to ones for my own machine.
If anyone else has some experience in how to solve this exception, I would realy appreciate any advice.
Here is the console output when I try to compile.
Information:javac 10 was used to compile java sources
Information:3/29/2018 4:19 PM - Compilation completed with 1 error and
0 warnings in 716ms Error:java:
java.lang.UnsupportedOperationException
Here is my code, nearly identical to the 'how-to-get-started-with-snmp4j' tutorial i linked to.
public static void main(String[] args) throws IOException {
try {
Snmp snmp4j = new Snmp(new DefaultUdpTransportMapping());
snmp4j.listen();
Address add = new UdpAddress("192.168.1.10" + "/" + "161");
CommunityTarget target = new CommunityTarget();
target.setAddress(add);
target.setTimeout(500);
target.setRetries(3);
target.setCommunity(new OctetString("public"));
target.setVersion(SnmpConstants.version2c);
PDU request = new PDU();
request.setType(PDU.GET);
OID oid = new OID(".1.3.6.1.4.1.34832.512.1.1.1.2");
request.add(new VariableBinding(oid));
PDU responsePDU = null;
ResponseEvent responseEvent;
responseEvent = snmp4j.send(request, target);
if (responseEvent != null) {
responsePDU = responseEvent.getResponse();
if (responsePDU != null) {
Vector tmpv = responsePDU.getVariableBindings();
if (tmpv != null) {
for (int k = 0; k < tmpv.size(); k++) {
VariableBinding vb = (VariableBinding) tmpv.get(k);
String output = null;
if (vb.isException()) {
String errorstring = vb.getVariable().getSyntaxString();
System.out.println("Error:" + errorstring);
} else {
String sOid = vb.getOid().toString();
Variable var = vb.getVariable();
OctetString oct = new OctetString((OctetString) var);
String sVar = oct.toString();
System.out.println("success:" + sVar);
}
}
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
Turns out the error had nothing to do with SNMP4j. It happened with any program I compiled.
In order to fix this, I uninstalled JDK 10 and installed JDK 9 instead. I was using Intellij. Not sure exactly what caused this, but uninstalling and reinstalling was the solution.
I'm having a problem while using the SNMP4J library. My code works great when the SNMP server I'm sending the request to is running, but when it isn't running, I want the SNMP request to eventually time-out. However, it never times out. For example, the code below, even when dcadb2 does not exist (i.e. can not ping this host name), the program will never print "Timed out". It will attempt to reach the device for infinity.
private ResponseEvent getSnmpResponse() {
PDU pdu = createPdu();
Target target = getTarget();
try {
ResponseEvent event = snmp.send(pdu, target, null);
return event;
}
catch (IOException e ){
System.out.println("Timed out");
}
}
protected PDU createPdu() {
PDU pdu = new PDU();
pdu.add(new VariableBinding(new OID(DISK_TOTAL_OID)));
pdu.add(new VariableBinding(new OID(DISK_AVAIL_OID)));
pdu.add(new VariableBinding(new OID(DISK_USED_OID)));
pdu.add(new VariableBinding(new OID(DISK_PERCENT_USED_OID)));
pdu.setType( PDU.GET );
return pdu;
}
private Target getTarget() {
CommunityTarget target = new CommunityTarget();
target.setCommunity( new OctetString("public") );
target.setAddress( GenericAddress.parse("dcadb2/161") );
target.setRetries( 1 );
target.setTimeout( 1000L );
target.setVersion( SnmpConstants.version2c );
return target;
}
I found the solution. It turns out SNMP4J (or at least the version I'm using, 1.11.2) will time out if you give it an IP that doesn't exist, but not if you give it a hostname that doesn't exist. In the latter case, the thread will continue for infinity. So the solution is to use IP addresses.
I'm using this SNMP4J code to do some SNMP walks. But, when I run it on say, 1.3.6.1.2.1.31.1.1.1.1 which is ifName, it gets all the interfaces which are represented by 1.3.6.1.2.1.31.1.1.1.1.x, but then it also grabs 1.3.6.1.2.1.31.1.1.1.2 which are ifInMulticastPkts and then sometimes 1.3.6.1.2.1.31.1.1.1.3 which are ifInBroadcastPkts. I'm only interested in ifName.
How do keep the GETBULK from incrementing the last digit before traversing the MIB?
public ArrayList<String> walk(String oid) throws IOException, InterruptedException {
Snmp snmp = new Snmp(new DefaultUdpTransportMapping());
snmp.listen();
Address targetAddress = GenericAddress.parse(address);
CommunityTarget target = new CommunityTarget();
target.setCommunity(new OctetString(community));
target.setVersion(SnmpConstants.version2c);
target.setAddress(targetAddress);
target.setTimeout(3000); //3s
target.setRetries(1);
PDU pdu = new PDU();
pdu.setType(PDU.GETBULK);
pdu.setMaxRepetitions(200);
pdu.setNonRepeaters(0);
pdu.add(new VariableBinding(new OID(oid)));
ResponseEvent responseEvent = snmp.send(pdu, target);
PDU response = responseEvent.getResponse();
ArrayList<String> responsePieces = new ArrayList<String>();
if (response == null) {
System.out.println("TimeOut...");
}
else
{
if (response.getErrorStatus() == PDU.noError)
{
Vector<? extends VariableBinding> vbs = response.getVariableBindings();
for (VariableBinding vb : vbs) {
responsePieces.add(vb.toString());
}
}
else
{
System.out.println("Error:" + response.getErrorStatusText());
}
}
return responsePieces;
}
You should probably be using the getTable method of the TableUtils class to fetch the column(s) you need. That way, you don't have to worry about the nitty-gritty details of how the protocol behaves when walking a table.
That said, if you want to do it yourself... What you've discovered is the normal behavior of GetBulk. The Agent is only responsible for returning as many rows as you specified (200), if it has them. The response will also indicate what OID you should request if you want more rows.
It is only you as a manager who can tell when you've got all the data you want, and stop sending new GetBulk requests. You should simply discard the unwanted data in the last response. In your case, detect whether an OID is no longer a child of the column you requested.
You can read more about how SNMP walking and GetBulk work, in RFC 1905, particularly sections 4.2.3 and 4.2.3.1.
But do use the method provided by the API, it will save you some gray hairs, and is guaranteed to be correct.
Ok so the program is designed to take in connections, validate them, and resend that validation code. Before anyone get's angry it's just a simple little project and is not designed to be overly complex haha. However for some very strange reason the function is hanging on send.setAddess(packet.getAddress); I know this because I have commented out each individual line of code that deals with the Datagram packet "send" and have found that it "hangs" (or never progresses forward in the method again) on that particular line. Any thoughts? Am I doing something cluelessly wrong? I tried it on a linux server as well to make sure it didn't have anything to do with me and the same crap happened.
public static boolean authorize(String n, DatagramPacket packet) {
DatagramPacket send = new DatagramPacket(new byte[4096], 4096);
try {
System.out.println("in auth");
String[] t1 = n.split("%#");
String name = t1[1];
int k = genKey(name);
clients.put(name, k);
send.setAddress(packet.getAddress());
System.out.println("set add");
send.setPort(packet.getPort());
System.out.println("set port");
send.setData(("l-succeed%#" + Integer.toString(k)).getBytes());
System.out.println("set data");
main.dispathcer(send);
System.out.println("called send");
return true;
} catch(Exception e) {
send.setData("l-failed".getBytes());
main.dispathcer(send);
return false;
}
}
EDIT: it took 6 minutes before the authorization token was received by the client. So obviously the setAddress() works but is taking far too long...
It's possible that the process is hanging because there's an issue doing DNS resolution on the address for packet when you call .getAddress(). A few DNS calls are made in order to create the InetAddress object. On these machines, are you able to do a reverse DNS lookup on the IP that the packet packet came from? Try setting an entry for this IP in your /etc/hosts file.