static void abuf_json_string(struct autobuf *abuf, const char* key, const char* value) { abuf_json_insert_comma(abuf); abuf_appendf(abuf, "\t\"%s\": \"%s\"", key, value); }
static void abuf_json_close_object(struct autobuf *abuf) { abuf_appendf(abuf, "\t}\n"); currentjsondepth--; }
static void abuf_json_boolean(struct autobuf *abuf, const char* key, int value) { abuf_json_insert_comma(abuf); abuf_appendf(abuf, "\t\"%s\": %s", key, value ? "true" : "false"); }
static int _print_raw_tlvblock(struct autobuf *out, const char *prefix, uint8_t *blockptr, size_t *idx, size_t length) { char valueprefix[128]; uint16_t blocklength, tlv_len, tlv_singlelength; uint8_t *tlvptr; size_t idx2; uint8_t tlv_flags, startidx, endidx; if (2 > length) { return -1; } abuf_appendf(out, "%s,-------------------\n", prefix); abuf_appendf(out, "%s| TLV BLOCK\n", prefix); abuf_appendf(out, "%s|-------------------\n", prefix); blocklength = (blockptr[*idx] << 8) | blockptr[*idx + 1]; abuf_appendf(out, "%s| * TLV Block Size: %u\n", prefix, blocklength); if (blocklength + 2u > length) { return -1; } *idx += 2; tlvptr = &blockptr[*idx]; for (idx2 = 0; idx2 < blocklength;) { if (idx2 + 2 > blocklength) { return -1; } abuf_appendf(out, "%s| ,-------------------\n", prefix); abuf_appendf(out, "%s| | TLV\n", prefix); abuf_appendf(out, "%s| |-------------------\n", prefix); abuf_appendf(out, "%s| | type: %u\n", prefix, tlvptr[idx2]); idx2++; tlv_flags = tlvptr[idx2]; abuf_appendf(out, "%s| | flags: 0x%02x\n", prefix, tlv_flags); idx2++; if (tlv_flags & RFC5444_TLV_FLAG_TYPEEXT) { if (idx2 + 1 > blocklength) { return -1; } abuf_appendf(out, "%s| | ext-type: %u\n", prefix, tlvptr[idx2]); idx2++; } startidx = 0; endidx = 0; if (tlv_flags & (RFC5444_TLV_FLAG_SINGLE_IDX | RFC5444_TLV_FLAG_MULTI_IDX)) { if (idx2 + 1 > blocklength) { return -1; } startidx = tlvptr[idx2]; endidx = startidx; abuf_appendf(out, "%s| | index-start: %u\n", prefix, startidx); idx2++; } if (tlv_flags & (RFC5444_TLV_FLAG_MULTI_IDX)) { if (idx2 + 1 > blocklength) { return -1; } endidx = tlvptr[idx2]; if (endidx < startidx) { return -1; } abuf_appendf(out, "%s| | index-end: %u\n", prefix, endidx); idx2++; } tlv_len = 0; if (tlv_flags & (RFC5444_TLV_FLAG_EXTVALUE)) { if (idx2 + 1 > blocklength) { return -1; } tlv_len = tlvptr[idx2] << 8; idx2++; } if (tlv_flags & (RFC5444_TLV_FLAG_VALUE)) { if (idx2 + 1 > blocklength) { return -1; } tlv_len |= tlvptr[idx2]; idx2++; } if (tlv_flags & (RFC5444_TLV_FLAG_EXTVALUE | RFC5444_TLV_FLAG_VALUE)) { abuf_appendf(out, "%s| | length: %u\n", prefix, tlv_len); } if (idx2 + tlv_len > blocklength) { return -1; } if (tlv_flags & RFC5444_TLV_FLAG_MULTIVALUE) { if (tlv_len % (endidx - startidx + 1)) { return -1; } tlv_singlelength = tlv_len / (endidx - startidx + 1); } else { tlv_singlelength = tlv_len; endidx = startidx; } snprintf(valueprefix, sizeof(valueprefix), "%s| | ", prefix); for (; startidx <= endidx; startidx++) { if (idx2 + tlv_singlelength > blocklength) { return -1; } abuf_hexdump(out, valueprefix, &tlvptr[idx2], tlv_singlelength); idx2 += tlv_singlelength; abuf_puts(out, "\n"); } } if (blocklength != idx2) { return -1; } *idx += blocklength; return 0; }
int rfc5444_print_raw(struct autobuf *out, void *buffer, size_t length) { static uint8_t ZEROTAIL[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; uint8_t *ptr, *end; size_t idx, idx2, prefix_idx, i; uint8_t flags, head_len, tail_len, *head, *tail, num_addr; uint16_t msg_size, addr_length, mid_len; ptr = buffer; idx = 0; end = &ptr[length]; if (idx + 1 > length) { return -1; } abuf_puts(out, "\t,------------------\n"); abuf_puts(out, "\t| PACKET\n"); abuf_puts(out, "\t|------------------\n"); flags = ptr[0]; abuf_appendf(out, "\t| Packet version: %u\n", flags >> 4); abuf_appendf(out, "\t| Packet flags: 0x%02x\n", flags & 0x0f); idx++; if (flags & RFC5444_PKT_FLAG_SEQNO) { if (idx + 2 > length) { return -1; } abuf_appendf(out, "\t| Packet seq number: %u\n", (ptr[0] << 8) | ptr[1]); idx += 2; } if (flags & RFC5444_PKT_FLAG_TLV) { if (idx + 2 > length) { return -1; } if (_print_raw_tlvblock(out, "\t| | ", ptr, &idx, length)) { return -1; } } while (idx < length) { idx2 = idx; /* print messages */ if (idx2 + 4 > length) { return -1; } abuf_puts(out, "\t| ,-------------------\n"); abuf_puts(out, "\t| | MESSAGE\n"); abuf_puts(out, "\t| |-------------------\n"); abuf_appendf(out, "\t| | Message type: %u\n", ptr[idx]); flags = ptr[idx2 + 1]; abuf_appendf(out, "\t| | Message flags: 0x%02x\n", flags >> 4); addr_length = (flags & 15) + 1; abuf_appendf(out, "\t| | Address length: %u\n", addr_length); msg_size = (ptr[idx2 + 2] << 8) + ptr[idx + 3]; abuf_appendf(out, "\t| | Size: %u\n", msg_size); idx2 += 4; if (flags & RFC5444_MSG_FLAG_ORIGINATOR) { if (idx2 + addr_length > idx + msg_size) { return -1; } abuf_appendf(out, "\t| | Originator address: "); _print_hex(out, &ptr[idx2], addr_length, end); idx2 += addr_length; } if (flags & RFC5444_MSG_FLAG_HOPLIMIT) { if (idx2 + 1 > idx + msg_size) { return -1; } abuf_appendf(out, "\t| | Hop limit: %u\n", ptr[idx2]); idx2++; } if (flags & RFC5444_MSG_FLAG_HOPCOUNT) { if (idx2 + 1 > idx + msg_size) { return -1; } abuf_appendf(out, "\t| | Hop count: %u\n", ptr[idx2]); idx2++; } if (flags & RFC5444_MSG_FLAG_SEQNO) { if (idx2 + 2 > idx + msg_size) { return -1; } abuf_appendf(out, "\t| | Sequence Number: %u\n", (ptr[idx2] << 8) | ptr[idx2 + 1]); idx2 += 2; } if (_print_raw_tlvblock(out, "\t| | ", ptr, &idx2, msg_size)) { return -1; } while (idx2 < idx + msg_size) { /* print address blocks */ if (idx2 + 2 > idx + msg_size) { return -1; } abuf_puts(out, "\t| | ,-------------------\n"); abuf_puts(out, "\t| | | ADDRESS-BLOCK\n"); abuf_puts(out, "\t| | |-------------------\n"); num_addr = ptr[idx2]; abuf_appendf(out, "\t| | | Num-Addr: %u\n", num_addr); flags = ptr[idx2 + 1]; abuf_appendf(out, "\t| | | Flags: 0x%02x\n", flags); idx2 += 2; head_len = tail_len = 0; head = NULL; tail = NULL; if (flags & RFC5444_ADDR_FLAG_HEAD) { if (idx2 + 1 > idx + msg_size) { return -1; } head_len = ptr[idx2]; idx2++; if (idx2 + head_len > idx + msg_size) { return -1; } head = &ptr[idx2]; abuf_appendf(out, "\t| | | Head: "); _print_hex(out, head, head_len, end); abuf_puts(out, "\n"); idx2 += head_len; } if (flags & RFC5444_ADDR_FLAG_FULLTAIL) { if (idx2 + 1 > idx + msg_size) { return -1; } tail_len = ptr[idx2]; idx2++; if (idx2 + tail_len > idx + msg_size) { return -1; } tail = &ptr[idx2]; abuf_appendf(out, "\t| | | Tail: "); _print_hex(out, tail, tail_len, end); abuf_puts(out, "\n"); idx2 += tail_len; } if (flags & RFC5444_ADDR_FLAG_ZEROTAIL) { if (idx2 + 1 > idx + msg_size) { return -1; } tail_len = ptr[idx2]; tail = ZEROTAIL; abuf_appendf(out, "\t| | | ZeroTail: "); _print_hex(out, tail, tail_len, end); abuf_puts(out, "\n"); idx2++; } if (head_len + tail_len >= addr_length) { return -1; } mid_len = (addr_length - head_len - tail_len) * num_addr; if (idx2 + mid_len > idx + msg_size) { return -1; } prefix_idx = idx + mid_len; if (flags & RFC5444_ADDR_FLAG_SINGLEPLEN) { if (prefix_idx + 1 > idx + msg_size) { return -1; } } else if (flags & RFC5444_ADDR_FLAG_MULTIPLEN) { if (prefix_idx + num_addr > idx + msg_size) { return -1; } } else { prefix_idx = 0; } for (i = 0; i < num_addr; i++) { abuf_puts(out, "\t| | | ,-------------------\n"); abuf_puts(out, "\t| | | | Address\n"); abuf_puts(out, "\t| | | |-------------------\n"); abuf_appendf(out, "\t| | | | Address: "); if (head_len) { _print_hex(out, head, head_len, end); abuf_puts(out, " | "); } _print_hex(out, &ptr[idx2], addr_length - head_len - tail_len, end); idx2 += addr_length - head_len - tail_len; if (tail_len) { abuf_puts(out, " | "); _print_hex(out, tail, tail_len, end); } if (prefix_idx) { abuf_appendf(out, " / %u", ptr[prefix_idx]); } if (flags & RFC5444_ADDR_FLAG_MULTIPLEN) { prefix_idx++; } abuf_puts(out, "\n"); } if (_print_raw_tlvblock(out, "\t| | | ", ptr, &idx2, msg_size)) { return -1; } } if (idx + msg_size != idx2) { return -1; } idx = idx2; } return 0; }
static void abuf_json_close_array(struct autobuf *abuf) { abuf_appendf(abuf, "]}\n"); }
static void abuf_json_close_array_entry(struct autobuf *abuf) { abuf_appendf(abuf, "}"); }
static void abuf_json_open_array(struct autobuf *abuf, const char* header) { arrayentrynumber = 0; abuf_appendf(abuf, "{\"%s\": [\n", header); }
static void abuf_json_close_object(struct autobuf *abuf) { abuf_appendf(abuf, "\t}\n}\n"); }
static void abuf_json_open_object(struct autobuf *abuf, const char* header) { entrynumber = 0; abuf_appendf(abuf, "{\"%s\": {", header); }
static void abuf_json_float(struct autobuf *abuf, const char* key, float value) { abuf_json_insert_comma(abuf); abuf_appendf(abuf, "\t\"%s\": %.03f", key, (double)value); }
static void abuf_json_int(struct autobuf *abuf, const char* key, long value) { abuf_json_insert_comma(abuf); abuf_appendf(abuf, "\t\"%s\": %li", key, value); }