package ZClient; import java.io.IOException; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.Date; import java.util.EventListener; import java.util.EventObject; import javax.swing.event.EventListenerList; import jpcap.JpcapCaptor; import jpcap.NetworkInterface; import jpcap.PacketReceiver; import ZClient.EAPSender.EAPNameExcetion; import ZClient.PacketProc.EAPListener; /** * Dot1X is the main class of dot1x application<p> * @author Lingle<p> * Email: mea08@126.com<p> */ public class Dot1X{ private static final Dot1X dot1x=new Dot1X(); private static NetworkInterface[] devices = JpcapCaptor.getDeviceList(); public static long LENOVO_KEEP_GAP=60000; private NetworkInterface selectedDevice =null; private final EAPSender eapSender=new EAPSender(); private JpcapCaptor eapWatcher =null; private byte[] ip =null; private byte[] mac =null; private EventListenerList listeners =null; public class OpenDevException extends Exception{ private static final long serialVersionUID = -3485654124088246345L; public OpenDevException() { super("Open Selected Device Error!"); } } public class NoIPException extends Exception{ private static final long serialVersionUID = -1398907348086842693L; public NoIPException() { super("Selected device has no IP!"); } } public class NoDeviceException extends Exception{ private static final long serialVersionUID = -6577467488384162978L; public NoDeviceException() { super("Have no device?"); } } private boolean hasListerner() { if(listeners==null){ return false; }else return true; } /** * event define */ public class Dot1XMsgSourceObject { public int msgType; public String message; public Dot1XMsgSourceObject (int type, String msg) { msgType = type; message = new Date().toLocaleString().substring(9, 17)+" "+msg; } } public class Dot1XMsgEvent extends EventObject{ private static final long serialVersionUID = 7003505759602936517L; public Dot1XMsgEvent(int msgType, String messsage) { super(new Dot1XMsgSourceObject(msgType,messsage)); } /** * @param msgType 0:EAPMessage,1:KeepOnline,2:device,3:debug stderr * @param messsage */ public Dot1XMsgSourceObject getSource() { return (Dot1XMsgSourceObject) super.getSource(); } } public interface Dot1XMsgListener extends EventListener { public void msgUpdateAction(Dot1XMsgEvent dMsgEvent); } public void addDot1XMsgListener(Dot1XMsgListener listener) { if (!hasListerner()) { listeners=new EventListenerList(); } listeners.add(Dot1XMsgListener.class, listener); } /** * @param msgType 0:EAPMessage,1:KeepOnline,2:device,3:debug stderr * @param messsage */ private void postDot1XMessage(int msgType, String messsage) { for (Dot1XMsgListener listener : listeners.getListeners(Dot1XMsgListener.class)) { listener.msgUpdateAction(new Dot1XMsgEvent(msgType, messsage)); } } interface ThreadStopListener extends EventListener { public abstract void threadStopAction(Class<? extends Thread> t); } private void addThreadListener(ThreadStopListener listener){ if (!hasListerner()) { listeners=new EventListenerList(); } listeners.add(ThreadStopListener.class, listener); } private void postThreadStop(Class<? extends Thread> t) { for (ThreadStopListener listener : listeners.getListeners(ThreadStopListener.class)) { listener.threadStopAction(t); } } private void removeThreadListener(ThreadStopListener listener) { if (hasListerner()) listeners.remove(ThreadStopListener.class,listener); } private abstract class EAPSuccAdapter implements EAPListener{ @Override public void failureEventAction() {} @Override public void pktRecivedAction(String messsage) {} } private abstract class EAPFailAdapter implements EAPListener{ @Override public void successEventAction() {} @Override public void pktRecivedAction(String messsage) {} } private abstract class EAPMessAdapter implements EAPListener{ @Override public void successEventAction() {} @Override public void failureEventAction() {} } /** * thread define */ private class KeepOnlineThread extends Thread implements ThreadStopListener{ public KeepOnlineThread() { setName("KeepOnline.."); setPriority(7); start(); } @Override public synchronized void run() { while (true) { try { Thread.sleep(LENOVO_KEEP_GAP); eapSender.sendEapOnline(); if (hasListerner()) postDot1XMessage(1, "Send EAP_KEEP_ONLINE"); } catch (InterruptedException e) { if (hasListerner()) postDot1XMessage(3, "Error:" + e.getMessage()); } } } @Override public void threadStopAction(Class<? extends Thread> t) { if (t.isInstance(this)) { removeThreadListener(this); stop(); } } } private class EapWatchThread extends Thread implements ThreadStopListener{ public EapWatchThread() { setName("EapWatching.."); setPriority(7); start(); } @Override public synchronized void run() { if (hasEapWatcher()) { try { eapWatcher.setFilter("ether dst " + getMACString() + " and ether proto 0x888e", true); } catch (IOException e) { if (hasListerner()) postDot1XMessage(3, e.getMessage()); } PacketReceiver pktReceiver = new PacketProc(eapSender); ((PacketProc) pktReceiver).addEapListener(new EAPMessAdapter() { public void pktRecivedAction(String messsage) { if (hasListerner()) postDot1XMessage(0, messsage); } }); ((PacketProc) pktReceiver).addEapListener(new EAPSuccAdapter() { @Override public void successEventAction() { postThreadStop(KeepOnlineThread.class); addThreadListener(new KeepOnlineThread()); } }); ((PacketProc) pktReceiver).addEapListener(new EAPFailAdapter() { @Override public void failureEventAction() { postThreadStop(KeepOnlineThread.class); eapWatcher.breakLoop(); } }); eapWatcher.loopPacket(-1, pktReceiver); removeThreadListener(this); } } @Override public void threadStopAction(Class<? extends Thread> t) { if (t.isInstance(this)) { if (hasEapWatcher()) eapWatcher.breakLoop(); } } } private Dot1X(){} private boolean hasEapWatcher(){ if(eapWatcher==null){ return false; }else return true; } public void setDevice(int devindex) throws NoIPException, NoDeviceException { try {selectedDevice=devices[devindex];} catch (ArrayIndexOutOfBoundsException e1) { throw new NoDeviceException(); } mac=selectedDevice.mac_address; try {ip=selectedDevice.addresses[0].address.getAddress();} catch (ArrayIndexOutOfBoundsException e1) { throw new NoIPException(); } try { eapWatcher = JpcapCaptor.openDevice(selectedDevice, 65535, true, 20); eapSender.setSender(eapWatcher.getJpcapSenderInstance(), ip, mac); } catch (IOException e) {if (hasListerner()) postDot1XMessage(3, "Error:"+e.getMessage()); } } public void setName(String username,String password) throws OpenDevException{ if(hasEapWatcher()){eapSender.setName(username, password);} else throw new OpenDevException(); } public void Start() throws OpenDevException{ if (hasEapWatcher()) { postThreadStop(EapWatchThread.class); postThreadStop(KeepOnlineThread.class); addThreadListener(new EapWatchThread()); try { eapSender.sendEapStart(); if (hasListerner()) postDot1XMessage(0, "Send EAP_START"); } catch (EAPNameExcetion e) { if (hasListerner()) postDot1XMessage(0, e.getMessage()); postThreadStop(EapWatchThread.class); postThreadStop(KeepOnlineThread.class); if (hasEapWatcher()) eapWatcher.breakLoop(); } } else throw new OpenDevException(); } public void Stop() { if (hasEapWatcher()) eapSender.sendEapLogOff(); postThreadStop(EapWatchThread.class); postThreadStop(KeepOnlineThread.class); if (hasEapWatcher()) eapWatcher.breakLoop(); postDot1XMessage(0, "EAP_STOP"); } public static String[] getDeviceList() { String[] devs=new String[devices.length]; for (int i=0; i<devices.length; i++) { devs[i]=devices[i].description; } return devs; } public String getMACString() { try { return String.format("%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); } catch (java.lang.NullPointerException e) { return "00:00:00:00"; } } public String getIPString() { try { return InetAddress.getByAddress(ip).getHostAddress(); } catch (UnknownHostException e) { return "0.0.0.0"; } } public static Dot1X getDot1XInstance() { return dot1x; } }