// $Id: DHCPPacketDecoder.java,v 1.13 2004/11/03 16:17:05 dphull Exp $ import java.util.HashMap; public final class DHCPPacketDecoder { private DHCPFingerprint dhcpFingerprint; public DHCPPacketDecoder(String fingerprintsFile) { dhcpFingerprint = DHCPFingerprintLoader.load(fingerprintsFile); } public DHCPClientInformation decode(byte[] rawPacket) { int messageType; if ((rawPacket == null) || (rawPacket.length < 48)) { DHCPClientInformation dci = new DHCPClientInformation(); dci.setMessageType("Badly formed packet"); return dci; } messageType = getMessageType(rawPacket); if (messageType == 1 || messageType == 3) { HashMap dhcpOptions = decodeOptions(rawPacket); DHCPClientInformation dci = new DHCPClientInformation(); dci.setVendorClassID(decodeVendorClassID(dhcpOptions)); dci.setRequestedIP(decodeRequestedIP(dhcpOptions)); dci.setSystemName(decodeSystemName(dhcpOptions)); dci.setMessageType(decodeMessageType(dhcpOptions)); dci.setMacAddress(decodeMAC(rawPacket)); dci.setOperatingSystem(decodeOS(dhcpOptions)); byte[] rawIP = new byte[4]; System.arraycopy(rawPacket, 12, rawIP, 0, 4); dci.setIpAddress(decodeIP(rawIP)); return dci; } else { DHCPClientInformation dci = new DHCPClientInformation(); dci.setMessageType("IGNORE"); return dci; } } private int getMessageType(byte[] rawPacket) { final int optionsStart = 240; int index = 0; while (optionsStart + index < rawPacket.length) { if (rawPacket[optionsStart + index] == 0) { index++; continue; } else if (rawPacket[optionsStart + index] == 53) { return rawPacket[optionsStart + index + 2]; } else if (rawPacket[optionsStart + index] == 255) { return 0; } else { index += rawPacket[optionsStart + index++]; } } return 0; } public static String decodeIP(byte[] rawIP) { if(rawIP == null) { return "null"; } String theIP = ""; int octet; for (int i = 0; i < 4; i++) { octet = rawIP[i]; if (octet < 0) { octet += 256; } theIP += octet; if (i < 3) { theIP += "."; } } if(theIP.equals("0.0.0.0")) { return null; } return (theIP); } public static String decodeRequestedIP(HashMap dhcpOptions) { return decodeIP((byte[])dhcpOptions.get("50")); } public String decodeVendorClassID(HashMap dhcpOptions) { return extractString((byte[]) dhcpOptions.get("60")); } public static String decodeSystemName(HashMap dhcpOptions) { return extractString((byte[]) dhcpOptions.get("12")); } private static String extractString(byte[] raw) { if(raw != null) { StringBuffer sb = new StringBuffer(raw.length); for(int i=0;i 0) { value = new byte[(int) lengthOctet]; for (int j = 0; j < (int) lengthOctet; j++) { value[j] = options[optionsPosition++]; } dhcpOptions.put(Byte.toString(code), value); } else { System.out.println("WARNING: Negative length octet (" + lengthOctet + ") found."); } } else { System.out.println("WARNING: Option " + code + " starts at " + optionsPosition + " and has a length of " + lengthOctet + "."); System.out.println("WARNING: This exceeds the total length of the options array which is " + options.length + "."); } } } return dhcpOptions; } else { return null; } } }