-src := bitmap.c bitops.c blake2s.c blake2b.c checksum.c defer.c event.c flowspec.c idm.c ip.c lists.c lockfree.c mac.c md5.c mempool.c net.c netindex.c patmatch.c printf.c rcu.c resource.c runtime.c sha1.c sha256.c sha512.c slab.c slists.c strtoul.c tbf.c timer.c xmalloc.c
+src := bitmap.c bitops.c blake2s.c blake2b.c cbor.c cbor_parse_tools.c cbor_shortcuts.c checksum.c defer.c event.c flowspec.c idm.c ip.c lists.c lockfree.c mac.c md5.c mempool.c net.c netindex.c patmatch.c printf.c rcu.c resource.c runtime.c sha1.c sha256.c sha512.c slab.c slists.c strtoul.c tbf.c timer.c xmalloc.c
obj := $(src-o-files)
$(all-lib)
obj := $(src-o-files)
$(all-daemon)
-tests_src := a-set_test.c a-path_test.c attribute_cleanup_test.c bitmap_test.c heap_test.c buffer_test.c event_test.c flowspec_test.c bitops_test.c patmatch_test.c fletcher16_test.c slist_test.c rt-normalize_test.c checksum_test.c lists_test.c locking_test.c mac_test.c ip_test.c hash_test.c printf_test.c rcu_test.c slab_test.c tlists_test.c type_test.c
+tests_src := a-set_test.c a-path_test.c attribute_cleanup_test.c bitmap_test.c cbor_test.c heap_test.c buffer_test.c event_test.c flowspec_test.c bitops_test.c patmatch_test.c fletcher16_test.c slist_test.c rt-normalize_test.c checksum_test.c lists_test.c locking_test.c mac_test.c ip_test.c hash_test.c printf_test.c rcu_test.c slab_test.c tlists_test.c type_test.c
tests_targets := $(tests_targets) $(tests-target-files)
tests_objs := $(tests_objs) $(src-o-files)
--- /dev/null
+#include <stdint.h>
+#include <string.h>
+
+#include "lib/cbor.h"
+
+
+void write_item(struct cbor_writer *writer, uint8_t major, uint64_t num);
+void check_memory(struct cbor_writer *writer, int add_size);
+
+struct cbor_writer *cbor_init(uint8_t *buff, uint32_t capacity, struct linpool *lp)
+{
+ struct cbor_writer *writer = (struct cbor_writer*)lp_alloc(lp, sizeof(struct cbor_writer));
+ writer->cbor = buff;
+ writer->capacity = capacity;
+ writer->pt = 0;
+ writer->lp = lp;
+ return writer;
+}
+
+void cbor_open_block(struct cbor_writer *writer) { // We will need to close the block later manualy
+ check_memory(writer, 2);
+ writer->cbor[writer->pt] = 0xbf;
+ writer->pt++;
+}
+
+void cbor_open_list(struct cbor_writer *writer)
+{
+ check_memory(writer, 2);
+ writer->cbor[writer->pt] = 0x9f;
+ writer->pt++;
+}
+
+void cbor_close_block_or_list(struct cbor_writer *writer)
+{
+ check_memory(writer, 2);
+ writer->cbor[writer->pt] = 0xff;
+ writer->pt++;
+}
+
+void cbor_open_block_with_length(struct cbor_writer *writer, uint32_t length)
+{
+ write_item(writer, 5, length);
+}
+
+void cbor_open_list_with_length(struct cbor_writer *writer, uint32_t length)
+{
+ write_item(writer, 4, length);
+}
+
+
+void cbor_add_int(struct cbor_writer *writer, int64_t item)
+{
+ if (item >= 0)
+ {
+ write_item(writer, 0, item); // 0 is the "major" (three bits) introducing positive int, 1 is for negative
+ }
+ else
+ {
+ write_item(writer, 1, -item - 1);
+ }
+}
+
+void cbor_epoch_time(struct cbor_writer *writer, int64_t time, int shift)
+{
+ write_item(writer, 6, 1); // 6 is TAG, 1 is tag number for epoch time
+ cbor_relativ_time(writer, time, shift);
+}
+
+void cbor_relativ_time(struct cbor_writer *writer, int64_t time, int shift)
+{
+ write_item(writer, 6, 4); // 6 is TAG, 4 is tag number for decimal fraction
+ cbor_open_list_with_length(writer, 2);
+ cbor_add_int(writer, shift);
+ cbor_add_int(writer, time);
+}
+
+void cbor_add_ipv4(struct cbor_writer *writer, ip4_addr addr)
+{
+ write_item(writer, 6, 52); // 6 is TAG, 52 is tag number for ipv4
+ write_item(writer, 2, 4); // bytestring of length 4
+ put_ip4(&writer->cbor[writer->pt], addr);
+ writer->pt += 4;
+}
+
+void cbor_add_ipv6(struct cbor_writer *writer, ip6_addr addr)
+{
+ write_item(writer, 6, 54); // 6 is TAG, 54 is tag number for ipv6
+ write_item(writer, 2, 16); // bytestring of length 16
+ put_ip6(&writer->cbor[writer->pt], addr);
+ writer->pt += 16;
+}
+
+
+void cbor_add_ipv4_prefix(struct cbor_writer *writer, net_addr_ip4 *n)
+{
+ write_item(writer, 6, 52); // 6 is TAG, 52 is tag number for ipv4
+ cbor_open_block_with_length(writer, 2);
+ cbor_add_int(writer, n->pxlen);
+ write_item(writer, 2, 4); // bytestring of length 4
+ put_ip4(&writer->cbor[writer->pt], n->prefix);
+ writer->pt += 4;
+}
+
+
+void cbor_add_ipv6_prefix(struct cbor_writer *writer, net_addr_ip6 *n)
+{
+ write_item(writer, 6, 54); // 6 is TAG, 54 is tag number for ipv6
+ cbor_open_block_with_length(writer, 2);
+ cbor_add_int(writer, n->pxlen);
+
+ write_item(writer, 2, 16);
+ put_ip6(&writer->cbor[writer->pt], n->prefix);
+ writer->pt += 16;
+}
+
+
+void cbor_add_uint(struct cbor_writer *writer, uint64_t item)
+{
+ write_item(writer, 0, item);
+}
+
+void cbor_add_tag(struct cbor_writer *writer, int item)
+{
+ write_item(writer, 6, item);
+}
+
+void cbor_add_string(struct cbor_writer *writer, const char *string)
+{
+ int length = strlen(string);
+ write_item(writer, 3, length); // 3 is major, then goes length of string and string
+ check_memory(writer, length);
+ memcpy(writer->cbor+writer->pt, string, length);
+ writer->pt+=length;
+}
+
+void cbor_nonterminated_string(struct cbor_writer *writer, const char *string, uint32_t length)
+{
+ write_item(writer, 3, length); // 3 is major, then goes length of string and string
+ check_memory(writer, length);
+ memcpy(writer->cbor+writer->pt, string, length);
+ writer->pt+=length;
+}
+
+void write_item(struct cbor_writer *writer, uint8_t major, uint64_t num)
+{
+ //log("write major %i %li", major, num);
+ major = major<<5;
+ check_memory(writer, 10);
+ if (num > ((uint64_t)1<<(4*8))-1)
+ { // We need 8 bytes to encode the num
+ major += 0x1b; // reserving those bytes
+ writer->cbor[writer->pt] = major;
+ writer->pt++;
+ for (int i = 7; i>=0; i--)
+ { // write n-th byte of num
+ uint8_t to_write = (num>>(i*8)) & 0xff;
+ writer->cbor[writer->pt] = to_write;
+ writer->pt++;
+ }
+ return;
+ }
+ if (num > (1<<(2*8))-1)
+ { // We need 4 bytes to encode the num
+ major += 0x1a; // reserving those bytes
+ writer->cbor[writer->pt] = major;
+ writer->pt++;
+ for (int i = 3; i>=0; i--)
+ { // write n-th byte of num
+ uint8_t to_write = (num>>(i*8)) & 0xff;
+ writer->cbor[writer->pt] = to_write;
+ writer->pt++;
+ }
+ return;
+ }
+ if (num > (1<<(8))-1)
+ { // We need 2 bytes to encode the num
+ major += 0x19; // reserving those bytes
+ writer->cbor[writer->pt] = major;
+ writer->pt++;
+ for (int i = 1; i>=0; i--)
+ { // write n-th byte of num
+ uint8_t to_write = (num>>(i*8)) & 0xff;
+ writer->cbor[writer->pt] = to_write;
+ writer->pt++;
+ }
+ return;
+ }
+ if (num > 23)
+ { // byte is enough, but aditional value would be too big
+ major += 0x18; // reserving that byte
+ writer->cbor[writer->pt] = major;
+ writer->pt++;
+ uint8_t to_write = num & 0xff;
+ writer->cbor[writer->pt] = to_write;
+ writer->pt++;
+ return;
+ }
+ //log("write item major %i num %i writer->pt %i writer->capacity %i writer %i", major, num, writer->pt, writer->capacity, writer);
+ major += num; // we can store the num as additional value
+ writer->cbor[writer->pt] = major;
+ writer->pt++;
+}
+
+void cbor_write_item_with_constant_val_length_4(struct cbor_writer *writer, uint8_t major, uint64_t num)
+{
+// this is only for headers which should be constantly long.
+ major = major<<5;
+ check_memory(writer, 10);
+ major += 0x1a; // reserving those bytes
+ writer->cbor[writer->pt] = major;
+ writer->pt++;
+ for (int i = 3; i>=0; i--)
+ { // write n-th byte of num
+ uint8_t to_write = (num>>(i*8)) & 0xff;
+ writer->cbor[writer->pt] = to_write;
+ writer->pt++;
+ }
+}
+
+
+void rewrite_4bytes_int(struct cbor_writer *writer, int pt, int num)
+{
+ for (int i = 3; i>=0; i--)
+ {
+ uint8_t to_write = (num>>(i*8)) & 0xff;
+ writer->cbor[pt] = to_write;
+ pt++;
+ }
+}
+
+void check_memory(struct cbor_writer *writer, int add_size)
+{
+ if (writer->capacity - writer->pt-add_size < 0)
+ {
+ bug("There is not enough space for cbor response in given buffer");
+ }
+}
--- /dev/null
+#ifndef CBOR_H
+#define CBOR_H
+
+#include "nest/bird.h"
+
+
+struct cbor_writer {
+ int pt; // where will next byte go
+ int capacity;
+ int8_t *cbor;
+ struct linpool *lp;
+};
+
+
+struct cbor_writer *cbor_init(uint8_t *buff, uint32_t capacity, struct linpool *lp);
+
+void cbor_open_block(struct cbor_writer *writer);
+
+void cbor_open_list(struct cbor_writer *writer);
+
+void cbor_close_block_or_list(struct cbor_writer *writer);
+
+void cbor_open_block_with_length(struct cbor_writer *writer, uint32_t length);
+
+void cbor_open_list_with_length(struct cbor_writer *writer, uint32_t length);
+
+
+void cbor_add_int(struct cbor_writer *writer, int64_t item);
+
+void cbor_add_ipv4(struct cbor_writer *writer, ip4_addr);
+
+void cbor_add_ipv6(struct cbor_writer *writer, ip6_addr);
+
+void cbor_epoch_time(struct cbor_writer *writer, int64_t time, int shift);
+
+void cbor_relativ_time(struct cbor_writer *writer, int64_t time, int shift);
+
+void cbor_add_ipv4_prefix(struct cbor_writer *writer, net_addr_ip4 *n);
+
+
+void cbor_add_ipv6_prefix(struct cbor_writer *writer, net_addr_ip6 *n);
+
+
+void cbor_add_uint(struct cbor_writer *writer, uint64_t item);
+
+void cbor_add_tag(struct cbor_writer *writer, int item);
+
+void cbor_add_string(struct cbor_writer *writer, const char *string);
+
+void cbor_nonterminated_string(struct cbor_writer *writer, const char *string, uint32_t length);
+
+void write_item(struct cbor_writer *writer, uint8_t major, uint64_t num);
+
+void cbor_write_item_with_constant_val_length_4(struct cbor_writer *writer, uint8_t major, uint64_t num);
+
+void rewrite_4bytes_int(struct cbor_writer *writer, int pt, int num);
+
+#endif
--- /dev/null
+#include <string.h>
+#include "lib/cbor_parse_tools.h"
+
+uint compare_buff_str(struct buff_reader *buf_read, uint length, char *string) {
+ if (length != strlen(string)) {
+ return 0;
+ }
+ for (size_t i = 0; i < strlen(string); i++) {
+ if (buf_read->buff[i+buf_read->pt]!=string[i]) {
+ return 0;
+ }
+ }
+ return 1;
+};
+
+struct value
+get_value(struct buff_reader *reader)
+{
+ struct value val;
+ byte *buff = reader->buff;
+ val.major = buff[reader->pt]>>5;
+ int first_byte_val = buff[reader->pt] - (val.major<<5);
+ if (first_byte_val <=23) {
+ val.val = first_byte_val;
+ reader->pt++;
+ } else if (first_byte_val == 0x18)
+ {
+ val.val = buff[reader->pt+1];
+ reader->pt+=2;
+ } else if (first_byte_val == 0x19)
+ {
+ val.val = buff[reader->pt+1];
+ val.val = val.val << 8;
+ val.val += buff[reader->pt+2];
+ reader->pt += 3;
+ } else if (first_byte_val == 0x1a)
+ {
+ val.val = 0;
+ for (int i = 1; i < 4; i++)
+ {
+ val.val += buff[reader->pt+i];
+ val.val = val.val << 8;
+ }
+ val.val += buff[reader->pt+4];
+ reader->pt+=5;
+ } else if (first_byte_val == 0x1b)
+ {
+ val.val = 0;
+ for (int i = 1; i < 8; i++) {
+ val.val += buff[reader->pt+i];
+ val.val = val.val << 8;
+ }
+ val.val += buff[reader->pt+8];
+ reader->pt += 9;
+ } else if (first_byte_val == 0x1f)
+ {
+ val.val = -1;
+ reader->pt++;
+ }
+ if (val.major == NEG_INT)
+ val.val = -1 - val.val;
+ return val;
+}
+
+
+int val_is_break(struct value val)
+{
+ return val.major == FLOAT && val.val == -1; // break code is 0xff, so the major is same for float and break
+}
--- /dev/null
+#include "sysdep/config.h"
+#include "lib/birdlib.h"
+
+enum functions {
+ SHOW_STATUS = 0,
+ SHOW_MEMORY = 1,
+ SHOW_SYMBOLS = 2,
+ SHOW_OSPF = 3,
+ SHOW_PROTOCOLS = 4,
+};
+
+enum cbor_majors {
+ UINT = 0,
+ NEG_INT = 1,
+ BYTE_STR = 2,
+ TEXT = 3,
+ ARRAY = 4,
+ BLOCK = 5,
+ TAG = 6,
+ FLOAT = 7,
+};
+
+
+struct value {
+ int major;
+ int64_t val;
+};
+
+struct buff_reader {
+ byte *buff;
+ uint pt;
+ uint size;
+};
+
+
+uint compare_buff_str(struct buff_reader *buf_read, uint length, char *string);
+
+struct value
+get_value(struct buff_reader *reader);
+
+
+int val_is_break(struct value val);
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "lib/cbor_shortcuts.h"
+
+
+
+void cbor_string_string(struct cbor_writer *writer, char *key, const char *value) {
+ cbor_add_string(writer, key);
+ cbor_add_string(writer, value);
+}
+
+void cbor_string_int(struct cbor_writer *writer, char *key, int64_t value) {
+ cbor_add_string(writer, key);
+ cbor_add_int(writer, value);
+}
+
+void cbor_string_uint(struct cbor_writer *writer, char *key, u64 value) {
+ cbor_add_string(writer, key);
+ cbor_add_uint(writer, value);
+}
+
+void cbor_string_epoch_time(struct cbor_writer *writer, char *key, int64_t time, int shift) {
+ cbor_add_string(writer, key);
+ cbor_epoch_time(writer, time, shift);
+}
+
+void cbor_string_relativ_time(struct cbor_writer *writer, char *key, int64_t time, int shift) {
+ cbor_add_string(writer, key);
+ cbor_relativ_time(writer, time, shift);
+}
+
+void cbor_string_ip(struct cbor_writer *writer, char *key, ip_addr addr) {
+ cbor_add_string(writer, key);
+ if (ipa_is_ip4(addr))
+ cbor_add_ipv4(writer, ipa_to_ip4(addr));
+ else
+ cbor_add_ipv6(writer, ipa_to_ip6(addr));
+}
+
+void cbor_string_ipv4(struct cbor_writer *writer, char *key, ip4_addr addr) {
+ cbor_add_string(writer, key);
+ cbor_add_ipv4(writer, addr);
+}
+
+void cbor_string_ipv6(struct cbor_writer *writer, char *key, ip6_addr addr) {
+ cbor_add_string(writer, key);
+ cbor_add_ipv6(writer, addr);
+}
+
+void cbor_named_block_two_ints(struct cbor_writer *writer, char *key, char *name1, int val1, char *name2, int val2) {
+ cbor_add_string(writer, key);
+ cbor_open_block_with_length(writer, 2);
+ cbor_add_string(writer, name1);
+ cbor_add_int(writer, val1);
+ cbor_add_string(writer, name2);
+ cbor_add_int(writer, val2);
+}
+
+void cbor_write_to_file(struct cbor_writer *writer, char *filename) {
+ FILE *write_ptr;
+
+ write_ptr = fopen(filename, "wb");
+
+ fwrite(writer->cbor, writer->pt, 1, write_ptr);
+ fclose(write_ptr);
+}
+
+void cbor_add_net(struct cbor_writer *writer, const net_addr *N) {
+ // Original switch comes from lib/net.c and contains more cases.
+ net_addr_union *n = (void *) N;
+
+ switch (n->n.type)
+ {
+ case NET_IP4:
+ cbor_add_ipv4_prefix(writer, &n->ip4);
+ return;
+ case NET_IP6:
+ cbor_add_ipv6_prefix(writer, &n->ip6);
+ return;
+ default:
+ bug("net type unsupported by cbor (yet).");
+ }
+}
+
+
+
--- /dev/null
+#ifndef CBOR_SHORTCUTS_H
+#define CBOR_SHORTCUTS_H
+
+#include "lib/cbor.h"
+#include "sysdep/config.h"
+#include "lib/birdlib.h"
+#include "nest/protocol.h"
+#include "lib/ip.h"
+
+
+void cbor_string_string(struct cbor_writer *writer, char *key, const char *value);
+
+void cbor_string_int(struct cbor_writer *writer, char *key, int64_t value);
+
+void cbor_string_epoch_time(struct cbor_writer *writer, char *key, int64_t time, int shift);
+void cbor_string_relativ_time(struct cbor_writer *writer, char *key, int64_t time, int shift);
+void cbor_string_uint(struct cbor_writer *writer, char *key, u64 value);
+void cbor_string_ip(struct cbor_writer *writer, char *key, ip_addr);
+void cbor_string_ipv4(struct cbor_writer *writer, char *key, ip4_addr);
+void cbor_string_ipv6(struct cbor_writer *writer, char *key, ip6_addr);
+void cbor_named_block_two_ints(struct cbor_writer *writer, char *key, char *name1, int val1, char *name2, int val2);
+void cbor_write_to_file(struct cbor_writer *writer, char *filename);
+
+void cbor_add_net(struct cbor_writer *writer, const net_addr *N);
+
+#endif
--- /dev/null
+
+#include "test/birdtest.h"
+#include "lib/cbor.h"
+#include "lib/cbor_parse_tools.h"
+
+#define BUFF_LEN 100
+
+struct cbor_writer *w;
+struct buff_reader reader;
+
+void print_to_file_for_control_from_outside(void)
+{
+ FILE *write_ptr;
+
+ write_ptr = fopen("a.cbor", "wb");
+
+ fwrite(w->cbor, w->pt, 1, write_ptr);
+ fclose(write_ptr);
+
+}
+
+static int test_int(void)
+{
+ reader.pt = w->pt = 0;
+ int num_items = 13;
+ int64_t test_int[] = {-123456789012345678, -1234567890, -12345, -123, -25, -13, 0, 13, 25, 123, 12345, 1234567890, 123456789012345678};
+ byte bin_int[] = {0x8d, 0x3b, 0x1, 0xb6, 0x9b, 0x4b, 0xa6, 0x30, 0xf3, 0x4d, 0x3a, 0x49, 0x96, 0x2, 0xd1, 0x39, 0x30, 0x38, 0x38, 0x7a, 0x38, 0x18, 0x2c, 0x0, 0xd, 0x18, 0x19, 0x18, 0x7b, 0x19, 0x30, 0x39, 0x1a, 0x49, 0x96, 0x2, 0xd2, 0x1b, 0x1, 0xb6, 0x9b, 0x4b, 0xa6, 0x30, 0xf3, 0x4e};
+ cbor_open_list_with_length(w, num_items);
+ for (int i = 0; i < num_items; i++)
+ {
+ cbor_add_int(w, test_int[i]);
+ }
+
+ for (long unsigned int i = 0; i < sizeof(bin_int); i++)
+ {
+ bt_assert((w->cbor[i] & 0xff) == (bin_int[i] & 0xff));
+ }
+
+ struct value val = get_value(&reader);
+ bt_assert(val.major = ARRAY);
+ bt_assert(val.val = num_items);
+ for (int i = 0; i < num_items; i++)
+ {
+ val = get_value(&reader);
+ bt_assert(val.major == NEG_INT || val.major == UINT);
+ bt_assert(val.val == test_int[i]);
+ }
+ return 1;
+}
+
+static int non_aligned_int(void)
+{
+ w->pt = reader.pt = 0;
+ int num_items = 4;
+ cbor_open_list_with_length(w, num_items);
+
+ cbor_add_int(w, 30);
+ w->cbor[w->pt - 1] = 1;
+
+ cbor_add_int(w, 300);
+ w->cbor[w->pt - 2] = 0;
+ w->cbor[w->pt - 1] = 1;
+
+ cbor_add_int(w, 300000000);
+ for (int i = 4; i > 1; i--)
+ {
+ w->cbor[w->pt - i] = 0;
+ }
+ w->cbor[w->pt - 1] = 1;
+
+ cbor_add_int(w, 30000000000000000);
+ for (int i = 8; i > 1; i--)
+ {
+ w->cbor[w->pt - i] = 0;
+ }
+ w->cbor[w->pt - 1] = 1;
+
+ struct value val = get_value(&reader);
+ bt_assert(val.major = ARRAY);
+ bt_assert(val.val = num_items);
+
+ for (int i = 0; i < num_items; i++)
+ {
+ val = get_value(&reader);
+ bt_assert(val.major == UINT);
+ bt_assert(val.val == 1);
+ }
+ return 1;
+}
+
+static int test_majors(void)
+{
+ w->pt = reader.pt = 0;
+ cbor_open_block(w);
+ cbor_open_list_with_length(w, 4);
+ cbor_add_string(w, "b");
+ cbor_add_int(w, 1);
+ cbor_add_int(w, -1);
+ cbor_add_ipv4(w, ip4_build(18, 4, 0, 0));
+ cbor_close_block_or_list(w);
+
+ struct value val = get_value(&reader);
+ bt_assert(val.major == BLOCK);
+ val = get_value(&reader);
+ bt_assert(val.major == ARRAY);
+ val = get_value(&reader);
+ bt_assert(val.major == TEXT);
+ reader.pt += val.val;
+ val = get_value(&reader);
+ bt_assert(val.major == UINT);
+ val = get_value(&reader);
+ bt_assert(val.major == NEG_INT);
+ val = get_value(&reader);
+ bt_assert(val.major == TAG);
+ val = get_value(&reader);
+ bt_assert(val.major == BYTE_STR);
+ reader.pt += val.val;
+ val = get_value(&reader);
+ bt_assert(val_is_break(val));
+ return 1;
+}
+
+int main(int argc, char *argv[])
+{
+ bt_init(argc, argv);
+ byte buff[BUFF_LEN];
+ w = cbor_init(buff, BUFF_LEN, tmp_linpool);
+ reader.buff = buff;
+ reader.size = BUFF_LEN;
+ reader.pt = 0;
+
+ bt_test_suite(test_int, "Adding and reading integer from cbor.");
+ bt_test_suite(non_aligned_int, "Reading non-alligned int from cbor.");
+ bt_test_suite(test_majors, "Test cbor datatypes.");
+
+ return bt_exit_value();
+}