mirror of https://github.com/OISF/suricata
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
9729 lines
247 KiB
C
9729 lines
247 KiB
C
/* Copyright (C) 2015 Open Information Security Foundation
|
|
*
|
|
* You can copy, redistribute or modify this Program under the terms of
|
|
* the GNU General Public License version 2 as published by the Free
|
|
* Software Foundation.
|
|
*
|
|
* 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
|
|
* version 2 along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
* 02110-1301, USA.
|
|
*/
|
|
|
|
/**
|
|
* \file
|
|
*
|
|
* \author Jason Ish <jason.ish@oisf.net>
|
|
*
|
|
* This file contains the DNP3 object decoders.
|
|
*/
|
|
|
|
#include "suricata-common.h"
|
|
|
|
#include "app-layer-dnp3.h"
|
|
#include "app-layer-dnp3-objects.h"
|
|
|
|
void DNP3FreeObjectPoint(int group, int variation, void *point);
|
|
|
|
#if 0
|
|
static void DNP3HexDump(uint8_t *data, int len)
|
|
{
|
|
for (int i = 0; i < len; i++) {
|
|
printf("%02x ", data[i]);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/**
|
|
* \brief Allocate a list for DNP3 points.
|
|
*/
|
|
DNP3PointList *DNP3PointListAlloc(void)
|
|
{
|
|
DNP3PointList *items = SCCalloc(1, sizeof(*items));
|
|
if (unlikely(items == NULL)) {
|
|
return NULL;
|
|
}
|
|
TAILQ_INIT(items);
|
|
return items;
|
|
}
|
|
|
|
/**
|
|
* \brief Free a DNP3PointList.
|
|
*/
|
|
void DNP3FreeObjectPointList(int group, int variation, DNP3PointList *list)
|
|
{
|
|
DNP3Point *point;
|
|
while ((point = TAILQ_FIRST(list)) != NULL) {
|
|
TAILQ_REMOVE(list, point, next);
|
|
if (point->data != NULL) {
|
|
DNP3FreeObjectPoint(group, variation, point->data);
|
|
}
|
|
SCFree(point);
|
|
}
|
|
SCFree(list);
|
|
}
|
|
|
|
/**
|
|
* \brief Read an uint8_t from a buffer.
|
|
*
|
|
* Reads a uint8_t from a buffer advancing the pointer and
|
|
* decrementing the length.
|
|
*
|
|
* \param buf A pointer to the buffer to read from.
|
|
* \param len A pointer to the buffer length.
|
|
* \param out A pointer to where the value will be stored.
|
|
*
|
|
* \retval Returns 1 if there was enough space in the buffer to read from,
|
|
* otherwise 0 is returned.
|
|
*/
|
|
static int DNP3ReadUint8(const uint8_t **buf, uint32_t *len, uint8_t *out)
|
|
{
|
|
if (*len < (int)sizeof(*out)) {
|
|
return 0;
|
|
}
|
|
*out = *(uint8_t *)(*buf);
|
|
*buf += sizeof(*out);
|
|
*len -= sizeof(*out);
|
|
return 1;
|
|
}
|
|
|
|
/**
|
|
* \brief Read an uint16_t from a buffer.
|
|
*
|
|
* Reads an uint16_t from a buffer advancing the pointer and
|
|
* decrementing the length.
|
|
*
|
|
* \param buf A pointer to the buffer to read from.
|
|
* \param len A pointer to the buffer length.
|
|
* \param out A pointer to where the value will be stored.
|
|
*
|
|
* \retval Returns 1 if there was enough space in the buffer to read from,
|
|
* otherwise 0 is returned.
|
|
*/
|
|
static int DNP3ReadUint16(const uint8_t **buf, uint32_t *len, uint16_t *out)
|
|
{
|
|
if (*len < (int)sizeof(*out)) {
|
|
return 0;
|
|
}
|
|
*out = DNP3_SWAP16(*(uint16_t *)(*buf));
|
|
*buf += sizeof(*out);
|
|
*len -= sizeof(*out);
|
|
return 1;
|
|
}
|
|
|
|
/**
|
|
* \brief Read an unsigned 24 bit integer from a buffer.
|
|
*
|
|
* Reads an an unsigned 24 bit integer from a buffer advancing the
|
|
* pointer and decrementing the length.
|
|
*
|
|
* \param buf A pointer to the buffer to read from.
|
|
* \param len A pointer to the buffer length.
|
|
* \param out A pointer to where the value will be stored.
|
|
*
|
|
* \retval Returns 1 if there was enough space in the buffer to read from,
|
|
* otherwise 0 is returned.
|
|
*/
|
|
static int DNP3ReadUint24(const uint8_t **buf, uint32_t *len, uint32_t *out)
|
|
{
|
|
if (*len < (int)(sizeof(uint8_t) * 3)) {
|
|
return 0;
|
|
}
|
|
|
|
#if __BYTE_ORDER__ == __BIG_ENDIAN
|
|
*out = ((uint32_t)(*buf)[0] << 16) | ((uint32_t)(*buf)[1] << 8) |
|
|
(uint32_t)(*buf)[2];
|
|
#elif __BYTE_ORDER == __LITTLE_ENDIAN
|
|
*out = ((uint64_t)(*buf)[0]) | ((uint64_t)(*buf)[1] << 8) |
|
|
((uint64_t)(*buf)[2] << 16);
|
|
#endif
|
|
|
|
*buf += 3;
|
|
*len -= 3;
|
|
|
|
return 1;
|
|
}
|
|
|
|
/**
|
|
* \brief Read an uint32_t from a buffer.
|
|
*
|
|
* Reads an uint32_t from a buffer advancing the pointer and
|
|
* decrementing the length.
|
|
*
|
|
* \param buf A pointer to the buffer to read from.
|
|
* \param len A pointer to the buffer length.
|
|
* \param out A pointer to where the value will be stored.
|
|
*
|
|
* \retval Returns 1 if there was enough space in the buffer to read from,
|
|
* otherwise 0 is returned.
|
|
*/
|
|
static int DNP3ReadUint32(const uint8_t **buf, uint32_t *len, uint32_t *out)
|
|
{
|
|
if (*len < (int)sizeof(*out)) {
|
|
return 0;
|
|
}
|
|
*out = DNP3_SWAP32(*(uint32_t *)(*buf));
|
|
*buf += sizeof(*out);
|
|
*len -= sizeof(*out);
|
|
return 1;
|
|
}
|
|
|
|
/**
|
|
* \brief Read an unsigned 48 bit integer from a buffer.
|
|
*
|
|
* Reads an an unsigned 48 bit integer from a buffer advancing the
|
|
* pointer and decrementing the length.
|
|
*
|
|
* \param buf A pointer to the buffer to read from.
|
|
* \param len A pointer to the buffer length.
|
|
* \param out A pointer to where the value will be stored.
|
|
*
|
|
* \retval Returns 1 if there was enough space in the buffer to read from,
|
|
* otherwise 0 is returned.
|
|
*/
|
|
static int DNP3ReadUint48(const uint8_t **buf, uint32_t *len, uint64_t *out)
|
|
{
|
|
if (*len < (int)(sizeof(uint8_t) * 6)) {
|
|
return 0;
|
|
}
|
|
|
|
#if __BYTE_ORDER__ == __BIG_ENDIAN
|
|
*out = ((uint64_t)(*buf)[0] << 40) | ((uint64_t)(*buf)[1] << 32) |
|
|
((uint64_t)(*buf)[2] << 24) | ((uint64_t)(*buf)[3] << 16) |
|
|
((uint64_t)(*buf)[4] << 8) | (uint64_t)(*buf)[5];
|
|
#elif __BYTE_ORDER == __LITTLE_ENDIAN
|
|
*out = ((uint64_t)(*buf)[0]) | ((uint64_t)(*buf)[1] << 8) |
|
|
((uint64_t)(*buf)[2] << 16) | ((uint64_t)(*buf)[3] << 24) |
|
|
((uint64_t)(*buf)[4] << 32) | ((uint64_t)(*buf)[5] << 40);
|
|
#endif
|
|
|
|
*buf += 6;
|
|
*len -= 6;
|
|
|
|
return 1;
|
|
}
|
|
|
|
/**
|
|
* \brief Read a 32 bit float from a buffer.
|
|
*
|
|
* Reads an 32 bit float from a buffer advancing the pointer and
|
|
* decrementing the length.
|
|
*
|
|
* \param buf A pointer to the buffer to read from.
|
|
* \param len A pointer to the buffer length.
|
|
* \param out A pointer to where the value will be stored.
|
|
*
|
|
* \retval Returns 1 if there was enough space in the buffer to read from,
|
|
* otherwise 0 is returned.
|
|
*/
|
|
static int DNP3ReadFloat32(const uint8_t **buf, uint32_t *len, float *out)
|
|
{
|
|
if (*len < 4) {
|
|
return 0;
|
|
}
|
|
|
|
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
|
*((uint8_t *)out + 0) = (*buf)[0];
|
|
*((uint8_t *)out + 1) = (*buf)[1];
|
|
*((uint8_t *)out + 2) = (*buf)[2];
|
|
*((uint8_t *)out + 3) = (*buf)[3];
|
|
#else
|
|
*((uint8_t *)out + 3) = (*buf)[0];
|
|
*((uint8_t *)out + 2) = (*buf)[1];
|
|
*((uint8_t *)out + 1) = (*buf)[2];
|
|
*((uint8_t *)out + 0) = (*buf)[3];
|
|
#endif
|
|
*len -= 4;
|
|
*buf += 4;
|
|
|
|
return 1;
|
|
}
|
|
|
|
/**
|
|
* \brief Read a 64 bit float from a buffer.
|
|
*
|
|
* Reads an 64 bit float from a buffer advancing the pointer and
|
|
* decrementing the length.
|
|
*
|
|
* \param buf A pointer to the buffer to read from.
|
|
* \param len A pointer to the buffer length.
|
|
* \param out A pointer to where the value will be stored.
|
|
*
|
|
* \retval Returns 1 if there was enough space in the buffer to read from,
|
|
* otherwise 0 is returned.
|
|
*/
|
|
static int DNP3ReadFloat64(const uint8_t **buf, uint32_t *len, double *out)
|
|
{
|
|
if (*len < 8) {
|
|
return 0;
|
|
}
|
|
|
|
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
|
*((uint8_t *)out + 0) = (*buf)[0];
|
|
*((uint8_t *)out + 1) = (*buf)[1];
|
|
*((uint8_t *)out + 2) = (*buf)[2];
|
|
*((uint8_t *)out + 3) = (*buf)[3];
|
|
*((uint8_t *)out + 4) = (*buf)[4];
|
|
*((uint8_t *)out + 5) = (*buf)[5];
|
|
*((uint8_t *)out + 6) = (*buf)[6];
|
|
*((uint8_t *)out + 7) = (*buf)[7];
|
|
#else
|
|
*((uint8_t *)out + 7) = (*buf)[0];
|
|
*((uint8_t *)out + 6) = (*buf)[1];
|
|
*((uint8_t *)out + 5) = (*buf)[2];
|
|
*((uint8_t *)out + 4) = (*buf)[3];
|
|
*((uint8_t *)out + 3) = (*buf)[4];
|
|
*((uint8_t *)out + 2) = (*buf)[5];
|
|
*((uint8_t *)out + 1) = (*buf)[6];
|
|
*((uint8_t *)out + 0) = (*buf)[7];
|
|
#endif
|
|
*len -= 8;
|
|
*buf += 8;
|
|
|
|
return 1;
|
|
}
|
|
|
|
/**
|
|
* \brief Get the prefix value and advance the buffer.
|
|
*/
|
|
static int DNP3ReadPrefix(
|
|
const uint8_t **buf, uint32_t *len, uint8_t prefix_code, uint32_t *out)
|
|
{
|
|
uint8_t prefix_len = 0;
|
|
|
|
switch (prefix_code) {
|
|
case 0x01:
|
|
case 0x04:
|
|
prefix_len = 1;
|
|
break;
|
|
case 0x02:
|
|
case 0x05:
|
|
prefix_len = 2;
|
|
break;
|
|
case 0x03:
|
|
case 0x06:
|
|
prefix_len = 4;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (*len < (uint32_t)prefix_len) {
|
|
return 0;
|
|
}
|
|
|
|
switch (prefix_len) {
|
|
case sizeof(uint32_t):
|
|
if (!DNP3ReadUint32(buf, len, out)) {
|
|
return 0;
|
|
}
|
|
break;
|
|
case sizeof(uint16_t): {
|
|
/* Temp value for strict-aliasing. */
|
|
uint16_t val = 0;
|
|
if (!DNP3ReadUint16(buf, len, &val)) {
|
|
return 0;
|
|
}
|
|
*out = val;
|
|
break;
|
|
}
|
|
case sizeof(uint8_t): {
|
|
/* Temp value for strict-aliasing. */
|
|
uint8_t val = 0;
|
|
if (!DNP3ReadUint8(buf, len, &val)) {
|
|
return 0;
|
|
}
|
|
*out = val;
|
|
break;
|
|
}
|
|
default:
|
|
*out = 0;
|
|
break;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
/**
|
|
* \brief Add an object to a DNP3PointList.
|
|
*
|
|
* \retval 1 if successfull, 0 on failure.
|
|
*/
|
|
static int DNP3AddPoint(DNP3PointList *list, void *object, uint32_t point_index,
|
|
uint8_t prefix_code, uint32_t prefix)
|
|
{
|
|
DNP3Point *point = SCCalloc(1, sizeof(*point));
|
|
if (unlikely(point == NULL)) {
|
|
return 0;
|
|
}
|
|
TAILQ_INSERT_TAIL(list, point, next);
|
|
point->data = object;
|
|
point->prefix = prefix;
|
|
point->index = point_index;
|
|
switch (prefix_code) {
|
|
case 0x00:
|
|
break;
|
|
case 0x01:
|
|
case 0x02:
|
|
case 0x03:
|
|
point->index = prefix;
|
|
break;
|
|
case 0x04:
|
|
case 0x05:
|
|
case 0x06:
|
|
point->size = prefix;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
/* START GENERATED CODE */
|
|
|
|
/* Code generated by:
|
|
* ./scripts/dnp3-gen/dnp3-gen.py
|
|
*/
|
|
|
|
static int DNP3DecodeObjectG1V1(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG1V1 *object = NULL;
|
|
uint32_t bytes = (count / 8) + 1;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
for (uint32_t i = 0; i < bytes; i++) {
|
|
|
|
uint8_t octet;
|
|
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
|
|
for (int j = 0; j < 8 && count; j = j + 1) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
object->state = (octet >> j) & 0x1;
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
count--;
|
|
point_index++;
|
|
}
|
|
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG1V2(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG1V2 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->chatter_filter = (octet >> 5) & 0x1;
|
|
object->reserved = (octet >> 6) & 0x1;
|
|
object->state = (octet >> 7) & 0x1;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG2V1(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG2V1 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadUint8(buf, len, &object->state)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG2V2(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG2V2 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->chatter_filter = (octet >> 5) & 0x1;
|
|
object->reserved = (octet >> 6) & 0x1;
|
|
object->state = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadUint48(buf, len, &object->timestamp)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG2V3(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG2V3 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->chatter_filter = (octet >> 5) & 0x1;
|
|
object->reserved = (octet >> 6) & 0x1;
|
|
object->state = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadUint16(buf, len, &object->timestamp)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG3V1(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG3V1 *object = NULL;
|
|
uint32_t bytes = (count / 8) + 1;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
for (uint32_t i = 0; i < bytes; i++) {
|
|
|
|
uint8_t octet;
|
|
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
|
|
for (int j = 0; j < 8 && count; j = j + 2) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
object->state = (octet >> j) & 0x3;
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
count--;
|
|
point_index++;
|
|
}
|
|
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG3V2(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG3V2 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->chatter_filter = (octet >> 5) & 0x1;
|
|
object->state = (octet >> 6) & 0x3;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG4V1(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG4V1 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->chatter_filter = (octet >> 5) & 0x1;
|
|
object->state = (octet >> 6) & 0x3;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG4V2(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG4V2 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->chatter_filter = (octet >> 5) & 0x1;
|
|
object->state = (octet >> 6) & 0x3;
|
|
}
|
|
if (!DNP3ReadUint48(buf, len, &object->timestamp)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG4V3(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG4V3 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->chatter_filter = (octet >> 5) & 0x1;
|
|
object->state = (octet >> 6) & 0x3;
|
|
}
|
|
if (!DNP3ReadUint16(buf, len, &object->relative_time_ms)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG10V1(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG10V1 *object = NULL;
|
|
uint32_t bytes = (count / 8) + 1;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
for (uint32_t i = 0; i < bytes; i++) {
|
|
|
|
uint8_t octet;
|
|
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
|
|
for (int j = 0; j < 8 && count; j = j + 1) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
object->state = (octet >> j) & 0x1;
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
count--;
|
|
point_index++;
|
|
}
|
|
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG10V2(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG10V2 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->reserved0 = (octet >> 5) & 0x1;
|
|
object->reserved1 = (octet >> 6) & 0x1;
|
|
object->state = (octet >> 7) & 0x1;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG11V1(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG11V1 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->reserved0 = (octet >> 5) & 0x1;
|
|
object->reserved1 = (octet >> 6) & 0x1;
|
|
object->state = (octet >> 7) & 0x1;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG11V2(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG11V2 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->reserved0 = (octet >> 5) & 0x1;
|
|
object->reserved1 = (octet >> 6) & 0x1;
|
|
object->state = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadUint48(buf, len, &object->timestamp)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG12V1(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG12V1 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->op_type = (octet >> 0) & 0xf;
|
|
object->qu = (octet >> 4) & 0x1;
|
|
object->cr = (octet >> 5) & 0x1;
|
|
object->tcc = (octet >> 6) & 0x3;
|
|
}
|
|
if (!DNP3ReadUint8(buf, len, &object->count)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint32(buf, len, &object->ontime)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint32(buf, len, &object->offtime)) {
|
|
goto error;
|
|
}
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->status_code = (octet >> 0) & 0x7f;
|
|
object->reserved = (octet >> 7) & 0x1;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG12V2(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG12V2 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->op_type = (octet >> 0) & 0xf;
|
|
object->qu = (octet >> 4) & 0x1;
|
|
object->cr = (octet >> 5) & 0x1;
|
|
object->tcc = (octet >> 6) & 0x3;
|
|
}
|
|
if (!DNP3ReadUint8(buf, len, &object->count)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint32(buf, len, &object->ontime)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint32(buf, len, &object->offtime)) {
|
|
goto error;
|
|
}
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->status_code = (octet >> 0) & 0x7f;
|
|
object->reserved = (octet >> 7) & 0x1;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG12V3(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG12V3 *object = NULL;
|
|
uint32_t bytes = (count / 8) + 1;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
for (uint32_t i = 0; i < bytes; i++) {
|
|
|
|
uint8_t octet;
|
|
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
|
|
for (int j = 0; j < 8 && count; j = j + 1) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
object->point = (octet >> j) & 0x1;
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
count--;
|
|
point_index++;
|
|
}
|
|
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG13V1(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG13V1 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->status_code = (octet >> 0) & 0x7f;
|
|
object->commanded_state = (octet >> 7) & 0x1;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG13V2(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG13V2 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->status_code = (octet >> 0) & 0x7f;
|
|
object->commanded_state = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadUint48(buf, len, &object->timestamp)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG20V1(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG20V1 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->rollover = (octet >> 5) & 0x1;
|
|
object->discontinuity = (octet >> 6) & 0x1;
|
|
object->reserved0 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadUint32(buf, len, &object->count)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG20V2(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG20V2 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->rollover = (octet >> 5) & 0x1;
|
|
object->discontinuity = (octet >> 6) & 0x1;
|
|
object->reserved0 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadUint16(buf, len, &object->count)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG20V3(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG20V3 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->rollover = (octet >> 5) & 0x1;
|
|
object->reserved0 = (octet >> 6) & 0x1;
|
|
object->reserved1 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadUint32(buf, len, &object->count)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG20V4(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG20V4 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->rollover = (octet >> 5) & 0x1;
|
|
object->reserved0 = (octet >> 6) & 0x1;
|
|
object->reserved1 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadUint16(buf, len, &object->count)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG20V5(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG20V5 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadUint32(buf, len, &object->count)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG20V6(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG20V6 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadUint16(buf, len, &object->count)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG20V7(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG20V7 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadUint32(buf, len, &object->count)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG20V8(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG20V8 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadUint16(buf, len, &object->count)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG21V1(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG21V1 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->rollover = (octet >> 5) & 0x1;
|
|
object->discontinuity = (octet >> 6) & 0x1;
|
|
object->reserved0 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadUint32(buf, len, &object->count)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG21V2(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG21V2 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->rollover = (octet >> 5) & 0x1;
|
|
object->discontinuity = (octet >> 6) & 0x1;
|
|
object->reserved0 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadUint16(buf, len, &object->count)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG21V3(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG21V3 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->rollover = (octet >> 5) & 0x1;
|
|
object->reserved0 = (octet >> 6) & 0x1;
|
|
object->reserved1 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadUint32(buf, len, &object->count)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG21V4(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG21V4 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->rollover = (octet >> 5) & 0x1;
|
|
object->reserved0 = (octet >> 6) & 0x1;
|
|
object->reserved1 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadUint16(buf, len, &object->count)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG21V5(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG21V5 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->rollover = (octet >> 5) & 0x1;
|
|
object->discontinuity = (octet >> 6) & 0x1;
|
|
object->reserved1 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadUint32(buf, len, &object->count)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint48(buf, len, &object->timestamp)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG21V6(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG21V6 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->rollover = (octet >> 5) & 0x1;
|
|
object->discontinuity = (octet >> 6) & 0x1;
|
|
object->reserved1 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadUint16(buf, len, &object->count)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint48(buf, len, &object->timestamp)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG21V7(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG21V7 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->rollover = (octet >> 5) & 0x1;
|
|
object->reserved0 = (octet >> 6) & 0x1;
|
|
object->reserved1 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadUint32(buf, len, &object->count)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint48(buf, len, &object->timestamp)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG21V8(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG21V8 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->rollover = (octet >> 5) & 0x1;
|
|
object->reserved0 = (octet >> 6) & 0x1;
|
|
object->reserved1 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadUint16(buf, len, &object->count)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint48(buf, len, &object->timestamp)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG21V9(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG21V9 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadUint32(buf, len, &object->count)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG21V10(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG21V10 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadUint16(buf, len, &object->count)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG21V11(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG21V11 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadUint32(buf, len, &object->count)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG21V12(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG21V12 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadUint16(buf, len, &object->count)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG22V1(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG22V1 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->rollover = (octet >> 5) & 0x1;
|
|
object->discontinuity = (octet >> 6) & 0x1;
|
|
object->reserved0 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadUint32(buf, len, &object->count)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG22V2(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG22V2 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->rollover = (octet >> 5) & 0x1;
|
|
object->discontinuity = (octet >> 6) & 0x1;
|
|
object->reserved0 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadUint16(buf, len, &object->count)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG22V3(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG22V3 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->rollover = (octet >> 5) & 0x1;
|
|
object->reserved0 = (octet >> 6) & 0x1;
|
|
object->reserved1 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadUint32(buf, len, &object->count)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG22V4(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG22V4 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->rollover = (octet >> 5) & 0x1;
|
|
object->reserved0 = (octet >> 6) & 0x1;
|
|
object->reserved1 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadUint16(buf, len, &object->count)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG22V5(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG22V5 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->rollover = (octet >> 5) & 0x1;
|
|
object->reserved0 = (octet >> 6) & 0x1;
|
|
object->reserved1 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadUint32(buf, len, &object->count)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint48(buf, len, &object->timestamp)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG22V6(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG22V6 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->rollover = (octet >> 5) & 0x1;
|
|
object->discontinuity = (octet >> 6) & 0x1;
|
|
object->reserved0 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadUint16(buf, len, &object->count)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint48(buf, len, &object->timestamp)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG22V7(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG22V7 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->rollover = (octet >> 5) & 0x1;
|
|
object->reserved0 = (octet >> 6) & 0x1;
|
|
object->reserved1 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadUint32(buf, len, &object->count)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint48(buf, len, &object->timestamp)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG22V8(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG22V8 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->rollover = (octet >> 5) & 0x1;
|
|
object->reserved0 = (octet >> 6) & 0x1;
|
|
object->reserved1 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadUint16(buf, len, &object->count)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint48(buf, len, &object->timestamp)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG23V1(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG23V1 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->rollover = (octet >> 5) & 0x1;
|
|
object->discontinuity = (octet >> 6) & 0x1;
|
|
object->reserved0 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadUint32(buf, len, &object->count)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG23V2(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG23V2 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->rollover = (octet >> 5) & 0x1;
|
|
object->reserved0 = (octet >> 6) & 0x1;
|
|
object->reserved1 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadUint16(buf, len, &object->count)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG23V3(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG23V3 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->rollover = (octet >> 5) & 0x1;
|
|
object->reserved0 = (octet >> 6) & 0x1;
|
|
object->reserved1 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadUint32(buf, len, &object->count)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG23V4(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG23V4 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->rollover = (octet >> 5) & 0x1;
|
|
object->reserved0 = (octet >> 6) & 0x1;
|
|
object->reserved1 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadUint16(buf, len, &object->count)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG23V5(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG23V5 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->rollover = (octet >> 5) & 0x1;
|
|
object->discontinuity = (octet >> 6) & 0x1;
|
|
object->reserved0 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadUint32(buf, len, &object->count)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint48(buf, len, &object->timestamp)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG23V6(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG23V6 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->rollover = (octet >> 5) & 0x1;
|
|
object->discontinuity = (octet >> 6) & 0x1;
|
|
object->reserved0 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadUint16(buf, len, &object->count)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint48(buf, len, &object->timestamp)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG23V7(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG23V7 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->rollover = (octet >> 5) & 0x1;
|
|
object->reserved0 = (octet >> 6) & 0x1;
|
|
object->reserved1 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadUint32(buf, len, &object->count)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint48(buf, len, &object->timestamp)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG23V8(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG23V8 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->rollover = (octet >> 5) & 0x1;
|
|
object->reserved0 = (octet >> 6) & 0x1;
|
|
object->reserved1 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadUint16(buf, len, &object->count)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint48(buf, len, &object->timestamp)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG30V1(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG30V1 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->over_range = (octet >> 5) & 0x1;
|
|
object->reference_err = (octet >> 6) & 0x1;
|
|
object->reserved0 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadUint32(buf, len, (uint32_t *)&object->value)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG30V2(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG30V2 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->over_range = (octet >> 5) & 0x1;
|
|
object->reference_err = (octet >> 6) & 0x1;
|
|
object->reserved0 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadUint16(buf, len, (uint16_t *)&object->value)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG30V3(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG30V3 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadUint32(buf, len, (uint32_t *)&object->value)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG30V4(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG30V4 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadUint16(buf, len, (uint16_t *)&object->value)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG30V5(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG30V5 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->over_range = (octet >> 5) & 0x1;
|
|
object->reference_err = (octet >> 6) & 0x1;
|
|
object->reserved0 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadFloat32(buf, len, &object->value)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG30V6(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG30V6 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->over_range = (octet >> 5) & 0x1;
|
|
object->reference_err = (octet >> 6) & 0x1;
|
|
object->reserved0 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadFloat64(buf, len, &object->value)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG31V1(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG31V1 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->over_range = (octet >> 5) & 0x1;
|
|
object->reference_err = (octet >> 6) & 0x1;
|
|
object->reserved0 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadUint32(buf, len, (uint32_t *)&object->value)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG31V2(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG31V2 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->over_range = (octet >> 5) & 0x1;
|
|
object->reference_err = (octet >> 6) & 0x1;
|
|
object->reserved0 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadUint16(buf, len, (uint16_t *)&object->value)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG31V3(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG31V3 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->over_range = (octet >> 5) & 0x1;
|
|
object->reference_err = (octet >> 6) & 0x1;
|
|
object->reserved0 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadUint32(buf, len, (uint32_t *)&object->value)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint48(buf, len, &object->timestamp)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG31V4(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG31V4 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->over_range = (octet >> 5) & 0x1;
|
|
object->reference_err = (octet >> 6) & 0x1;
|
|
object->reserved0 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadUint16(buf, len, (uint16_t *)&object->value)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint48(buf, len, &object->timestamp)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG31V5(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG31V5 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadUint32(buf, len, (uint32_t *)&object->value)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG31V6(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG31V6 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadUint16(buf, len, (uint16_t *)&object->value)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG31V7(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG31V7 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->over_range = (octet >> 5) & 0x1;
|
|
object->reference_err = (octet >> 6) & 0x1;
|
|
object->reserved0 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadFloat32(buf, len, &object->value)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG31V8(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG31V8 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->over_range = (octet >> 5) & 0x1;
|
|
object->reference_err = (octet >> 6) & 0x1;
|
|
object->reserved0 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadFloat64(buf, len, &object->value)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG32V1(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG32V1 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->over_range = (octet >> 5) & 0x1;
|
|
object->reference_err = (octet >> 6) & 0x1;
|
|
object->reserved0 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadUint32(buf, len, (uint32_t *)&object->value)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG32V2(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG32V2 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->over_range = (octet >> 5) & 0x1;
|
|
object->reference_err = (octet >> 6) & 0x1;
|
|
object->reserved0 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadUint16(buf, len, (uint16_t *)&object->value)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG32V3(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG32V3 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->over_range = (octet >> 5) & 0x1;
|
|
object->reference_err = (octet >> 6) & 0x1;
|
|
object->reserved0 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadUint32(buf, len, (uint32_t *)&object->value)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint48(buf, len, &object->timestamp)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG32V4(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG32V4 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->over_range = (octet >> 5) & 0x1;
|
|
object->reference_err = (octet >> 6) & 0x1;
|
|
object->reserved0 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadUint16(buf, len, (uint16_t *)&object->value)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint48(buf, len, &object->timestamp)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG32V5(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG32V5 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->over_range = (octet >> 5) & 0x1;
|
|
object->reference_err = (octet >> 6) & 0x1;
|
|
object->reserved0 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadFloat32(buf, len, &object->value)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG32V6(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG32V6 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->over_range = (octet >> 5) & 0x1;
|
|
object->reference_err = (octet >> 6) & 0x1;
|
|
object->reserved0 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadFloat64(buf, len, &object->value)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG32V7(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG32V7 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->over_range = (octet >> 5) & 0x1;
|
|
object->reference_err = (octet >> 6) & 0x1;
|
|
object->reserved0 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadFloat32(buf, len, &object->value)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint48(buf, len, &object->timestamp)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG32V8(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG32V8 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->over_range = (octet >> 5) & 0x1;
|
|
object->reference_err = (octet >> 6) & 0x1;
|
|
object->reserved0 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadFloat64(buf, len, &object->value)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint48(buf, len, &object->timestamp)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG33V1(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG33V1 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->over_range = (octet >> 5) & 0x1;
|
|
object->reference_err = (octet >> 6) & 0x1;
|
|
object->reserved0 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadUint32(buf, len, (uint32_t *)&object->value)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG33V2(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG33V2 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->over_range = (octet >> 5) & 0x1;
|
|
object->reference_err = (octet >> 6) & 0x1;
|
|
object->reserved0 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadUint16(buf, len, (uint16_t *)&object->value)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG33V3(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG33V3 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->over_range = (octet >> 5) & 0x1;
|
|
object->reference_err = (octet >> 6) & 0x1;
|
|
object->reserved0 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadUint32(buf, len, (uint32_t *)&object->value)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint48(buf, len, &object->timestamp)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG33V4(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG33V4 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->over_range = (octet >> 5) & 0x1;
|
|
object->reference_err = (octet >> 6) & 0x1;
|
|
object->reserved0 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadUint16(buf, len, (uint16_t *)&object->value)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint48(buf, len, &object->timestamp)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG33V5(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG33V5 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->over_range = (octet >> 5) & 0x1;
|
|
object->reference_err = (octet >> 6) & 0x1;
|
|
object->reserved0 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadFloat32(buf, len, &object->value)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG33V6(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG33V6 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->over_range = (octet >> 5) & 0x1;
|
|
object->reference_err = (octet >> 6) & 0x1;
|
|
object->reserved0 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadFloat64(buf, len, &object->value)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG33V7(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG33V7 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->over_range = (octet >> 5) & 0x1;
|
|
object->reference_err = (octet >> 6) & 0x1;
|
|
object->reserved0 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadFloat32(buf, len, &object->value)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint48(buf, len, &object->timestamp)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG33V8(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG33V8 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->over_range = (octet >> 5) & 0x1;
|
|
object->reference_err = (octet >> 6) & 0x1;
|
|
object->reserved0 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadFloat64(buf, len, &object->value)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint48(buf, len, &object->timestamp)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG34V1(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG34V1 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadUint16(buf, len, &object->deadband_value)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG34V2(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG34V2 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadUint32(buf, len, &object->deadband_value)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG34V3(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG34V3 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadFloat32(buf, len, &object->deadband_value)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG40V1(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG40V1 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->over_range = (octet >> 5) & 0x1;
|
|
object->reference_err = (octet >> 6) & 0x1;
|
|
object->reserved0 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadUint32(buf, len, (uint32_t *)&object->value)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG40V2(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG40V2 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->over_range = (octet >> 5) & 0x1;
|
|
object->reference_err = (octet >> 6) & 0x1;
|
|
object->reserved0 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadUint16(buf, len, (uint16_t *)&object->value)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG40V3(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG40V3 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->over_range = (octet >> 5) & 0x1;
|
|
object->reference_err = (octet >> 6) & 0x1;
|
|
object->reserved0 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadFloat32(buf, len, &object->value)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG40V4(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG40V4 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->over_range = (octet >> 5) & 0x1;
|
|
object->reference_err = (octet >> 6) & 0x1;
|
|
object->reserved0 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadFloat64(buf, len, &object->value)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG41V1(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG41V1 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadUint32(buf, len, (uint32_t *)&object->value)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint8(buf, len, &object->control_status)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG41V2(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG41V2 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadUint16(buf, len, (uint16_t *)&object->value)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint8(buf, len, &object->control_status)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG41V3(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG41V3 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadFloat32(buf, len, &object->value)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint8(buf, len, &object->control_status)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG41V4(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG41V4 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadFloat64(buf, len, &object->value)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint8(buf, len, &object->control_status)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG42V1(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG42V1 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->over_range = (octet >> 5) & 0x1;
|
|
object->reference_err = (octet >> 6) & 0x1;
|
|
object->reserved0 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadUint32(buf, len, (uint32_t *)&object->value)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG42V2(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG42V2 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->over_range = (octet >> 5) & 0x1;
|
|
object->reference_err = (octet >> 6) & 0x1;
|
|
object->reserved0 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadUint16(buf, len, (uint16_t *)&object->value)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG42V3(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG42V3 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->over_range = (octet >> 5) & 0x1;
|
|
object->reference_err = (octet >> 6) & 0x1;
|
|
object->reserved0 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadUint32(buf, len, (uint32_t *)&object->value)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint48(buf, len, &object->timestamp)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG42V4(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG42V4 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->over_range = (octet >> 5) & 0x1;
|
|
object->reference_err = (octet >> 6) & 0x1;
|
|
object->reserved0 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadUint16(buf, len, (uint16_t *)&object->value)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint48(buf, len, &object->timestamp)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG42V5(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG42V5 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->over_range = (octet >> 5) & 0x1;
|
|
object->reference_err = (octet >> 6) & 0x1;
|
|
object->reserved0 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadFloat32(buf, len, &object->value)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG42V6(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG42V6 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->over_range = (octet >> 5) & 0x1;
|
|
object->reference_err = (octet >> 6) & 0x1;
|
|
object->reserved0 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadFloat64(buf, len, &object->value)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG42V7(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG42V7 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->over_range = (octet >> 5) & 0x1;
|
|
object->reference_err = (octet >> 6) & 0x1;
|
|
object->reserved0 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadFloat32(buf, len, &object->value)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint48(buf, len, &object->timestamp)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG42V8(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG42V8 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->over_range = (octet >> 5) & 0x1;
|
|
object->reference_err = (octet >> 6) & 0x1;
|
|
object->reserved0 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadFloat64(buf, len, &object->value)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint48(buf, len, &object->timestamp)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG43V1(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG43V1 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->status_code = (octet >> 0) & 0x7f;
|
|
object->reserved0 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadUint32(buf, len, (uint32_t *)&object->commanded_value)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG43V2(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG43V2 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->status_code = (octet >> 0) & 0x7f;
|
|
object->reserved0 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadUint16(buf, len, (uint16_t *)&object->commanded_value)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG43V3(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG43V3 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->status_code = (octet >> 0) & 0x7f;
|
|
object->reserved0 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadUint32(buf, len, (uint32_t *)&object->commanded_value)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint48(buf, len, &object->timestamp)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG43V4(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG43V4 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->status_code = (octet >> 0) & 0x7f;
|
|
object->reserved0 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadUint16(buf, len, (uint16_t *)&object->commanded_value)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint48(buf, len, &object->timestamp)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG43V5(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG43V5 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->status_code = (octet >> 0) & 0x7f;
|
|
object->reserved0 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadFloat32(buf, len, &object->commanded_value)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG43V6(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG43V6 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->status_code = (octet >> 0) & 0x7f;
|
|
object->reserved0 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadFloat64(buf, len, &object->commanded_value)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG43V7(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG43V7 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->status_code = (octet >> 0) & 0x7f;
|
|
object->reserved0 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadFloat32(buf, len, &object->commanded_value)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint48(buf, len, &object->timestamp)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG43V8(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG43V8 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->status_code = (octet >> 0) & 0x7f;
|
|
object->reserved0 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadFloat64(buf, len, &object->commanded_value)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint48(buf, len, &object->timestamp)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG50V1(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG50V1 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadUint48(buf, len, &object->timestamp)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG50V2(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG50V2 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadUint48(buf, len, &object->timestamp)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint32(buf, len, &object->interval)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG50V3(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG50V3 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadUint48(buf, len, &object->timestamp)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG50V4(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG50V4 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadUint48(buf, len, &object->timestamp)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint32(buf, len, &object->interval_count)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint8(buf, len, &object->interval_units)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG51V1(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG51V1 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadUint48(buf, len, &object->timestamp)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG51V2(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG51V2 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadUint48(buf, len, &object->timestamp)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG52V1(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG52V1 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadUint16(buf, len, &object->delay_secs)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG52V2(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG52V2 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadUint16(buf, len, &object->delay_ms)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG70V1(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG70V1 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadUint16(buf, len, &object->filename_size)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint8(buf, len, &object->filetype_code)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint8(buf, len, &object->attribute_code)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint16(buf, len, &object->start_record)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint16(buf, len, &object->end_record)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint32(buf, len, &object->file_size)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint48(buf, len, &object->created_timestamp)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint16(buf, len, &object->permission)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint32(buf, len, &object->file_id)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint32(buf, len, &object->owner_id)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint32(buf, len, &object->group_id)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint8(buf, len, &object->file_function_code)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint8(buf, len, &object->status_code)) {
|
|
goto error;
|
|
}
|
|
if (object->filename_size > 0) {
|
|
if (*len < object->filename_size) {
|
|
/* Not enough data. */
|
|
goto error;
|
|
}
|
|
memcpy(object->filename, *buf, object->filename_size);
|
|
*buf += object->filename_size;
|
|
*len -= object->filename_size;
|
|
}
|
|
object->filename[object->filename_size] = '\0';
|
|
if (!DNP3ReadUint16(buf, len, &object->data_size)) {
|
|
goto error;
|
|
}
|
|
if (object->data_size > 0) {
|
|
if (*len < object->data_size) {
|
|
/* Not enough data. */
|
|
goto error;
|
|
}
|
|
memcpy(object->data, *buf, object->data_size);
|
|
*buf += object->data_size;
|
|
*len -= object->data_size;
|
|
}
|
|
object->data[object->data_size] = '\0';
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG70V2(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG70V2 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadUint16(buf, len, &object->username_offset)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint16(buf, len, &object->username_size)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint16(buf, len, &object->password_offset)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint16(buf, len, &object->password_size)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint32(buf, len, &object->authentication_key)) {
|
|
goto error;
|
|
}
|
|
if (object->username_size > 0) {
|
|
if (*len < object->username_size) {
|
|
/* Not enough data. */
|
|
goto error;
|
|
}
|
|
memcpy(object->username, *buf, object->username_size);
|
|
*buf += object->username_size;
|
|
*len -= object->username_size;
|
|
}
|
|
object->username[object->username_size] = '\0';
|
|
if (object->password_size > 0) {
|
|
if (*len < object->password_size) {
|
|
/* Not enough data. */
|
|
goto error;
|
|
}
|
|
memcpy(object->password, *buf, object->password_size);
|
|
*buf += object->password_size;
|
|
*len -= object->password_size;
|
|
}
|
|
object->password[object->password_size] = '\0';
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG70V3(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG70V3 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadUint16(buf, len, &object->filename_offset)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint16(buf, len, &object->filename_size)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint48(buf, len, &object->created)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint16(buf, len, &object->permissions)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint32(buf, len, &object->authentication_key)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint32(buf, len, &object->file_size)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint16(buf, len, &object->operational_mode)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint16(buf, len, &object->maximum_block_size)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint16(buf, len, &object->request_id)) {
|
|
goto error;
|
|
}
|
|
if (object->filename_size > 0) {
|
|
if (*len < object->filename_size) {
|
|
/* Not enough data. */
|
|
goto error;
|
|
}
|
|
memcpy(object->filename, *buf, object->filename_size);
|
|
*buf += object->filename_size;
|
|
*len -= object->filename_size;
|
|
}
|
|
object->filename[object->filename_size] = '\0';
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG70V4(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG70V4 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
uint32_t offset;
|
|
|
|
if (!DNP3PrefixIsSize(prefix_code)) {
|
|
goto error;
|
|
}
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
offset = *len;
|
|
|
|
if (!DNP3ReadUint32(buf, len, &object->file_handle)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint32(buf, len, &object->file_size)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint16(buf, len, &object->maximum_block_size)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint16(buf, len, &object->request_id)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint8(buf, len, &object->status_code)) {
|
|
goto error;
|
|
}
|
|
if (prefix - (offset - *len) >= 255 || prefix < (offset - *len)) {
|
|
goto error;
|
|
}
|
|
object->optional_text_len = (uint8_t)(prefix - (offset - *len));
|
|
if (object->optional_text_len > 0) {
|
|
if (*len < object->optional_text_len) {
|
|
/* Not enough data. */
|
|
goto error;
|
|
}
|
|
memcpy(object->optional_text, *buf, object->optional_text_len);
|
|
*buf += object->optional_text_len;
|
|
*len -= object->optional_text_len;
|
|
}
|
|
object->optional_text[object->optional_text_len] = '\0';
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG70V5(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG70V5 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
uint32_t offset;
|
|
|
|
if (!DNP3PrefixIsSize(prefix_code)) {
|
|
goto error;
|
|
}
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
offset = *len;
|
|
|
|
if (!DNP3ReadUint32(buf, len, &object->file_handle)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint32(buf, len, &object->block_number)) {
|
|
goto error;
|
|
}
|
|
if (prefix - (offset - *len) >= 255 || prefix < (offset - *len)) {
|
|
goto error;
|
|
}
|
|
object->file_data_len = (uint8_t)(prefix - (offset - *len));
|
|
if (object->file_data_len > 0) {
|
|
if (*len < object->file_data_len) {
|
|
/* Not enough data. */
|
|
goto error;
|
|
}
|
|
memcpy(object->file_data, *buf, object->file_data_len);
|
|
*buf += object->file_data_len;
|
|
*len -= object->file_data_len;
|
|
}
|
|
object->file_data[object->file_data_len] = '\0';
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG70V6(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG70V6 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
uint32_t offset;
|
|
|
|
if (!DNP3PrefixIsSize(prefix_code)) {
|
|
goto error;
|
|
}
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
offset = *len;
|
|
|
|
if (!DNP3ReadUint32(buf, len, &object->file_handle)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint32(buf, len, &object->block_number)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint8(buf, len, &object->status_code)) {
|
|
goto error;
|
|
}
|
|
if (prefix - (offset - *len) >= 255 || prefix < (offset - *len)) {
|
|
goto error;
|
|
}
|
|
object->optional_text_len = (uint8_t)(prefix - (offset - *len));
|
|
if (object->optional_text_len > 0) {
|
|
if (*len < object->optional_text_len) {
|
|
/* Not enough data. */
|
|
goto error;
|
|
}
|
|
memcpy(object->optional_text, *buf, object->optional_text_len);
|
|
*buf += object->optional_text_len;
|
|
*len -= object->optional_text_len;
|
|
}
|
|
object->optional_text[object->optional_text_len] = '\0';
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG70V7(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG70V7 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadUint16(buf, len, &object->filename_offset)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint16(buf, len, &object->filename_size)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint16(buf, len, &object->file_type)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint32(buf, len, &object->file_size)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint48(buf, len, &object->created_timestamp)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint16(buf, len, &object->permissions)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint16(buf, len, &object->request_id)) {
|
|
goto error;
|
|
}
|
|
if (object->filename_size > 0) {
|
|
if (*len < object->filename_size) {
|
|
/* Not enough data. */
|
|
goto error;
|
|
}
|
|
memcpy(object->filename, *buf, object->filename_size);
|
|
*buf += object->filename_size;
|
|
*len -= object->filename_size;
|
|
}
|
|
object->filename[object->filename_size] = '\0';
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG70V8(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG70V8 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
uint32_t offset;
|
|
|
|
if (prefix_code != 5) {
|
|
goto error;
|
|
}
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
offset = *len;
|
|
|
|
if (prefix - (offset - *len) >= 65535 || prefix < (offset - *len)) {
|
|
goto error;
|
|
}
|
|
object->file_specification_len = (uint16_t)(prefix - (offset - *len));
|
|
if (object->file_specification_len > 0) {
|
|
if (*len < object->file_specification_len) {
|
|
/* Not enough data. */
|
|
goto error;
|
|
}
|
|
memcpy(object->file_specification, *buf, object->file_specification_len);
|
|
*buf += object->file_specification_len;
|
|
*len -= object->file_specification_len;
|
|
}
|
|
object->file_specification[object->file_specification_len] = '\0';
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG80V1(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG80V1 *object = NULL;
|
|
uint32_t bytes = (count / 8) + 1;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
for (uint32_t i = 0; i < bytes; i++) {
|
|
|
|
uint8_t octet;
|
|
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
|
|
for (int j = 0; j < 8 && count; j = j + 1) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
object->state = (octet >> j) & 0x1;
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
count--;
|
|
point_index++;
|
|
}
|
|
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG81V1(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG81V1 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->fill_percentage = (octet >> 0) & 0x7f;
|
|
object->overflow_state = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadUint8(buf, len, &object->group)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint8(buf, len, &object->variation)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG83V1(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG83V1 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
if (*len < 4) {
|
|
goto error;
|
|
}
|
|
memcpy(object->vendor_code, *buf, 4);
|
|
object->vendor_code[4] = '\0';
|
|
*buf += 4;
|
|
*len -= 4;
|
|
if (!DNP3ReadUint16(buf, len, &object->object_id)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint16(buf, len, &object->length)) {
|
|
goto error;
|
|
}
|
|
if (object->length > 0) {
|
|
if (*len < object->length) {
|
|
/* Not enough data. */
|
|
goto error;
|
|
}
|
|
object->data_objects = SCCalloc(1, object->length);
|
|
if (unlikely(object->data_objects == NULL)) {
|
|
goto error;
|
|
}
|
|
memcpy(object->data_objects, *buf, object->length);
|
|
*buf += object->length;
|
|
*len -= object->length;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
if (object->data_objects != NULL) {
|
|
SCFree(object->data_objects);
|
|
}
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG86V2(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG86V2 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->rd = (octet >> 0) & 0x1;
|
|
object->wr = (octet >> 1) & 0x1;
|
|
object->st = (octet >> 2) & 0x1;
|
|
object->ev = (octet >> 3) & 0x1;
|
|
object->df = (octet >> 4) & 0x1;
|
|
object->padding0 = (octet >> 5) & 0x1;
|
|
object->padding1 = (octet >> 6) & 0x1;
|
|
object->padding2 = (octet >> 7) & 0x1;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG102V1(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG102V1 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadUint8(buf, len, &object->value)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG120V1(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG120V1 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
uint32_t offset;
|
|
|
|
if (prefix_code != 5) {
|
|
goto error;
|
|
}
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
offset = *len;
|
|
|
|
if (!DNP3ReadUint32(buf, len, &object->csq)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint16(buf, len, &object->usr)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint8(buf, len, &object->mal)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint8(buf, len, &object->reason)) {
|
|
goto error;
|
|
}
|
|
if (prefix < (offset - *len)) {
|
|
goto error;
|
|
}
|
|
object->challenge_data_len = (uint16_t)(prefix - (offset - *len));
|
|
if (object->challenge_data_len > 0) {
|
|
if (*len < object->challenge_data_len) {
|
|
/* Not enough data. */
|
|
goto error;
|
|
}
|
|
object->challenge_data = SCCalloc(1, object->challenge_data_len);
|
|
if (unlikely(object->challenge_data == NULL)) {
|
|
goto error;
|
|
}
|
|
memcpy(object->challenge_data, *buf, object->challenge_data_len);
|
|
*buf += object->challenge_data_len;
|
|
*len -= object->challenge_data_len;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
if (object->challenge_data != NULL) {
|
|
SCFree(object->challenge_data);
|
|
}
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG120V2(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG120V2 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
uint32_t offset;
|
|
|
|
if (prefix_code != 5) {
|
|
goto error;
|
|
}
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
offset = *len;
|
|
|
|
if (!DNP3ReadUint32(buf, len, &object->csq)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint16(buf, len, &object->usr)) {
|
|
goto error;
|
|
}
|
|
if (prefix < (offset - *len)) {
|
|
goto error;
|
|
}
|
|
object->mac_value_len = (uint16_t)(prefix - (offset - *len));
|
|
if (object->mac_value_len > 0) {
|
|
if (*len < object->mac_value_len) {
|
|
/* Not enough data. */
|
|
goto error;
|
|
}
|
|
object->mac_value = SCCalloc(1, object->mac_value_len);
|
|
if (unlikely(object->mac_value == NULL)) {
|
|
goto error;
|
|
}
|
|
memcpy(object->mac_value, *buf, object->mac_value_len);
|
|
*buf += object->mac_value_len;
|
|
*len -= object->mac_value_len;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
if (object->mac_value != NULL) {
|
|
SCFree(object->mac_value);
|
|
}
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG120V3(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG120V3 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadUint32(buf, len, &object->csq)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint16(buf, len, &object->user_number)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG120V4(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG120V4 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadUint16(buf, len, &object->user_number)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG120V5(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG120V5 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
uint32_t offset;
|
|
|
|
if (prefix_code != 5) {
|
|
goto error;
|
|
}
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
offset = *len;
|
|
|
|
if (!DNP3ReadUint32(buf, len, &object->ksq)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint16(buf, len, &object->user_number)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint8(buf, len, &object->key_wrap_alg)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint8(buf, len, &object->key_status)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint8(buf, len, &object->mal)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint16(buf, len, &object->challenge_data_len)) {
|
|
goto error;
|
|
}
|
|
if (object->challenge_data_len > 0) {
|
|
if (*len < object->challenge_data_len) {
|
|
/* Not enough data. */
|
|
goto error;
|
|
}
|
|
object->challenge_data = SCCalloc(1, object->challenge_data_len);
|
|
if (unlikely(object->challenge_data == NULL)) {
|
|
goto error;
|
|
}
|
|
memcpy(object->challenge_data, *buf, object->challenge_data_len);
|
|
*buf += object->challenge_data_len;
|
|
*len -= object->challenge_data_len;
|
|
}
|
|
if (prefix < (offset - *len)) {
|
|
goto error;
|
|
}
|
|
object->mac_value_len = (uint16_t)(prefix - (offset - *len));
|
|
if (object->mac_value_len > 0) {
|
|
if (*len < object->mac_value_len) {
|
|
/* Not enough data. */
|
|
goto error;
|
|
}
|
|
object->mac_value = SCCalloc(1, object->mac_value_len);
|
|
if (unlikely(object->mac_value == NULL)) {
|
|
goto error;
|
|
}
|
|
memcpy(object->mac_value, *buf, object->mac_value_len);
|
|
*buf += object->mac_value_len;
|
|
*len -= object->mac_value_len;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
if (object->challenge_data != NULL) {
|
|
SCFree(object->challenge_data);
|
|
}
|
|
if (object->mac_value != NULL) {
|
|
SCFree(object->mac_value);
|
|
}
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG120V6(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG120V6 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
uint32_t offset;
|
|
|
|
if (prefix_code != 5) {
|
|
goto error;
|
|
}
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
offset = *len;
|
|
|
|
if (!DNP3ReadUint24(buf, len, &object->ksq)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint16(buf, len, &object->usr)) {
|
|
goto error;
|
|
}
|
|
if (prefix < (offset - *len)) {
|
|
goto error;
|
|
}
|
|
object->wrapped_key_data_len = (uint16_t)(prefix - (offset - *len));
|
|
if (object->wrapped_key_data_len > 0) {
|
|
if (*len < object->wrapped_key_data_len) {
|
|
/* Not enough data. */
|
|
goto error;
|
|
}
|
|
object->wrapped_key_data = SCCalloc(1, object->wrapped_key_data_len);
|
|
if (unlikely(object->wrapped_key_data == NULL)) {
|
|
goto error;
|
|
}
|
|
memcpy(object->wrapped_key_data, *buf, object->wrapped_key_data_len);
|
|
*buf += object->wrapped_key_data_len;
|
|
*len -= object->wrapped_key_data_len;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
if (object->wrapped_key_data != NULL) {
|
|
SCFree(object->wrapped_key_data);
|
|
}
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG120V7(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG120V7 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
uint32_t offset;
|
|
|
|
if (prefix_code != 5) {
|
|
goto error;
|
|
}
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
offset = *len;
|
|
|
|
if (!DNP3ReadUint32(buf, len, &object->sequence_number)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint16(buf, len, &object->usr)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint16(buf, len, &object->association_id)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint8(buf, len, &object->error_code)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint48(buf, len, &object->time_of_error)) {
|
|
goto error;
|
|
}
|
|
if (prefix - (offset - *len) >= 65535 || prefix < (offset - *len)) {
|
|
goto error;
|
|
}
|
|
object->error_text_len = (uint16_t)(prefix - (offset - *len));
|
|
if (object->error_text_len > 0) {
|
|
if (*len < object->error_text_len) {
|
|
/* Not enough data. */
|
|
goto error;
|
|
}
|
|
memcpy(object->error_text, *buf, object->error_text_len);
|
|
*buf += object->error_text_len;
|
|
*len -= object->error_text_len;
|
|
}
|
|
object->error_text[object->error_text_len] = '\0';
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG120V8(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG120V8 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
uint32_t offset;
|
|
|
|
if (prefix_code != 5) {
|
|
goto error;
|
|
}
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
offset = *len;
|
|
|
|
if (!DNP3ReadUint8(buf, len, &object->key_change_method)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint8(buf, len, &object->certificate_type)) {
|
|
goto error;
|
|
}
|
|
if (prefix < (offset - *len)) {
|
|
goto error;
|
|
}
|
|
object->certificate_len = (uint16_t)(prefix - (offset - *len));
|
|
if (object->certificate_len > 0) {
|
|
if (*len < object->certificate_len) {
|
|
/* Not enough data. */
|
|
goto error;
|
|
}
|
|
object->certificate = SCCalloc(1, object->certificate_len);
|
|
if (unlikely(object->certificate == NULL)) {
|
|
goto error;
|
|
}
|
|
memcpy(object->certificate, *buf, object->certificate_len);
|
|
*buf += object->certificate_len;
|
|
*len -= object->certificate_len;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
if (object->certificate != NULL) {
|
|
SCFree(object->certificate);
|
|
}
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG120V9(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG120V9 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
uint32_t offset;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
offset = *len;
|
|
|
|
if (prefix < (offset - *len)) {
|
|
goto error;
|
|
}
|
|
object->mac_value_len = (uint16_t)(prefix - (offset - *len));
|
|
if (object->mac_value_len > 0) {
|
|
if (*len < object->mac_value_len) {
|
|
/* Not enough data. */
|
|
goto error;
|
|
}
|
|
object->mac_value = SCCalloc(1, object->mac_value_len);
|
|
if (unlikely(object->mac_value == NULL)) {
|
|
goto error;
|
|
}
|
|
memcpy(object->mac_value, *buf, object->mac_value_len);
|
|
*buf += object->mac_value_len;
|
|
*len -= object->mac_value_len;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
if (object->mac_value != NULL) {
|
|
SCFree(object->mac_value);
|
|
}
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG120V10(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG120V10 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (prefix_code != 5) {
|
|
goto error;
|
|
}
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadUint8(buf, len, &object->key_change_method)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint8(buf, len, &object->operation)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint32(buf, len, &object->scs)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint16(buf, len, &object->user_role)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint16(buf, len, &object->user_role_expiry_interval)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint16(buf, len, &object->username_len)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint16(buf, len, &object->user_public_key_len)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint16(buf, len, &object->certification_data_len)) {
|
|
goto error;
|
|
}
|
|
if (object->username_len > 0) {
|
|
if (*len < object->username_len) {
|
|
/* Not enough data. */
|
|
goto error;
|
|
}
|
|
memcpy(object->username, *buf, object->username_len);
|
|
*buf += object->username_len;
|
|
*len -= object->username_len;
|
|
}
|
|
object->username[object->username_len] = '\0';
|
|
if (object->user_public_key_len > 0) {
|
|
if (*len < object->user_public_key_len) {
|
|
/* Not enough data. */
|
|
goto error;
|
|
}
|
|
object->user_public_key = SCCalloc(1, object->user_public_key_len);
|
|
if (unlikely(object->user_public_key == NULL)) {
|
|
goto error;
|
|
}
|
|
memcpy(object->user_public_key, *buf, object->user_public_key_len);
|
|
*buf += object->user_public_key_len;
|
|
*len -= object->user_public_key_len;
|
|
}
|
|
if (object->certification_data_len > 0) {
|
|
if (*len < object->certification_data_len) {
|
|
/* Not enough data. */
|
|
goto error;
|
|
}
|
|
object->certification_data = SCCalloc(1, object->certification_data_len);
|
|
if (unlikely(object->certification_data == NULL)) {
|
|
goto error;
|
|
}
|
|
memcpy(object->certification_data, *buf, object->certification_data_len);
|
|
*buf += object->certification_data_len;
|
|
*len -= object->certification_data_len;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
if (object->user_public_key != NULL) {
|
|
SCFree(object->user_public_key);
|
|
}
|
|
if (object->certification_data != NULL) {
|
|
SCFree(object->certification_data);
|
|
}
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG120V11(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG120V11 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (prefix_code != 5) {
|
|
goto error;
|
|
}
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadUint8(buf, len, &object->key_change_method)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint16(buf, len, &object->username_len)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint16(buf, len, &object->master_challenge_data_len)) {
|
|
goto error;
|
|
}
|
|
if (object->username_len > 0) {
|
|
if (*len < object->username_len) {
|
|
/* Not enough data. */
|
|
goto error;
|
|
}
|
|
memcpy(object->username, *buf, object->username_len);
|
|
*buf += object->username_len;
|
|
*len -= object->username_len;
|
|
}
|
|
object->username[object->username_len] = '\0';
|
|
if (object->master_challenge_data_len > 0) {
|
|
if (*len < object->master_challenge_data_len) {
|
|
/* Not enough data. */
|
|
goto error;
|
|
}
|
|
object->master_challenge_data = SCCalloc(1, object->master_challenge_data_len);
|
|
if (unlikely(object->master_challenge_data == NULL)) {
|
|
goto error;
|
|
}
|
|
memcpy(object->master_challenge_data, *buf, object->master_challenge_data_len);
|
|
*buf += object->master_challenge_data_len;
|
|
*len -= object->master_challenge_data_len;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
if (object->master_challenge_data != NULL) {
|
|
SCFree(object->master_challenge_data);
|
|
}
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG120V12(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG120V12 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (prefix_code != 5) {
|
|
goto error;
|
|
}
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadUint32(buf, len, &object->ksq)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint16(buf, len, &object->user_number)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint16(buf, len, &object->challenge_data_len)) {
|
|
goto error;
|
|
}
|
|
if (object->challenge_data_len > 0) {
|
|
if (*len < object->challenge_data_len) {
|
|
/* Not enough data. */
|
|
goto error;
|
|
}
|
|
object->challenge_data = SCCalloc(1, object->challenge_data_len);
|
|
if (unlikely(object->challenge_data == NULL)) {
|
|
goto error;
|
|
}
|
|
memcpy(object->challenge_data, *buf, object->challenge_data_len);
|
|
*buf += object->challenge_data_len;
|
|
*len -= object->challenge_data_len;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
if (object->challenge_data != NULL) {
|
|
SCFree(object->challenge_data);
|
|
}
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG120V13(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG120V13 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (prefix_code != 5) {
|
|
goto error;
|
|
}
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadUint32(buf, len, &object->ksq)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint16(buf, len, &object->user_number)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint16(buf, len, &object->encrypted_update_key_len)) {
|
|
goto error;
|
|
}
|
|
if (object->encrypted_update_key_len > 0) {
|
|
if (*len < object->encrypted_update_key_len) {
|
|
/* Not enough data. */
|
|
goto error;
|
|
}
|
|
object->encrypted_update_key_data = SCCalloc(1, object->encrypted_update_key_len);
|
|
if (unlikely(object->encrypted_update_key_data == NULL)) {
|
|
goto error;
|
|
}
|
|
memcpy(object->encrypted_update_key_data, *buf, object->encrypted_update_key_len);
|
|
*buf += object->encrypted_update_key_len;
|
|
*len -= object->encrypted_update_key_len;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
if (object->encrypted_update_key_data != NULL) {
|
|
SCFree(object->encrypted_update_key_data);
|
|
}
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG120V14(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG120V14 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
uint32_t offset;
|
|
|
|
if (prefix_code != 5) {
|
|
goto error;
|
|
}
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
offset = *len;
|
|
|
|
if (prefix < (offset - *len)) {
|
|
goto error;
|
|
}
|
|
object->digital_signature_len = (uint16_t)(prefix - (offset - *len));
|
|
if (object->digital_signature_len > 0) {
|
|
if (*len < object->digital_signature_len) {
|
|
/* Not enough data. */
|
|
goto error;
|
|
}
|
|
object->digital_signature = SCCalloc(1, object->digital_signature_len);
|
|
if (unlikely(object->digital_signature == NULL)) {
|
|
goto error;
|
|
}
|
|
memcpy(object->digital_signature, *buf, object->digital_signature_len);
|
|
*buf += object->digital_signature_len;
|
|
*len -= object->digital_signature_len;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
if (object->digital_signature != NULL) {
|
|
SCFree(object->digital_signature);
|
|
}
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG120V15(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG120V15 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
uint32_t offset;
|
|
|
|
if (prefix_code != 5) {
|
|
goto error;
|
|
}
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
offset = *len;
|
|
|
|
if (prefix < (offset - *len)) {
|
|
goto error;
|
|
}
|
|
object->mac_len = (uint16_t)(prefix - (offset - *len));
|
|
if (object->mac_len > 0) {
|
|
if (*len < object->mac_len) {
|
|
/* Not enough data. */
|
|
goto error;
|
|
}
|
|
object->mac = SCCalloc(1, object->mac_len);
|
|
if (unlikely(object->mac == NULL)) {
|
|
goto error;
|
|
}
|
|
memcpy(object->mac, *buf, object->mac_len);
|
|
*buf += object->mac_len;
|
|
*len -= object->mac_len;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
if (object->mac != NULL) {
|
|
SCFree(object->mac);
|
|
}
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG121V1(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG121V1 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->reserved0 = (octet >> 5) & 0x1;
|
|
object->discontinuity = (octet >> 6) & 0x1;
|
|
object->reserved1 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadUint16(buf, len, &object->association_id)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint32(buf, len, &object->count_value)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG122V1(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG122V1 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->reserved0 = (octet >> 5) & 0x1;
|
|
object->discontinuity = (octet >> 6) & 0x1;
|
|
object->reserved1 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadUint16(buf, len, &object->association_id)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint32(buf, len, &object->count_value)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int DNP3DecodeObjectG122V2(const uint8_t **buf, uint32_t *len,
|
|
uint8_t prefix_code, uint32_t start, uint32_t count,
|
|
DNP3PointList *points)
|
|
{
|
|
DNP3ObjectG122V2 *object = NULL;
|
|
uint32_t prefix = 0;
|
|
uint32_t point_index = start;
|
|
|
|
if (*len < count/8) {
|
|
goto error;
|
|
}
|
|
while (count--) {
|
|
|
|
object = SCCalloc(1, sizeof(*object));
|
|
if (unlikely(object == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
{
|
|
uint8_t octet;
|
|
if (!DNP3ReadUint8(buf, len, &octet)) {
|
|
goto error;
|
|
}
|
|
object->online = (octet >> 0) & 0x1;
|
|
object->restart = (octet >> 1) & 0x1;
|
|
object->comm_lost = (octet >> 2) & 0x1;
|
|
object->remote_forced = (octet >> 3) & 0x1;
|
|
object->local_forced = (octet >> 4) & 0x1;
|
|
object->reserved0 = (octet >> 5) & 0x1;
|
|
object->discontinuity = (octet >> 6) & 0x1;
|
|
object->reserved1 = (octet >> 7) & 0x1;
|
|
}
|
|
if (!DNP3ReadUint16(buf, len, &object->association_id)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint32(buf, len, &object->count_value)) {
|
|
goto error;
|
|
}
|
|
if (!DNP3ReadUint48(buf, len, &object->timestamp)) {
|
|
goto error;
|
|
}
|
|
|
|
if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
|
|
goto error;
|
|
}
|
|
|
|
object = NULL;
|
|
point_index++;
|
|
}
|
|
|
|
return 1;
|
|
error:
|
|
if (object != NULL) {
|
|
SCFree(object);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
void DNP3FreeObjectPoint(int group, int variation, void *point)
|
|
{
|
|
switch(DNP3_OBJECT_CODE(group, variation)) {
|
|
case DNP3_OBJECT_CODE(83, 1): {
|
|
DNP3ObjectG83V1 *object = (DNP3ObjectG83V1 *) point;
|
|
if (object->data_objects != NULL) {
|
|
SCFree(object->data_objects);
|
|
}
|
|
break;
|
|
}
|
|
case DNP3_OBJECT_CODE(120, 1): {
|
|
DNP3ObjectG120V1 *object = (DNP3ObjectG120V1 *) point;
|
|
if (object->challenge_data != NULL) {
|
|
SCFree(object->challenge_data);
|
|
}
|
|
break;
|
|
}
|
|
case DNP3_OBJECT_CODE(120, 2): {
|
|
DNP3ObjectG120V2 *object = (DNP3ObjectG120V2 *) point;
|
|
if (object->mac_value != NULL) {
|
|
SCFree(object->mac_value);
|
|
}
|
|
break;
|
|
}
|
|
case DNP3_OBJECT_CODE(120, 5): {
|
|
DNP3ObjectG120V5 *object = (DNP3ObjectG120V5 *) point;
|
|
if (object->challenge_data != NULL) {
|
|
SCFree(object->challenge_data);
|
|
}
|
|
if (object->mac_value != NULL) {
|
|
SCFree(object->mac_value);
|
|
}
|
|
break;
|
|
}
|
|
case DNP3_OBJECT_CODE(120, 6): {
|
|
DNP3ObjectG120V6 *object = (DNP3ObjectG120V6 *) point;
|
|
if (object->wrapped_key_data != NULL) {
|
|
SCFree(object->wrapped_key_data);
|
|
}
|
|
break;
|
|
}
|
|
case DNP3_OBJECT_CODE(120, 8): {
|
|
DNP3ObjectG120V8 *object = (DNP3ObjectG120V8 *) point;
|
|
if (object->certificate != NULL) {
|
|
SCFree(object->certificate);
|
|
}
|
|
break;
|
|
}
|
|
case DNP3_OBJECT_CODE(120, 9): {
|
|
DNP3ObjectG120V9 *object = (DNP3ObjectG120V9 *) point;
|
|
if (object->mac_value != NULL) {
|
|
SCFree(object->mac_value);
|
|
}
|
|
break;
|
|
}
|
|
case DNP3_OBJECT_CODE(120, 10): {
|
|
DNP3ObjectG120V10 *object = (DNP3ObjectG120V10 *) point;
|
|
if (object->user_public_key != NULL) {
|
|
SCFree(object->user_public_key);
|
|
}
|
|
if (object->certification_data != NULL) {
|
|
SCFree(object->certification_data);
|
|
}
|
|
break;
|
|
}
|
|
case DNP3_OBJECT_CODE(120, 11): {
|
|
DNP3ObjectG120V11 *object = (DNP3ObjectG120V11 *) point;
|
|
if (object->master_challenge_data != NULL) {
|
|
SCFree(object->master_challenge_data);
|
|
}
|
|
break;
|
|
}
|
|
case DNP3_OBJECT_CODE(120, 12): {
|
|
DNP3ObjectG120V12 *object = (DNP3ObjectG120V12 *) point;
|
|
if (object->challenge_data != NULL) {
|
|
SCFree(object->challenge_data);
|
|
}
|
|
break;
|
|
}
|
|
case DNP3_OBJECT_CODE(120, 13): {
|
|
DNP3ObjectG120V13 *object = (DNP3ObjectG120V13 *) point;
|
|
if (object->encrypted_update_key_data != NULL) {
|
|
SCFree(object->encrypted_update_key_data);
|
|
}
|
|
break;
|
|
}
|
|
case DNP3_OBJECT_CODE(120, 14): {
|
|
DNP3ObjectG120V14 *object = (DNP3ObjectG120V14 *) point;
|
|
if (object->digital_signature != NULL) {
|
|
SCFree(object->digital_signature);
|
|
}
|
|
break;
|
|
}
|
|
case DNP3_OBJECT_CODE(120, 15): {
|
|
DNP3ObjectG120V15 *object = (DNP3ObjectG120V15 *) point;
|
|
if (object->mac != NULL) {
|
|
SCFree(object->mac);
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
SCFree(point);
|
|
}
|
|
|
|
/**
|
|
* \brief Decode a DNP3 object.
|
|
*
|
|
* \retval 0 on success. On failure a positive integer corresponding
|
|
* to a DNP3 application layer event will be returned.
|
|
*/
|
|
int DNP3DecodeObject(int group, int variation, const uint8_t **buf,
|
|
uint32_t *len, uint8_t prefix_code, uint32_t start,
|
|
uint32_t count, DNP3PointList *points)
|
|
{
|
|
int rc = 0;
|
|
|
|
switch (DNP3_OBJECT_CODE(group, variation)) {
|
|
case DNP3_OBJECT_CODE(1, 1):
|
|
rc = DNP3DecodeObjectG1V1(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(1, 2):
|
|
rc = DNP3DecodeObjectG1V2(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(2, 1):
|
|
rc = DNP3DecodeObjectG2V1(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(2, 2):
|
|
rc = DNP3DecodeObjectG2V2(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(2, 3):
|
|
rc = DNP3DecodeObjectG2V3(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(3, 1):
|
|
rc = DNP3DecodeObjectG3V1(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(3, 2):
|
|
rc = DNP3DecodeObjectG3V2(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(4, 1):
|
|
rc = DNP3DecodeObjectG4V1(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(4, 2):
|
|
rc = DNP3DecodeObjectG4V2(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(4, 3):
|
|
rc = DNP3DecodeObjectG4V3(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(10, 1):
|
|
rc = DNP3DecodeObjectG10V1(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(10, 2):
|
|
rc = DNP3DecodeObjectG10V2(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(11, 1):
|
|
rc = DNP3DecodeObjectG11V1(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(11, 2):
|
|
rc = DNP3DecodeObjectG11V2(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(12, 1):
|
|
rc = DNP3DecodeObjectG12V1(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(12, 2):
|
|
rc = DNP3DecodeObjectG12V2(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(12, 3):
|
|
rc = DNP3DecodeObjectG12V3(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(13, 1):
|
|
rc = DNP3DecodeObjectG13V1(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(13, 2):
|
|
rc = DNP3DecodeObjectG13V2(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(20, 1):
|
|
rc = DNP3DecodeObjectG20V1(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(20, 2):
|
|
rc = DNP3DecodeObjectG20V2(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(20, 3):
|
|
rc = DNP3DecodeObjectG20V3(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(20, 4):
|
|
rc = DNP3DecodeObjectG20V4(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(20, 5):
|
|
rc = DNP3DecodeObjectG20V5(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(20, 6):
|
|
rc = DNP3DecodeObjectG20V6(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(20, 7):
|
|
rc = DNP3DecodeObjectG20V7(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(20, 8):
|
|
rc = DNP3DecodeObjectG20V8(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(21, 1):
|
|
rc = DNP3DecodeObjectG21V1(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(21, 2):
|
|
rc = DNP3DecodeObjectG21V2(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(21, 3):
|
|
rc = DNP3DecodeObjectG21V3(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(21, 4):
|
|
rc = DNP3DecodeObjectG21V4(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(21, 5):
|
|
rc = DNP3DecodeObjectG21V5(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(21, 6):
|
|
rc = DNP3DecodeObjectG21V6(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(21, 7):
|
|
rc = DNP3DecodeObjectG21V7(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(21, 8):
|
|
rc = DNP3DecodeObjectG21V8(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(21, 9):
|
|
rc = DNP3DecodeObjectG21V9(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(21, 10):
|
|
rc = DNP3DecodeObjectG21V10(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(21, 11):
|
|
rc = DNP3DecodeObjectG21V11(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(21, 12):
|
|
rc = DNP3DecodeObjectG21V12(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(22, 1):
|
|
rc = DNP3DecodeObjectG22V1(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(22, 2):
|
|
rc = DNP3DecodeObjectG22V2(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(22, 3):
|
|
rc = DNP3DecodeObjectG22V3(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(22, 4):
|
|
rc = DNP3DecodeObjectG22V4(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(22, 5):
|
|
rc = DNP3DecodeObjectG22V5(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(22, 6):
|
|
rc = DNP3DecodeObjectG22V6(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(22, 7):
|
|
rc = DNP3DecodeObjectG22V7(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(22, 8):
|
|
rc = DNP3DecodeObjectG22V8(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(23, 1):
|
|
rc = DNP3DecodeObjectG23V1(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(23, 2):
|
|
rc = DNP3DecodeObjectG23V2(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(23, 3):
|
|
rc = DNP3DecodeObjectG23V3(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(23, 4):
|
|
rc = DNP3DecodeObjectG23V4(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(23, 5):
|
|
rc = DNP3DecodeObjectG23V5(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(23, 6):
|
|
rc = DNP3DecodeObjectG23V6(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(23, 7):
|
|
rc = DNP3DecodeObjectG23V7(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(23, 8):
|
|
rc = DNP3DecodeObjectG23V8(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(30, 1):
|
|
rc = DNP3DecodeObjectG30V1(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(30, 2):
|
|
rc = DNP3DecodeObjectG30V2(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(30, 3):
|
|
rc = DNP3DecodeObjectG30V3(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(30, 4):
|
|
rc = DNP3DecodeObjectG30V4(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(30, 5):
|
|
rc = DNP3DecodeObjectG30V5(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(30, 6):
|
|
rc = DNP3DecodeObjectG30V6(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(31, 1):
|
|
rc = DNP3DecodeObjectG31V1(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(31, 2):
|
|
rc = DNP3DecodeObjectG31V2(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(31, 3):
|
|
rc = DNP3DecodeObjectG31V3(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(31, 4):
|
|
rc = DNP3DecodeObjectG31V4(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(31, 5):
|
|
rc = DNP3DecodeObjectG31V5(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(31, 6):
|
|
rc = DNP3DecodeObjectG31V6(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(31, 7):
|
|
rc = DNP3DecodeObjectG31V7(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(31, 8):
|
|
rc = DNP3DecodeObjectG31V8(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(32, 1):
|
|
rc = DNP3DecodeObjectG32V1(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(32, 2):
|
|
rc = DNP3DecodeObjectG32V2(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(32, 3):
|
|
rc = DNP3DecodeObjectG32V3(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(32, 4):
|
|
rc = DNP3DecodeObjectG32V4(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(32, 5):
|
|
rc = DNP3DecodeObjectG32V5(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(32, 6):
|
|
rc = DNP3DecodeObjectG32V6(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(32, 7):
|
|
rc = DNP3DecodeObjectG32V7(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(32, 8):
|
|
rc = DNP3DecodeObjectG32V8(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(33, 1):
|
|
rc = DNP3DecodeObjectG33V1(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(33, 2):
|
|
rc = DNP3DecodeObjectG33V2(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(33, 3):
|
|
rc = DNP3DecodeObjectG33V3(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(33, 4):
|
|
rc = DNP3DecodeObjectG33V4(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(33, 5):
|
|
rc = DNP3DecodeObjectG33V5(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(33, 6):
|
|
rc = DNP3DecodeObjectG33V6(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(33, 7):
|
|
rc = DNP3DecodeObjectG33V7(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(33, 8):
|
|
rc = DNP3DecodeObjectG33V8(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(34, 1):
|
|
rc = DNP3DecodeObjectG34V1(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(34, 2):
|
|
rc = DNP3DecodeObjectG34V2(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(34, 3):
|
|
rc = DNP3DecodeObjectG34V3(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(40, 1):
|
|
rc = DNP3DecodeObjectG40V1(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(40, 2):
|
|
rc = DNP3DecodeObjectG40V2(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(40, 3):
|
|
rc = DNP3DecodeObjectG40V3(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(40, 4):
|
|
rc = DNP3DecodeObjectG40V4(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(41, 1):
|
|
rc = DNP3DecodeObjectG41V1(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(41, 2):
|
|
rc = DNP3DecodeObjectG41V2(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(41, 3):
|
|
rc = DNP3DecodeObjectG41V3(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(41, 4):
|
|
rc = DNP3DecodeObjectG41V4(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(42, 1):
|
|
rc = DNP3DecodeObjectG42V1(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(42, 2):
|
|
rc = DNP3DecodeObjectG42V2(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(42, 3):
|
|
rc = DNP3DecodeObjectG42V3(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(42, 4):
|
|
rc = DNP3DecodeObjectG42V4(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(42, 5):
|
|
rc = DNP3DecodeObjectG42V5(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(42, 6):
|
|
rc = DNP3DecodeObjectG42V6(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(42, 7):
|
|
rc = DNP3DecodeObjectG42V7(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(42, 8):
|
|
rc = DNP3DecodeObjectG42V8(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(43, 1):
|
|
rc = DNP3DecodeObjectG43V1(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(43, 2):
|
|
rc = DNP3DecodeObjectG43V2(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(43, 3):
|
|
rc = DNP3DecodeObjectG43V3(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(43, 4):
|
|
rc = DNP3DecodeObjectG43V4(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(43, 5):
|
|
rc = DNP3DecodeObjectG43V5(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(43, 6):
|
|
rc = DNP3DecodeObjectG43V6(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(43, 7):
|
|
rc = DNP3DecodeObjectG43V7(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(43, 8):
|
|
rc = DNP3DecodeObjectG43V8(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(50, 1):
|
|
rc = DNP3DecodeObjectG50V1(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(50, 2):
|
|
rc = DNP3DecodeObjectG50V2(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(50, 3):
|
|
rc = DNP3DecodeObjectG50V3(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(50, 4):
|
|
rc = DNP3DecodeObjectG50V4(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(51, 1):
|
|
rc = DNP3DecodeObjectG51V1(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(51, 2):
|
|
rc = DNP3DecodeObjectG51V2(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(52, 1):
|
|
rc = DNP3DecodeObjectG52V1(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(52, 2):
|
|
rc = DNP3DecodeObjectG52V2(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(70, 1):
|
|
rc = DNP3DecodeObjectG70V1(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(70, 2):
|
|
rc = DNP3DecodeObjectG70V2(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(70, 3):
|
|
rc = DNP3DecodeObjectG70V3(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(70, 4):
|
|
rc = DNP3DecodeObjectG70V4(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(70, 5):
|
|
rc = DNP3DecodeObjectG70V5(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(70, 6):
|
|
rc = DNP3DecodeObjectG70V6(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(70, 7):
|
|
rc = DNP3DecodeObjectG70V7(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(70, 8):
|
|
rc = DNP3DecodeObjectG70V8(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(80, 1):
|
|
rc = DNP3DecodeObjectG80V1(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(81, 1):
|
|
rc = DNP3DecodeObjectG81V1(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(83, 1):
|
|
rc = DNP3DecodeObjectG83V1(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(86, 2):
|
|
rc = DNP3DecodeObjectG86V2(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(102, 1):
|
|
rc = DNP3DecodeObjectG102V1(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(120, 1):
|
|
rc = DNP3DecodeObjectG120V1(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(120, 2):
|
|
rc = DNP3DecodeObjectG120V2(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(120, 3):
|
|
rc = DNP3DecodeObjectG120V3(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(120, 4):
|
|
rc = DNP3DecodeObjectG120V4(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(120, 5):
|
|
rc = DNP3DecodeObjectG120V5(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(120, 6):
|
|
rc = DNP3DecodeObjectG120V6(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(120, 7):
|
|
rc = DNP3DecodeObjectG120V7(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(120, 8):
|
|
rc = DNP3DecodeObjectG120V8(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(120, 9):
|
|
rc = DNP3DecodeObjectG120V9(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(120, 10):
|
|
rc = DNP3DecodeObjectG120V10(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(120, 11):
|
|
rc = DNP3DecodeObjectG120V11(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(120, 12):
|
|
rc = DNP3DecodeObjectG120V12(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(120, 13):
|
|
rc = DNP3DecodeObjectG120V13(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(120, 14):
|
|
rc = DNP3DecodeObjectG120V14(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(120, 15):
|
|
rc = DNP3DecodeObjectG120V15(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(121, 1):
|
|
rc = DNP3DecodeObjectG121V1(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(122, 1):
|
|
rc = DNP3DecodeObjectG122V1(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
case DNP3_OBJECT_CODE(122, 2):
|
|
rc = DNP3DecodeObjectG122V2(buf, len, prefix_code, start, count,
|
|
points);
|
|
break;
|
|
default:
|
|
return DNP3_DECODER_EVENT_UNKNOWN_OBJECT;
|
|
}
|
|
|
|
return rc ? 0 : DNP3_DECODER_EVENT_MALFORMED;
|
|
}
|
|
|
|
/* END GENERATED CODE */
|