Skip to content

Commit

Permalink
Merge pull request #357 from Trihydro/psid-pencode
Browse files Browse the repository at this point in the history
PSID P-Encoding
  • Loading branch information
bbrotsos committed Aug 5, 2019
2 parents 0b906ec + c7beceb commit 634c326
Show file tree
Hide file tree
Showing 2 changed files with 164 additions and 111 deletions.
197 changes: 116 additions & 81 deletions jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/snmp/SnmpSession.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import javax.xml.bind.DatatypeConverter;

import org.ietf.jgss.Oid;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.snmp4j.PDU;
Expand Down Expand Up @@ -58,7 +59,7 @@
* over UDP and is actually connection-less.
*/
public class SnmpSession {

private static final Logger logger = LoggerFactory.getLogger(SnmpSession.class);

private Snmp snmp;
Expand All @@ -71,9 +72,8 @@ public class SnmpSession {
/**
* Constructor for SnmpSession
*
* @param props
* SnmpProperties for the session (target address, retries,
* timeout, etc)
* @param props SnmpProperties for the session (target address, retries,
* timeout, etc)
* @throws IOException
*/
public SnmpSession(RSU rsu) throws IOException {
Expand All @@ -86,12 +86,12 @@ public SnmpSession(RSU rsu) throws IOException {
target.setTimeout(rsu.getRsuTimeout());
target.setVersion(SnmpConstants.version3);
if (rsu.getRsuUsername() != null) {
target.setSecurityLevel(SecurityLevel.AUTH_NOPRIV);
target.setSecurityName(new OctetString(rsu.getRsuUsername()));
target.setSecurityLevel(SecurityLevel.AUTH_NOPRIV);
target.setSecurityName(new OctetString(rsu.getRsuUsername()));
} else {
target.setSecurityLevel(SecurityLevel.NOAUTH_NOPRIV);
target.setSecurityLevel(SecurityLevel.NOAUTH_NOPRIV);
}

// Set up the UDP transport mapping over which requests are sent
transport = null;
try {
Expand All @@ -107,10 +107,10 @@ public SnmpSession(RSU rsu) throws IOException {
USM usm = new USM(SecurityProtocols.getInstance(), new OctetString(MPv3.createLocalEngineID()), 0);
SecurityModels.getInstance().addSecurityModel(usm);
if (rsu.getRsuUsername() != null) {
snmp.getUSM().addUser(new OctetString(rsu.getRsuUsername()), new UsmUser(new OctetString(rsu.getRsuUsername()),
AuthSHA.ID, new OctetString(rsu.getRsuPassword()), null, null));
snmp.getUSM().addUser(new OctetString(rsu.getRsuUsername()), new UsmUser(new OctetString(rsu.getRsuUsername()),
AuthSHA.ID, new OctetString(rsu.getRsuPassword()), null, null));
}

// Assert the ready flag so the user can begin sending messages
ready = true;

Expand All @@ -119,8 +119,7 @@ public SnmpSession(RSU rsu) throws IOException {
/**
* Sends a SET-type PDU to the target specified by the constructor.
*
* @param pdu
* The message content to be sent to the target
* @param pdu The message content to be sent to the target
* @return ResponseEvent
* @throws IOException
*/
Expand Down Expand Up @@ -152,8 +151,7 @@ public ResponseEvent set(PDU pdu, Snmp snmpob, UserTarget targetob, Boolean keep
/**
* Sends a SET-type PDU to the target specified by the constructor.
*
* @param pdu
* The message content to be sent to the target
* @param pdu The message content to be sent to the target
* @return ResponseEvent
* @throws IOException
*/
Expand Down Expand Up @@ -196,16 +194,15 @@ public void startListen() throws IOException {
/**
* Create an SNMP session given the values in
*
* @param tim
* - The TIM parameters (payload, channel, mode, etc)
* @param props
* - The SNMP properties (ip, username, password, etc)
* @param tim - The TIM parameters (payload, channel, mode, etc)
* @param props - The SNMP properties (ip, username, password, etc)
* @return ResponseEvent
* @throws TimPduCreatorException
* @throws IOException
* @throws ParseException
* @throws ParseException
*/
public static ResponseEvent createAndSend(SNMP snmp, RSU rsu, String payload, RequestVerb requestVerb) throws ParseException, IOException {
public static ResponseEvent createAndSend(SNMP snmp, RSU rsu, String payload, RequestVerb requestVerb)
throws ParseException, IOException {

SnmpSession session = new SnmpSession(rsu);

Expand Down Expand Up @@ -251,66 +248,104 @@ public void endSession() throws IOException {
* Assembles the various RSU elements of a TimParameters object into a usable
* PDU.
*
* @param index
* Storage index on the RSU
* @param params
* TimParameters POJO that stores status, channel, payload, etc.
* @param index Storage index on the RSU
* @param params TimParameters POJO that stores status, channel, payload, etc.
* @return PDU
* @throws ParseException
*/
public static ScopedPDU createPDU(SNMP snmp, String payload, int index, RequestVerb verb) throws ParseException {

//////////////////////////////
// - OID examples - //
//////////////////////////////
// rsuSRMStatus.3 = 4
// --> 1.4.1.11.3 = 4
// rsuSRMTxChannel.3 = 3
// --> 1.4.1.5.3 = 178
// rsuSRMTxMode.3 = 1
// --> 1.4.1.4.3 = 1
// rsuSRMPsid.3 x "8300"
// --> 1.4.1.2.3 x "8300"
// rsuSRMDsrcMsgId.3 = 31
// --> 1.4.1.3.3 = 31
// rsuSRMTxInterval.3 = 1
// --> 1.4.1.6.3 = 1
// rsuSRMDeliveryStart.3 x "010114111530"
// --> 1.4.1.7.3 = "010114111530"
// rsuSRMDeliveryStop.3 x "010114130000"
// --> 1.4.1.8.3 = "010114130000"
// rsuSRMPayload.3 x "0EFF82445566778899000000AABBCCDDEEFF00E00EA0C12A00"
// --> 1.4.1.9.3 = "0EFF82445566778899000000AABBCCDDEEFF00E00EA0C12A00"
// rsuSRMEnable.3 = 1
// --> 1.4.1.10.3 = 1
//////////////////////////////

VariableBinding rsuSRMPsid = new VariableBinding(new OID("1.0.15628.4.1.4.1.2.".concat(Integer.toString(index))), new OctetString(DatatypeConverter.parseHexBinary(snmp.getRsuid())));
VariableBinding rsuSRMDsrcMsgId = new VariableBinding(new OID("1.0.15628.4.1.4.1.3.".concat(Integer.toString(index))), new Integer32(snmp.getMsgid()));
VariableBinding rsuSRMTxMode = new VariableBinding(new OID("1.0.15628.4.1.4.1.4.".concat(Integer.toString(index))), new Integer32(snmp.getMode()));
VariableBinding rsuSRMTxChannel = new VariableBinding(new OID("1.0.15628.4.1.4.1.5.".concat(Integer.toString(index))), new Integer32(snmp.getChannel()));
VariableBinding rsuSRMTxInterval = new VariableBinding(new OID("1.0.15628.4.1.4.1.6.".concat(Integer.toString(index))), new Integer32(snmp.getInterval()));
VariableBinding rsuSRMDeliveryStart = new VariableBinding(new OID("1.0.15628.4.1.4.1.7.".concat(Integer.toString(index))), new OctetString(DatatypeConverter.parseHexBinary(SNMP.snmpTimestampFromIso(snmp.getDeliverystart()))));
VariableBinding rsuSRMDeliveryStop = new VariableBinding(new OID("1.0.15628.4.1.4.1.8.".concat(Integer.toString(index))), new OctetString(DatatypeConverter.parseHexBinary(SNMP.snmpTimestampFromIso(snmp.getDeliverystop()))));
VariableBinding rsuSRMPayload = new VariableBinding(new OID("1.0.15628.4.1.4.1.9.".concat(Integer.toString(index))), new OctetString(DatatypeConverter.parseHexBinary(payload)));
VariableBinding rsuSRMEnable = new VariableBinding(new OID("1.0.15628.4.1.4.1.10.".concat(Integer.toString(index))), new Integer32(snmp.getEnable()));
VariableBinding rsuSRMStatus = new VariableBinding(new OID("1.0.15628.4.1.4.1.11.".concat(Integer.toString(index))), new Integer32(snmp.getStatus()));

ScopedPDU pdu = new ScopedPDU();
pdu.add(rsuSRMPsid);
pdu.add(rsuSRMDsrcMsgId);
pdu.add(rsuSRMTxMode);
pdu.add(rsuSRMTxChannel);
pdu.add(rsuSRMTxInterval);
pdu.add(rsuSRMDeliveryStart);
pdu.add(rsuSRMDeliveryStop);
pdu.add(rsuSRMPayload);
pdu.add(rsuSRMEnable);
if (verb == ServiceRequest.OdeInternal.RequestVerb.POST) {
pdu.add(rsuSRMStatus);
}
pdu.setType(PDU.SET);

return pdu;
}
}
public static ScopedPDU createPDU(SNMP snmp, String payload, int index, RequestVerb verb) throws ParseException {

//////////////////////////////
// - OID examples - //
//////////////////////////////
// rsuSRMStatus.3 = 4
// --> 1.4.1.11.3 = 4
// rsuSRMTxChannel.3 = 3
// --> 1.4.1.5.3 = 178
// rsuSRMTxMode.3 = 1
// --> 1.4.1.4.3 = 1
// rsuSRMPsid.3 x "8300"
// --> 1.4.1.2.3 x "8300"
// rsuSRMDsrcMsgId.3 = 31
// --> 1.4.1.3.3 = 31
// rsuSRMTxInterval.3 = 1
// --> 1.4.1.6.3 = 1
// rsuSRMDeliveryStart.3 x "010114111530"
// --> 1.4.1.7.3 = "010114111530"
// rsuSRMDeliveryStop.3 x "010114130000"
// --> 1.4.1.8.3 = "010114130000"
// rsuSRMPayload.3 x "0EFF82445566778899000000AABBCCDDEEFF00E00EA0C12A00"
// --> 1.4.1.9.3 = "0EFF82445566778899000000AABBCCDDEEFF00E00EA0C12A00"
// rsuSRMEnable.3 = 1
// --> 1.4.1.10.3 = 1
//////////////////////////////

VariableBinding rsuSRMPsid = SnmpSession.getPEncodedVariableBinding("1.0.15628.4.1.4.1.2.".concat(Integer.toString(index)),
snmp.getRsuid());
VariableBinding rsuSRMDsrcMsgId = new VariableBinding(
new OID("1.0.15628.4.1.4.1.3.".concat(Integer.toString(index))), new Integer32(snmp.getMsgid()));
VariableBinding rsuSRMTxMode = new VariableBinding(
new OID("1.0.15628.4.1.4.1.4.".concat(Integer.toString(index))), new Integer32(snmp.getMode()));
VariableBinding rsuSRMTxChannel = new VariableBinding(
new OID("1.0.15628.4.1.4.1.5.".concat(Integer.toString(index))), new Integer32(snmp.getChannel()));
VariableBinding rsuSRMTxInterval = new VariableBinding(
new OID("1.0.15628.4.1.4.1.6.".concat(Integer.toString(index))), new Integer32(snmp.getInterval()));
VariableBinding rsuSRMDeliveryStart = new VariableBinding(
new OID("1.0.15628.4.1.4.1.7.".concat(Integer.toString(index))),
new OctetString(DatatypeConverter.parseHexBinary(SNMP.snmpTimestampFromIso(snmp.getDeliverystart()))));
VariableBinding rsuSRMDeliveryStop = new VariableBinding(
new OID("1.0.15628.4.1.4.1.8.".concat(Integer.toString(index))),
new OctetString(DatatypeConverter.parseHexBinary(SNMP.snmpTimestampFromIso(snmp.getDeliverystop()))));
VariableBinding rsuSRMPayload = new VariableBinding(
new OID("1.0.15628.4.1.4.1.9.".concat(Integer.toString(index))),
new OctetString(DatatypeConverter.parseHexBinary(payload)));
VariableBinding rsuSRMEnable = new VariableBinding(
new OID("1.0.15628.4.1.4.1.10.".concat(Integer.toString(index))), new Integer32(snmp.getEnable()));
VariableBinding rsuSRMStatus = new VariableBinding(
new OID("1.0.15628.4.1.4.1.11.".concat(Integer.toString(index))), new Integer32(snmp.getStatus()));

ScopedPDU pdu = new ScopedPDU();
pdu.add(rsuSRMPsid);
pdu.add(rsuSRMDsrcMsgId);
pdu.add(rsuSRMTxMode);
pdu.add(rsuSRMTxChannel);
pdu.add(rsuSRMTxInterval);
pdu.add(rsuSRMDeliveryStart);
pdu.add(rsuSRMDeliveryStop);
pdu.add(rsuSRMPayload);
pdu.add(rsuSRMEnable);
if (verb == ServiceRequest.OdeInternal.RequestVerb.POST) {
pdu.add(rsuSRMStatus);
}
pdu.setType(PDU.SET);

return pdu;
}

public static VariableBinding getPEncodedVariableBinding(String oid, String val) {
Integer intVal = Integer.parseInt(val, 16);
Integer additionValue = null;

if (intVal >= 0 && intVal <= 127) {
// P = V
// here we must instantiate the OctetString directly with the hex string to avoid inadvertently creating the ASCII character codes
// for instance OctetString.fromString("20", 16) produces the space character (" ") rather than hex 20
return new VariableBinding(new OID(oid), new OctetString(Integer.toHexString(intVal)));
} else if (intVal >= 128 && intVal <= 16511) {
// P = V + 0x7F80
additionValue = 0x7F80;
} else if (intVal >= 016512 && intVal <= 2113663) {
// P = V + 0xBFBF80
additionValue = 0xBFBF80;
} else if (intVal >= 2113664 && intVal <= 270549119) {
// P = V + 0xDFDFBF80
additionValue = 0xDFDFBF80;
}

if (additionValue != null) {
return new VariableBinding(new OID(oid),
OctetString.fromString(Integer.toHexString(intVal + additionValue), 16));
}
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import org.snmp4j.TransportMapping;
import org.snmp4j.UserTarget;
import org.snmp4j.security.USM;
import org.snmp4j.smi.VariableBinding;
import org.snmp4j.transport.DefaultUdpTransportMapping;

import mockit.Expectations;
Expand All @@ -43,8 +44,9 @@ public class SnmpSessionTest {
RSU testProps;
SnmpSession snmpSession;

@Injectable USM mockUSM;

@Injectable
USM mockUSM;

@Before
public void setUp() throws Exception {
String testUsername = "testUser";
Expand Down Expand Up @@ -104,7 +106,7 @@ public void testGetSetMethods(@Mocked Snmp mockSnmp, @Mocked TransportMapping mo
assertEquals(mockUserTarget, snmpSession.getTarget());
}

@Test(expected = IOException.class)
@Test(expected = IOException.class)
public void testResponseEventUDPException(@Mocked Snmp mockSnmp, @Mocked TransportMapping mockTransportMapping,
@Mocked UserTarget mockUserTarget, @Mocked PDU mockPDU) throws IOException {

Expand All @@ -119,8 +121,8 @@ public void testResponseEventUDPException(@Mocked Snmp mockSnmp, @Mocked Transpo
}

@Test(expected = IOException.class)
public void testResponseEventSNMPException(@Mocked Snmp mockSnmp,
@Mocked UserTarget mockUserTarget, @Mocked PDU mockPDU) throws IOException {
public void testResponseEventSNMPException(@Mocked Snmp mockSnmp, @Mocked UserTarget mockUserTarget,
@Mocked PDU mockPDU) throws IOException {

new Expectations() {
{
Expand All @@ -131,35 +133,51 @@ public void testResponseEventSNMPException(@Mocked Snmp mockSnmp,
snmpSession.set(mockPDU, mockSnmp, mockUserTarget, false);
}

@Test
public void shouldCreatePDU() throws ParseException {
@Test
public void shouldCreatePDU() throws ParseException {

String expectedResult = "[1.0.15628.4.1.4.1.2.3 = 80:03, 1.0.15628.4.1.4.1.3.3 = 2, 1.0.15628.4.1.4.1.4.3 = 3, 1.0.15628.4.1.4.1.5.3 = 4, 1.0.15628.4.1.4.1.6.3 = 5, 1.0.15628.4.1.4.1.7.3 = 07:e1:0c:02:11:2f, 1.0.15628.4.1.4.1.8.3 = 07:e1:0c:02:11:2f, 1.0.15628.4.1.4.1.9.3 = 88, 1.0.15628.4.1.4.1.10.3 = 9, 1.0.15628.4.1.4.1.11.3 = 10]";
String expectedResult2 = "[1.0.15628.4.1.4.1.2.3 = 80:03, 1.0.15628.4.1.4.1.3.3 = 2, 1.0.15628.4.1.4.1.4.3 = 3, 1.0.15628.4.1.4.1.5.3 = 4, 1.0.15628.4.1.4.1.6.3 = 5, 1.0.15628.4.1.4.1.7.3 = 07:e1:0c:02:11:2f, 1.0.15628.4.1.4.1.8.3 = 07:e1:0c:02:11:2f, 1.0.15628.4.1.4.1.9.3 = 88, 1.0.15628.4.1.4.1.10.3 = 9]";

String expectedResult = "[1.0.15628.4.1.4.1.2.3 = 11, 1.0.15628.4.1.4.1.3.3 = 2, 1.0.15628.4.1.4.1.4.3 = 3, 1.0.15628.4.1.4.1.5.3 = 4, 1.0.15628.4.1.4.1.6.3 = 5, 1.0.15628.4.1.4.1.7.3 = 07:e1:0c:02:11:2f, 1.0.15628.4.1.4.1.8.3 = 07:e1:0c:02:11:2f, 1.0.15628.4.1.4.1.9.3 = 88, 1.0.15628.4.1.4.1.10.3 = 9, 1.0.15628.4.1.4.1.11.3 = 10]";
String expectedResult2 = "[1.0.15628.4.1.4.1.2.3 = 11, 1.0.15628.4.1.4.1.3.3 = 2, 1.0.15628.4.1.4.1.4.3 = 3, 1.0.15628.4.1.4.1.5.3 = 4, 1.0.15628.4.1.4.1.6.3 = 5, 1.0.15628.4.1.4.1.7.3 = 07:e1:0c:02:11:2f, 1.0.15628.4.1.4.1.8.3 = 07:e1:0c:02:11:2f, 1.0.15628.4.1.4.1.9.3 = 88, 1.0.15628.4.1.4.1.10.3 = 9]";
String rsuSRMPsid = "00000083";
int rsuSRMDsrcMsgId = 2;
int rsuSRMTxMode = 3;
int rsuSRMTxChannel = 4;
int rsuSRMTxInterval = 5;
String rsuSRMPayload = "88";
int rsuSRMEnable = 9;
int rsuSRMStatus = 10;


String rsuSRMPsid = "11";
int rsuSRMDsrcMsgId = 2;
int rsuSRMTxMode = 3;
int rsuSRMTxChannel = 4;
int rsuSRMTxInterval = 5;
String rsuSRMPayload = "88";
int rsuSRMEnable = 9;
int rsuSRMStatus = 10;
SNMP testParams = new SNMP(rsuSRMPsid, rsuSRMDsrcMsgId, rsuSRMTxMode, rsuSRMTxChannel, rsuSRMTxInterval,
"2017-12-02T17:47:11-05:00", "2017-12-02T17:47:11-05:00", rsuSRMEnable, rsuSRMStatus);

SNMP testParams = new SNMP(
rsuSRMPsid, rsuSRMDsrcMsgId, rsuSRMTxMode, rsuSRMTxChannel,
rsuSRMTxInterval, "2017-12-02T17:47:11-05:00", "2017-12-02T17:47:11-05:00",
rsuSRMEnable, rsuSRMStatus);
ScopedPDU result = SnmpSession.createPDU(testParams, rsuSRMPayload, 3, RequestVerb.POST);

ScopedPDU result = SnmpSession.createPDU(testParams, rsuSRMPayload, 3, RequestVerb.POST);
assertEquals("Incorrect type, expected PDU.SET (-93)", -93, result.getType());
assertEquals(expectedResult, result.getVariableBindings().toString());

assertEquals("Incorrect type, expected PDU.SET (-93)", -93, result.getType());
assertEquals(expectedResult, result.getVariableBindings().toString());
ScopedPDU result2 = SnmpSession.createPDU(testParams, rsuSRMPayload, 3, RequestVerb.GET);

ScopedPDU result2 = SnmpSession.createPDU(testParams, rsuSRMPayload, 3, RequestVerb.GET);
assertEquals("Incorrect type, expected PDU.SET (-93)", -93, result2.getType());
assertEquals(expectedResult2, result2.getVariableBindings().toString());
}

assertEquals("Incorrect type, expected PDU.SET (-93)", -93, result2.getType());
assertEquals(expectedResult2, result2.getVariableBindings().toString());
}
}
@Test
public void shouldProperlyPEncode(){
String oid = "1.0.15628.4.1.4.1.2.3";
String tim_hex="00000083";
String bsm_hex="00000020";
String data_log_transfer_hex="0020408E";
String ota_update_hex = "0020408F";

VariableBinding vb1 = SnmpSession.getPEncodedVariableBinding(oid, tim_hex);
VariableBinding vb2 = SnmpSession.getPEncodedVariableBinding(oid, bsm_hex);
VariableBinding vb3 = SnmpSession.getPEncodedVariableBinding(oid, data_log_transfer_hex);
VariableBinding vb4 = SnmpSession.getPEncodedVariableBinding(oid, ota_update_hex);

assertEquals("P-Encoding failed for " + tim_hex,"80:03", vb1.toValueString());
assertEquals("P-Encoding failed for " + bsm_hex,"20", vb2.toValueString());
assertEquals("P-Encoding failed for " + data_log_transfer_hex,"e0:00:00:0e", vb3.toValueString());
assertEquals("P-Encoding failed for " + ota_update_hex,"e0:00:00:0f", vb4.toValueString());
}
}

0 comments on commit 634c326

Please sign in to comment.