import java.io.*;
import java.net.*;
import java.text.*;
import java.util.*;
public class LinksysTrap extends Thread
{
DatagramSocket dgSocket = null;
Thread recvThread = null;
boolean running = false;
String filefmt;
String enterprise;
String fname="";
File outfile=null;
FileWriter outWrite = null;
SimpleDateFormat stf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
SimpleDateFormat sdf;
// the packet
byte [] data = new byte[32768];
int ofs, end; // values for packet
// current token
int tlen, ttype, tofs; // values for current token
// trap fields
int ver;
String comm;
String ent;
String ipa;
int gtt, stt, tt;
String oid;
String val;
LinksysTrap(String e, String p)
{
enterprise = e;
filefmt = p;
sdf = new SimpleDateFormat(filefmt);
}
private boolean startup(int port)
{
try
{
dgSocket = new DatagramSocket(port);
System.out.println("bound to port="+port);
if(openFile(new Date()))
{
running = true;
this.start();
}
else dgSocket.close();
}
catch(IOException e){e.printStackTrace(); running = false;}
return running;
}
public void run()
{
doRecv();
}
private void doRecv()
{
DatagramPacket pkt = new DatagramPacket(data,32768);
while(running)
{
try
{
dgSocket.receive(pkt);
end = pkt.getLength();
ofs = 0;
// System.out.println("packet received from:"+pkt.getAddress()+" port="+pkt.getPort()
// +" length="+end);
decode();
}
catch(IOException e){e.printStackTrace(); running = false;}
}
dgSocket.close();
}
static public void main(String [] args)
{
int port = 162;
String ent ="1.3.6.14.1152.21.2.2.1";
String filefmt="'traps'yyyyMM'.csv'";
for(int i = 0; i<args.length; i++)
{
String arg = args[i];
if(arg.length() > 2)
{
char c0 = arg.charAt(0);
if(c0 == '-')
{
char c1 = arg.charAt(1);
arg = arg.substring(2);
switch(c1)
{
case 'p': // port
try{port = new Integer(arg).intValue();}
catch(NumberFormatException exc){badCmd();}
break;
case 'e': // enterprise
ent = arg;
break;
case 'f': // file prefix
filefmt = arg;
break;
default:
badCmd();
break;
}
}else badCmd();
}else badCmd();
}
LinksysTrap st = new LinksysTrap(ent, filefmt);
if(!st.startup(port))System.exit(0);
}
private static void badCmd()
{
System.out.println("LinksysTrap -pport -eenterprise -ffilenameformat");
System.out.println(" default -p162 -e1.3.6.14.1152.21.2.2.1 -f'traps'yyyyMM'.csv'");
System.exit(0);
}
private void decode()
{
try
{
getSeq(0x30); // packet
ver = getInt(0x02); // version
comm = getString(); // community
getSeq(0xa4); // trap pdu
ent = getOID(); // enterprise
if(! ent.equals(enterprise))
{
System.out.println("trap ignored from enterprise="+ent);
return;
}
ipa = getIPA(); // ip address
gtt = getInt(0x02); // generic trap type
stt = getInt(0x02); // specific trap type
tt = getInt(0x43); // time up
getSeq(0x30); // varbind list
getSeq(0x30); // varbind
oid = getOID(); // trap oid
val = getString(); // trap value
}
catch (IllegalArgumentException e)
{
System.out.println("decoding error ofs="+ofs);
display(data,0,end);
e.printStackTrace();
}
// System.out.println("trap received from enterprise="+ent);
// System.out.println(" val="+val);
record(val);
}
private boolean openFile(Date dt)
{
String fn = sdf.format(dt);
if(!fn.equals(fname))
{
if(outWrite != null)
{
try{outWrite.close();} // close output writer
catch(IOException ce){ce.printStackTrace();}
finally {outWrite = null;}
}
fname = fn;
System.out.println("Opening file="+fname);
outfile = new File(fname);
try
{
outWrite = new FileWriter(fname,true);
if(0 == outfile.length())
{
outWrite.write("Timestamp,Direction,Source Address,Source Port,Destination Address,Destination Port\n");
outWrite.flush();
}
}
catch (IOException e)
{
e.printStackTrace();
if(outWrite != null)
{
try{outWrite.close();}catch(Exception ce){}
outWrite= null;
}
}
}
return outWrite != null;
}
private void record(String val)
{
Date dt = new Date();
String ts = stf.format(dt);
if(openFile(dt))
{
String cs="";
int i = 0;
int j = 0;
int z = val.length();
if(val.charAt(0) == '@')i = 1;
while(i < z)
{
if(' '==val.charAt(i))i++;
else
{
j = val.indexOf(' ',i);
if(j == -1)j = z;
cs += ","+val.substring(i,j);
i=j+1;
}
}
if(cs.charAt(cs.length()-1) != '\n')cs+='\n';
cs = ts+cs;
System.out.println("cs="+cs);
try
{
outWrite.write(cs);
outWrite.flush();
}
catch(IOException we){we.printStackTrace();}
}
else running = false;
}
private void getSeq(int type)
{getHeader(type);}
// get an integer, this should deal with sign but doesn't yet ********* TBD
private int getInt(int type)
{
getHeader(type);
int len = tlen;
int r = 0;
while(0 < len--)r = (256*r)+getUByte();
return r;
}
private String getString()
{
getHeader(0x04);
String s = new String(data, tofs, tlen);
ofs+=tlen;
return s;
}
private String getOID()
{
String s = "";
getHeader(0x06);
int i = getUByte(); // get first byte
if(i >= 40){s = "1."; i -=40;}
s += (i+".");
int len = tlen-1;
while(0 < len--)
{
i = getUByte();
s+=i;
if(i>1)s+=".";
}
return s;
}
private String getIPA()
{
String s = "";
getHeader(0x40);
int i;
int len = tlen;
while(0 < len--)
{
i = getUByte();
s+=i;
if(i>1)s+=".";
}
return s;
}
// get token header
private void getHeader(int type)
{
int i,n;
ttype = getUByte(); // token type
if(type != 0 && type != ttype)
{
System.out.println("ofs="+ofs+" ttype="+ttype);
throw new IllegalArgumentException("invalid type");
}
n = getUByte();
if(n >= 128)
{
i = n-128;
n = 0;
while(0 < i--)n=(n*256)+getUByte();
}
tofs = ofs;
tlen = n;
// System.out.println("tofs="+tofs+ " tlen="+tlen+" ttype="+ttype);
}
// get an unsigned byte from data
private int getUByte()
{
if(ofs >= end)throw new IllegalArgumentException("data too short");
int b = data[ofs++];
if(b < 0)b+=256;
return b;
}
private static final String HexValue[]={"0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"};
public static void display(byte[]ba, int ofs, int len)
{
int dlen;
String dstr;
while(len>0)
{
if(len < 16)
{
dlen = len;
char[] c48 = new char[48];
java.util.Arrays.fill(c48, ' ');
String fill48 = String.valueOf(c48);
dstr = fill48.substring(0,3*(16-dlen));
}
else
{
dlen = 16;
dstr = "";
}
dstr = tohex4(ofs)+": "+atohex(ba,ofs,dlen)+dstr+": "+atochar(ba,ofs,dlen);
System.out.println(dstr);
ofs+=dlen;
len-=dlen;
}
}
public static String atochar(byte[]ba, int ofs, int len)
{
String s="";
char ch;
byte b;
for(int i=ofs;i<(ofs+len);i++)
{
b = ba[i];
if(b < 32 || b >126)ch = '.';
else ch = (char)b;
s+=ch;
}
return s;
}
public static String atohex(byte[]ba, int ofs, int len)
{
String s="";
for(int i=ofs;i<(ofs+len);i++)
{
s += (tohex2(ba[i])+" ");
}
return s;
}
public static String tohex2(int b)
{
int i = b;
if(i<0)i+=256;
re