summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBjørn Mork <bjorn@mork.no>2019-05-03 13:56:24 +0200
committerBjørn Mork <bjorn@mork.no>2019-05-03 13:56:24 +0200
commit17720d54d1a08a7373c27bae294c313eff9f75f6 (patch)
tree7df6787d573b95c1139a8a8995f882e7868ec1a8
parent95b54d686a6fe32bd40d1642db6bc29fa20ec729 (diff)
WiP: cleanup
Signed-off-by: Bjørn Mork <bjorn@mork.no>
-rw-r--r--Makefile2
-rw-r--r--obinsectd.c88
2 files changed, 37 insertions, 53 deletions
diff --git a/Makefile b/Makefile
index 06283ef..5d5856e 100644
--- a/Makefile
+++ b/Makefile
@@ -12,5 +12,5 @@ all: $(BINARIES)
rm -f *.o *.so *.lo *~ $(BINARIES)
obinsectd: obinsectd.c
- $(CC) $(CFLAGS) -DDEBUG -Wno-unused-function $(LDFLAGS) -o $@ $^
+ $(CC) $(CFLAGS) -DDEBUG $(LDFLAGS) -o $@ $^
diff --git a/obinsectd.c b/obinsectd.c
index e2fcbfb..8f81051 100644
--- a/obinsectd.c
+++ b/obinsectd.c
@@ -304,28 +304,6 @@ static unsigned char *hdlc_start(unsigned char *buf, size_t buflen)
return p;
}
-static const char *hdlc_control(unsigned char control)
-{
- static char buf[] = "I-frame (rsn=X, ssn=X)";
-
- if (control & 3) { /* U-frame */
- switch (control & 0xec) {
- case 0:
- return "UI-frame";
- default:
- return "unknown U-frame";
- }
- } else if (control & 1) { /* S-frame */
- switch (control & 0x0c) {
- default:
- sprintf(buf, "S-frame (rsn=%d)", control >> 5);
- }
- } else { /* I-frame */
- sprintf(buf, "I-frame (rsn=%d, ssn=%d)", control >> 5, (control >> 1) & 7);
- }
- return buf;
-}
-
static unsigned char *hdlc_verify(unsigned char *buf, size_t buflen, json_object **hdlc)
{
int i, format, segmentation, length, src, dst, control, hcs, fcs, check;
@@ -456,29 +434,6 @@ static bool is_obis(unsigned char *code)
return true;
}
-/*
- * cosem_variable_len() returns true if the type stores its length in the second byte
- *
- * NOTE: the length is not necessarily octects, for example for arrays
- * (number of elements) and structs (number of fields)
- */
-static bool cosem_variable_len(unsigned char type)
-{
- /* ref DLMS Blue-Book-Ed-122-Excerpt.pdf section 4.1.5 "Common data types" */
- switch (type) {
- case 1:
- case 2:
- /* case 4: - who knows? */
- case 9:
- case 10:
- case 12:
- /* case 13: - who knows? */
- return true;
- default:
- return false;
- }
-}
-
static json_object *cosem_object_new_int(unsigned char *raw, size_t intlen, bool sign)
{
__uint32_t hi, lo;
@@ -511,6 +466,16 @@ static json_object *json_object_new_bytearray(unsigned char *raw, size_t len)
return ret;
}
+static bool is_ascii_printable(unsigned char *raw, size_t len)
+{
+ int i;
+
+ for (i = 0; i < len; i++)
+ if (raw[i] < 32 || raw[i] > 127)
+ return false;
+ return true;
+}
+
/* parse_cosem() returns the number of eaten bytes, as well as a JSON object in ret */
static int parse_cosem(unsigned char *buf, size_t buflen, int lvl, json_object **ret)
{
@@ -519,6 +484,8 @@ static int parse_cosem(unsigned char *buf, size_t buflen, int lvl, json_object *
char fieldname[32]; /* "double-long-unsigned" is 20 bytes */
time_t t;
+ *ret = NULL;
+
/* ref DLMS Blue-Book-Ed-122-Excerpt.pdf section 4.1.5 "Common data types" */
switch (buf[0]) {
case 0: // null-data
@@ -530,6 +497,8 @@ static int parse_cosem(unsigned char *buf, size_t buflen, int lvl, json_object *
len = 2;
for (i = 0; i < buf[1]; i++) {
n = parse_cosem(&buf[len], buflen - len, lvl + 1, &myobj);
+ if (n < 0 || len > buflen)
+ goto err;
json_object_array_add(*ret, myobj);
len += n;
}
@@ -539,6 +508,8 @@ static int parse_cosem(unsigned char *buf, size_t buflen, int lvl, json_object *
len = 2;
for (i = 0; i < buf[1]; i++) {
n = parse_cosem(&buf[len], buflen - len, lvl + 1, &myobj);
+ if (n < 0 || len > buflen)
+ goto err;
sprintf(fieldname, "%s-%u", is_obis(&buf[len]) ? "obis" : cosem_typestr(buf[len]), i);
json_object_object_add(*ret, fieldname, myobj);
len += n;
@@ -554,15 +525,24 @@ static int parse_cosem(unsigned char *buf, size_t buflen, int lvl, json_object *
break;
case 9: // octet-string
len = 2 + buf[1];
+
+ /* is this an OBIS code? */
if (is_obis(buf)) {
sprintf(fieldname, "%u-%u:%u.%u.%u.%u", buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]);
*ret = json_object_new_string(fieldname);
-// *ret = cosem_object_new(buf, len, json_object_new_bytearray(&buf[2], buf[1]));
+
+ /*
+ * Kamstrup will camouflage date-time fields as octet-strings. We recode
+ * as readable date instead of unix epoch time, to keep type compatibility
+ */
} else if (buf[1] == 12 && buf[2] == 7) { /* works until 2047 */
t = decode_datetime(&buf[2]);
*ret = json_object_new_string_len(ctime(&t), 24);
- } else
+ } else if (is_ascii_printable(&buf[2], buf[1])) {
*ret = json_object_new_string_len((char *)&buf[2], buf[1]);
+ } else {
+ *ret = json_object_new_bytearray(&buf[2], buf[1]);
+ }
break;
case 10: // visible-string
len = 2 + buf[1];
@@ -606,15 +586,19 @@ static int parse_cosem(unsigned char *buf, size_t buflen, int lvl, json_object *
break;
default:
fprintf(stderr, "ERROR: Unsupported COSEM data type: %d (%02x)\n", buf[0], buf[0]);
- *ret = NULL;
- len = -1;
}
if (len > buflen) {
fprintf(stderr, "ERROR: Buggy COSEM data - buffer too short: %zd < %d\n", buflen, len);
- *ret = NULL;
- len = -1;
+ goto err;
}
- return len;
+ if (*ret)
+ return len;
+
+err:
+ if (*ret)
+ json_object_put(*ret);
+ *ret = NULL;
+ return -1;
}
static int parse_payload(unsigned char *buf, size_t buflen, json_object *hdlc)