/* * This file is part of jsFlow. * * Copyright (c) 2009 DE-CIX Management GmbH <http://www.de-cix.net> - All rights * reserved. * * Author: Thomas King <thomas.king@de-cix.net> * * This software is licensed under the Apache License, version 2.0. A copy of * the license agreement is included in this distribution. */ package net.decix.jsflow.header; import java.util.Vector; import net.decix.util.Address; import net.decix.util.HeaderBytesException; import net.decix.util.HeaderException; import net.decix.util.HeaderParseException; import net.decix.util.MacAddress; import net.decix.util.Utility; public class SFlowHeader { private long version; // 2, 4, 5 private long ipVersionAgent; // 1=v4, 2=v6 private Address addressAgent; private long subAgentID; private long seqNumber; private long sysUptime; // in milliseconds private long numberSamples; // in datagrams private Vector<SampleDataHeader> sampleDataHeaders; public SFlowHeader() { sampleDataHeaders = new Vector<SampleDataHeader>(); } public void setVersion(long version) throws HeaderException { if (!((version == 2) || (version == 4) || (version == 5))) throw new HeaderException("Version " + version + " is not in the valid range (2, 4, 5)"); this.version = version; } public void setIPVersionAgent(long ipVersionAgent) throws HeaderException { if (!((ipVersionAgent == 1) || (ipVersionAgent == 2))) throw new HeaderException("IPVersionAgent " + ipVersionAgent + " is not in the valid rang (1, 2)"); this.ipVersionAgent = ipVersionAgent; } public long getIPVersionAgent() { return ipVersionAgent; } public void setAddressAgent(Address addressAgent) { this.addressAgent = addressAgent; } public Address getAddressAgent() { return addressAgent; } public long getSubAgentID() { return subAgentID; } public long getSeqNumber() { return seqNumber; } public long getVersion() { return version; } public long getSysUptime() { return sysUptime; } public void setSubAgentID(long subAgentID) { this.subAgentID = subAgentID; } public void setSequenceNumber(long seqNumber) { this.seqNumber = seqNumber; } public void setSystemUptime(long sysUptime) { this.sysUptime = sysUptime; } public void setNumberSamples(long numberSamples) { this.numberSamples = numberSamples; } public long getNumberSample() { return numberSamples; } public void addSampleDataHeader(SampleDataHeader sampleDataHeader) { sampleDataHeaders.add(sampleDataHeader); } public Vector<SampleDataHeader> getSampleDataHeaders() { return sampleDataHeaders; } public static SFlowHeader parse(byte[] data) throws HeaderParseException { try { if (data.length < 28) throw new HeaderParseException("Data array too short."); SFlowHeader rph = new SFlowHeader(); // sflow version byte[] version = new byte[4]; System.arraycopy(data, 0, version, 0, 4); rph.setVersion(Utility.fourBytesToLong(version)); // agent ip version byte[] ipVersion = new byte[4]; System.arraycopy(data, 4, ipVersion, 0, 4); rph.setIPVersionAgent(Utility.fourBytesToLong(ipVersion)); // agent ip address if (rph.getIPVersionAgent() == 1) { // IPv4 int firstOctet = Utility.oneByteToInteger(data[8]); int secondOctet = Utility.oneByteToInteger(data[9]); int thirdOctet = Utility.oneByteToInteger(data[10]); int fourthOctet = Utility.oneByteToInteger(data[11]); rph.setAddressAgent(new Address(firstOctet, secondOctet, thirdOctet, fourthOctet)); } if (rph.getIPVersionAgent() == 2) { // IPv6 System.err.println("IPv6 is not supported by RawPacketHeader"); } // subagent id byte[] subAgentID = new byte[4]; System.arraycopy(data, 12, subAgentID, 0, 4); rph.setSubAgentID(Utility.fourBytesToLong(subAgentID)); // datagram sequence number byte[] seqNumber = new byte[4]; System.arraycopy(data, 16, seqNumber, 0, 4); rph.setSequenceNumber(Utility.fourBytesToLong(seqNumber)); // sys uptime byte[] sysUptime = new byte[4]; System.arraycopy(data, 20, sysUptime, 0, 4); rph.setSystemUptime(Utility.fourBytesToLong(sysUptime)); // number samples byte[] numberSamples = new byte[4]; System.arraycopy(data, 24, numberSamples, 0, 4); rph.setNumberSamples(Utility.fourBytesToLong(numberSamples)); // sample data headers int offset = 28; for (int i = 0; i < rph.getNumberSample(); i++) { byte[] subData = new byte[data.length - offset]; System.arraycopy(data, offset, subData, 0, data.length - offset); SampleDataHeader sdh = SampleDataHeader.parse(subData); rph.addSampleDataHeader(sdh); offset += (sdh.getSampleLength() + 8); } return rph; } catch (Exception e) { throw new HeaderParseException("Parse error: " + e.getMessage()); } } public byte[] getBytes() throws HeaderBytesException { try { int lengthSampleData = 0; for (SampleDataHeader sd : sampleDataHeaders) { lengthSampleData += (sd.getSampleLength() + 8); } byte[] data = new byte[0]; if (ipVersionAgent == 1) data = new byte[28 + lengthSampleData]; if (ipVersionAgent == 2) { System.err.println("IPv6 is not supported by RawPacketHeader"); } // sflow version System.arraycopy(Utility.longToFourBytes(version), 0, data, 0, 4); // agent ip version System.arraycopy(Utility.longToFourBytes(ipVersionAgent), 0, data, 4, 4); // agent ip address System.arraycopy(addressAgent.getBytes(), 0, data, 8, 4); // subagent id System.arraycopy(Utility.longToFourBytes(subAgentID), 0, data, 12, 4); // datagram sequence number System.arraycopy(Utility.longToFourBytes(seqNumber), 0, data, 16, 4); // sys uptime System.arraycopy(Utility.longToFourBytes(sysUptime), 0, data, 20, 4); // number samples System.arraycopy(Utility.longToFourBytes(numberSamples), 0, data, 24, 4); int offset = 0; for (SampleDataHeader sd : sampleDataHeaders) { byte[] temp = sd.getBytes(); System.arraycopy(temp, 0, data, 28 + offset, temp.length); offset += (sd.getSampleLength() + 8); } return data; } catch (Exception e) { throw new HeaderBytesException("Error while generating the bytes: " + e.getMessage()); } } public String toString() { StringBuilder sb = new StringBuilder(); sb.append("[SFlowHeader]: "); sb.append("Version: "); sb.append(getVersion()); sb.append(", IPAgentVersion: "); sb.append(getIPVersionAgent()); sb.append(", IPAdressOfAgent: "); sb.append(getAddressAgent()); sb.append(", SubAgentID: "); sb.append(getSubAgentID()); sb.append(", DatagramSequenceNumber: "); sb.append(getSeqNumber()); sb.append(", SwitchUptime: "); sb.append(getSysUptime()); sb.append(", Samples: "); sb.append(getNumberSample()); sb.append(", "); for(SampleDataHeader sdh : sampleDataHeaders){ sb.append(sdh); sb.append(" "); } return sb.toString(); } }