#6 DMR Decoder (#947)

* #6 DMR decoder feature - work in progress

* #6 DMR Decoder.

* #6 DMR Decoder.  Code review updates.

Co-authored-by: Zhenyu Mao <maozhenyu@foxmail.com>
Co-authored-by: Denny <denny@denny-desktop>
This commit is contained in:
Denny Sheirer
2020-10-12 04:57:59 -04:00
committed by GitHub
parent b061db1189
commit 7eec82deee
436 changed files with 36258 additions and 2409 deletions

View File

@@ -20,11 +20,11 @@
package io.github.dsheirer.module.decode.ip;
import io.github.dsheirer.bits.BinaryMessage;
import io.github.dsheirer.bits.CorrectedBinaryMessage;
public abstract class Packet implements IPacket
{
private BinaryMessage mMessage;
private CorrectedBinaryMessage mMessage;
private int mOffset;
/**
@@ -32,7 +32,7 @@ public abstract class Packet implements IPacket
* @param message containing the packet
* @param offset to the packet within the message
*/
public Packet(BinaryMessage message, int offset)
public Packet(CorrectedBinaryMessage message, int offset)
{
mMessage = message;
mOffset = offset;
@@ -41,7 +41,7 @@ public abstract class Packet implements IPacket
/**
* Underlying message that contains this packet
*/
public BinaryMessage getMessage()
public CorrectedBinaryMessage getMessage()
{
return mMessage;
}

View File

@@ -1,7 +1,7 @@
/*
* ******************************************************************************
* sdrtrunk
* Copyright (C) 2014-2019 Dennis Sheirer
* Copyright (C) 2014-2020 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -20,13 +20,17 @@
package io.github.dsheirer.module.decode.ip;
import io.github.dsheirer.bits.BinaryMessage;
import io.github.dsheirer.bits.CorrectedBinaryMessage;
import io.github.dsheirer.module.decode.ip.ars.ARSPacket;
import io.github.dsheirer.module.decode.ip.cellocator.MCGPHeader;
import io.github.dsheirer.module.decode.ip.cellocator.MCGPMessageFactory;
import io.github.dsheirer.module.decode.ip.icmp.ICMPPacket;
import io.github.dsheirer.module.decode.ip.ipv4.IPV4Header;
import io.github.dsheirer.module.decode.ip.ipv4.IPV4Packet;
import io.github.dsheirer.module.decode.ip.lrrp.LRRPPacket;
import io.github.dsheirer.module.decode.ip.udp.UDPPacket;
import io.github.dsheirer.module.decode.ip.udp.UDPPort;
import io.github.dsheirer.module.decode.ip.xcmp.XCMPPacket;
import io.github.dsheirer.module.decode.p25.phase1.message.pdu.packet.sndcp.SNDCPPacketHeader;
import io.github.dsheirer.module.decode.p25.reference.IPHeaderCompression;
@@ -42,7 +46,7 @@ public class PacketMessageFactory
* @param offset to the IP packet within the message
* @return constructed packet message parser
*/
public static IPacket create(SNDCPPacketHeader sndcpPacketHeader, BinaryMessage message, int offset)
public static IPacket create(SNDCPPacketHeader sndcpPacketHeader, CorrectedBinaryMessage message, int offset)
{
if(sndcpPacketHeader.getIPHeaderCompression() == IPHeaderCompression.NONE)
{
@@ -62,6 +66,26 @@ public class PacketMessageFactory
}
}
/**
* Creates an IP packet message parser
*
* @param message containing an IP packet
* @param offset to the IP packet within the message
* @return constructed packet message parser
*/
public static IPacket create(CorrectedBinaryMessage message, int offset)
{
int version = IPV4Header.getIPVersion(message, offset);
switch(version)
{
case 4:
return new IPV4Packet(message, offset);
default:
return new UnknownPacket(message, offset);
}
}
/**
* Creates an IP packet protocol payload message parser.
*
@@ -70,10 +94,12 @@ public class PacketMessageFactory
* @param offset to the start of the IP packet payload
* @return constructed packet message parser
*/
public static IPacket create(IPProtocol protocol, BinaryMessage binaryMessage, int offset)
public static IPacket create(IPProtocol protocol, CorrectedBinaryMessage binaryMessage, int offset)
{
switch(protocol)
{
case ICMP:
return new ICMPPacket(binaryMessage, offset);
case UDP:
return new UDPPacket(binaryMessage, offset);
default:
@@ -88,32 +114,37 @@ public class PacketMessageFactory
* @param destinationPort for the packet (to identify the protocol/format)
* @param binaryMessage containing the IP/UDP payload
* @param offset in the message to the start of the payload
* @return constructed packet messge parser
* @return constructed packet message parser
*/
public static IPacket createUDPPayload(int sourcePort, int destinationPort, BinaryMessage binaryMessage, int offset)
public static IPacket createUDPPayload(UDPPort sourcePort, UDPPort destinationPort, CorrectedBinaryMessage binaryMessage, int offset)
{
switch(destinationPort)
switch(destinationPort.getValue())
{
case 231:
//Cellocator
case 231: //Cellocator
if(MCGPHeader.isCellocatorMessage(binaryMessage, offset))
{
return MCGPMessageFactory.create(binaryMessage, offset);
}
break;
case 4001: //Location Service
break;
return new LRRPPacket(binaryMessage, offset);
case 4004: //XCMP Service
break;
return new XCMPPacket(binaryMessage, offset);
case 4005: //Automatic Registration Service
return new ARSPacket(binaryMessage, offset);
case 4007: //Text Message Service
break;
case 4008: //Telemetry Service
break;
case 4009: //Over The Air Programming (OTAP)
break;
case 4012: //Battery Management
break;
case 4013: //Job Ticket Server
break;
}
switch(sourcePort)
switch(sourcePort.getValue())
{
case 231:
//Cellocator

View File

@@ -26,6 +26,9 @@ import io.github.dsheirer.module.decode.p25.phase1.message.pdu.packet.sndcp.SNDC
import java.util.Collections;
import java.util.List;
import java.util.Collections;
import java.util.List;
public class UnknownCompressedHeaderPacket implements IPacket
{
private SNDCPPacketHeader mSNDCPPacketHeader;

View File

@@ -22,6 +22,7 @@ package io.github.dsheirer.module.decode.ip;
import io.github.dsheirer.bits.BinaryMessage;
import io.github.dsheirer.identifier.Identifier;
import java.util.Collections;
import java.util.List;

View File

@@ -21,9 +21,12 @@
package io.github.dsheirer.module.decode.ip.ars;
import io.github.dsheirer.bits.BinaryMessage;
import io.github.dsheirer.identifier.Identifier;
import io.github.dsheirer.module.decode.ip.Header;
public class ARSHeader extends Header
import java.util.List;
public abstract class ARSHeader extends Header
{
private static final int[] LENGTH = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
private static final int HEADER_EXTENSION_FLAG = 16;
@@ -43,19 +46,6 @@ public class ARSHeader extends Header
super(message, offset);
}
public String toString()
{
StringBuilder sb = new StringBuilder();
sb.append("ARS ").append(getPDUType());
if(getPDUType() == ARSPDUType.UNKNOWN)
{
sb.append(" PACKET:").append(getMessage().toHexString());
}
return sb.toString();
}
/**
* Checks that the underlying message is long enough to contain the PDU
*/
@@ -141,4 +131,9 @@ public class ARSHeader extends Header
return 16 + 8;
}
}
/**
* Identifiers for this packet
*/
public abstract List<Identifier> getIdentifiers();
}

View File

@@ -44,7 +44,7 @@ public class ARSHeaderFactory
return new RegistrationAcknowledgement(message, offset);
case UNKNOWN:
default:
return new ARSHeader(message, offset);
return new UnknownARSHeader(message, offset);
}
}
}

View File

@@ -20,11 +20,11 @@
package io.github.dsheirer.module.decode.ip.ars;
import io.github.dsheirer.bits.BinaryMessage;
import io.github.dsheirer.bits.CorrectedBinaryMessage;
import io.github.dsheirer.identifier.Identifier;
import io.github.dsheirer.module.decode.ip.IPacket;
import io.github.dsheirer.module.decode.ip.Packet;
import java.util.Collections;
import java.util.List;
public class ARSPacket extends Packet
@@ -37,7 +37,7 @@ public class ARSPacket extends Packet
* @param message containing the packet
* @param offset to the packet within the message
*/
public ARSPacket(BinaryMessage message, int offset)
public ARSPacket(CorrectedBinaryMessage message, int offset)
{
super(message, offset);
}
@@ -71,6 +71,6 @@ public class ARSPacket extends Packet
@Override
public List<Identifier> getIdentifiers()
{
return Collections.emptyList();
return getHeader().getIdentifiers();
}
}

View File

@@ -21,6 +21,10 @@
package io.github.dsheirer.module.decode.ip.ars;
import io.github.dsheirer.bits.BinaryMessage;
import io.github.dsheirer.identifier.Identifier;
import java.util.Collections;
import java.util.List;
public class DeviceDeRegistration extends ARSHeader
{
@@ -41,4 +45,10 @@ public class DeviceDeRegistration extends ARSHeader
sb.append("ARS DEVICE/USER DE-REGISTRATION");
return sb.toString();
}
@Override
public List<Identifier> getIdentifiers()
{
return Collections.emptyList();
}
}

View File

@@ -21,9 +21,23 @@
package io.github.dsheirer.module.decode.ip.ars;
import io.github.dsheirer.bits.BinaryMessage;
import io.github.dsheirer.identifier.Identifier;
import io.github.dsheirer.module.decode.ip.ars.identifier.ARSDevice;
import io.github.dsheirer.module.decode.ip.ars.identifier.ARSPassword;
import io.github.dsheirer.module.decode.ip.ars.identifier.ARSUser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
/**
* Automatic Registration Service - Device Registration
*/
public class DeviceRegistration extends ARSHeader
{
private final static Logger mLog = LoggerFactory.getLogger(DeviceRegistration.class);
private static final int SECOND_HEADER_EXTENSION_FLAG = 24;
private static final int[] EVENT = {25, 26};
private static final int[] ENCODING = {27, 28, 29, 30, 31};
@@ -32,6 +46,11 @@ public class DeviceRegistration extends ARSHeader
private static final int[] BYTE_VALUE = {0, 1, 2, 3, 4, 5, 6, 7};
private ARSDevice mDevice;
private ARSUser mUser;
private ARSPassword mPassword;
private List<Identifier> mIdentifiers;
/**
* Constructs a parser for a header contained within a binary message starting at the offset.
*
@@ -41,6 +60,7 @@ public class DeviceRegistration extends ARSHeader
public DeviceRegistration(BinaryMessage message, int offset)
{
super(message, offset);
parsePayload();
}
public String toString()
@@ -52,10 +72,23 @@ public class DeviceRegistration extends ARSHeader
{
if(hasHeaderExtension())
{
sb.append(isInitialEvent() ? "-INITIAL " : "-REFRESH ");
sb.append(isInitialEvent() ? "-INITIAL" : "-REFRESH");
}
sb.append(" ").append(getPayload());
if(hasDevice())
{
sb.append(" DEVICE:").append(getDevice());
}
if(hasUser())
{
sb.append(" USER:").append(getUser());
}
if(hasPassword())
{
sb.append(" PW:").append(getPassword());
}
}
else
{
@@ -72,14 +105,62 @@ public class DeviceRegistration extends ARSHeader
return getMessage().getInt(EVENT, getOffset()) == 1;
}
/**
* ARS User Id
* @return user or null
*/
public ARSUser getUser()
{
return mUser;
}
/**
* Indicates if this packet has a user Id
*/
public boolean hasUser()
{
return mUser != null;
}
/**
* ARS Password
* @return password or null
*/
public ARSPassword getPassword()
{
return mPassword;
}
/**
* Indicates if this packet has a password
*/
public boolean hasPassword()
{
return mPassword != null;
}
/**
* ARS Device
* @return device or null
*/
public ARSDevice getDevice()
{
return mDevice;
}
/**
* Indicates if this packet has a device Id
*/
public boolean hasDevice()
{
return mDevice != null;
}
/**
* Device, user and password values contained in the registration packet.
*/
public String getPayload()
private void parsePayload()
{
StringBuilder sb = new StringBuilder();
sb.append("DEVICE:");
int pointer = getOffset();
if(hasHeaderExtension())
@@ -91,53 +172,62 @@ public class DeviceRegistration extends ARSHeader
pointer += DEVICE_IDENTIFIER_START;
}
int identifierSize = getMessage().getInt(BYTE_VALUE, pointer += 8);
int deviceIdentifierSize = getMessage().getInt(BYTE_VALUE, pointer);
if(identifierSize > 0)
pointer += 8;
if(deviceIdentifierSize > 0)
{
for(int x = 0; x < identifierSize; x++)
StringBuilder sb = new StringBuilder();
for(int x = 0; x < deviceIdentifierSize; x++)
{
sb.append(getCharacter(pointer += 8));
sb.append(getCharacter(pointer));
pointer += 8;
}
try
{
int device = Integer.parseInt(sb.toString());
mDevice = ARSDevice.createFrom(device);
}
catch(Exception e)
{
mLog.error("Error parsing ARS device identifier from value [" + sb.toString() + "]");
}
}
else
{
sb.append("(none)");
}
sb.append(" USER:");
int userIdentifierSize = getMessage().getInt(BYTE_VALUE, pointer += 8);
int userIdentifierSize = getMessage().getInt(BYTE_VALUE, pointer);
pointer += 8;
if(userIdentifierSize > 0)
{
StringBuilder sb = new StringBuilder();
for(int x = 0; x < userIdentifierSize; x++)
{
sb.append(getCharacter(pointer += 8));
sb.append(getCharacter(pointer));
pointer += 8;
}
}
else
{
sb.append("(none)");
mUser = ARSUser.createFrom(sb.toString());
}
sb.append(" PASSWORD:");
int passwordSize = getMessage().getInt(BYTE_VALUE, pointer += 8);
int passwordSize = getMessage().getInt(BYTE_VALUE, pointer);
pointer += 8;
if(passwordSize > 0)
{
StringBuilder sb = new StringBuilder();
for(int x = 0; x < passwordSize; x++)
{
sb.append(getCharacter(pointer += 8));
sb.append(getCharacter(pointer));
pointer += 8;
}
}
else
{
sb.append("(none)");
}
return sb.toString();
mPassword = ARSPassword.createFrom(sb.toString());
}
}
/**
@@ -150,4 +240,30 @@ public class DeviceRegistration extends ARSHeader
{
return (char)getMessage().getByte(BYTE_VALUE, offset);
}
@Override
public List<Identifier> getIdentifiers()
{
if(mIdentifiers == null)
{
mIdentifiers = new ArrayList<>();
if(hasUser())
{
mIdentifiers.add(getUser());
}
if(hasDevice())
{
mIdentifiers.add(getDevice());
}
if(hasPassword())
{
mIdentifiers.add(getPassword());
}
}
return mIdentifiers;
}
}

View File

@@ -21,6 +21,10 @@
package io.github.dsheirer.module.decode.ip.ars;
import io.github.dsheirer.bits.BinaryMessage;
import io.github.dsheirer.identifier.Identifier;
import java.util.Collections;
import java.util.List;
public class QueryMessage extends ARSHeader
{
@@ -41,4 +45,10 @@ public class QueryMessage extends ARSHeader
sb.append("ARS QUERY MESSAGE");
return sb.toString();
}
@Override
public List<Identifier> getIdentifiers()
{
return Collections.emptyList();
}
}

View File

@@ -21,6 +21,10 @@
package io.github.dsheirer.module.decode.ip.ars;
import io.github.dsheirer.bits.BinaryMessage;
import io.github.dsheirer.identifier.Identifier;
import java.util.Collections;
import java.util.List;
public class RegistrationAcknowledgement extends ARSHeader
{
@@ -93,4 +97,10 @@ public class RegistrationAcknowledgement extends ARSHeader
{
return getMessage().getInt(TIMER_OR_REASON, getOffset());
}
@Override
public List<Identifier> getIdentifiers()
{
return Collections.emptyList();
}
}

View File

@@ -1,7 +1,6 @@
/*
* ******************************************************************************
* sdrtrunk
* Copyright (C) 2014-2018 Dennis Sheirer
* *****************************************************************************
* Copyright (C) 2014-2020 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,14 +14,21 @@
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
* *****************************************************************************
* ****************************************************************************
*/
package io.github.dsheirer.module.decode.ip.ars;
import io.github.dsheirer.bits.BinaryMessage;
import io.github.dsheirer.identifier.Identifier;
public class DeviceRegistrationAcknowledge extends ARSHeader
import java.util.Collections;
import java.util.List;
/**
* Unknown ARS Header
*/
public class UnknownARSHeader extends ARSHeader
{
/**
* Constructs a parser for a header contained within a binary message starting at the offset.
@@ -30,7 +36,7 @@ public class DeviceRegistrationAcknowledge extends ARSHeader
* @param message containing the header
* @param offset to the header within the message
*/
public DeviceRegistrationAcknowledge(BinaryMessage message, int offset)
public UnknownARSHeader(BinaryMessage message, int offset)
{
super(message, offset);
}
@@ -38,7 +44,15 @@ public class DeviceRegistrationAcknowledge extends ARSHeader
public String toString()
{
StringBuilder sb = new StringBuilder();
sb.append("DEVICE REGISTRATION ACKNOWLEDGED");
sb.append("*UNKNOWN* ").append(getPDUType());
sb.append(" PACKET:").append(getMessage().toHexString());
return sb.toString();
}
@Override
public List<Identifier> getIdentifiers()
{
return Collections.emptyList();
}
}

View File

@@ -21,7 +21,14 @@
package io.github.dsheirer.module.decode.ip.ars;
import io.github.dsheirer.bits.BinaryMessage;
import io.github.dsheirer.identifier.Identifier;
import java.util.Collections;
import java.util.List;
/**
* Automatic Registration Service - User De-Registration
*/
public class UserDeRegistration extends ARSHeader
{
/**
@@ -38,7 +45,13 @@ public class UserDeRegistration extends ARSHeader
public String toString()
{
StringBuilder sb = new StringBuilder();
sb.append("ARS USER DE-REGISTRATION");
sb.append("USER DE-REGISTRATION");
return sb.toString();
}
@Override
public List<Identifier> getIdentifiers()
{
return Collections.emptyList();
}
}

View File

@@ -21,6 +21,10 @@
package io.github.dsheirer.module.decode.ip.ars;
import io.github.dsheirer.bits.BinaryMessage;
import io.github.dsheirer.identifier.Identifier;
import java.util.Collections;
import java.util.List;
public class UserDeRegistrationAcknowledge extends ARSHeader
{
@@ -38,7 +42,13 @@ public class UserDeRegistrationAcknowledge extends ARSHeader
public String toString()
{
StringBuilder sb = new StringBuilder();
sb.append("ARS USER DE-REGISTRATION ACKNOWLEDGED");
sb.append("USER DE-REGISTRATION ACKNOWLEDGED");
return sb.toString();
}
@Override
public List<Identifier> getIdentifiers()
{
return Collections.emptyList();
}
}

View File

@@ -21,9 +21,19 @@
package io.github.dsheirer.module.decode.ip.ars;
import io.github.dsheirer.bits.BinaryMessage;
import io.github.dsheirer.identifier.Identifier;
import io.github.dsheirer.module.decode.ip.ars.identifier.ARSDevice;
import io.github.dsheirer.module.decode.ip.ars.identifier.ARSPassword;
import io.github.dsheirer.module.decode.ip.ars.identifier.ARSUser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
public class UserRegistration extends ARSHeader
{
private final static Logger mLog = LoggerFactory.getLogger(UserRegistration.class);
private static final int HEADER_EXTENSION_FLAG = 24;
private static final int[] EVENT = {25, 26};
private static final int[] ENCODING = {27, 28, 29, 30, 31};
@@ -32,6 +42,11 @@ public class UserRegistration extends ARSHeader
private static final int[] BYTE_VALUE = {0, 1, 2, 3, 4, 5, 6, 7};
private ARSDevice mDevice;
private ARSUser mUser;
private ARSPassword mPassword;
private List<Identifier> mIdentifiers;
/**
* Constructs a parser for a header contained within a binary message starting at the offset.
*
@@ -41,6 +56,7 @@ public class UserRegistration extends ARSHeader
public UserRegistration(BinaryMessage message, int offset)
{
super(message, offset);
parsePayload();
}
public String toString()
@@ -50,7 +66,20 @@ public class UserRegistration extends ARSHeader
if(isValid())
{
sb.append(" ").append(getPayload());
if(hasDevice())
{
sb.append(" DEVICE:").append(getDevice());
}
if(hasUser())
{
sb.append(" USER:").append(getUser());
}
if(hasPassword())
{
sb.append(" PW:").append(getPassword());
}
}
else
{
@@ -62,11 +91,8 @@ public class UserRegistration extends ARSHeader
/**
* Device, user and password values contained in the registration packet.
*/
public String getPayload()
private void parsePayload()
{
StringBuilder sb = new StringBuilder();
sb.append("DEVICE:");
int pointer = getOffset();
if(hasHeaderExtension())
@@ -78,53 +104,114 @@ public class UserRegistration extends ARSHeader
pointer += DEVICE_IDENTIFIER_START;
}
int identifierSize = getMessage().getInt(BYTE_VALUE, pointer += 8);
int deviceIdentifierSize = getMessage().getInt(BYTE_VALUE, pointer);
if(identifierSize > 0)
pointer += 8;
if(deviceIdentifierSize > 0)
{
for(int x = 0; x < identifierSize; x++)
StringBuilder sb = new StringBuilder();
for(int x = 0; x < deviceIdentifierSize; x++)
{
sb.append(getCharacter(pointer += 8));
sb.append(getCharacter(pointer));
pointer += 8;
}
try
{
int device = Integer.parseInt(sb.toString());
mDevice = ARSDevice.createFrom(device);
}
catch(Exception e)
{
//Abort processing
return;
}
}
else
{
sb.append("(none)");
}
sb.append(" USER:");
int userIdentifierSize = getMessage().getInt(BYTE_VALUE, pointer += 8);
int userIdentifierSize = getMessage().getInt(BYTE_VALUE, pointer);
pointer += 8;
if(userIdentifierSize > 0)
{
StringBuilder sb = new StringBuilder();
for(int x = 0; x < userIdentifierSize; x++)
{
sb.append(getCharacter(pointer += 8));
sb.append(getCharacter(pointer));
pointer += 8;
}
}
else
{
sb.append("(none)");
mUser = ARSUser.createFrom(sb.toString());
}
sb.append(" PASSWORD:");
int passwordSize = getMessage().getInt(BYTE_VALUE, pointer += 8);
int passwordSize = getMessage().getInt(BYTE_VALUE, pointer);
pointer += 8;
if(passwordSize > 0)
{
StringBuilder sb = new StringBuilder();
for(int x = 0; x < passwordSize; x++)
{
sb.append(getCharacter(pointer += 8));
sb.append(getCharacter(pointer));
pointer += 8;
}
}
else
{
sb.append("(none)");
}
return sb.toString();
mPassword = ARSPassword.createFrom(sb.toString());
}
}
/**
* ARS User Id
* @return user or null
*/
public ARSUser getUser()
{
return mUser;
}
/**
* Indicates if this packet has a user Id
*/
public boolean hasUser()
{
return mUser != null;
}
/**
* ARS Password
* @return password or null
*/
public ARSPassword getPassword()
{
return mPassword;
}
/**
* Indicates if this packet has a password
*/
public boolean hasPassword()
{
return mPassword != null;
}
/**
* ARS Device
* @return device or null
*/
public ARSDevice getDevice()
{
return mDevice;
}
/**
* Indicates if this packet has a device Id
*/
public boolean hasDevice()
{
return mDevice != null;
}
/**
@@ -137,4 +224,30 @@ public class UserRegistration extends ARSHeader
{
return (char)getMessage().getByte(BYTE_VALUE, offset);
}
@Override
public List<Identifier> getIdentifiers()
{
if(mIdentifiers == null)
{
mIdentifiers = new ArrayList<>();
if(hasUser())
{
mIdentifiers.add(getUser());
}
if(hasDevice())
{
mIdentifiers.add(getDevice());
}
if(hasPassword())
{
mIdentifiers.add(getPassword());
}
}
return mIdentifiers;
}
}

View File

@@ -21,6 +21,10 @@
package io.github.dsheirer.module.decode.ip.ars;
import io.github.dsheirer.bits.BinaryMessage;
import io.github.dsheirer.identifier.Identifier;
import java.util.Collections;
import java.util.List;
public class UserRegistrationAcknowledge extends ARSHeader
{
@@ -85,4 +89,10 @@ public class UserRegistrationAcknowledge extends ARSHeader
return "NONE";
}
@Override
public List<Identifier> getIdentifiers()
{
return Collections.emptyList();
}
}

View File

@@ -0,0 +1,64 @@
/*
* *****************************************************************************
* Copyright (C) 2014-2020 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
* ****************************************************************************
*/
package io.github.dsheirer.module.decode.ip.ars.identifier;
import io.github.dsheirer.identifier.Form;
import io.github.dsheirer.identifier.IdentifierClass;
import io.github.dsheirer.identifier.Role;
import io.github.dsheirer.identifier.integer.IntegerIdentifier;
import io.github.dsheirer.protocol.Protocol;
/**
* Automatic Registration Service - Device Identifier
*/
public class ARSDevice extends IntegerIdentifier
{
/**
* Constructs an instance
* @param value of the device identifier
* @param role of the device (TO/FROM)
*/
public ARSDevice(int value, Role role)
{
super(value, IdentifierClass.USER, Form.ARS_DEVICE, role);
}
@Override
public Protocol getProtocol()
{
return Protocol.ARS;
}
/**
* Creates an ARS device with a FROM role
*/
public static ARSDevice createFrom(int value)
{
return new ARSDevice(value, Role.FROM);
}
/**
* Creates an ARS device with a TO role
*/
public static ARSDevice createTo(int value)
{
return new ARSDevice(value, Role.TO);
}
}

View File

@@ -0,0 +1,64 @@
/*
* *****************************************************************************
* Copyright (C) 2014-2020 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
* ****************************************************************************
*/
package io.github.dsheirer.module.decode.ip.ars.identifier;
import io.github.dsheirer.identifier.Form;
import io.github.dsheirer.identifier.IdentifierClass;
import io.github.dsheirer.identifier.Role;
import io.github.dsheirer.identifier.string.StringIdentifier;
import io.github.dsheirer.protocol.Protocol;
/**
* Automatic Registration Service - User Password
*/
public class ARSPassword extends StringIdentifier
{
/**
* Constructs an instance
* @param value of the password
* @param role of the password (TO/FROM)
*/
public ARSPassword(String value, Role role)
{
super(value, IdentifierClass.USER, Form.ARS_USER, role);
}
@Override
public Protocol getProtocol()
{
return Protocol.ARS;
}
/**
* Creates an ARS password with a FROM role
*/
public static ARSPassword createFrom(String value)
{
return new ARSPassword(value, Role.FROM);
}
/**
* Creates an ARS password with a TO role
*/
public static ARSPassword createTo(String value)
{
return new ARSPassword(value, Role.TO);
}
}

View File

@@ -0,0 +1,64 @@
/*
* *****************************************************************************
* Copyright (C) 2014-2020 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
* ****************************************************************************
*/
package io.github.dsheirer.module.decode.ip.ars.identifier;
import io.github.dsheirer.identifier.Form;
import io.github.dsheirer.identifier.IdentifierClass;
import io.github.dsheirer.identifier.Role;
import io.github.dsheirer.identifier.string.StringIdentifier;
import io.github.dsheirer.protocol.Protocol;
/**
* Automatic Registration Service - User Identifier
*/
public class ARSUser extends StringIdentifier
{
/**
* Constructs an instance
* @param value of the user
* @param role of the user (TO/FROM)
*/
public ARSUser(String value, Role role)
{
super(value, IdentifierClass.USER, Form.ARS_USER, role);
}
@Override
public Protocol getProtocol()
{
return Protocol.ARS;
}
/**
* Creates an ARS user with a FROM role
*/
public static ARSUser createFrom(String value)
{
return new ARSUser(value, Role.FROM);
}
/**
* Creates an ARS user with a TO role
*/
public static ARSUser createTo(String value)
{
return new ARSUser(value, Role.TO);
}
}

View File

@@ -19,7 +19,7 @@
package io.github.dsheirer.module.decode.ip.cellocator;
import io.github.dsheirer.bits.BinaryMessage;
import io.github.dsheirer.bits.CorrectedBinaryMessage;
import java.util.Calendar;
import java.util.Date;
@@ -62,7 +62,7 @@ public class AcknowledgeMessage extends MCGPPacket
* @param message containing the packet
* @param offset to the packet within the message
*/
public AcknowledgeMessage(MCGPHeader header, BinaryMessage message, int offset)
public AcknowledgeMessage(MCGPHeader header, CorrectedBinaryMessage message, int offset)
{
super(header, message, offset);
}

View File

@@ -19,7 +19,7 @@
package io.github.dsheirer.module.decode.ip.cellocator;
import io.github.dsheirer.bits.BinaryMessage;
import io.github.dsheirer.bits.CorrectedBinaryMessage;
/**
* Unit (Outbound) data being forwarded over the wireless interface to a central application
@@ -46,7 +46,7 @@ public class ForwardedDataMessage extends MCGPPacket
* @param message containing the packet
* @param offset to the packet within the message
*/
public ForwardedDataMessage(MCGPHeader header, BinaryMessage message, int offset)
public ForwardedDataMessage(MCGPHeader header, CorrectedBinaryMessage message, int offset)
{
super(header, message, offset);
}

View File

@@ -19,7 +19,7 @@
package io.github.dsheirer.module.decode.ip.cellocator;
import io.github.dsheirer.bits.BinaryMessage;
import io.github.dsheirer.bits.CorrectedBinaryMessage;
/**
* Controller (Inbound) Generic Command
@@ -44,7 +44,7 @@ public class GenericCommandMessage extends MCGPPacket
* @param message containing the packet
* @param offset to the packet within the message
*/
public GenericCommandMessage(MCGPHeader header, BinaryMessage message, int offset)
public GenericCommandMessage(MCGPHeader header, CorrectedBinaryMessage message, int offset)
{
super(header, message, offset);
}

View File

@@ -19,11 +19,12 @@
package io.github.dsheirer.module.decode.ip.cellocator;
import io.github.dsheirer.bits.BinaryMessage;
import io.github.dsheirer.bits.CorrectedBinaryMessage;
import org.apache.commons.math3.util.FastMath;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
import org.apache.commons.math3.util.FastMath;
/**
* Unit (Outbound) Status and Location
@@ -101,7 +102,7 @@ public class LocationStatusMessage extends MCGPPacket
* @param message containing the packet
* @param offset to the packet within the message
*/
public LocationStatusMessage(MCGPHeader header, BinaryMessage message, int offset)
public LocationStatusMessage(MCGPHeader header, CorrectedBinaryMessage message, int offset)
{
super(header, message, offset);
}

View File

@@ -20,7 +20,7 @@
package io.github.dsheirer.module.decode.ip.cellocator;
import io.github.dsheirer.bits.BinaryMessage;
import io.github.dsheirer.bits.CorrectedBinaryMessage;
/**
* Creates an MCGP packet and header for parsing the contents of the packet.
@@ -33,7 +33,7 @@ public class MCGPMessageFactory
* @param offset into the message for the start of the MCGP payload
* @return MCGP packet message parser
*/
public static MCGPPacket create(BinaryMessage message, int offset)
public static MCGPPacket create(CorrectedBinaryMessage message, int offset)
{
MCGPHeader header = new MCGPHeader(message, offset);
int payloadOffset = offset + MCGPHeader.HEADER_LENGTH;

View File

@@ -20,10 +20,11 @@
package io.github.dsheirer.module.decode.ip.cellocator;
import io.github.dsheirer.bits.BinaryMessage;
import io.github.dsheirer.bits.CorrectedBinaryMessage;
import io.github.dsheirer.identifier.Identifier;
import io.github.dsheirer.module.decode.ip.IPacket;
import io.github.dsheirer.module.decode.ip.Packet;
import java.util.Collections;
import java.util.List;
@@ -41,7 +42,7 @@ public abstract class MCGPPacket extends Packet
* @param message containing the packet
* @param offset to the packet within the message
*/
public MCGPPacket(MCGPHeader header, BinaryMessage message, int offset)
public MCGPPacket(MCGPHeader header, CorrectedBinaryMessage message, int offset)
{
super(message, offset);
mHeader = header;

View File

@@ -20,6 +20,7 @@
package io.github.dsheirer.module.decode.ip.cellocator;
import io.github.dsheirer.bits.BinaryMessage;
import io.github.dsheirer.bits.CorrectedBinaryMessage;
/**
* Inbound (from Controller) Modular Request Message
@@ -44,7 +45,7 @@ public class ModularRequestMessage extends MCGPPacket
* @param message containing the packet
* @param offset to the packet within the message
*/
public ModularRequestMessage(MCGPHeader header, BinaryMessage message, int offset)
public ModularRequestMessage(MCGPHeader header, CorrectedBinaryMessage message, int offset)
{
super(header, message, offset);
}

View File

@@ -20,6 +20,7 @@
package io.github.dsheirer.module.decode.ip.cellocator;
import io.github.dsheirer.bits.BinaryMessage;
import io.github.dsheirer.bits.CorrectedBinaryMessage;
/**
* Modular Message
@@ -47,7 +48,7 @@ public class ModularResponseMessage extends MCGPPacket
* @param message containing the packet
* @param offset to the packet within the message
*/
public ModularResponseMessage(MCGPHeader header, BinaryMessage message, int offset)
public ModularResponseMessage(MCGPHeader header, CorrectedBinaryMessage message, int offset)
{
super(header, message, offset);
}

View File

@@ -19,7 +19,7 @@
package io.github.dsheirer.module.decode.ip.cellocator;
import io.github.dsheirer.bits.BinaryMessage;
import io.github.dsheirer.bits.CorrectedBinaryMessage;
import org.apache.commons.lang3.StringUtils;
/**
@@ -48,7 +48,7 @@ public class ProgrammingCommandMessage extends MCGPPacket
* @param message containing the packet
* @param offset to the packet within the message
*/
public ProgrammingCommandMessage(MCGPHeader header, BinaryMessage message, int offset)
public ProgrammingCommandMessage(MCGPHeader header, CorrectedBinaryMessage message, int offset)
{
super(header, message, offset);
}

View File

@@ -19,7 +19,7 @@
package io.github.dsheirer.module.decode.ip.cellocator;
import io.github.dsheirer.bits.BinaryMessage;
import io.github.dsheirer.bits.CorrectedBinaryMessage;
/**
* Unit (Outbound) Programming Status/Response
@@ -47,7 +47,7 @@ public class ProgrammingStatusMessage extends MCGPPacket
* @param message containing the packet
* @param offset to the packet within the message
*/
public ProgrammingStatusMessage(MCGPHeader header, BinaryMessage message, int offset)
public ProgrammingStatusMessage(MCGPHeader header, CorrectedBinaryMessage message, int offset)
{
super(header, message, offset);
}

View File

@@ -19,7 +19,7 @@
package io.github.dsheirer.module.decode.ip.cellocator;
import io.github.dsheirer.bits.BinaryMessage;
import io.github.dsheirer.bits.CorrectedBinaryMessage;
import io.github.dsheirer.module.decode.ip.IPacket;
import io.github.dsheirer.module.decode.ip.UnknownPacket;
@@ -37,7 +37,7 @@ public class UnknownMCGPMessage extends MCGPPacket
* @param message containing the packet
* @param offset to the packet within the message
*/
public UnknownMCGPMessage(MCGPHeader header, BinaryMessage message, int offset)
public UnknownMCGPMessage(MCGPHeader header, CorrectedBinaryMessage message, int offset)
{
super(header, message, offset);
}

View File

@@ -0,0 +1,94 @@
/*
* ******************************************************************************
* sdrtrunk
* Copyright (C) 2014-2018 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
* *****************************************************************************
*/
package io.github.dsheirer.module.decode.ip.icmp;
import io.github.dsheirer.bits.BinaryMessage;
import io.github.dsheirer.module.decode.ip.Header;
/**
* Internet Control Message Protocol (ICMP) Header
*/
public class ICMPHeader extends Header
{
private static final int[] TYPE = {0, 1, 2, 3, 4, 5, 6, 7};
private static final int[] CODE = {8, 9, 10, 11, 12, 13, 14, 15};
private static final int[] TYPE_CODE = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
/**
* Constructs a parser for a header contained within a binary message starting at the offset.
*
* @param message containing the header
* @param offset to the header within the message
*/
public ICMPHeader(BinaryMessage message, int offset)
{
super(message, offset);
checkValid();
}
public String toString()
{
StringBuilder sb = new StringBuilder();
ICMPTypeCode typeCode = getTypeCode();
if(typeCode != ICMPTypeCode.UNKNOWN)
{
sb.append("ICMP ").append(typeCode);
}
else
{
sb.append("ICMP UNKNOWN TYPE CODE:").append(getTypeCodeValue());
}
return sb.toString();
}
public ICMPTypeCode getTypeCode()
{
return ICMPTypeCode.fromValue(getTypeCodeValue());
}
public int getTypeCodeValue()
{
return getMessage().getInt(TYPE_CODE, getOffset());
}
public int getType()
{
return getMessage().getInt(TYPE, getOffset());
}
public int getCode()
{
return getMessage().getInt(CODE, getOffset());
}
private void checkValid()
{
setValid(getMessage().size() >= getOffset() + getLength());
}
@Override
public int getLength()
{
return 64;
}
}

View File

@@ -0,0 +1,119 @@
/*
* ******************************************************************************
* sdrtrunk
* Copyright (C) 2014-2018 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
* *****************************************************************************
*/
package io.github.dsheirer.module.decode.ip.icmp;
import io.github.dsheirer.bits.CorrectedBinaryMessage;
import io.github.dsheirer.identifier.Identifier;
import io.github.dsheirer.module.decode.ip.IPacket;
import io.github.dsheirer.module.decode.ip.Packet;
import io.github.dsheirer.module.decode.ip.PacketMessageFactory;
import io.github.dsheirer.module.decode.ip.UnknownPacket;
import java.util.ArrayList;
import java.util.List;
/**
* Internet Control Message Protocol (ICMP) Packet
*/
public class ICMPPacket extends Packet
{
private ICMPHeader mHeader;
private IPacket mPayload;
private List<Identifier> mIdentifiers;
/**
* Constructs a parser for a header contained within a binary message starting at the offset.
*
* @param message containing the packet
* @param offset to the packet within the message
*/
public ICMPPacket(CorrectedBinaryMessage message, int offset)
{
super(message, offset);
}
public String toString()
{
StringBuilder sb = new StringBuilder();
if(getHeader().isValid())
{
sb.append(getHeader());
}
else
{
sb.append("INVALID HEADER");
}
sb.append(" PACKET:").append(getPayload());
return sb.toString();
}
@Override
public ICMPHeader getHeader()
{
if(mHeader == null)
{
mHeader = new ICMPHeader(getMessage(), getOffset());
}
return mHeader;
}
@Override
public IPacket getPayload()
{
if(mPayload == null && getHeader().isValid())
{
if(getHeader().isValid())
{
int offset = getOffset();
int headerLength = getHeader().getLength();
int totalOffset = offset + headerLength;
mPayload = PacketMessageFactory.create(getMessage(), getOffset() + getHeader().getLength());
}
else
{
//Set the offset to the message offset plus 64 bits for UDP header
mPayload = new UnknownPacket(getMessage(), getOffset() + getHeader().getLength());
}
}
return mPayload;
}
@Override
public List<Identifier> getIdentifiers()
{
if(mIdentifiers == null)
{
mIdentifiers = new ArrayList<>();
//Roll up the identifiers from the payload packet
if(hasPayload())
{
mIdentifiers.addAll(getPayload().getIdentifiers());
}
}
return mIdentifiers;
}
}

View File

@@ -0,0 +1,139 @@
/*
* *****************************************************************************
* Copyright (C) 2014-2020 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
* ****************************************************************************
*/
package io.github.dsheirer.module.decode.ip.icmp;
import java.util.Map;
import java.util.TreeMap;
/**
* ICMP Type:Code enumeration
*/
public enum ICMPTypeCode
{
ECHO_REPLY(0,0,"ECHO REPLY"),
//Type: 3 Destination Unreachable
DESTINATION_NETWORK_UNREACHABLE(3,0, "DESTINATION NETWORK UNREACHABLE"),
DESTINATION_HOST_UNREACHABLE(3,1, "DESTINATION HOST UNREACHABLE"),
DESTINATION_PROTOCOL_UNREACHABLE(3,2, "DESTINATION PROTOCOL UNREACHABLE"),
DESTINATION_PORT_UNREACHABLE(3,3, "DESTINATION PORT UNREACHABLE"),
FRAGMENTATION_REQUIRED(3,4, "FRAGMENTATION REQUIRED"),
SOURCE_ROUTE_FAILED(3,5, "SOURCE ROUTE FAILED"),
DESTINATION_NETWORK_UNKNOWN(3,6, "DESTINATION NETWORK UNKNOWN"),
DESTINATION_HOST_UNKNOWN(3,7, "DESTINATION HOST UNKNOWN"),
SOURCE_HOST_ISOLATED(3,8, "SOURCE HOST ISOLATED"),
NETWORK_ADMINISTRATIVELY_PROHIBITED(3,9, "NETWORK ADMINISTRATIVELY PROHIBITED"),
HOST_ADMINISTRATIVELY_PROHIBITED(3,10, "HOST ADMINISTRATIVELY PROHIBITED"),
NETWORK_UNREACHABLE_FOR_TOS(3,11, "NETWORK UNREACHABLE FOR TOS"),
HOST_UNREACHABLE_FOR_TOS(3,12, "HOST UNREACHABLE FOR TOS"),
COMMUNICATION_ADMINISTRATIVELY_PROHIBITED(3,13, "COMMUNICATION ADMINISTRATIVELY PROHIBITED"),
HOST_PRECEDENCE_VIOLATION(3,14, "HOST PRECEDENCE VIOLATION"),
PRECEDENCE_CUTOFF_IN_EFFECT(3,15, "PRECEDENCE CUTOFF IN EFFECT"),
//Type: 5 Redirect Message
REDIRECT_DATAGRAM_FOR_THE_NETWORK(5,0, "REDIRECT DATAGRAM FOR THE NETWORK"),
REDIRECT_DATAGRAM_FOR_THE_HOST(5,1, "REDIRECT DATAGRAM FOR THE HOST"),
REDIRECT_DATAGRAM_FOR_THE_TOS_AND_NETWORK(5,2, "REDIRECT DATAGRAM FOR THE TOS & NETWORK"),
REDIRECT_DATAGRAM_FOR_THE_TOS_AND_HOST(5,3, "REDIRECT DATAGRAM FOR THE TOS & HOST"),
//Type: 8 Echo Request
ECHO_REQUEST(8,0, "ECHO REQUEST"),
//Type: 9 Router Advertisement
ROUTER_ADVERTISEMENT(9, 0, "ROUTER ADVERTISEMENT"),
//Type: 10 Router Solicitation
ROUTER_SOLICITATION(10,0,"ROUTER SOLICITATION"),
//Type: 11 Time Exceeded
TTL_EXPIRED_IN_TRANSIT(11, 0, "TTL EXPIRED IN TRANSIT"),
FRAGMENT_REASSEMBLY_TIME_EXCEEDED(11, 1, "FRAGMENT REASSEMBLY TIME EXCEEDED"),
//Type: 12 Bad IP Header
IP_HEADER_ERROR_POINTER(12, 0, "IP HEADER ERROR - POINTER INDICATES ERROR"),
IP_HEADER_ERROR_MISSING_OPTION(12,1,"IP HEADER ERROR - MISSING REQUIRED OPTION"),
IP_HEADER_ERROR_BAD_LENGTH(12,2,"IP HEADER ERROR - BAD LENGTH"),
//Type: 13 Timestamp
TIMESTAMP(13, 0, "TIMESTAMP"),
//Type: 14 Timestamp Reply
TIMESTAMP_REPLY(14, 0, "TIMESTAMP REPLY"),
//Type: 42 Extended Echo Request
EXTENDED_ECHO_REQUEST(42, 0, "EXTENDED ECHO REQUEST"),
//Type: 43 Extended Echo Reply
EXTENDED_ECHO_REPLY_NO_ERROR(43, 0, "EXTENDED ECHO - NO ERROR"),
EXTENDED_ECHO_REPLY_MALFORMED_QUERY(43, 1, "EXTENDED ECHO - MALFORMED QUERY"),
EXTENDED_ECHO_REPLY_NO_INTERFACE(43, 2, "EXTENDED ECHO - NO SUCH INTERFACE"),
EXTENDED_ECHO_REPLY_NO_TABLE(43, 3, "EXTENDED ECHO - NO SUCH TABLE ENTRY"),
EXTENDED_ECHO_REPLY_MULTIPLE_INTERFACES(43, 4, "EXTENDED ECHO - MULTIPLE INTERFACES"),
UNKNOWN(-1, -1, "UNKNOWN");
private int mValue;
private String mLabel;
ICMPTypeCode(int type, int code, String label)
{
mValue = (type << 8) + code;
mLabel = label;
}
private static final Map<Integer,ICMPTypeCode> LOOKUP_MAP = new TreeMap<>();
static
{
for(ICMPTypeCode type: ICMPTypeCode.values())
{
LOOKUP_MAP.put(type.getValue(), type);
}
}
/**
* Utility method to lookup the ICMP type:code entry from the combined 16-bit value form the ICMP header
* @param value to lookup
* @return entry or UNKNOWN
*/
public static ICMPTypeCode fromValue(int value)
{
if(LOOKUP_MAP.containsKey(value))
{
return LOOKUP_MAP.get(value);
}
return UNKNOWN;
}
/**
* 16-bit value that is the type and code bytes combined.
*/
public int getValue()
{
return mValue;
}
@Override
public String toString()
{
return mLabel;
}
}

View File

@@ -73,11 +73,11 @@ public class IPV4Header extends Header
return;
}
if(getMessage().size() < totalLength + getOffset())
{
setValid(false);
return;
}
// if(getMessage().size() < totalLength + getOffset())
// {
// setValid(false);
// return;
// }
}
@Override

View File

@@ -20,12 +20,13 @@
package io.github.dsheirer.module.decode.ip.ipv4;
import io.github.dsheirer.bits.BinaryMessage;
import io.github.dsheirer.bits.CorrectedBinaryMessage;
import io.github.dsheirer.identifier.Identifier;
import io.github.dsheirer.module.decode.ip.IPacket;
import io.github.dsheirer.module.decode.ip.Packet;
import io.github.dsheirer.module.decode.ip.PacketMessageFactory;
import io.github.dsheirer.module.decode.ip.UnknownPacket;
import java.util.ArrayList;
import java.util.List;
@@ -44,7 +45,7 @@ public class IPV4Packet extends Packet
* @param message containing an IPV4 packet
* @param offset to the start of the packet within the binary message
*/
public IPV4Packet(BinaryMessage message, int offset)
public IPV4Packet(CorrectedBinaryMessage message, int offset)
{
super(message, offset);
}
@@ -120,14 +121,14 @@ public class IPV4Packet extends Packet
if(mIdentifiers == null)
{
mIdentifiers = new ArrayList<>();
mIdentifiers.add(getHeader().getFromAddress());
mIdentifiers.add(getHeader().getToAddress());
//Roll up the identifiers from the payload packet
if(hasPayload())
{
mIdentifiers.addAll(getPayload().getIdentifiers());
}
mIdentifiers.add(getHeader().getToAddress());
mIdentifiers.add(getHeader().getFromAddress());
}
return mIdentifiers;

View File

@@ -0,0 +1,87 @@
/*
* *****************************************************************************
* Copyright (C) 2014-2020 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
* ****************************************************************************
*/
package io.github.dsheirer.module.decode.ip.lrrp;
import io.github.dsheirer.bits.BinaryMessage;
import io.github.dsheirer.identifier.Identifier;
import io.github.dsheirer.module.decode.ip.Header;
import java.util.Collections;
import java.util.List;
/**
* Location Request/Response Protocol (LRRP) Header
*/
public class LRRPHeader extends Header
{
private static final int[] TYPE = {0, 1, 2, 3, 4, 5, 6, 7};
private static final int[] LENGTH = {8, 9, 10, 11, 12, 13, 14, 15};
/**
* Constructs a parser for a header contained within a binary message starting at the offset.
*
* @param message containing the header
* @param offset to the header within the message
*/
public LRRPHeader(BinaryMessage message, int offset)
{
super(message, offset);
}
/**
* Checks that the underlying message is long enough to contain the PDU
*/
private void checkValid()
{
setValid(getMessage().size() >= (getOffset() + getLength() + getPayloadLength()));
}
/**
* Length of the payload in 8-bit characters
*
* @return
*/
public int getPayloadLength()
{
return getMessage().getInt(LENGTH, getOffset());
}
/**
* Length of this header in bits
*
* Note this length value includes the first 2 bytes of the message that indicates the overall
* message length and the length of the PDU header byte(s).
*
* This method may need to be overridden if there is more than 1 extension header in a PDU.
*/
@Override
public int getLength()
{
return 16;
}
/**
* Identifiers for this packet
*/
public List<Identifier> getIdentifiers()
{
return Collections.emptyList();
}
}

View File

@@ -0,0 +1,133 @@
/*
* *****************************************************************************
* Copyright (C) 2014-2020 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
* ****************************************************************************
*/
package io.github.dsheirer.module.decode.ip.lrrp;
import io.github.dsheirer.bits.CorrectedBinaryMessage;
import io.github.dsheirer.identifier.Identifier;
import io.github.dsheirer.module.decode.ip.IPacket;
import io.github.dsheirer.module.decode.ip.Packet;
import io.github.dsheirer.module.decode.ip.lrrp.token.Token;
import io.github.dsheirer.module.decode.ip.lrrp.token.TokenFactory;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* Location Request/Response Protocol (LRRP) Packet
*/
public class LRRPPacket extends Packet
{
//Constant for parsing a hexadecimal byte token identifier
private static final int[] BYTE_VALUE = {0, 1, 2, 3, 4, 5, 6, 7};
public static final int TOKEN_START = 16;
private LRRPHeader mHeader;
private List<Token> mTokens;
/**
* Constructs a parser for a header contained within a binary message starting at the offset.
*
* @param message containing the packet
* @param offset to the packet within the message
*/
public LRRPPacket(CorrectedBinaryMessage message, int offset)
{
super(message, offset);
}
public String toString()
{
StringBuilder sb = new StringBuilder();
sb.append("LRRP");
for(Token token: getTokens())
{
sb.append(" ").append(token);
}
return sb.toString();
}
@Override
public LRRPHeader getHeader()
{
if(mHeader == null)
{
mHeader = new LRRPHeader(getMessage(), getOffset());
}
return mHeader;
}
/**
* List of LRRP tokens parsed from the packet
*/
public List<Token> getTokens()
{
parseTokens();
return mTokens;
}
private void parseTokens()
{
if(mTokens == null)
{
mTokens = new ArrayList<>();
int characterCount = getHeader().getPayloadLength();
int offset = getOffset() + TOKEN_START;
while(characterCount > 0 && offset < getMessage().size())
{
String tokenId = getTokenIdentifier(offset);
Token token = TokenFactory.createToken(tokenId, getMessage(), offset, characterCount);
mTokens.add(token);
int length = token.getByteLength();
characterCount -= token.getByteLength();
offset += (8 * token.getByteLength());
}
Collections.sort(mTokens, (o1, o2) -> o1.getTokenType().compareTo(o2.getTokenType()));
}
}
/**
* Parses the string hexadecimal value of the 8-bit value that starts at the specified offset.
*/
private String getTokenIdentifier(int offset)
{
int id = getMessage().getInt(BYTE_VALUE, offset);
return String.format("%02X", id);
}
@Override
public IPacket getPayload()
{
//The payload is a sequence of tokens. There is no packet payload.
return null;
}
@Override
public List<Identifier> getIdentifiers()
{
return getHeader().getIdentifiers();
}
}

View File

@@ -0,0 +1,64 @@
/*
* *****************************************************************************
* Copyright (C) 2014-2020 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
* ****************************************************************************
*/
package io.github.dsheirer.module.decode.ip.lrrp.token;
import io.github.dsheirer.bits.CorrectedBinaryMessage;
/**
* LRRP Heading Token
*
* Start Token: 0x56
* Total Length: 2 bytes
*/
public class Heading extends Token
{
private static final int[] HEADING = new int[]{8, 9, 10, 11, 12, 13, 14, 15};
/**
* Constructs an instance of a heading token.
*
* @param message containing the heading
* @param offset to the start of the token
*/
public Heading(CorrectedBinaryMessage message, int offset)
{
super(message, offset);
}
@Override
public TokenType getTokenType()
{
return TokenType.HEADING;
}
/**
* Heading degrees relative to true North
*/
public long getHeading()
{
return getMessage().getInt(HEADING, getOffset());
}
@Override
public String toString()
{
return "HEADING:" + getHeading();
}
}

View File

@@ -0,0 +1,96 @@
/*
* *****************************************************************************
* Copyright (C) 2014-2020 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
* ****************************************************************************
*/
package io.github.dsheirer.module.decode.ip.lrrp.token;
import io.github.dsheirer.bits.BinaryMessage;
import io.github.dsheirer.bits.CorrectedBinaryMessage;
/**
* LRRP Identity Token
*
* Start Token: 0x22
* Total Length: 6 bytes
*/
public class Identity extends Token
{
private static final int IDENTIFIER_START = 16;
private static final int[] BYTE_VALUE = new int[]{0, 1, 2, 3, 4, 5, 6, 7};
/**
* Constructs an instance of a heading token.
*
* @param message containing the heading
* @param offset to the start of the token
*/
public Identity(CorrectedBinaryMessage message, int offset)
{
super(message, offset);
}
@Override
public TokenType getTokenType()
{
return TokenType.IDENTITY;
}
private BinaryMessage getTokenContents()
{
return getMessage().getSubMessage(getOffset(), getOffset() + 48);
}
/**
* Extracts the payload contents.
*
* Note: assumes that the values are 1-4 bytes in big-endian format? Not sure if this is correct because the
* values that I observed only had value in the LSB and the 3 MSBs were all zeros.
*/
public int getID()
{
int length = getVariableLengthPayloadSize();
int payloadOffset = 16;
int value = 0;
while(0 < length && length <= 4)
{
int byteValue = getMessage().getInt(BYTE_VALUE, getOffset() + payloadOffset);
byteValue = Integer.rotateLeft(byteValue, payloadOffset - 16);
value += byteValue;
payloadOffset += 8;
length--;
}
return value;
}
@Override
public String toString()
{
int id = getID();
if(id != 0)
{
return "ID:" + id;
}
return "ID:" + getTokenContents().toHexString();
}
}

View File

@@ -0,0 +1,64 @@
/*
* *****************************************************************************
* Copyright (C) 2014-2020 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
* ****************************************************************************
*/
package io.github.dsheirer.module.decode.ip.lrrp.token;
import io.github.dsheirer.identifier.Role;
import io.github.dsheirer.identifier.location.LocationIdentifier;
import io.github.dsheirer.identifier.location.Point;
import io.github.dsheirer.protocol.Protocol;
/**
* LRRP Position/Location
*/
public class LRRPPosition extends LocationIdentifier
{
/**
* Constructs an instance
*
* @param value location
* @param role to or from
*/
public LRRPPosition(Point value, Role role)
{
super(value, role);
}
@Override
public Protocol getProtocol()
{
return Protocol.LRRP;
}
/**
* Creates a FROM position
*/
public static LRRPPosition createFrom(double latitude, double longitude)
{
return new LRRPPosition(new Point(latitude, longitude), Role.FROM);
}
/**
* Creates a TO position
*/
public static LRRPPosition createTo(double latitude, double longitude)
{
return new LRRPPosition(new Point(latitude, longitude), Role.TO);
}
}

View File

@@ -0,0 +1,93 @@
/*
* *****************************************************************************
* Copyright (C) 2014-2020 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
* ****************************************************************************
*/
package io.github.dsheirer.module.decode.ip.lrrp.token;
import io.github.dsheirer.bits.CorrectedBinaryMessage;
/**
* LRRP Position Token
*
* Start Token: 0x66
* Total Length: 9 bytes
*/
public class Position extends Token
{
private static final int[] LATITUDE = new int[]{8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39};
private static final int[] LONGITUDE = new int[]{40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71};
private static final double LATITUDE_MULTIPLIER = 180.0 / 4294967295.0d;
private static final double LONGITUDE_MULTIPLIER = 360.0 / 4294967295.0d;
private LRRPPosition mPosition;
/**
* Constructs an instance of a heading token.
*
* @param message containing the heading
* @param offset to the start of the token
*/
public Position(CorrectedBinaryMessage message, int offset)
{
super(message, offset);
}
@Override
public TokenType getTokenType()
{
return TokenType.POSITION;
}
/**
* Position value
*/
public LRRPPosition getPosition()
{
if(mPosition == null)
{
mPosition = LRRPPosition.createFrom(getLatitude(), getLongitude());
}
return mPosition;
}
/**
* Latitude in degrees decimal
*/
public double getLatitude()
{
return getMessage().getInt(LATITUDE, getOffset()) * LATITUDE_MULTIPLIER;
}
/**
* Longitude in degrees decimal
*/
public double getLongitude()
{
return getMessage().getInt(LONGITUDE, getOffset()) * LONGITUDE_MULTIPLIER;
}
@Override
public String toString()
{
return "POSITION:" + getPosition();
}
}

View File

@@ -0,0 +1,64 @@
/*
* *****************************************************************************
* Copyright (C) 2014-2020 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
* ****************************************************************************
*/
package io.github.dsheirer.module.decode.ip.lrrp.token;
import io.github.dsheirer.bits.CorrectedBinaryMessage;
/**
* LRRP 3-D Position with latitude, longitude and altitude
*/
public class Position3D extends Position
{
private static final int[] ALTITUDE = new int[]{72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87};
/**
* Constructs an instance of a heading token.
*
* @param message containing the heading
* @param offset to the start of the token
*/
public Position3D(CorrectedBinaryMessage message, int offset)
{
super(message, offset);
}
@Override
public TokenType getTokenType()
{
return TokenType.POSITION_3D;
}
/**
* Altitude
*
* @return altitude in meters
*/
public int getAltitude()
{
return getMessage().getInt(ALTITUDE, getOffset());
}
@Override
public String toString()
{
return "POSITION:" + getPosition() + " ALT:" + getAltitude() + " MTRS";
}
}

View File

@@ -0,0 +1,65 @@
/*
* *****************************************************************************
* Copyright (C) 2014-2020 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
* ****************************************************************************
*/
package io.github.dsheirer.module.decode.ip.lrrp.token;
import io.github.dsheirer.bits.CorrectedBinaryMessage;
/**
* LRRP Speed Token
*
* Start Token: 0x6C
* Total Length: 3 bytes
*/
public class Speed extends Token
{
private static final int[] UNKNOWN = new int[]{8, 9, 10, 11, 12, 13, 14, 15};
private static final int[] SPEED = new int[]{16, 17, 18, 19, 20, 21, 22, 23};
/**
* Constructs an instance of a heading token.
*
* @param message containing the heading
* @param offset to the start of the token
*/
public Speed(CorrectedBinaryMessage message, int offset)
{
super(message, offset);
}
@Override
public TokenType getTokenType()
{
return TokenType.SPEED;
}
/**
* Speed in kilometers per hour (kph)
*/
public long getSpeed()
{
return getMessage().getInt(SPEED, getOffset());
}
@Override
public String toString()
{
return "SPEED:" + getSpeed() + " KPH";
}
}

View File

@@ -0,0 +1,84 @@
/*
* *****************************************************************************
* Copyright (C) 2014-2020 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
* ****************************************************************************
*/
package io.github.dsheirer.module.decode.ip.lrrp.token;
import io.github.dsheirer.bits.CorrectedBinaryMessage;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.TimeZone;
/**
* LRRP Timestamp Token
*
* Start Token: 0x34
* Total Length: 6 bytes
*/
public class Timestamp extends Token
{
private static final int[] YEAR = new int[]{8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21};
private static final int[] MONTH = new int[]{22, 23, 24, 25};
private static final int[] DAY = new int[]{26, 27, 28, 29, 30};
private static final int[] HOUR = new int[]{31, 32, 33, 34, 35};
private static final int[] MINUTE = new int[]{36, 37, 38, 39, 40, 41};
private static final int[] SECOND = new int[]{42, 43, 44, 45, 46, 47};
/**
* Constructs an instance of a timestamp token.
*
* @param message containing the timestamp
* @param offset to the start of the token
*/
public Timestamp(CorrectedBinaryMessage message, int offset)
{
super(message, offset);
}
@Override
public TokenType getTokenType()
{
return TokenType.TIMESTAMP;
}
/**
* Timestamp value in milliseconds
*/
public long getTimestamp()
{
int year = getMessage().getInt(YEAR, getOffset());
int month = getMessage().getInt(MONTH, getOffset()) - 1;
int day = getMessage().getInt(DAY, getOffset());
int hour = getMessage().getInt(HOUR, getOffset());
int minute = getMessage().getInt(MINUTE, getOffset());
int second = getMessage().getInt(SECOND, getOffset());
Calendar calendar = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
calendar.clear();
calendar.set(year, month, day, hour, minute, second);
return calendar.getTimeInMillis();
}
@Override
public String toString()
{
return "TIME:" + new Date(getTimestamp()).toString().toUpperCase();
}
}

View File

@@ -0,0 +1,96 @@
/*
* *****************************************************************************
* Copyright (C) 2014-2020 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
* ****************************************************************************
*/
package io.github.dsheirer.module.decode.ip.lrrp.token;
import io.github.dsheirer.bits.CorrectedBinaryMessage;
/**
* LRRP Token.
*
* LRRP packets are composed of a sequence of tokens that makeup a set of values for the LRRP report.
*/
public abstract class Token
{
/**
* Length field for a variable length token
*/
private static final int[] VARIABLE_LENGTH_BYTE_COUNT = new int[]{8, 9, 10, 11, 12, 13, 14, 15};
private CorrectedBinaryMessage mMessage;
private int mOffset;
/**
* Constructs an instance
*
* @param message containing the token and value
* @param offset to the start of the token identifier
*/
public Token(CorrectedBinaryMessage message, int offset)
{
mMessage = message;
mOffset = offset;
}
/**
* Message that contains this token and value.
*/
protected CorrectedBinaryMessage getMessage()
{
return mMessage;
}
/**
* Offset to the start of the token identifier within the message
*
* @return bit offset value
*/
protected int getOffset()
{
return mOffset;
}
/**
* Type of token and value
*/
public abstract TokenType getTokenType();
/**
* Token payload byte length for variable length tokens.
*/
public int getVariableLengthPayloadSize()
{
return getMessage().getInt(VARIABLE_LENGTH_BYTE_COUNT, getOffset());
}
/**
* Number of bytes for this token including the token identifier
*/
public int getByteLength()
{
if(getTokenType().isVariableLength())
{
return getVariableLengthPayloadSize() + 2; //Variable Length Payload + Id + Length Field
}
else
{
return getTokenType().getLength() + 1; //Fixed Length Payload + Id
}
}
}

View File

@@ -0,0 +1,54 @@
/*
* *****************************************************************************
* Copyright (C) 2014-2020 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
* ****************************************************************************
*/
package io.github.dsheirer.module.decode.ip.lrrp.token;
import io.github.dsheirer.bits.CorrectedBinaryMessage;
/**
* LRRP Token Factory
*/
public class TokenFactory
{
public static Token createToken(String id, CorrectedBinaryMessage message, int offset, int remainingCharacterCount)
{
TokenType tokenType = TokenType.fromValue(id);
switch(tokenType)
{
case HEADING:
return new Heading(message, offset);
case POSITION:
return new Position(message, offset);
case POSITION_3D:
return new Position3D(message, offset);
case SPEED:
return new Speed(message, offset);
case TIMESTAMP:
return new Timestamp(message, offset);
case IDENTITY:
return new Identity(message, offset);
case UNKNOWN_23:
return new Unknown23(message, offset);
case UNKNOWN:
default:
return new UnknownToken(message, offset, remainingCharacterCount);
}
}
}

View File

@@ -0,0 +1,105 @@
/*
* *****************************************************************************
* Copyright (C) 2014-2020 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
* ****************************************************************************
*/
package io.github.dsheirer.module.decode.ip.lrrp.token;
import java.util.HashMap;
import java.util.Map;
/**
* LRRP Token Types
*
* Variable length tokens consist of an identifier, a length indicator, and then a sequence of bytes equal in length
* to the length indicator.
*/
public enum TokenType
{
POSITION("66", 8),
POSITION_3D("51", 10),
HEADING("56", 1),
SPEED("6C", 2),
TIMESTAMP("34", 5),
IDENTITY("22", -1),
UNKNOWN_23("23", 1),
UNKNOWN("0",0);
private String mValue;
private int mLength;
/**
* Constructs an instance
* @param value of the token
* @param length of the token, exclusive of the identifier, where -1 indicates a variable length token.
*/
TokenType(String value, int length)
{
mValue = value;
mLength = length;
}
/**
* String (Numeric) value of the token
*/
public String getValue()
{
return mValue;
}
/**
* Indicates if this token is variable length.
*/
public boolean isVariableLength()
{
return mLength == -1;
}
/**
* Length of the token value in bytes.
* Note: byte count does not include the token byte itself.
*/
public int getLength()
{
return mLength;
}
private static final Map<String,TokenType> LOOKUP_MAP = new HashMap<>();
static
{
for(TokenType tokenType: TokenType.values())
{
LOOKUP_MAP.put(tokenType.getValue(), tokenType);
}
}
/**
* Lookup a token from a 2-character string value
* @param value that represents the token
* @return matching token or UNKNOWN.
*/
public static TokenType fromValue(String value)
{
if(value != null && LOOKUP_MAP.containsKey(value))
{
return LOOKUP_MAP.get(value);
}
return UNKNOWN;
}
}

View File

@@ -0,0 +1,62 @@
/*
* *****************************************************************************
* Copyright (C) 2014-2020 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
* ****************************************************************************
*/
package io.github.dsheirer.module.decode.ip.lrrp.token;
import io.github.dsheirer.bits.BinaryMessage;
import io.github.dsheirer.bits.CorrectedBinaryMessage;
/**
* LRRP Unknown Token
*
* Start Token: 0x23
* Total Length: 2 bytes
*/
public class Unknown23 extends Token
{
private static final int[] UNKNOWN = new int[]{8, 9, 10, 11, 12, 13, 14, 15};
/**
* Constructs an instance of a heading token.
*
* @param message containing the heading
* @param offset to the start of the token
*/
public Unknown23(CorrectedBinaryMessage message, int offset)
{
super(message, offset);
}
@Override
public TokenType getTokenType()
{
return TokenType.UNKNOWN_23;
}
private BinaryMessage getTokenContents()
{
return getMessage().getSubMessage(getOffset(), getOffset() + 16);
}
@Override
public String toString()
{
return "UNK:" + getTokenContents().toHexString();
}
}

View File

@@ -0,0 +1,61 @@
/*
* *****************************************************************************
* Copyright (C) 2014-2020 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
* ****************************************************************************
*/
package io.github.dsheirer.module.decode.ip.lrrp.token;
import io.github.dsheirer.bits.BinaryMessage;
import io.github.dsheirer.bits.CorrectedBinaryMessage;
/**
* Unknown or Unrecognized token. This class is also used to capture the remaining character content of the token
* string when parsing tokens from a LRRP packet, to account for the remaining token content.
*/
public class UnknownToken extends Token
{
private int mCharacterLength;
/**
* Constructs an instance
*
* @param message containing the token and value
* @param offset to the start of the token identifier
*/
public UnknownToken(CorrectedBinaryMessage message, int offset, int characterLength)
{
super(message, offset);
mCharacterLength = characterLength;
}
@Override
public TokenType getTokenType()
{
return TokenType.UNKNOWN;
}
private BinaryMessage getTokenContents()
{
return getMessage().getSubMessage(getOffset(), getOffset() + (mCharacterLength * 8));
}
@Override
public String toString()
{
return "UNK:" + getTokenContents().toHexString();
}
}

View File

@@ -28,6 +28,9 @@ public class UDPHeader extends Header
private static final int[] SOURCE_PORT = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
private static final int[] DESTINATION_PORT = {16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31};
private UDPPort mSourcePort;
private UDPPort mDestinationPort;
/**
* Constructs a parser for a header contained within a binary message starting at the offset.
*
@@ -63,16 +66,26 @@ public class UDPHeader extends Header
* Source UDP port number
* @return
*/
public int getSourcePort()
public UDPPort getSourcePort()
{
return getMessage().getInt(SOURCE_PORT, getOffset());
if(mSourcePort == null)
{
mSourcePort = UDPPort.createFrom(getMessage().getInt(SOURCE_PORT, getOffset()));
}
return mSourcePort;
}
/**
* Destination UDP port number
*/
public int getDestinationPort()
public UDPPort getDestinationPort()
{
return getMessage().getInt(DESTINATION_PORT, getOffset());
if(mDestinationPort == null)
{
mDestinationPort = UDPPort.createTo(getMessage().getInt(DESTINATION_PORT, getOffset()));
}
return mDestinationPort;
}
}

View File

@@ -20,20 +20,21 @@
package io.github.dsheirer.module.decode.ip.udp;
import io.github.dsheirer.bits.BinaryMessage;
import io.github.dsheirer.bits.CorrectedBinaryMessage;
import io.github.dsheirer.identifier.Identifier;
import io.github.dsheirer.module.decode.ip.IPacket;
import io.github.dsheirer.module.decode.ip.Packet;
import io.github.dsheirer.module.decode.ip.PacketMessageFactory;
import io.github.dsheirer.module.decode.ip.UnknownPacket;
import java.util.Collections;
import java.util.ArrayList;
import java.util.List;
public class UDPPacket extends Packet
{
private UDPHeader mHeader;
private IPacket mPayload;
private List<Identifier> mIdentifiers;
/**
* Constructs a parser for a header contained within a binary message starting at the offset.
@@ -41,7 +42,7 @@ public class UDPPacket extends Packet
* @param message containing the packet
* @param offset to the packet within the message
*/
public UDPPacket(BinaryMessage message, int offset)
public UDPPacket(CorrectedBinaryMessage message, int offset)
{
super(message, offset);
}
@@ -77,7 +78,7 @@ public class UDPPacket extends Packet
@Override
public IPacket getPayload()
{
if(mPayload == null)
if(mPayload == null && getHeader().isValid())
{
if(getHeader().isValid())
{
@@ -97,11 +98,19 @@ public class UDPPacket extends Packet
@Override
public List<Identifier> getIdentifiers()
{
if(hasPayload())
if(mIdentifiers == null)
{
return getPayload().getIdentifiers();
mIdentifiers = new ArrayList<>();
mIdentifiers.add(getHeader().getSourcePort());
mIdentifiers.add(getHeader().getDestinationPort());
//Roll up the identifiers from the payload packet
if(hasPayload())
{
mIdentifiers.addAll(getPayload().getIdentifiers());
}
}
return Collections.emptyList();
return mIdentifiers;
}
}

View File

@@ -0,0 +1,64 @@
/*
* *****************************************************************************
* Copyright (C) 2014-2020 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
* ****************************************************************************
*/
package io.github.dsheirer.module.decode.ip.udp;
import io.github.dsheirer.identifier.Form;
import io.github.dsheirer.identifier.IdentifierClass;
import io.github.dsheirer.identifier.Role;
import io.github.dsheirer.identifier.integer.IntegerIdentifier;
import io.github.dsheirer.protocol.Protocol;
/**
* UDP Port Number Identifier
*/
public class UDPPort extends IntegerIdentifier
{
/**
* Constructs an instance
* @param value of the port
* @param role of the port (TO/FROM)
*/
public UDPPort(int value, Role role)
{
super(value, IdentifierClass.NETWORK, Form.UDP_PORT, role);
}
@Override
public Protocol getProtocol()
{
return Protocol.UDP;
}
/**
* Utility method to create a FROM port
*/
public static UDPPort createFrom(int value)
{
return new UDPPort(value, Role.FROM);
}
/**
* Utility method to create a TO port
*/
public static UDPPort createTo(int value)
{
return new UDPPort(value, Role.TO);
}
}

View File

@@ -0,0 +1,170 @@
/*
* *****************************************************************************
* Copyright (C) 2014-2020 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
* ****************************************************************************
*/
package io.github.dsheirer.module.decode.ip.xcmp;
import com.google.common.base.Joiner;
import io.github.dsheirer.bits.CorrectedBinaryMessage;
import io.github.dsheirer.identifier.Identifier;
import io.github.dsheirer.module.decode.dmr.identifier.DMRNetwork;
import io.github.dsheirer.module.decode.ip.IHeader;
import io.github.dsheirer.module.decode.ip.IPacket;
import io.github.dsheirer.module.decode.ip.Packet;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* XCMP Transfer: Network Frequency File
*/
public class NetworkFrequencyFile extends Packet
{
private static final int[] VERSION = new int[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
private static final int[] SEGMENT_NUMBER = new int[]{16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31};
private static final int[] SEGMENT_COUNT = new int[]{32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47};
private static final int[] NETWORK = new int[]{48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59};
private static final int[] UNKNOWN = new int[]{60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76,
77, 78, 79};
private static final int REPEATER_STRUCTURE_START = 80;
private static final int REPEATER_STRUCTURE_LENGTH = 72;
private List<Repeater> mRepeaters;
private DMRNetwork mNetwork;
/**
* Constructs a parser for a header contained within a binary message starting at the offset.
*
* @param message containing the packet
* @param offset to the packet within the message
*/
public NetworkFrequencyFile(CorrectedBinaryMessage message, int offset)
{
super(message, offset);
}
public String toString()
{
StringBuilder sb = new StringBuilder();
sb.append("NETWORK FREQUENCY FILE VERSION:").append(getVersion());
sb.append(" NETWORK:").append(getNetwork());
sb.append(" SEGMENT:").append(getSegmentNumber()).append(" OF ").append(getSegmentCount());
List<Repeater> repeaters = getRepeaters();
if(repeaters.isEmpty())
{
sb.append(" NO REPEATER INFO");
}
else
{
sb.append(" ").append(Joiner.on(" | ").join(mRepeaters));
}
return sb.toString();
}
public DMRNetwork getNetwork()
{
if(mNetwork == null)
{
mNetwork = DMRNetwork.create(getMessage().getInt(NETWORK, getOffset()));
}
return mNetwork;
}
/**
* Unknown 20-bit field contents
*/
public String getUnknown()
{
return String.format("%05X", getMessage().getInt(UNKNOWN, getOffset()));
}
/**
* Segment number for this packet
*
* @return
*/
public int getSegmentNumber()
{
return getMessage().getInt(SEGMENT_NUMBER, getOffset());
}
/**
* Number of segments contained in the complete file
*/
public int getSegmentCount()
{
return getMessage().getInt(SEGMENT_COUNT, getOffset());
}
/**
* List of repeater structures parsed from the Network Information File segment
*/
public List<Repeater> getRepeaters()
{
if(mRepeaters == null)
{
mRepeaters = new ArrayList<>();
int offset = getOffset() + REPEATER_STRUCTURE_START;
for(int x = 0; x < 15; x++)
{
if(offset <= getMessage().length())
{
Repeater repeater = new Repeater(getMessage(), offset, getNetwork());
if(repeater.isValid())
{
mRepeaters.add(repeater);
}
offset += REPEATER_STRUCTURE_LENGTH;
}
}
}
return mRepeaters;
}
public int getVersion()
{
return getMessage().getInt(VERSION, getOffset());
}
@Override
public IHeader getHeader()
{
return null;
}
@Override
public IPacket getPayload()
{
return null;
}
@Override
public List<Identifier> getIdentifiers()
{
return Collections.emptyList();
}
}

View File

@@ -0,0 +1,157 @@
/*
* *****************************************************************************
* Copyright (C) 2014-2020 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
* ****************************************************************************
*/
package io.github.dsheirer.module.decode.ip.xcmp;
import io.github.dsheirer.bits.CorrectedBinaryMessage;
import io.github.dsheirer.module.decode.dmr.identifier.DMRNetwork;
import io.github.dsheirer.module.decode.dmr.identifier.DMRSite;
/**
* Repeater Structure Parser
*/
public class Repeater
{
private static int[] SITE = new int[]{0, 1, 2, 3, 4, 5, 6, 7};
private static int[] REPEATER_ID = new int[]{8, 9, 10, 11};
private static int CONTROL_CHANNEL_FLAG = 12;
private static int[] UPLINK_FREQUENCY = new int[]{13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39};
private static int[] COLOR_CODE = new int[]{40, 41, 42, 43};
private static int RESERVED = 44;
private static int[] DOWNLINK_FREQUENCY = new int[]{45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71};
private CorrectedBinaryMessage mMessage;
private int mOffset;
private DMRNetwork mDMRNetwork;
private DMRSite mSite;
/**
* Constructs an instance
*
* @param message containing a repeater structure
* @param offset into the message to where the repeater structure starts
*/
public Repeater(CorrectedBinaryMessage message, int offset, DMRNetwork dmrNetwork)
{
mMessage = message;
mOffset = offset;
mDMRNetwork = dmrNetwork;
}
@Override
public String toString()
{
StringBuilder sb = new StringBuilder();
sb.append("REPEATER:").append(getNetwork()).append(".").append(getSite()).append(".").append(getRepeaterNumber());
sb.append(" CC:").append(getColorCode());
sb.append(" DN:").append(getDownlinkFrequency() / 1E6d);
sb.append(" UP:").append(getUplinkFrequency() / 1E6d);
if(isControlChannel())
{
sb.append(" CONTROL");
}
return sb.toString();
}
public DMRNetwork getNetwork()
{
return mDMRNetwork;
}
/**
* Message containing this repeater structure
*/
private CorrectedBinaryMessage getMessage()
{
return mMessage;
}
/**
* Offset into the message where this structure starts
*/
private int getOffset()
{
return mOffset;
}
/**
* Indicates if this repeater structure contains valid information
* @return true if valid, or false if the downlink and uplink frequency values are the same.
*/
public boolean isValid()
{
return getDownlinkFrequency() != getUplinkFrequency();
}
/**
* Color code for the repeater
*/
public int getColorCode()
{
return getMessage().getInt(COLOR_CODE, getOffset());
}
/**
* Repeater receive / uplink frequency
* @return frequency in Hertz
*/
public long getUplinkFrequency()
{
return getMessage().getInt(UPLINK_FREQUENCY, getOffset()) * 10l;
}
/**
* Repeater transmit / downlink frequency
* @return frequency in Hertz
*/
public long getDownlinkFrequency()
{
return getMessage().getInt(DOWNLINK_FREQUENCY, getOffset()) * 10l;
}
/**
* Indicates if this is a control channel
*/
public boolean isControlChannel()
{
return getMessage().get(CONTROL_CHANNEL_FLAG + getOffset());
}
/**
* Repeater Number/ID
*
* @return id as a 1-based index
*/
public int getRepeaterNumber()
{
return getMessage().getInt(REPEATER_ID, getOffset()) + 1;
}
public DMRSite getSite()
{
if(mSite == null)
{
mSite = DMRSite.create(getMessage().getInt(SITE, getOffset()));
}
return mSite;
}
}

View File

@@ -0,0 +1,110 @@
/*
* *****************************************************************************
* Copyright (C) 2014-2020 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
* ****************************************************************************
*/
package io.github.dsheirer.module.decode.ip.xcmp;
import io.github.dsheirer.bits.BinaryMessage;
import io.github.dsheirer.identifier.Identifier;
import io.github.dsheirer.module.decode.ip.Header;
import java.util.Collections;
import java.util.List;
/**
* EXtensible Command Message Protocol (XCMP) Header
*/
public class XCMPHeader extends Header
{
private static final int[] MESSAGE_TYPE = {0, 1, 2, 3, 4, 5, 6, 7};
/**
* Constructs a parser for a header contained within a binary message starting at the offset.
*
* @param message containing the header
* @param offset to the header within the message
*/
public XCMPHeader(BinaryMessage message, int offset)
{
super(message, offset);
}
/**
* Identify the XCMP message type from the message
*/
public static XCMPMessageType getMessageType(BinaryMessage message, int offset)
{
return XCMPMessageType.fromValue(message.getInt(MESSAGE_TYPE, offset));
}
/**
* Identify the XCMP message type for this message
*/
public XCMPMessageType getMessageType()
{
return getMessageType(getMessage(), getOffset());
}
/**
* Message Type Value
*/
public int getMessageTypeValue()
{
return getMessage().getInt(MESSAGE_TYPE, getOffset());
}
/**
* Length of this header in bits
*
* Note this length value includes the first 2 bytes of the message that indicates the overall
* message length and the length of the PDU header byte(s).
*
* This method may need to be overridden if there is more than 1 extension header in a PDU.
*/
@Override
public int getLength()
{
return 8;
}
/**
* Identifiers for this packet
*/
public List<Identifier> getIdentifiers()
{
return Collections.emptyList();
}
@Override
public String toString()
{
StringBuilder sb = new StringBuilder();
sb.append("XCMP");
if(getMessageType() != XCMPMessageType.UNKNOWN)
{
sb.append(" ").append(getMessageType());
}
else
{
sb.append(" UNKNOWN FILE TYPE:").append(String.format("%02X", getMessageTypeValue()));
}
return sb.toString();
}
}

View File

@@ -0,0 +1,78 @@
/*
* *****************************************************************************
* Copyright (C) 2014-2020 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
* ****************************************************************************
*/
package io.github.dsheirer.module.decode.ip.xcmp;
import java.util.Map;
import java.util.TreeMap;
/**
* XCMP Message Types enumeration
*/
public enum XCMPMessageType
{
NETWORK_FREQUENCY_FILE(2, "NETWORK FREQUENCY FILE"),
UNKNOWN(-1, "UNKNOWN");
private int mValue;
private String mLabel;
XCMPMessageType(int value, String label)
{
mValue = value;
mLabel = label;
}
/**
* Numeric value for the type
*/
public int getValue()
{
return mValue;
}
@Override
public String toString()
{
return mLabel;
}
private static final Map<Integer,XCMPMessageType> LOOKUP_MAP = new TreeMap<>();
static
{
for(XCMPMessageType type: XCMPMessageType.values())
{
LOOKUP_MAP.put(type.getValue(), type);
}
}
/**
* Lookup the XCMP Message type from the value
*/
public static XCMPMessageType fromValue(int value)
{
if(LOOKUP_MAP.containsKey(value))
{
return LOOKUP_MAP.get(value);
}
return UNKNOWN;
}
}

View File

@@ -0,0 +1,85 @@
/*
* *****************************************************************************
* Copyright (C) 2014-2020 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
* ****************************************************************************
*/
package io.github.dsheirer.module.decode.ip.xcmp;
import io.github.dsheirer.bits.CorrectedBinaryMessage;
import io.github.dsheirer.identifier.Identifier;
import io.github.dsheirer.module.decode.ip.IPacket;
import io.github.dsheirer.module.decode.ip.Packet;
import java.util.List;
/**
* EXtensible Command Message Protocol (XCMP) Packet
*/
public class XCMPPacket extends Packet
{
private XCMPHeader mHeader;
private IPacket mPayload;
/**
* Constructs a parser for a header contained within a binary message starting at the offset.
*
* @param message containing the packet
* @param offset to the packet within the message
*/
public XCMPPacket(CorrectedBinaryMessage message, int offset)
{
super(message, offset);
}
@Override
public String toString()
{
StringBuilder sb = new StringBuilder();
sb.append(getHeader());
sb.append(" ").append(getPayload());
return sb.toString();
}
@Override
public XCMPHeader getHeader()
{
if(mHeader == null)
{
mHeader = new XCMPHeader(getMessage(), getOffset());
}
return mHeader;
}
@Override
public IPacket getPayload()
{
if(mPayload == null)
{
mPayload = XCMPPacketFactory.create(getMessage(), getOffset() + getHeader().getLength(),
getHeader().getMessageType());
}
return mPayload;
}
@Override
public List<Identifier> getIdentifiers()
{
return getHeader().getIdentifiers();
}
}

View File

@@ -0,0 +1,45 @@
/*
* *****************************************************************************
* Copyright (C) 2014-2020 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
* ****************************************************************************
*/
package io.github.dsheirer.module.decode.ip.xcmp;
import io.github.dsheirer.bits.CorrectedBinaryMessage;
import io.github.dsheirer.module.decode.ip.IPacket;
import io.github.dsheirer.module.decode.ip.UnknownPacket;
public class XCMPPacketFactory
{
/**
* Creates an XCMP Packet payload
* @param message containing the full packet payload
* @param offset to the start of the XCMP message
* @return XCMP packet parser
*/
public static IPacket create(CorrectedBinaryMessage message, int offset, XCMPMessageType messageType)
{
switch(messageType)
{
case NETWORK_FREQUENCY_FILE:
return new NetworkFrequencyFile(message, offset);
case UNKNOWN:
default:
return new UnknownPacket(message, offset);
}
}
}