Author: nextgens
Date: 2006-05-07 23:27:20 +0000 (Sun, 07 May 2006)
New Revision: 8646

Added:
   trunk/plugins/SNMP/
   trunk/plugins/SNMP/SNMP.java
   trunk/plugins/SNMP/snmplib/
   trunk/plugins/SNMP/snmplib/BERDecoder.java
   trunk/plugins/SNMP/snmplib/BEREncoder.java
   trunk/plugins/SNMP/snmplib/BadFormatException.java
   trunk/plugins/SNMP/snmplib/DataConstantInt.java
   trunk/plugins/SNMP/snmplib/DataConstantString.java
   trunk/plugins/SNMP/snmplib/DataFetcher.java
   trunk/plugins/SNMP/snmplib/DataStatisticsInfo.java
   trunk/plugins/SNMP/snmplib/InfoSystem.java
   trunk/plugins/SNMP/snmplib/MultiplexedDataFetcher.java
   trunk/plugins/SNMP/snmplib/SNMPAgent.java
   trunk/plugins/SNMP/snmplib/SNMPBindtoCallback.java
   trunk/plugins/SNMP/snmplib/SNMPCounter32.java
   trunk/plugins/SNMP/snmplib/SNMPGauge32.java
   trunk/plugins/SNMP/snmplib/SNMPInteger32.java
   trunk/plugins/SNMP/snmplib/SNMPPortNumberCallback.java
   trunk/plugins/SNMP/snmplib/SNMPStarter.java
   trunk/plugins/SNMP/snmplib/SNMPTimeTicks.java
   trunk/plugins/SNMP/snmplib/SNMPTypeWrapperNum.java
Log:
SNMP: new plugin

Added: trunk/plugins/SNMP/SNMP.java
===================================================================
--- trunk/plugins/SNMP/SNMP.java        2006-05-07 23:24:54 UTC (rev 8645)
+++ trunk/plugins/SNMP/SNMP.java        2006-05-07 23:27:20 UTC (rev 8646)
@@ -0,0 +1,55 @@
+package plugins;
+
+import freenet.config.Config;
+import freenet.config.SubConfig;
+import freenet.pluginmanager.*;
+import freenet.support.Logger;
+import plugins.snmplib.*;
+
+
+public class SNMP implements FredPlugin{
+       boolean goon=true;
+       PluginRespirator pr;
+       private int port;
+       private String bindto;
+
+       public void terminate() {
+               Logger.normal(this,"Stopping SNMP");
+               SNMPAgent.stopSNMPAgent();
+               goon=false;
+       }
+       
+       public int getPort(){
+               return port;
+       }
+       
+       public String getBindto(){
+               return bindto;
+       }
+
+       public void runPlugin(PluginRespirator pr) {
+               this.pr = pr;
+               SNMPAgent.stopSNMPAgent();
+               
+               try{
+               Config c=pr.getNode().config;
+               SubConfig sc=new SubConfig("plugins.snmp",c);
+               sc.register("port", 4000,2, true, "SNMP port number", "SNMP 
port number", new SNMPPortNumberCallback());
+               sc.register("bindto", "127.0.0.1", 2, true, "Ip address to bind 
to", "Ip address to bind the SNMP server to", new SNMPBindtoCallback());
+               
+               bindto=sc.getString("bindto");
+               port=sc.getInt("port");
+               
+               SNMPAgent.setSNMPPort(port);
+        System.out.println("Starting SNMP server on "+bindto+":"+port);
+        SNMPStarter.initialize();
+               Logger.normal(this,"Starting SNMP server on "+bindto+":"+port);
+               
+               sc.finishedInitialization();
+               while(goon){};
+               }catch (IllegalArgumentException e){
+                       Logger.error(this, "Error loading SNMP server");
+               }
+       }
+}
+

Added: trunk/plugins/SNMP/snmplib/BERDecoder.java
===================================================================
--- trunk/plugins/SNMP/snmplib/BERDecoder.java  2006-05-07 23:24:54 UTC (rev 
8645)
+++ trunk/plugins/SNMP/snmplib/BERDecoder.java  2006-05-07 23:27:20 UTC (rev 
8646)
@@ -0,0 +1,133 @@
+package plugins.snmplib;
+
+import java.util.Stack;
+
+public class BERDecoder {
+       private byte[] buf;
+       private int ptr = 0;
+       private Stack seqStack;
+       
+       public BERDecoder(byte[] buf) {
+               this.buf = buf;
+               seqStack = new Stack();
+       }
+       
+       public void startSequence() throws BadFormatException {
+               startSequence((byte)0x30);
+       }
+       
+       public void startSequence(byte id) throws BadFormatException {
+               if (buf[ptr] != id)
+                       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));
+               seqStack.push(new Integer(len));
+       }
+       
+       public void endSequence() throws BadFormatException {
+               int length = ((Integer)seqStack.pop()).intValue();
+               int pos = ((Integer)seqStack.pop()).intValue();
+               if (pos != ptr)
+                       throw new BadFormatException("Wrong length of field " + 
+                                       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];
+       }
+       
+       public long[] fetchOID() throws BadFormatException {
+               startSequence((byte)0x06);
+               long[] ret = readOID();
+               endSequence();
+               return ret;
+       }
+       
+       private long[] readOID() throws BadFormatException {
+               if (buf[ptr] != 0x2b)
+                       throw new BadFormatException("Bad start of OID");
+               int inptr = ptr;
+               ptr++;
+               int length = ((Integer)seqStack.peek()).intValue();
+               if (length < 2)
+                       return new long[0];
+               long ret[] = new long[length]; // it won't getlonger then this
+               int i;
+               for(i = 0; i < length ; i++) {
+                       ret[i] = readBERInt();
+                       if ((ptr - inptr) >= length)
+                               break;
+               }
+               
+               if (i < length) { // Bring out the scissors
+                       long ret2[] = (long[])ret.clone();
+                       ret = new long[i + 1];
+                       for ( ; i >= 0 ; i--)
+                               ret[i] = ret2[i];
+               }
+               return ret;
+       }
+       
+       
+       public byte[] fetchOctetString() throws BadFormatException {
+               startSequence((byte)0x04);
+               byte[] ret = readOctetString();
+               endSequence();
+               return ret;
+       }
+       
+       private byte[] readOctetString() {
+               int length = ((Integer)seqStack.peek()).intValue();
+               byte ret[] = new byte[length];
+               for(int i = 0; i < length ; i++) {
+                       ret[i] = buf[ptr++];
+               }
+               return ret;
+       }
+
+       
+       public void fetchNull() throws BadFormatException {
+               startSequence((byte)0x05);
+               endSequence();
+       }
+
+       public int fetchInt() throws BadFormatException {
+               startSequence((byte)0x02);
+               int ret = readInt();
+               endSequence();
+               return ret;
+       }
+       
+       private int readInt() {
+               int length = ((Integer)seqStack.peek()).intValue();
+               int ret = 0;
+               for ( ; length > 0 ; length--) {
+                       ret = ret * 256;
+                       ret = ret + ((((int)buf[ptr])+256)%256);
+                       ptr++;
+               }
+               return ret;
+       }
+       
+       
+       
+       private int readBERInt() {
+               int ret = 0;
+               do {
+                       ret = ret * 128;
+                       ret = ret + ((((int)buf[ptr])+128)%128);
+                       ptr++;
+               } while (buf[ptr-1] < 0);
+               return ret;
+       }
+
+}

Added: trunk/plugins/SNMP/snmplib/BEREncoder.java
===================================================================
--- trunk/plugins/SNMP/snmplib/BEREncoder.java  2006-05-07 23:24:54 UTC (rev 
8645)
+++ trunk/plugins/SNMP/snmplib/BEREncoder.java  2006-05-07 23:27:20 UTC (rev 
8646)
@@ -0,0 +1,231 @@
+package plugins.snmplib;
+
+import java.util.Stack;
+import java.util.Vector;
+
+public class BEREncoder {
+       private IDVector fields;
+       private Stack fstack;
+       
+       public BEREncoder() {
+               this((byte)0x30);
+       }
+       
+       public BEREncoder(byte id) {
+               fields = new IDVector(id);
+               fstack = new Stack();
+               fstack.add(fields);
+       }
+       
+       
+       public int toBytes(byte[] buf) {
+               while (fields.size() > 1)
+                       endSequence();
+               
+               int len = vecToBytes(fields, buf, 0);
+               byte tmpbt;
+               // Remember.. this function writes backwards first!
+               for (int i = 0 ; i < len/2 ; i++) {
+                       tmpbt = buf[i];
+                       buf[i] = buf[len - 1 - i];
+                       buf[len - 1 - i] = tmpbt;
+               }
+                       
+               return len;
+       }
+       
+       private int vecToBytes(IDVector v, byte[] buf, int offset) {
+               int inoffset = offset;
+               for (int i = v.size() - 1 ; i >= 0 ; i--) {
+                       Object o = v.get(i); 
+//                     if (o instanceof Integer) {
+//                             int dlen = intToBytes(((Integer)o).intValue(), 
buf, offset);
+                       if (o == null) {
+                               buf[offset++] = 0x00;
+                               buf[offset++] = 0x05;
+                       } else if (o instanceof Long) {
+                               int dlen = intToBytes(((Long)o).longValue(), 
buf, offset);
+                               offset += dlen;
+                               offset += intToBERBytes(dlen, buf, offset);
+                               buf[offset++] = 0x02;
+                       } else if (o instanceof SNMPTypeWrapperNum) {
+                               int dlen = 
intToBytes(((SNMPTypeWrapperNum)o).getValue(), buf, offset);
+                               offset += dlen;
+                               offset += intToBERBytes(dlen, buf, offset);
+                               buf[offset++] = 
((SNMPTypeWrapperNum)o).getTypeID();
+                       } else if (o instanceof IDVector) {
+                               int dlen = vecToBytes((IDVector)o, buf, offset);
+                               offset += dlen;
+                               offset += intToBERBytes(dlen, buf, offset);
+                               buf[offset++] = ((IDVector)o).getVid();
+                       } else if (o instanceof ByteArrWrapper) {
+                               byte[] barr = ((ByteArrWrapper)o).arr;
+                               for (int j = 0 ; j < barr.length ; j++)
+                                       buf[offset + j] = barr[barr.length - 1 
- j];
+                               offset += barr.length;
+                               offset += intToBERBytes(barr.length, buf, 
offset);
+                               buf[offset++] = ((ByteArrWrapper)o).id;
+                       }
+//                             myoffset += intToBytes(v.get(i), buf, myoffset);
+
+               }
+               
+               return (offset - inoffset);
+       }
+       
+       
+       private int intToBytes(long i, byte[] buf, int offset) {
+               // TODO: handle negative numbers also!!!!
+               int inoffset = offset;
+               if (i == 0) {
+                       buf[offset++] = 0;
+               } else {
+                       for (; i > 0 ; i = i / 256) {
+                               buf[offset] = (byte)(i % 256);
+                               offset++;
+                       }
+               }
+               // make the number unsigned
+               /*
+                * No, we should allow signed numbers
+                * if (buf[offset-1]<0)
+                       buf[offset++] = 0;
+                       */
+               return (offset - inoffset);
+       }
+       
+       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;
+               buf[offset] = 0;
+               int inoffset = offset; 
+               //for (int j = bits.length - 1 ; j >= 0 ; j--) {
+               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) ) + "] ");
+                       }
+                       
+                       // 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++;
+                        */
+               }
+               return (offset - inoffset);
+       }
+       
+       
+       public void putSNMPTypeWrapperNum(SNMPTypeWrapperNum o) {
+               addToTop(o.clone());
+       }
+       
+       /*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));
+       }
+       
+       public void putCounter32(long i) {
+               addToTop(new SNMPCounter32(i));
+       }
+       
+       public void putNull() {
+               addToTop(null);
+       }
+       
+       public void putOctetString(byte buf[]) {
+               addToTop(new ByteArrWrapper((byte[])buf.clone(), (byte)0x04));
+       }
+
+       public void putOID(long buf[]) {
+               byte bufa[] = new byte[10*buf.length];
+               int offset = 1;
+               bufa[0] = 0x2b;
+               for (int i = 2 ; i < buf.length ; i++) {
+                       offset += intToBERBytes(buf[i], bufa, offset);
+               }
+               byte bufb[] = new byte[offset];
+               for (int i = 0 ; i < bufb.length ; i++)
+                       bufb[i] = bufa[i];
+               
+               addToTop(new ByteArrWrapper(bufb, (byte)0x06));
+       }
+
+       public void startSequence() {
+               startSequence((byte)0x30);
+       }
+       
+       public void startSequence(byte id) {
+               IDVector v = new IDVector(id);
+               addToTop(v);
+               fstack.add(v);
+       }
+       
+       public void endSequence() {
+               fstack.pop();
+       }
+       
+       private void addToTop(Object o) {
+               ((IDVector)fstack.peek()).addElement(o);
+       }
+       
+       private class ByteArrWrapper {
+               public byte arr[];
+               public byte id;
+               
+               public ByteArrWrapper(byte arr[], byte id) {
+                       this.arr = arr;
+                       this.id = id;
+               }
+       }
+       
+       // unpublic
+       private class IDVector extends Vector {
+               private static final long serialVersionUID = 
2689317091785298027L;
+               byte vid = (byte)0x30;
+               
+               public IDVector(byte id) {
+                       super();
+                       vid = id;
+               }
+               
+               public byte getVid() {
+                       return vid;
+               }
+
+       }
+}

Added: trunk/plugins/SNMP/snmplib/BadFormatException.java
===================================================================
--- trunk/plugins/SNMP/snmplib/BadFormatException.java  2006-05-07 23:24:54 UTC 
(rev 8645)
+++ trunk/plugins/SNMP/snmplib/BadFormatException.java  2006-05-07 23:27:20 UTC 
(rev 8646)
@@ -0,0 +1,7 @@
+package plugins.snmplib;
+
+public class BadFormatException extends Exception {
+       public BadFormatException(String s) {
+               super(s);
+       }
+}

Added: trunk/plugins/SNMP/snmplib/DataConstantInt.java
===================================================================
--- trunk/plugins/SNMP/snmplib/DataConstantInt.java     2006-05-07 23:24:54 UTC 
(rev 8645)
+++ trunk/plugins/SNMP/snmplib/DataConstantInt.java     2006-05-07 23:27:20 UTC 
(rev 8646)
@@ -0,0 +1,20 @@
+package plugins.snmplib;
+
+
+public class DataConstantInt implements DataFetcher {
+       private String OID;
+       private int value;
+       
+       public DataConstantInt(String oID, int value) {
+               this.OID = oID;
+               this.value = value;
+       }
+       
+       public String getSNMPOID() {
+               return OID;
+       }
+
+       public Object getSNMPData() {
+               return new Integer(value);
+       }
+}

Added: trunk/plugins/SNMP/snmplib/DataConstantString.java
===================================================================
--- trunk/plugins/SNMP/snmplib/DataConstantString.java  2006-05-07 23:24:54 UTC 
(rev 8645)
+++ trunk/plugins/SNMP/snmplib/DataConstantString.java  2006-05-07 23:27:20 UTC 
(rev 8646)
@@ -0,0 +1,19 @@
+package plugins.snmplib;
+
+public class DataConstantString implements DataFetcher {
+       private String OID;
+       private String value;
+       
+       public DataConstantString(String oID, String value) {
+               this.OID = oID;
+               this.value = value;
+       }
+       
+       public String getSNMPOID() {
+               return OID;
+       }
+
+       public Object getSNMPData() {
+               return value;
+       }
+}

Added: trunk/plugins/SNMP/snmplib/DataFetcher.java
===================================================================
--- trunk/plugins/SNMP/snmplib/DataFetcher.java 2006-05-07 23:24:54 UTC (rev 
8645)
+++ trunk/plugins/SNMP/snmplib/DataFetcher.java 2006-05-07 23:27:20 UTC (rev 
8646)
@@ -0,0 +1,10 @@
+package plugins.snmplib;
+
+public interface DataFetcher {
+       
+       public String getSNMPOID();
+       
+       /* Must return an Integer or a String */
+       public Object getSNMPData();
+
+}

Added: trunk/plugins/SNMP/snmplib/DataStatisticsInfo.java
===================================================================
--- trunk/plugins/SNMP/snmplib/DataStatisticsInfo.java  2006-05-07 23:24:54 UTC 
(rev 8645)
+++ trunk/plugins/SNMP/snmplib/DataStatisticsInfo.java  2006-05-07 23:27:20 UTC 
(rev 8646)
@@ -0,0 +1,35 @@
+package plugins.snmplib;
+
+import freenet.io.comm.IOStatisticCollector;
+
+public class DataStatisticsInfo implements DataFetcher {
+       private String OID;
+       int blocks;
+       boolean in;
+       
+       public DataStatisticsInfo(int blocks, boolean in) {
+               this.OID = "1.1." + blocks + "." + (in?"1":"0");
+               //System.err.println("adding: " + this.OID);
+               this.in = in;
+               this.blocks = blocks;
+       }
+       
+       public String getSNMPOID() {
+               //System.err.println("        " + this.OID);
+               return OID;
+       }
+
+       public Object getSNMPData() {
+               if (blocks == 0) {
+                       long io[] = IOStatisticCollector.getTotalIO();
+                       return new SNMPCounter32(io[in?1:0]);
+               }
+               // else sum all fields up to <blocks>
+               int res = 0;
+               int stats[][] = IOStatisticCollector.getTotalStatistics();
+               for (int i = 0 ; i < blocks ; i++)
+                       res += stats[i][in?1:0];
+               
+               return new Long(res);
+       }
+}

Added: trunk/plugins/SNMP/snmplib/InfoSystem.java
===================================================================
--- trunk/plugins/SNMP/snmplib/InfoSystem.java  2006-05-07 23:24:54 UTC (rev 
8645)
+++ trunk/plugins/SNMP/snmplib/InfoSystem.java  2006-05-07 23:27:20 UTC (rev 
8646)
@@ -0,0 +1,59 @@
+package plugins.snmplib;
+
+import freenet.node.Version;
+
+public class InfoSystem implements MultiplexedDataFetcher {
+       long created;
+
+       public InfoSystem() {
+               created = System.currentTimeMillis()/10;
+       }
+       
+       public String getSNMPOID(int index) {
+               switch (index) {
+                       
+               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";
+                       
+               case 4: //UCD-SNMP-MIB::memTotalReal.0
+                       return ".1.3.6.1.4.1.2021.4.5";
+               case 5: //UCD-SNMP-MIB::memAvailReal.0
+                       return ".1.3.6.1.4.1.2021.4.6";
+
+                       
+               }
+               // default
+               return null;
+       }
+
+       public Object getSNMPData(String oid) {
+               Runtime r = Runtime.getRuntime();
+               //System.err.println("requesting: " + oid);
+               if (oid.equals(".1.3.6.1.2.1.1.3.0")) //SNMPv2-MIB::sysUpTime.0
+                       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 SNMPInteger32(r.totalMemory());
+               if (oid.equals(".1.3.6.1.4.1.2021.4.6.0")) 
//UCD-SNMP-MIB::memAvailReal.0
+                       return new SNMPInteger32(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 SNMPInteger32(r.totalMemory());
+               if (oid.equals(".1.3.6.1.4.1.2021.4.6")) 
//UCD-SNMP-MIB::memAvailReal.0
+                       return new SNMPInteger32(r.freeMemory());
+               
+               return null;
+       }
+       
+
+}

Added: trunk/plugins/SNMP/snmplib/MultiplexedDataFetcher.java
===================================================================
--- trunk/plugins/SNMP/snmplib/MultiplexedDataFetcher.java      2006-05-07 
23:24:54 UTC (rev 8645)
+++ trunk/plugins/SNMP/snmplib/MultiplexedDataFetcher.java      2006-05-07 
23:27:20 UTC (rev 8646)
@@ -0,0 +1,11 @@
+package plugins.snmplib;
+
+public interface MultiplexedDataFetcher {
+       
+       /* Return null when the last OID is reached */
+       public String getSNMPOID(int index);
+       
+       /* Must return an Integer or a String */
+       public Object getSNMPData(String oid);
+
+}

Added: trunk/plugins/SNMP/snmplib/SNMPAgent.java
===================================================================
--- trunk/plugins/SNMP/snmplib/SNMPAgent.java   2006-05-07 23:24:54 UTC (rev 
8645)
+++ trunk/plugins/SNMP/snmplib/SNMPAgent.java   2006-05-07 23:27:20 UTC (rev 
8646)
@@ -0,0 +1,453 @@
+package plugins.snmplib;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.net.DatagramPacket;
+import java.net.DatagramSocket;
+import java.net.InetAddress;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.TreeMap;
+
+public class SNMPAgent implements Runnable {
+       private int port = 4445;
+       private String bindto = "127.0.0.1";
+
+       /**
+        * @param args  
+        */
+       public static void main(String[] args) throws IOException {
+               SNMPAgent.getSNMPAgent().addFetcher(new 
DataConstantInt("1.1.1", 10));
+               SNMPAgent.getSNMPAgent().addFetcher(new 
DataConstantInt("1.1.2", 20));
+               SNMPAgent.getSNMPAgent().addFetcher(new 
DataConstantInt("1.1.3", 30));
+               SNMPAgent.getSNMPAgent().addFetcher(new 
DataConstantInt("1.1.4", 40));
+               SNMPAgent.getSNMPAgent().addFetcher(new 
DataConstantInt("1.1.5", 50));
+               SNMPAgent.getSNMPAgent().addFetcher(new 
DataConstantString("1.1.0", "Step by 10"));
+               SNMPAgent.getSNMPAgent().addFetcher(new 
DataConstantString("1.2", "Nothing here"));
+       }
+       
+    protected DatagramSocket socket = null;
+    protected BufferedReader in = null;
+    protected boolean moreQuotes = true;
+    private TreeMap alldata;
+    private static SNMPAgent _SNMPAgent = null;
+
+    public static void setSNMPPort(int port) {
+       ensureCreated();
+       _SNMPAgent.port = port;
+       restartSNMPAgent();
+    }
+    
+    public int getSNMPort(){
+       return port;
+    }
+    
+    public static void setSNMPbindto(String adr){
+       ensureCreated();
+       _SNMPAgent.bindto=adr;
+       restartSNMPAgent();
+    }
+    
+    public String getSNMPbindto(){
+       return bindto;
+    }
+    
+    public static void restartSNMPAgent() {
+       ensureCreated();
+       _SNMPAgent.stopRunning();
+       new Thread(_SNMPAgent, "SNMP-Agent").start();
+    }
+    
+    public static void stopSNMPAgent(){
+        ensureCreated();
+        _SNMPAgent.stopRunning();
+    }
+    
+    public static SNMPAgent getSNMPAgent() {
+       ensureCreated();
+       return _SNMPAgent;
+    }
+    
+    private static void ensureCreated() {
+       if (_SNMPAgent == null)
+               _SNMPAgent = new SNMPAgent();
+    }
+    
+    private SNMPAgent() {
+       alldata = new TreeMap();
+       //alldata.put("99.99", null);
+    }
+    
+    public void addFetcher(DataFetcher df) {
+       //DataHandler dh = new DataHandler(df);
+       //alldata.put(dh.getStringOID(), dh);
+       alldata.put(df.getSNMPOID().replaceAll("^\\.1\\.3\\.",""), df);
+       //System.err.println("sAdded: " + df.getSNMPOID() + "as" + 
df.getSNMPOID().replaceAll("^\\.1\\.3\\.",""));
+    }
+    
+    public void addFetcher(MultiplexedDataFetcher df) {
+       String oid;
+       for (int i = 0 ; (oid = df.getSNMPOID(i)) != null ; i++) {
+               alldata.put(oid.replaceAll("^\\.1\\.3\\.",""), df);
+       //      System.err.println("mAdded: " + oid + " as: " + 
oid.replaceAll("^\\.1\\.3\\.",""));
+       }
+    }
+
+    public void removeFetcher(String OID) {
+       alldata.remove(((OID.startsWith("\\."))?"":".") + OID);
+    }
+    
+    public void stopRunning() {
+       try {
+               socket.close();
+       } catch (Throwable e) {
+               // prpbably since not running...
+       }
+    }
+
+    public void run() {
+       try {
+               socket = new DatagramSocket(port, 
InetAddress.getByName(bindto));
+       } catch (IOException e) {
+               e.printStackTrace();
+               return ;
+       }
+       // make smaller.... 0484 enough?
+
+        while (socket.isBound()) {
+               byte[] buf = new byte[65536];
+            DatagramPacket packet = new DatagramPacket(buf, buf.length);
+            
+            try {
+                socket.receive(packet);
+
+                RequestContainer rc = new RequestContainer();
+                int replylength = 0;
+                //DataHandler dh = null;
+
+                //if (rc != null)
+                //     throw new BadFormatException("asdfa");
+                
+                BERDecoder question = parseRequestStart(buf, rc);
+                
+                
+                BEREncoder reply = replyStart(rc);
+
+                int errIndex = 0;
+                int errStatus = 0;
+                
+                try {
+                       while (question.sequenceHasMore()) {
+                               errIndex++;
+                               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);
+                       }
+                } catch (NoSuchFieldException e) {
+                       errStatus = 0x02; // NO SUCH NAME
+                }
+                
+                if (errStatus != 0) {
+                       // Need to restart the question
+                       question = parseRequestStart(buf, rc);
+                       
+                       // TODO! This does not follow the standard, but works 
with SNMPWALK
+                       // Or does it? ;o)
+                    reply = replyStart(rc, errStatus, errIndex);
+                       while (question.sequenceHasMore()) {
+                               question.startSequence();
+                               
+
+                               reply.startSequence(); // value
+                       reply.putOID(question.fetchOID()); // oid
+                       reply.putNull();
+                       reply.endSequence();
+                       
+                       question.fetchNull();
+                               question.endSequence();
+                       }
+                }
+                
+                replylength = replyEnd(reply, buf);
+                //rc.pdutype == RequestContainer.PDU_GET_NEXT
+                
+                // send the response to the client at "address" and "port"
+                InetAddress address = packet.getAddress();
+                int port = packet.getPort();
+                packet = new DatagramPacket(buf, replylength, address, port);
+                socket.send(packet);
+                
+            } catch (IOException e) {
+                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) {
+               e.printStackTrace();
+               // not much to do.. ignore the request and it'll time out
+            }
+        }
+        socket.close();
+    }
+    
+    private String getAccualOID(String oid, boolean thisval) throws 
NoSuchFieldException {
+        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;
+        } else if (!keyfound ) {
+               throw new NoSuchFieldException("OID not found");
+        }
+        
+        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) {
+       return replyStart(rc, 0, 0);
+    }
+    private BEREncoder replyStart(RequestContainer rc, int errStatus, int 
errIndex) /* throws SnmpTooBigException */ {
+       int replyLength = 0;
+       BEREncoder be = new BEREncoder();
+       be.startSequence(); // whole pkg
+       be.putInteger(0); // version
+       be.putOctetString(rc.community); // community
+       be.startSequence((byte)0xa2); // Response
+       be.putInteger(rc.requestID); // RID
+       be.putInteger(errStatus); // err
+       be.putInteger(errIndex); // err
+       be.startSequence(); // OID:s and their values
+       
+       return be;
+    }
+    
+    private void replyAddOID(BEREncoder be, RequestContainer rc) throws 
NoSuchFieldException {
+       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.putOID(splitToLong(aOID)); // oid
+       //System.err.println("Will reply with OID: " + rc.OID + " -> " + aOID);
+       if (data instanceof Number)
+               be.putInteger(((Number)data).longValue());
+       else if (data instanceof SNMPTypeWrapperNum)
+               be.putSNMPTypeWrapperNum((SNMPTypeWrapperNum)data);
+//     else if (data instanceof SNMPCounter32)
+//             be.putCunter32(((SNMPCounter32)data).getValue());
+       else if (data instanceof String) {
+               char[] charr = ((String)data).toCharArray();
+               byte[] byarr = new byte[charr.length];
+               for (int i = 0 ; i < charr.length ; i++)
+                       byarr[i] = (byte)charr[i];
+               be.putOctetString(byarr);
+       }
+       be.endSequence();
+    }
+    
+    private int replyEnd(BEREncoder be, byte[] buf) /* throws 
SnmpTooBigException */ {
+       return be.toBytes(buf);
+    }
+
+    
+    // http://www.rane.com/note161.html
+    private BERDecoder parseRequestStart(byte buf[], RequestContainer rc) 
throws BadFormatException {
+       int tmpint;
+       
+       BERDecoder bd = new BERDecoder(buf);
+       bd.startSequence();
+       if ((tmpint = bd.fetchInt()) != 0)
+               throw new BadFormatException("Wrong version, expected 0, got "
+                               + tmpint);
+       
+       rc.community = bd.fetchOctetString();
+       if (! rc.setPDU(bd.peekRaw()))
+               throw new BadFormatException("Unknown PDU");
+       bd.startSequence(bd.peekRaw());
+       rc.requestID = bd.fetchInt();
+       
+       // TODO: care about errors eventually?
+       bd.fetchInt();
+       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++) {
+               ret[i] = Long.parseLong(nums[i]);
+               //System.err.print("," + Long.parseLong(nums[i]));
+       }
+       // System.err.println();
+       return ret;
+    }
+    /*
+       private class DataHandler {
+       //public Integer data;
+       public long lOID[] = null;
+       DataFetcher df;
+       
+       public DataHandler(DataFetcher df) {
+               lOID = splitToLong(df.getSNMPOID());
+               this.df = df;
+       }
+       
+        private long[] splitToLong(String list) {
+               String nums[] = list.split("\\.");
+               long ret[] = new long[nums.length];
+               for(int i = 0; i < ret.length ; i++)
+                       ret[i] = Long.parseLong(nums[i]);
+               return ret;
+        }
+
+        public Object getData() {
+               return df.getSNMPData(); 
+        }
+       
+       public String getStringOID() {
+               String ret = "";
+                       for (int i = 0; i < lOID.length ; i++)
+                               ret += "." + lOID[i];
+               return ret;
+       }
+    }
+    */
+    
+    
+    
+
+    private class RequestContainer {
+       public long lOID[] = null;
+       public byte community[] = null;
+       public int pdutype = 0;
+       public static final int PDU_GET_NEXT = 2;
+       public static final int PDU_GET_THIS = 1;
+       public int requestID = 0;
+       public String OID = null;
+       
+       public boolean setPDU(byte id) {
+               switch(id) {
+               case (byte)0xA0:
+                       pdutype = PDU_GET_THIS;
+               break;
+               
+               case (byte)0xA1:
+                       pdutype = PDU_GET_NEXT;
+               break;
+               
+               default:
+                       System.err.println("Unknown PDU: 0x" + 
Integer.toHexString((id + 256)%256));
+                       return false;
+               }
+               return true;
+       }
+       
+       public String toString() {
+               return ("Community: " + new String(community) +
+                               ", PDU: " + pdutype + ", OID: " + OID);
+       }
+       
+       public boolean pduIsGet() {
+               return ((pdutype == RequestContainer.PDU_GET_THIS) || 
+                               (pdutype == RequestContainer.PDU_GET_NEXT));
+       }
+    }
+}

Added: trunk/plugins/SNMP/snmplib/SNMPBindtoCallback.java
===================================================================
--- trunk/plugins/SNMP/snmplib/SNMPBindtoCallback.java  2006-05-07 23:24:54 UTC 
(rev 8645)
+++ trunk/plugins/SNMP/snmplib/SNMPBindtoCallback.java  2006-05-07 23:27:20 UTC 
(rev 8646)
@@ -0,0 +1,22 @@
+package plugins.snmplib;
+
+import freenet.config.InvalidConfigValueException;
+import freenet.config.StringCallback;
+
+public class SNMPBindtoCallback implements StringCallback {
+       
+       public SNMPBindtoCallback() {
+       }
+       
+       public String get() {
+               String bindto=SNMPAgent.getSNMPAgent().getSNMPbindto();
+               if(bindto!=null) return bindto;
+               return "127.0.0.1";
+       }
+
+       public void set(String val) throws InvalidConfigValueException {
+               if(val != get()) {
+                       SNMPAgent.setSNMPbindto(val);
+               }
+       }
+}
\ No newline at end of file

Added: trunk/plugins/SNMP/snmplib/SNMPCounter32.java
===================================================================
--- trunk/plugins/SNMP/snmplib/SNMPCounter32.java       2006-05-07 23:24:54 UTC 
(rev 8645)
+++ trunk/plugins/SNMP/snmplib/SNMPCounter32.java       2006-05-07 23:27:20 UTC 
(rev 8646)
@@ -0,0 +1,16 @@
+package plugins.snmplib;
+
+public class SNMPCounter32 extends SNMPTypeWrapperNum {
+       public SNMPCounter32() { super(); }
+       public SNMPCounter32(long value) { super(value); }
+       
+       public void setValue(long value) {
+               // TODO: make it prettier!
+               this.value = new Long(value).intValue();
+               //System.err.println("Value cut from: " + value + " to " + 
this.value);
+       }
+       
+       protected void init() {
+               this.typeID = 0x41;
+       }
+}

Added: trunk/plugins/SNMP/snmplib/SNMPGauge32.java
===================================================================
--- trunk/plugins/SNMP/snmplib/SNMPGauge32.java 2006-05-07 23:24:54 UTC (rev 
8645)
+++ trunk/plugins/SNMP/snmplib/SNMPGauge32.java 2006-05-07 23:27:20 UTC (rev 
8646)
@@ -0,0 +1,16 @@
+package plugins.snmplib;
+
+public class SNMPGauge32 extends SNMPTypeWrapperNum {
+       public SNMPGauge32() { super(); }
+       public SNMPGauge32(long value) { super(value); }
+       
+       public void setValue(long value) {
+               // TODO: make it prettier!
+               this.value = new Long(value).intValue();
+               //System.err.println("Value cut from: " + value + " to " + 
this.value);
+       }
+       
+       protected void init() {
+               this.typeID = 0x42;
+       }
+}

Added: trunk/plugins/SNMP/snmplib/SNMPInteger32.java
===================================================================
--- trunk/plugins/SNMP/snmplib/SNMPInteger32.java       2006-05-07 23:24:54 UTC 
(rev 8645)
+++ trunk/plugins/SNMP/snmplib/SNMPInteger32.java       2006-05-07 23:27:20 UTC 
(rev 8646)
@@ -0,0 +1,16 @@
+package plugins.snmplib;
+
+public class SNMPInteger32 extends SNMPTypeWrapperNum {
+       public SNMPInteger32() { super(); }
+       public SNMPInteger32(long value) { super(value); }
+       
+       public void setValue(long value) {
+               // TODO: make it prettier!
+               this.value = new Long(value).intValue();
+               //System.err.println("Value cut from: " + value + " to " + 
this.value);
+       }
+       
+       protected void init() {
+               this.typeID = 0x02;
+       }
+}

Added: trunk/plugins/SNMP/snmplib/SNMPPortNumberCallback.java
===================================================================
--- trunk/plugins/SNMP/snmplib/SNMPPortNumberCallback.java      2006-05-07 
23:24:54 UTC (rev 8645)
+++ trunk/plugins/SNMP/snmplib/SNMPPortNumberCallback.java      2006-05-07 
23:27:20 UTC (rev 8646)
@@ -0,0 +1,21 @@
+package plugins.snmplib;
+
+import plugins.SNMP;
+import freenet.config.IntCallback;
+import freenet.config.InvalidConfigValueException;
+
+public class SNMPPortNumberCallback implements IntCallback {
+       
+       public SNMPPortNumberCallback() {
+       }
+       
+       public int get() {
+               return SNMPAgent.getSNMPAgent().getSNMPort();
+       }
+
+       public void set(int val) throws InvalidConfigValueException {
+               if(val != get()) {
+                       SNMPAgent.setSNMPPort(val);
+               }
+       }
+}
\ No newline at end of file

Added: trunk/plugins/SNMP/snmplib/SNMPStarter.java
===================================================================
--- trunk/plugins/SNMP/snmplib/SNMPStarter.java 2006-05-07 23:24:54 UTC (rev 
8645)
+++ trunk/plugins/SNMP/snmplib/SNMPStarter.java 2006-05-07 23:27:20 UTC (rev 
8646)
@@ -0,0 +1,32 @@
+package plugins.snmplib;
+
+import freenet.config.Config;
+import freenet.io.comm.IOStatisticCollector;
+import freenet.node.Node;
+
+/**
+ * @author cyberdo
+ *
+ * Creates the SNMP-agent
+ */
+public class SNMPStarter {
+
+       private static boolean has_been_runned = false;
+
+       public static void initialize() {
+               //SNMPAgent.setSNMPPort(port);
+               if (has_been_runned) return;
+               // 0 is toatl I/O
+               for (int i = 0 ; i < IOStatisticCollector.STATISTICS_ENTRIES ; 
i++) {
+                       SNMPAgent.getSNMPAgent().addFetcher(new 
DataStatisticsInfo(i, true));
+                       SNMPAgent.getSNMPAgent().addFetcher(new 
DataStatisticsInfo(i, false));
+               }
+               SNMPAgent.getSNMPAgent().addFetcher(new InfoSystem());
+               
+               has_been_runned = true;
+       }
+
+       public static void maybeCreate(Node node, Config config) {
+               // FIXME any config needed for SNMPStarter?
+       }
+}

Added: trunk/plugins/SNMP/snmplib/SNMPTimeTicks.java
===================================================================
--- trunk/plugins/SNMP/snmplib/SNMPTimeTicks.java       2006-05-07 23:24:54 UTC 
(rev 8645)
+++ trunk/plugins/SNMP/snmplib/SNMPTimeTicks.java       2006-05-07 23:27:20 UTC 
(rev 8646)
@@ -0,0 +1,24 @@
+package plugins.snmplib;
+
+public class SNMPTimeTicks extends SNMPTypeWrapperNum {
+       public SNMPTimeTicks() { super(); }
+       public SNMPTimeTicks(long value) { super(value); }
+       
+       protected void init() {
+               this.typeID = 0x43;
+       }
+       
+       public String toString() {
+               long rest = value;
+               long dec = rest%100;
+               rest = rest/100;
+               long sec = rest%60;
+               rest = rest/60;
+               long min = rest%60;
+               rest = rest/60;
+               long hour = rest%24;
+               rest = rest/24;
+               long day = rest;
+               return day + ":" + hour + ":" + min + ":" + sec + "." + dec;
+       }
+}

Added: trunk/plugins/SNMP/snmplib/SNMPTypeWrapperNum.java
===================================================================
--- trunk/plugins/SNMP/snmplib/SNMPTypeWrapperNum.java  2006-05-07 23:24:54 UTC 
(rev 8645)
+++ trunk/plugins/SNMP/snmplib/SNMPTypeWrapperNum.java  2006-05-07 23:27:20 UTC 
(rev 8646)
@@ -0,0 +1,58 @@
+package plugins.snmplib;
+
+public abstract class SNMPTypeWrapperNum {
+       protected long value;
+       protected byte typeID;
+       
+       /**
+        * This methd is used to initialize for instance typeID;
+        */
+       protected abstract void init();
+       
+       public SNMPTypeWrapperNum() {
+               this(0);
+       }
+       
+       public SNMPTypeWrapperNum(long value) {
+               this.setValue(value);
+               init();
+       }
+       
+       //public final byte typeID;
+       //= 0x02;
+       public byte getTypeID() {
+               //System.err.println("Returning " + Integer.toHexString(typeID) 
+ " for a " + this.getClass().toString());
+               return typeID;
+       }
+       
+       public long getValue() {
+               return value;
+       }
+       
+       public void setValue(long value) {
+               this.value = value;
+       }
+       
+       public Object clone() {
+               Object ret = null;
+               try {
+                       ret = this.getClass().newInstance();
+                       ((SNMPTypeWrapperNum)ret).setValue(getValue());
+               } catch (SecurityException e) {
+                       // TODO Auto-generated catch block
+                       e.printStackTrace();
+               } catch (InstantiationException e) {
+                       // TODO Auto-generated catch block
+                       e.printStackTrace();
+               } catch (IllegalAccessException e) {
+                       // TODO Auto-generated catch block
+                       e.printStackTrace();
+               }
+               return ret;
+       }
+       
+       public String toString() {
+               return Long.toString(value);
+       }
+
+}


Reply via email to