Author: cyberdo
Date: 2006-02-04 02:48:11 +0000 (Sat, 04 Feb 2006)
New Revision: 8003

Added:
   trunk/freenet/src/snmplib/SNMPTimeTicks.java
Modified:
   trunk/freenet/src/freenet/node/Version.java
   trunk/freenet/src/snmplib/BERDecoder.java
   trunk/freenet/src/snmplib/BEREncoder.java
   trunk/freenet/src/snmplib/InfoSystem.java
   trunk/freenet/src/snmplib/SNMPAgent.java
   trunk/freenet/src/snmplib/SNMPStarter.java
Log:
433:
SNMP-bug now fixed. Still needs testing, but seems to work as supposed to.
MRTG-problem still not solved, but FRED behaves just as SNMPD, so the problem 
might be in MRTG.
Added OID:s: SNMPv2-MIB::sysUpTime.0 (.1.3.6.1.2.1.1.3.0) and 
SNMPv2-MIB::sysName.0 (.1.3.6.1.2.1.1.5.0)
sysUpTime is the node's uptime, and sysname is a string like "Fred 0.7 (433)"


Modified: trunk/freenet/src/freenet/node/Version.java
===================================================================
--- trunk/freenet/src/freenet/node/Version.java 2006-02-03 23:46:58 UTC (rev 
8002)
+++ trunk/freenet/src/freenet/node/Version.java 2006-02-04 02:48:11 UTC (rev 
8003)
@@ -20,7 +20,7 @@
        public static final String protocolVersion = "1.0";

        /** The build number of the current revision */
-       private static final int buildNumber = 432;
+       private static final int buildNumber = 433;

        /** Oldest build of Fred we will talk to */
        private static final int lastGoodBuild = 403;

Modified: trunk/freenet/src/snmplib/BERDecoder.java
===================================================================
--- trunk/freenet/src/snmplib/BERDecoder.java   2006-02-03 23:46:58 UTC (rev 
8002)
+++ trunk/freenet/src/snmplib/BERDecoder.java   2006-02-04 02:48:11 UTC (rev 
8003)
@@ -18,7 +18,9 @@

        public void startSequence(byte id) throws BadFormatException {
                if (buf[ptr] != id)
-                       throw new BadFormatException("Unknown Sequence");
+                       throw new BadFormatException("Unknown Sequence 
(expected: 0x" +
+                                       Integer.toHexString(id) + ", got: 0x" +
+                                       Integer.toHexString(buf[ptr]) + ")");
                ptr++;
                int len = readBERInt();
                seqStack.push(new Integer(ptr + len));
@@ -33,6 +35,12 @@
                                        length + ":" + pos + ":" + ptr);
        }

+       public boolean sequenceHasMore() {
+               //int length = ((Integer)seqStack.peek()).intValue();
+               int pos = ((Integer)seqStack.get(seqStack.size()-2)).intValue();
+               return (pos != ptr);
+       }
+       
        public byte peekRaw() {
                return buf[ptr];
        }
@@ -87,6 +95,11 @@
        }


+       public void fetchNull() throws BadFormatException {
+               startSequence((byte)0x05);
+               endSequence();
+       }
+
        public int fetchInt() throws BadFormatException {
                startSequence((byte)0x02);
                int ret = readInt();

Modified: trunk/freenet/src/snmplib/BEREncoder.java
===================================================================
--- trunk/freenet/src/snmplib/BEREncoder.java   2006-02-03 23:46:58 UTC (rev 
8002)
+++ trunk/freenet/src/snmplib/BEREncoder.java   2006-02-04 02:48:11 UTC (rev 
8003)
@@ -45,6 +45,11 @@
                                offset += dlen;
                                offset += intToBERBytes(dlen, buf, offset);
                                buf[offset++] = 0x02;
+                       } else if (o instanceof SNMPTimeTicks) {
+                               int dlen = 
intToBytes(((SNMPTimeTicks)o).timeValue(), buf, offset);
+                               offset += dlen;
+                               offset += intToBERBytes(dlen, buf, offset);
+                               buf[offset++] = 0x43;
                        } else if (o instanceof IDVector) {
                                int dlen = vecToBytes((IDVector)o, buf, offset);
                                offset += dlen;
@@ -84,26 +89,51 @@
        }

        private int intToBERBytes(long i, byte[] buf, int offset) {
-               String bs = Long.toBinaryString(i);
-               int len = (bs.length()%7);
-               bs = ("0000000" + bs).substring(len);
-               char bits[] = bs.toCharArray();
-               int eatenbits = 0;
+               //String bs = Long.toBinaryString(i);
+               //int len = (bs.length()%7);
+               //bs = ("0000000" + bs).substring(len);
+               //char bits[] = bs.toCharArray();
+               //int eatenbits = 0;
                buf[offset] = 0;
                int inoffset = offset; 
                //for (int j = bits.length - 1 ; j >= 0 ; j--) {
-               for (int j = 0 ; j < bits.length ; j++) {
-                       if (eatenbits == 7) {
-                               buf[offset] += 128;
-                               offset++;
-                               eatenbits = 0;
-                               buf[offset] = 0;
+               long j = i;
+               //System.out.print("intToBERBytes: " + i + ": ");
+               if (i == 0) {
+                       offset++;
+               } else {
+                       for ( ; j > 0 ; j = j/128) {
+                               buf[offset++] += (byte)(j%128);
+                               buf[offset]    = (byte)((j > 127)?128:0);
+                               //System.out.print("[" + (j%128) + " + " + ((j 
> 127)?128:0) + " = " + ((j%128) + ((j > 127)?128:0) ) + "] ");
                        }

-                       buf[offset] |= (bits[j]=='1'?1:0) << (6 - eatenbits);
-                       eatenbits++;
+                       // now; turn it around!
+                       if ((offset - inoffset) > 1) {
+                       //      System.err.println("Started at: " + inoffset + 
", ended at: " + offset);
+                               for (int p = 0 ; p < (offset - inoffset)/2  
;p++) {
+                       //              System.err.println("stap: " + 
(offset-p-1) + " <-> " + (inoffset+p));
+                                       byte tmp = buf[offset-p-1];
+                                       buf[offset-p-1] = buf[inoffset+p];
+                                       buf[inoffset+p] = tmp;
+                               }
+                       }
+                       //System.err.println();
+                       /*
+                        for (int j = 0 ; j < bits.length ; j++) {
+                        if (eatenbits == 7) {
+                        buf[offset] += 128;
+                        offset++;
+                        eatenbits = 0;
+                        buf[offset] = 0;
+                        }
+                        
+                        buf[offset] |= (bits[j]=='1'?1:0) << (6 - eatenbits);
+                        eatenbits++;
+                        }
+                        offset++;
+                        */
                }
-               offset++;
                return (offset - inoffset);
        }

@@ -112,6 +142,9 @@
        /*public void putInteger(int i) {
                addToTop(new Integer(i));
        }*/
+       public void putTimeticks(long i) {
+               addToTop(new SNMPTimeTicks(i));
+       }

        public void putInteger(long i) {
                addToTop(new Long(i));
@@ -125,7 +158,7 @@
                byte bufa[] = new byte[10*buf.length];
                int offset = 1;
                bufa[0] = 0x2b;
-               for (int i = 0 ; i < buf.length ; i++) {
+               for (int i = 2 ; i < buf.length ; i++) {
                        offset += intToBERBytes(buf[i], bufa, offset);
                }
                byte bufb[] = new byte[offset];

Modified: trunk/freenet/src/snmplib/InfoSystem.java
===================================================================
--- trunk/freenet/src/snmplib/InfoSystem.java   2006-02-03 23:46:58 UTC (rev 
8002)
+++ trunk/freenet/src/snmplib/InfoSystem.java   2006-02-04 02:48:11 UTC (rev 
8003)
@@ -1,20 +1,28 @@
 package snmplib;

+import freenet.node.Version;
+
 public class InfoSystem implements MultiplexedDataFetcher {
        long created;

        public InfoSystem() {
-               created = System.currentTimeMillis()/1000;
+               created = System.currentTimeMillis()/10;
        }

        public String getSNMPOID(int index) {
                switch (index) {
-               case 3: //SNMPv2-MIB::sysUpTime.0
-                       return ".1.3.6.1.2.1.1.3.0";
+                       
                case 0: //UCD-SNMP-MIB::memTotalReal.0
                        return ".1.3.6.1.4.1.2021.4.5.0";
                case 1: //UCD-SNMP-MIB::memAvailReal.0
                        return ".1.3.6.1.4.1.2021.4.6.0";
+               case 2: //SNMPv2-MIB::sysName.0
+                       return ".1.3.6.1.2.1.1.5.0";
+               case 3: //SNMPv2-MIB::sysUpTime.0
+                       return ".1.3.6.1.2.1.1.3.0";
+                       
+
+                       
                }
                // default
                return null;
@@ -23,13 +31,24 @@
        public Object getSNMPData(String oid) {
                Runtime r = Runtime.getRuntime();
                int oidhc = oid.hashCode();
+               //System.err.println("requesting: " + oid);
                if (oid.equals(".1.3.6.1.2.1.1.3.0")) //SNMPv2-MIB::sysUpTime.0
-                       return new Long(System.currentTimeMillis()/1000 - 
created);
+                       return new SNMPTimeTicks(System.currentTimeMillis()/10 
- created);
                if (oid.equals(".1.3.6.1.4.1.2021.4.5.0")) 
//UCD-SNMP-MIB::memTotalReal.0
                        return new Long(r.totalMemory());
                if (oid.equals(".1.3.6.1.4.1.2021.4.6.0")) 
//UCD-SNMP-MIB::memAvailReal.0
                        return new Long(r.freeMemory());
+

+               if (oid.equals(".1.3.6.1.2.1.1.5.0")) //SNMPv2-MIB::sysName.0
+                       return (Version.nodeName + " " + Version.nodeVersion + 
" (" + Version.buildNumber() + ")");
+
+               
+               if (oid.equals(".1.3.6.1.4.1.2021.4.5")) 
//UCD-SNMP-MIB::memTotalReal.0
+                       return new Long(r.totalMemory());
+               if (oid.equals(".1.3.6.1.4.1.2021.4.6")) 
//UCD-SNMP-MIB::memAvailReal.0
+                       return new Long(r.freeMemory());
+               
                return null;
        }


Modified: trunk/freenet/src/snmplib/SNMPAgent.java
===================================================================
--- trunk/freenet/src/snmplib/SNMPAgent.java    2006-02-03 23:46:58 UTC (rev 
8002)
+++ trunk/freenet/src/snmplib/SNMPAgent.java    2006-02-04 02:48:11 UTC (rev 
8003)
@@ -5,6 +5,7 @@
 import java.net.DatagramPacket;
 import java.net.DatagramSocket;
 import java.net.InetAddress;
+import java.util.Date;
 import java.util.Iterator;
 import java.util.TreeMap;

@@ -12,7 +13,7 @@
        private int port = 4445;

        /**
-        * @param args
+        * @param args 
         */
        public static void main(String[] args) throws IOException {
                SNMPAgent.getSNMPAgent().addFetcher(new 
DataConstantInt("1.1.1", 10));
@@ -39,7 +40,7 @@
     public static void restartSNMPAgent() {
        ensureCreated();
        _SNMPAgent.stopRunning();
-       new Thread(_SNMPAgent).start();
+       new Thread(_SNMPAgent, "SNMP-Agent").start();
     }

     public static SNMPAgent getSNMPAgent() {
@@ -54,6 +55,8 @@

     private SNMPAgent() {
        alldata = new TreeMap();
+       //alldata.put("99.99", null);
+       addFetcher(new DataConstantInt("99.99.99.99", 0));
     }

     public void addFetcher(DataFetcher df) {
@@ -91,68 +94,40 @@
                return ;
        }
        // make smaller.... 0484 enough?
-        byte[] buf = new byte[65535];
-        DatagramPacket packet = new DatagramPacket(buf, buf.length);

         while (socket.isBound()) {
+               byte[] buf = new byte[65536];
+            DatagramPacket packet = new DatagramPacket(buf, buf.length);
+            
             try {
                 socket.receive(packet);

                 RequestContainer rc = new RequestContainer();
-                
-                parseRequest(buf, rc);
-                
                 int replylength = 0;
-                boolean keyfound = false;
                 //DataHandler dh = null;
+
+                //if (rc != null)
+                //     throw new BadFormatException("asdfa");

-                Iterator it = alldata.keySet().iterator();
-                String key = "";
-                if (rc.OID.length() == 0)
-                       rc.OID = "";
+                BERDecoder question = parseRequestStart(buf, rc);

-                while (it.hasNext() && !keyfound) {
-                       key = (String)it.next();
-                       //System.err.println("is '"+ rc.OID + "' in: " + key);
-                       if (key.startsWith(rc.OID))
-                               keyfound = true;
-                }
+                
+                BEREncoder reply = replyStart(rc);

-                // keyfound /\ (equal -> hasnext)
-                //System.err.println("("+keyfound+" && 
(!"+key.equals(rc.OID)+" || "+it.hasNext()+"))");
-                if (keyfound && (!key.equals(rc.OID) || it.hasNext())) {
-                       key = key.equals(rc.OID)?(String)it.next():key;
-                       
-                       Object df = alldata.get(key);
-                       //Object key = null;
-                       Object data = null;
-                       //dh = (DataHandler)alldata.get(key);
-                       //rc.lOID = (long[])dh.lOID.clone();
-                       if (df instanceof DataFetcher) {
-                               data = ((DataFetcher)df).getSNMPData();
-                       } else if (df instanceof MultiplexedDataFetcher) {
-                               data = 
((MultiplexedDataFetcher)df).getSNMPData(key);
-                               if (data == null)
-                                       data = 
((MultiplexedDataFetcher)df).getSNMPData(".1.3."+key);
-                       } else
-                               data = new Integer(0);
-                       
-                       rc.lOID = splitToLong(key);
-                       //System.err.println(key);
-                       //for (int i = 0; i < rc.lOID.length ; i++)
-                               //      System.err.print("." + rc.lOID[i]);
-                       
-
-                       replylength = makeIntReply(buf, rc, data);
-                } else {
-                       if (rc.lOID.length > 0)
-                               rc.lOID[0] = 100;
-                       else {
-                               rc.lOID = new long[1];
-                               rc.lOID[0] = 0;
-                       }
-                       replylength = makeIntReply(buf, rc, new Integer(1));
+                
+                while (question.sequenceHasMore()) {
+                       question.startSequence();
+                       rc.lOID = question.fetchOID();
+                       rc.OID = (rc.lOID.length == 0)?".":"";
+                       for (int i = 0; i < rc.lOID.length ; i++)
+                               rc.OID += (i==0?"":".") + rc.lOID[i];
+                       //System.err.println("Doing: " + rc.OID);
+                       question.fetchNull();
+                       question.endSequence();
+                       replyAddOID(reply, rc);
                 }
+                replylength = replyEnd(reply, buf);
+                //rc.pdutype == RequestContainer.PDU_GET_NEXT

                 // send the response to the client at "address" and "port"
                 InetAddress address = packet.getAddress();
@@ -164,6 +139,17 @@
                 e.printStackTrace();
                 break;
             } catch (BadFormatException e) {
+               System.err.println("Datapacket length: " + packet.getLength());
+               for (int i = 0 ; i < packet.getLength() ; i++) {
+                       String num = "000" + Integer.toHexString(buf[i]);
+                       num = num.substring(num.length()-2);
+                       System.err.print("0x" + num + " ");
+                       if ((i+1)%8 == 0)
+                               System.err.print("  ");
+                       if ((i+1)%16 == 0)
+                               System.err.println();
+               }
+               System.err.println();
                e.printStackTrace();
                //System.err.println(e.toString());
             } catch (ArrayIndexOutOfBoundsException e) {
@@ -174,7 +160,86 @@
         socket.close();
     }

-    private int makeIntReply(byte buf[], RequestContainer rc, Object data) /* 
throws SnmpTooBigException */ {
+    private String getAccualOID(String oid, boolean thisval) {
+        boolean keyfound = false;
+        Iterator it = alldata.keySet().iterator();
+        String key = "";
+        while (it.hasNext() && !keyfound) {
+               key = (String)it.next();
+               if (key.startsWith(oid))
+                       keyfound = true;
+        }
+        
+        
+        if (it.hasNext() && !thisval) {
+               key = key.equals(oid)?(String)it.next():key;
+        }
+        
+        return key;
+    }
+    
+    private Object getResultFromOID(String oid, boolean thisval) {
+        /*boolean keyfound = false;
+        Iterator it = alldata.keySet().iterator();
+        String key = "";
+        while (it.hasNext() && !keyfound) {
+               key = (String)it.next();
+               if (key.startsWith(oid))
+                       keyfound = true;
+        }
+        */
+        // keyfound /\ ( (equal -> hasnext) V (rc.pdutype == rc.PDU_GET_THIS))
+        //System.err.println("("+keyfound+" && (!"+key.equals(rc.OID)+" || 
"+it.hasNext()+"))");
+        /*if (keyfound && (
+                       (!key.equals(rc.OID) || it.hasNext())) ||
+                       (rc.pdutype == RequestContainer.PDU_GET_THIS) ) {
+               */
+        Object data = null;
+        /*if (keyfound && (
+                       (!key.equals(oid) || it.hasNext())) ) {
+               if (it.hasNext() && !thisval)
+                       key = key.equals(oid)?(String)it.next():key;
+               */
+               Object df = alldata.get(oid);
+               
+               if (df instanceof DataFetcher) {
+                       data = ((DataFetcher)df).getSNMPData();
+               } else if (df instanceof MultiplexedDataFetcher) {
+                       data = ((MultiplexedDataFetcher)df).getSNMPData(oid);
+                       if (data == null) 
+                               if (!oid.startsWith(".1.3."))
+                                       data = 
((MultiplexedDataFetcher)df).getSNMPData(".1.3."+oid);
+                               else
+                                       data = 
((MultiplexedDataFetcher)df).getSNMPData(oid.substring(5));
+                       
+               } else
+                       data = null; //new Integer(0);
+               
+               //rc.lOID = splitToLong(key);
+               //replylength = makeIntReply(buf, rc, data);
+        //} else {
+               /*
+               if (rc.lOID.length > 0)
+                       rc.lOID[0] = 100;
+               else {
+                       rc.lOID = new long[1];
+                       rc.lOID[0] = 0;
+               }
+               data = new Integer(1);
+               */
+        //     data = null;
+               //replylength = makeIntReply(buf, rc, new Integer(1));
+        //}
+        if (data == null)
+               debug("DNF@"+oid);
+        return data;
+    }
+    
+    private void debug(String s) {
+       System.err.println("SNMP-Agent " + (new Date()) + ": " + s);
+    }
+    
+    private BEREncoder replyStart(RequestContainer rc) /* throws 
SnmpTooBigException */ {
        int replyLength = 0;
        BEREncoder be = new BEREncoder();
        be.startSequence(); // whole pkg
@@ -184,14 +249,23 @@
        be.putInteger(rc.requestID); // RID
        be.putInteger(0); // err
        be.putInteger(0); // err
+       be.startSequence(); // OID:s and their values
+       
+       return be;
+    }
+    
+    private void replyAddOID(BEREncoder be, RequestContainer rc) /* throws 
SnmpTooBigException */ {
+       String aOID = getAccualOID(rc.OID, rc.pdutype == 
RequestContainer.PDU_GET_THIS);
+       Object data = getResultFromOID(aOID, rc.pdutype == 
RequestContainer.PDU_GET_THIS);
        be.startSequence(); // value
-       be.startSequence(); // value
-       be.putOID(rc.lOID); // oid
-       
+       be.putOID(splitToLong(aOID)); // oid
+       //System.err.println("Will reply with OID: " + rc.OID + " -> " + aOID);
        if (data instanceof Integer)
                be.putInteger(((Integer)data).intValue());
        else if (data instanceof Long)
                be.putInteger(((Long)data).longValue());
+       else if (data instanceof SNMPTimeTicks)
+               be.putTimeticks(((SNMPTimeTicks)data).timeValue());
        else if (data instanceof String) {
                char[] charr = ((String)data).toCharArray();
                byte[] byarr = new byte[charr.length];
@@ -199,14 +273,16 @@
                        byarr[i] = (byte)charr[i];
                be.putOctetString(byarr);
        }
-       
-       replyLength = be.toBytes(buf);
-       
-       return replyLength;
+       be.endSequence();
     }

+    private int replyEnd(BEREncoder be, byte[] buf) /* throws 
SnmpTooBigException */ {
+       return be.toBytes(buf);
+    }
+
+    
     // http://www.rane.com/note161.html
-    private void parseRequest(byte buf[], RequestContainer rc) throws 
BadFormatException {
+    private BERDecoder parseRequestStart(byte buf[], RequestContainer rc) 
throws BadFormatException {
        int tmpint;

        BERDecoder bd = new BERDecoder(buf);
@@ -226,19 +302,28 @@
        bd.fetchInt();

        bd.startSequence();
+       /*
+       
        bd.startSequence();
        rc.lOID = bd.fetchOID();
        rc.OID = (rc.lOID.length == 0)?".":"";
        for (int i = 0; i < rc.lOID.length ; i++)
                rc.OID += (i==0?"":".") + rc.lOID[i];
-       
+       */
+       return bd;
     }

     private long[] splitToLong(String list) {
+       if (!list.startsWith(".1.3."))
+               list = ".1.3." + list;
+       list = list.substring(1);
        String nums[] = list.split("\\.");
        long ret[] = new long[nums.length];
-       for(int i = 0; i < ret.length ; i++)
+       for(int i = 0; i < ret.length ; i++) {
                ret[i] = Long.parseLong(nums[i]);
+               //System.err.print("," + Long.parseLong(nums[i]));
+       }
+       // System.err.println();
        return ret;
     }
     /*
@@ -296,7 +381,7 @@
                break;

                default:
-                       //System.err.println("Unknown PDU: 0x" + 
Integer.toHexString((id + 256)%256));
+                       System.err.println("Unknown PDU: 0x" + 
Integer.toHexString((id + 256)%256));
                        return false;
                }
                return true;
@@ -306,5 +391,10 @@
                return ("Community: " + new String(community) +
                                ", PDU: " + pdutype + ", OID: " + OID);
        }
+       
+       public boolean pduIsGet() {
+               return ((pdutype == RequestContainer.PDU_GET_THIS) || 
+                               (pdutype == RequestContainer.PDU_GET_NEXT));
+       }
     }
 }

Modified: trunk/freenet/src/snmplib/SNMPStarter.java
===================================================================
--- trunk/freenet/src/snmplib/SNMPStarter.java  2006-02-03 23:46:58 UTC (rev 
8002)
+++ trunk/freenet/src/snmplib/SNMPStarter.java  2006-02-04 02:48:11 UTC (rev 
8003)
@@ -1,6 +1,5 @@
 package snmplib;

-import snmplib.DataStatisticsInfo;
 import freenet.io.comm.IOStatisticCollector;

 /**

Added: trunk/freenet/src/snmplib/SNMPTimeTicks.java
===================================================================
--- trunk/freenet/src/snmplib/SNMPTimeTicks.java        2006-02-03 23:46:58 UTC 
(rev 8002)
+++ trunk/freenet/src/snmplib/SNMPTimeTicks.java        2006-02-04 02:48:11 UTC 
(rev 8003)
@@ -0,0 +1,27 @@
+package snmplib;
+
+public class SNMPTimeTicks {
+       private long ticks;
+       
+       public SNMPTimeTicks(long ticks) {
+               this.ticks = ticks;
+       }
+       
+       public long timeValue() {
+               return ticks;
+       }
+       
+       public String toString() {
+               long rest = ticks;
+               long dec = ticks%100;
+               rest = rest/100;
+               long sec = ticks%60;
+               rest = rest/60;
+               long min = ticks%60;
+               rest = rest/60;
+               long hour = ticks%24;
+               rest = rest/24;
+               long day = ticks;
+               return day + ":" + hour + ":" + min + ":" + sec + "." + dec;
+       }
+}


Reply via email to