1 #include <assert.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 
6 #include <axa/json.h>
7 #include <axa/axa_endian.h>
8 #include <axa/protocol.h>
9 #include <axa/wire.h>
10 #include <check.h>
11 #include <nmsg/container.h>
12 #include <nmsg/input.h>
13 #include <nmsg/message.h>
14 #include <nmsg/base/defs.h>
15 
16 nmsg_input_t nmsg_input;
17 
18 #define empty_test(op, name) do { \
19 	const char *expected; \
20 	axa_p_hdr_t hdr = { AXA_H2P32(sizeof(axa_p_hdr_t)), AXA_H2P_TAG(0), AXA_P_PVERS, op }; \
21 	char *out = NULL; \
22 	axa_json_res_t res; \
23 	axa_emsg_t emsg; \
24 	switch((op)) { \
25 	case AXA_P_OP_WHIT: \
26 	case AXA_P_OP_AHIT: \
27 	case AXA_P_OP_WATCH: \
28 	case AXA_P_OP_ANOM: \
29 	case AXA_P_OP_STOP: \
30 		hdr.tag = AXA_H2P_TAG(1); \
31 		break; \
32 	default: \
33 		break; \
34 	} \
35 	res = axa_body_to_json(&emsg, nmsg_input, &hdr, 0, 0, &out); \
36 	ck_assert_int_eq(res, AXA_JSON_RES_SUCCESS); \
37 	if (AXA_P2H_TAG(hdr.tag) == 0) \
38 		expected = "{\"tag\":\"*\",\"op\":\"" name "\"}"; \
39 	else \
40 		expected = "{\"tag\":1,\"op\":\"" name "\"}"; \
41 	ck_assert_str_eq(out, expected); \
42 	free(out); \
43 } while (0)
44 
45 #define truncated_test(op, axa_p_type_t, watch_len) do { \
46 	axa_p_hdr_t hdr = { AXA_H2P32(sizeof(axa_p_hdr_t) + watch_len), AXA_H2P_TAG(0), AXA_P_PVERS, op }; \
47 	axa_p_type_t type; \
48 	char *out = NULL; \
49 	axa_json_res_t res; \
50 	axa_emsg_t emsg; \
51 	switch((op)) { \
52 	case AXA_P_OP_WHIT: \
53 	case AXA_P_OP_AHIT: \
54 	case AXA_P_OP_WATCH: \
55 	case AXA_P_OP_ANOM: \
56 	case AXA_P_OP_STOP: \
57 		hdr.tag = AXA_H2P_TAG(1); \
58 		break; \
59 	default: \
60 		break; \
61 	} \
62 	memset(&type, 0, sizeof(type)); \
63 	res = axa_body_to_json(&emsg, nmsg_input, &hdr, (axa_p_body_t*)&type, (watch_len), &out); \
64 	ck_assert_int_eq(res, AXA_JSON_RES_FAILURE); \
65 	ck_assert_ptr_eq(out, NULL); \
66 } while (0)
67 
START_TEST(test_nop)68 START_TEST(test_nop)
69 {
70 	empty_test(AXA_P_OP_NOP, "NOP");
71 }
72 END_TEST
73 
START_TEST(test_hello)74 START_TEST(test_hello)
75 {
76 	const char *expected = "{\"tag\":\"*\",\"op\":\"HELLO\",\"id\":1,\"pvers_min\":2,\"pvers_max\":3,\"str\":\"hello\"}";
77 	axa_emsg_t emsg;
78 	axa_p_hello_t hello = { 1, 2, 3, "hello" };
79 	char *out = NULL;
80 	size_t watch_len = offsetof(axa_p_hello_t, str) + strlen(hello.str) + 1;
81 	axa_p_hdr_t hdr = { AXA_H2P32(sizeof(axa_p_hdr_t) + watch_len), AXA_H2P_TAG(AXA_TAG_NONE), AXA_P_PVERS, AXA_P_OP_HELLO };
82 	axa_json_res_t res;
83 	res = axa_body_to_json(&emsg, nmsg_input, &hdr, (axa_p_body_t*)&hello, watch_len, &out);
84 	ck_assert_int_eq(res, AXA_JSON_RES_SUCCESS);
85 	ck_assert_str_eq(out, expected);
86 	free(out);
87 }
88 END_TEST
89 
START_TEST(test_hello_empty)90 START_TEST(test_hello_empty)
91 {
92 	const char *expected = "{\"tag\":\"*\",\"op\":\"HELLO\",\"id\":1,\"pvers_min\":2,\"pvers_max\":3,\"str\":\"\"}";
93 	axa_emsg_t emsg;
94 	axa_p_hello_t hello = { 1, 2, 3, "" };
95 	char *out = NULL;
96 	size_t watch_len = offsetof(axa_p_hello_t, str) + strlen(hello.str) + 1;
97 	axa_p_hdr_t hdr = { AXA_H2P32(sizeof(axa_p_hdr_t) + watch_len), AXA_H2P_TAG(AXA_TAG_NONE), AXA_P_PVERS, AXA_P_OP_HELLO };
98 	axa_json_res_t res;
99 	res = axa_body_to_json(&emsg, nmsg_input, &hdr, (axa_p_body_t*)&hello, watch_len, &out);
100 	ck_assert_int_eq(res, AXA_JSON_RES_SUCCESS);
101 	ck_assert_str_eq(out, expected);
102 	free(out);
103 }
104 END_TEST
105 
START_TEST(test_hello_trunc)106 START_TEST(test_hello_trunc)
107 {
108 	truncated_test(AXA_P_OP_HELLO, axa_p_hello_t, offsetof(axa_p_hello_t, str) - 1);
109 }
110 END_TEST
111 
START_TEST(test_ok)112 START_TEST(test_ok)
113 {
114 	const char *expected = "{\"tag\":1,\"op\":\"OK\",\"orig_op\":\"WATCH HIT\",\"str\":\"success\"}";
115 	axa_emsg_t emsg;
116 	axa_p_result_t result = { AXA_P_OP_WHIT, "success" };
117 	size_t watch_len = offsetof(axa_p_result_t, str) + strlen(result.str) + 1;
118 	axa_p_hdr_t hdr = { AXA_H2P32(sizeof(axa_p_hdr_t) + watch_len), 1, AXA_P_PVERS, AXA_P_OP_OK };
119 	char *out = NULL;
120 	axa_json_res_t res = axa_body_to_json(&emsg, nmsg_input, &hdr, (axa_p_body_t*)&result, watch_len, &out);
121 	ck_assert_int_eq(res, AXA_JSON_RES_SUCCESS);
122 	ck_assert_str_eq(out, expected);
123 	free(out);
124 }
125 END_TEST
126 
START_TEST(test_ok_trunc)127 START_TEST(test_ok_trunc)
128 {
129 	truncated_test(AXA_P_OP_OK, axa_p_result_t, offsetof(axa_p_result_t, str) - 1);
130 }
131 END_TEST
132 
START_TEST(test_error)133 START_TEST(test_error)
134 {
135 	const char *expected = "{\"tag\":1,\"op\":\"ERROR\",\"orig_op\":\"OK\",\"str\":\"failure\"}";
136 	axa_emsg_t emsg;
137 	axa_p_result_t result = { AXA_P_OP_OK, "failure" };
138 	size_t watch_len = offsetof(axa_p_result_t, str) + strlen(result.str) + 1;
139 	axa_p_hdr_t hdr = { AXA_H2P32(sizeof(axa_p_hdr_t) + watch_len), 1, AXA_P_PVERS, AXA_P_OP_ERROR };
140 	char *out = NULL;
141 	axa_json_res_t res = axa_body_to_json(&emsg, nmsg_input, &hdr, (axa_p_body_t*)&result, watch_len, &out);
142 	ck_assert_int_eq(res, AXA_JSON_RES_SUCCESS);
143 	ck_assert_str_eq(out, expected);
144 	free(out);
145 }
146 END_TEST
147 
START_TEST(test_error_trunc)148 START_TEST(test_error_trunc)
149 {
150 	truncated_test(AXA_P_OP_ERROR, axa_p_result_t, offsetof(axa_p_result_t, str) - 1);
151 }
152 END_TEST
153 
START_TEST(test_missed)154 START_TEST(test_missed)
155 {
156 	const char *expected = "{\"tag\":\"*\",\"op\":\"MISSED\",\"missed\":2,\"dropped\":3,\"rlimit\":4,\"filtered\":5,\"last_report\":6}";
157 	axa_emsg_t emsg;
158 	axa_p_missed_t missed = { 2, 3, 4, 5, 6 };
159 	size_t watch_len = sizeof(missed);
160 	axa_p_hdr_t hdr = { AXA_H2P32(sizeof(axa_p_hdr_t) + watch_len), AXA_H2P_TAG(AXA_TAG_NONE), AXA_P_PVERS, AXA_P_OP_MISSED };
161 	char *out = NULL;
162 	axa_json_res_t res = axa_body_to_json(&emsg, nmsg_input, &hdr, (axa_p_body_t*)&missed, watch_len, &out);
163 	ck_assert_int_eq(res, AXA_JSON_RES_SUCCESS);
164 	ck_assert_str_eq(out, expected);
165 	free(out);
166 }
167 END_TEST
168 
START_TEST(test_missed_trunc)169 START_TEST(test_missed_trunc)
170 {
171 	truncated_test(AXA_P_OP_MISSED, axa_p_missed_t, sizeof(axa_p_missed_t) - 1);
172 }
173 END_TEST
174 
START_TEST(test_missed_rad)175 START_TEST(test_missed_rad)
176 {
177 	const char *expected = "{\"tag\":\"*\",\"op\":\"RAD MISSED\",\"sra_missed\":2,\"sra_dropped\":3,\"sra_rlimit\":4,\"sra_filtered\":5,\"dropped\":6,\"rlimit\":7,\"filtered\":8,\"last_report\":9}";
178 	axa_emsg_t emsg;
179 	axa_p_hdr_t hdr = { AXA_H2P32(sizeof(axa_p_hdr_t) + sizeof(axa_p_missed_rad_t)), AXA_H2P_TAG(AXA_TAG_NONE), AXA_P_PVERS, AXA_P_OP_MISSED_RAD };
180 	axa_p_missed_rad_t missed_rad = { 2, 3, 4, 5, 6, 7, 8, 9 };
181 	char *out = NULL;
182 	axa_json_res_t res = axa_body_to_json(&emsg, nmsg_input, &hdr, (axa_p_body_t*)&missed_rad, sizeof(missed_rad), &out);
183 	ck_assert_int_eq(res, AXA_JSON_RES_SUCCESS);
184 	ck_assert_str_eq(out, expected);
185 	free(out);
186 }
187 END_TEST
188 
START_TEST(test_missed_rad_trunc)189 START_TEST(test_missed_rad_trunc)
190 {
191 	truncated_test(AXA_P_OP_MISSED_RAD, axa_p_missed_rad_t, sizeof(axa_p_missed_rad_t) - 1);
192 }
193 END_TEST
194 
START_TEST(test_whit_nmsg)195 START_TEST(test_whit_nmsg)
196 {
197 	const char *expected = "{\"tag\":1,\"op\":\"WATCH HIT\",\"channel\":\"ch123\",\"field\":\"payload\",\"val_idx\":2,\"vname\":\"base\",\"mname\":\"pkt\",\"time\":\"1970-01-01 00:00:01.000000002\",\"nmsg\":{\"time\":\"1970-01-01 00:00:01.000000002\",\"vname\":\"base\",\"mname\":\"pkt\",\"message\":{\"len_frame\":32,\"payload\":\"RQAAIBI0QAD/EVmFAQIDBAUGBwgAewHIAAxP4t6tvu8=\"}}}";
198 	axa_emsg_t emsg;
199 	nmsg_container_t container;
200 	nmsg_msgmod_t mod;
201 	nmsg_message_t msg;
202 	void *clos;
203 	uint8_t packet[] = "\x45\x00\x00\x20\x12\x34\x40\x00\xff\x11\x59\x85\x01\x02\x03\x04\x05\x06\x07\x08\x00\x7b\x01\xc8\x00\x0c\x4f\xe2\xde\xad\xbe\xef";
204 	uint32_t packet_len = sizeof(packet)-1;
205 	uint8_t *pbuf;
206 	size_t pbuf_len;
207 	size_t whit_len;
208 	axa_p_whit_nmsg_t *whit;
209 	axa_p_whit_nmsg_hdr_t whit_hdr = {
210 		.hdr = { .ch=123, .type=AXA_P_WHIT_NMSG },
211 		.field_idx = 1,
212 		.val_idx = 2,
213 		.vid = NMSG_VENDOR_BASE_ID,
214 		.type = NMSG_VENDOR_BASE_PKT_ID,
215 		.ts = { 1, 2 }
216 	};
217 	char *out = NULL;
218 	axa_json_res_t res;
219 	axa_p_hdr_t hdr = { .tag=1, .pvers=AXA_P_PVERS, .op=AXA_P_OP_WHIT };
220 	struct timespec ts = { whit_hdr.ts.tv_sec , whit_hdr.ts.tv_nsec };
221 
222 	container = nmsg_container_init(1000);
223 	assert(container != NULL);
224 
225 	mod = nmsg_msgmod_lookup(NMSG_VENDOR_BASE_ID, NMSG_VENDOR_BASE_PKT_ID);
226 	assert(mod != NULL);
227 	assert(nmsg_msgmod_init(mod, &clos) == nmsg_res_success);
228 
229 	msg = nmsg_message_init(mod);
230 	assert (msg != NULL);
231 
232 	nmsg_message_set_time(msg, &ts);
233 	assert(nmsg_message_set_field(msg, "len_frame", 0, (void*)&packet_len, sizeof(packet_len)) == nmsg_res_success);
234 	assert(nmsg_message_set_field(msg, "payload", 0, packet, packet_len) == nmsg_res_success);
235 
236 	assert(nmsg_container_add(container, msg) == nmsg_res_success);
237 	assert(nmsg_container_serialize(container, &pbuf, &pbuf_len,
238 				true, false, 0, 0) == nmsg_res_success);
239 
240 	whit_len = offsetof(axa_p_whit_nmsg_t, b) + pbuf_len;
241 	whit = alloca(whit_len);
242 	assert(whit != NULL);
243 
244 	whit->hdr = whit_hdr;
245 	memcpy(&(whit->b), pbuf, pbuf_len);
246 	free(pbuf);
247 
248 	hdr.len = AXA_H2P32(sizeof(axa_p_hdr_t) + whit_len);
249 
250 	res = axa_body_to_json(&emsg, nmsg_input, &hdr, (axa_p_body_t*)whit, whit_len, &out);
251 	ck_assert_int_eq(res, AXA_JSON_RES_SUCCESS);
252 	ck_assert_str_eq(out, expected);
253 	free(out);
254 
255 	nmsg_message_destroy(&msg);
256 	nmsg_msgmod_fini(mod, &clos);
257 	nmsg_container_destroy(&container);
258 }
259 END_TEST
260 
START_TEST(test_whit_nmsg_trunc)261 START_TEST(test_whit_nmsg_trunc)
262 {
263 	truncated_test(AXA_P_OP_WHIT, axa_p_whit_nmsg_t, offsetof(axa_p_whit_nmsg_t, b) - 1);
264 }
265 END_TEST
266 
START_TEST(test_whit_ip4_udp)267 START_TEST(test_whit_ip4_udp)
268 {
269 	const char *expected = "{\"tag\":1,\"op\":\"WATCH HIT\",\"channel\":\"ch123\",\"time\":\"1970-01-01 00:00:01.000002\",\"af\":\"IPv4\",\"src\":\"1.2.3.4\",\"dst\":\"5.6.7.8\",\"ttl\":255,\"proto\":\"UDP\",\"src_port\":123,\"dst_port\":456,\"payload\":\"3q2+7w==\"}";
270 	axa_emsg_t emsg;
271 	uint8_t packet[] = "\x45\x00\x00\x20\x12\x34\x40\x00\xff\x11\x59\x85\x01\x02\x03\x04\x05\x06\x07\x08\x00\x7b\x01\xc8\x00\x0c\x4f\xe2\xde\xad\xbe\xef";
272 	size_t whit_len = offsetof(axa_p_whit_ip_t, b) + sizeof(packet) - 1;
273 	axa_p_whit_ip_t *whit = alloca(whit_len);
274 	axa_p_whit_ip_t whit_data = { .hdr={
275 		.hdr = { .ch=123, .type=AXA_P_WHIT_IP },
276 		.tv = { 1, 2 },
277 		.ip_len = sizeof(packet),
278 	}};
279 	axa_p_hdr_t hdr = { AXA_H2P32(sizeof(axa_p_hdr_t) + whit_len), 1, AXA_P_PVERS, AXA_P_OP_WHIT };
280 	char *out = NULL;
281 	axa_json_res_t res;
282 
283 	*whit = whit_data;
284 	memcpy(&(whit->b), packet, sizeof(packet) - 1);
285 
286 	res = axa_body_to_json(&emsg, nmsg_input, &hdr, (axa_p_body_t*)whit, whit_len, &out);
287 	ck_assert_int_eq(res, AXA_JSON_RES_SUCCESS);
288 	ck_assert_str_eq(out, expected);
289 	free(out);
290 }
291 END_TEST
292 
START_TEST(test_whit_ip4_tcp)293 START_TEST(test_whit_ip4_tcp)
294 {
295 	const char *expected = "{\"tag\":1,\"op\":\"WATCH HIT\",\"channel\":\"ch123\",\"time\":\"1970-01-01 00:00:01.000002\",\"af\":\"IPv4\",\"src\":\"1.2.3.4\",\"dst\":\"5.6.7.8\",\"ttl\":255,\"proto\":\"TCP\",\"src_port\":123,\"dst_port\":456,\"flags\":[\"SYN\",\"ACK\"],\"payload\":\"3q2+7w==\"}";
296 	axa_emsg_t emsg;
297 	uint8_t packet[] = "\x45\x00\x00\x28\x12\x34\x40\x00\xff\x06\x59\x88\x01\x02\x03\x04\x05\x06\x07\x08\x00\x7b\x01\xc8\x00\x00\x00\x64\x00\x00\x00\x64\x50\x12\x0f\xa0\x8d\x14\x00\x00\xde\xad\xbe\xef";
298 	size_t whit_len = offsetof(axa_p_whit_ip_t, b) + sizeof(packet) - 1;
299 	axa_p_whit_ip_t *whit = alloca(whit_len);
300 	axa_p_whit_ip_t whit_data = { .hdr={
301 		.hdr = { .ch=123, .type=AXA_P_WHIT_IP },
302 		.tv = { 1, 2 },
303 		.ip_len = sizeof(packet),
304 	}};
305 	axa_p_hdr_t hdr = { AXA_H2P32(sizeof(axa_p_hdr_t) + whit_len), 1, AXA_P_PVERS, AXA_P_OP_WHIT };
306 	char *out = NULL;
307 	axa_json_res_t res;
308 
309 	*whit = whit_data;
310 	memcpy(&(whit->b), packet, sizeof(packet) - 1);
311 
312 	res = axa_body_to_json(&emsg, nmsg_input, &hdr, (axa_p_body_t*)whit, whit_len, &out);
313 	ck_assert_int_eq(res, AXA_JSON_RES_SUCCESS);
314 	ck_assert_str_eq(out, expected);
315 	free(out);
316 }
317 END_TEST
318 
START_TEST(test_whit_ip4_trunc)319 START_TEST(test_whit_ip4_trunc)
320 {
321 	truncated_test(AXA_P_OP_WHIT, axa_p_whit_ip_t, offsetof(axa_p_whit_ip_t, b));
322 }
323 END_TEST
324 
START_TEST(test_whit_ip6)325 START_TEST(test_whit_ip6)
326 {
327 	const char *expected = "{\"tag\":1,\"op\":\"WATCH HIT\",\"channel\":\"ch123\",\"time\":\"1970-01-01 00:00:01.000002\",\"af\":\"IPv6\",\"src\":\"1:2:3:4:5:6:7:8\",\"dst\":\"9:b:a:b:c:d:e:f\",\"ttl\":255,\"proto\":\"UDP\",\"src_port\":123,\"dst_port\":456,\"payload\":\"3q2+7w==\"}";
328 	axa_emsg_t emsg;
329 	uint8_t packet[] = "\x60\x00\x00\x00\x00\x0c\x11\xff\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x06\x00\x07\x00\x08\x00\x09\x00\x0b\x00\x0a\x00\x0b\x00\x0c\x00\x0d\x00\x0e\x00\x0f\x00\x7b\x01\xc8\x00\x0c\x5f\x7e\xde\xad\xbe\xef";
330 	size_t whit_len = offsetof(axa_p_whit_ip_t, b) + sizeof(packet) - 1;
331 	axa_p_whit_ip_t *whit = alloca(whit_len);
332 	axa_p_whit_ip_t whit_data = { .hdr={
333 		.hdr = { .ch=123, .type=AXA_P_WHIT_IP },
334 		.tv = { 1, 2 },
335 		.ip_len = sizeof(packet),
336 	}};
337 	axa_p_hdr_t hdr = { AXA_H2P32(sizeof(axa_p_hdr_t) + whit_len), 1, AXA_P_PVERS, AXA_P_OP_WHIT };
338 	char *out = NULL;
339 	axa_json_res_t res;
340 
341 	*whit = whit_data;
342 	memcpy(&(whit->b), packet, sizeof(packet) - 1);
343 
344 	res = axa_body_to_json(&emsg, nmsg_input, &hdr, (axa_p_body_t*)whit, whit_len, &out);
345 	ck_assert_int_eq(res, AXA_JSON_RES_SUCCESS);
346 	ck_assert_str_eq(out, expected);
347 	free(out);
348 }
349 END_TEST
350 
START_TEST(test_whit_ip6_trunc)351 START_TEST(test_whit_ip6_trunc)
352 {
353 	truncated_test(AXA_P_OP_WHIT, axa_p_whit_ip_t, offsetof(axa_p_whit_ip_t, b));
354 }
355 END_TEST
356 
START_TEST(test_whit_trunc)357 START_TEST(test_whit_trunc)
358 {
359 	truncated_test(AXA_P_OP_WHIT, axa_p_whit_hdr_t, sizeof(axa_p_whit_hdr_t) - 1);
360 }
361 END_TEST
362 
START_TEST(test_watch_ip4)363 START_TEST(test_watch_ip4)
364 {
365 	const char *expected = "{\"tag\":1,\"op\":\"WATCH\",\"watch_type\":\"ipv4\",\"watch\":\"IP=12.34.56.0/24\"}";
366 	axa_emsg_t emsg;
367 	axa_p_watch_t watch = { AXA_P_WATCH_IPV4, 24, 0, 0, {} };
368 	size_t watch_len = offsetof(axa_p_watch_t, pat) + sizeof(struct in_addr);
369 	axa_p_hdr_t hdr = { AXA_H2P32(sizeof(axa_p_hdr_t) + watch_len), 1, AXA_P_PVERS, AXA_P_OP_WATCH };
370 	char *out = NULL;
371 	axa_json_res_t res;
372 	struct in_addr addr;
373 
374 	ck_assert(inet_aton("12.34.56.0", &addr));
375 	memcpy(&(watch.pat.addr), &addr, sizeof(watch.pat.addr));
376 
377 	res = axa_body_to_json(&emsg, nmsg_input, &hdr, (axa_p_body_t*)&watch, watch_len, &out);
378 	ck_assert_int_eq(res, AXA_JSON_RES_SUCCESS);
379 	ck_assert_str_eq(out, expected);
380 	free(out);
381 }
382 END_TEST
383 
START_TEST(test_watch_ip4_trunc)384 START_TEST(test_watch_ip4_trunc)
385 {
386 	axa_p_watch_t watch = { AXA_P_WATCH_IPV4, 24, 0, 0, {} };
387 	size_t watch_len = offsetof(axa_p_watch_t, pat);
388 	axa_p_hdr_t hdr = { AXA_H2P32(sizeof(axa_p_hdr_t) + watch_len), 1, AXA_P_PVERS, AXA_P_OP_WATCH };
389 	char *out = NULL;
390 	axa_emsg_t emsg;
391 	axa_json_res_t res = axa_body_to_json(&emsg, nmsg_input, &hdr, (axa_p_body_t*)&watch, watch_len, &out);
392 	ck_assert_int_eq(res, AXA_JSON_RES_FAILURE);
393 	ck_assert_ptr_eq(out, NULL);
394 }
395 END_TEST
396 
START_TEST(test_watch_ip4_overflow)397 START_TEST(test_watch_ip4_overflow)
398 {
399 	axa_p_watch_t watch = { AXA_P_WATCH_IPV4, 24, 0, 0, {} };
400 	size_t watch_len = sizeof(axa_p_watch_t);
401 	axa_p_hdr_t hdr = { AXA_H2P32(sizeof(axa_p_hdr_t) + watch_len), 1, AXA_P_PVERS, AXA_P_OP_WATCH };
402 	char *out = NULL;
403 	axa_json_res_t res;
404 	axa_emsg_t emsg;
405 	struct in_addr addr;
406 
407 	ck_assert(inet_aton("12.34.56.78", &addr));
408 	memcpy(&(watch.pat.addr), &addr, sizeof(watch.pat.addr));
409 
410 	res = axa_body_to_json(&emsg, nmsg_input, &hdr, (axa_p_body_t*)&watch, watch_len, &out);
411 	ck_assert_int_eq(res, AXA_JSON_RES_FAILURE);
412 	ck_assert_ptr_eq(out, NULL);
413 	free(out);
414 }
415 END_TEST
416 
START_TEST(test_watch_ip6)417 START_TEST(test_watch_ip6)
418 {
419 	const char *expected = "{\"tag\":1,\"op\":\"WATCH\",\"watch_type\":\"ipv6\",\"watch\":\"IP=1:2:3:4:5:6::/48\"}";
420 	axa_emsg_t emsg;
421 	axa_p_watch_t watch = { AXA_P_WATCH_IPV6, 48, 0, 0, {} };
422 	size_t watch_len = offsetof(axa_p_watch_t, pat) + sizeof(struct in6_addr);
423 	axa_p_hdr_t hdr = { AXA_H2P32(sizeof(axa_p_hdr_t) + watch_len), 1, AXA_P_PVERS, AXA_P_OP_WATCH };
424 	char *out = NULL;
425 	axa_json_res_t res;
426 	struct in6_addr addr6;
427 
428 	ck_assert(inet_pton(AF_INET6, "1:2:3:4:5:6::", &addr6));
429 	memcpy(&(watch.pat.addr6), &addr6, sizeof(watch.pat.addr6));
430 
431 	res = axa_body_to_json(&emsg, nmsg_input, &hdr, (axa_p_body_t*)&watch, watch_len, &out);
432 	ck_assert_int_eq(res, AXA_JSON_RES_SUCCESS);
433 	ck_assert_str_eq(out, expected);
434 	free(out);
435 }
436 END_TEST
437 
START_TEST(test_watch_dns)438 START_TEST(test_watch_dns)
439 {
440 	const char *expected = "{\"tag\":1,\"op\":\"WATCH\",\"watch_type\":\"dns\",\"watch\":\"dns=fsi.io\"}";
441 	axa_emsg_t emsg;
442 	axa_p_watch_t watch = { AXA_P_WATCH_DNS, 0, 0, 0, { .dns="\x03""fsi\x02io" } };
443 	size_t watch_len = offsetof(axa_p_watch_t, pat) + strlen((const char*)watch.pat.dns) + 1;
444 	axa_p_hdr_t hdr = { AXA_H2P32(sizeof(axa_p_hdr_t) + watch_len), 1, AXA_P_PVERS, AXA_P_OP_WATCH };
445 	char *out = NULL;
446 	axa_json_res_t res;
447 	ck_assert_int_eq(strlen((const char*)watch.pat.dns), 7);
448 	res = axa_body_to_json(&emsg, nmsg_input, &hdr, (axa_p_body_t*)&watch, watch_len, &out);
449 	ck_assert_int_eq(res, AXA_JSON_RES_SUCCESS);
450 	ck_assert_str_eq(out, expected);
451 	free(out);
452 }
453 END_TEST
454 
START_TEST(test_watch_dns_wildcard)455 START_TEST(test_watch_dns_wildcard)
456 {
457 	const char *expected = "{\"tag\":1,\"op\":\"WATCH\",\"watch_type\":\"dns\",\"watch\":\"dns=*.fsi.io\"}";
458 	axa_emsg_t emsg;
459 	axa_p_watch_t watch = { AXA_P_WATCH_DNS, 0, AXA_P_WATCH_FG_WILD, 0, { .dns="\x03""fsi\x02io" } };
460 	size_t watch_len = offsetof(axa_p_watch_t, pat) + strlen((const char*)watch.pat.dns) + 1;
461 	axa_p_hdr_t hdr = { AXA_H2P32(sizeof(axa_p_hdr_t) + watch_len), 1, AXA_P_PVERS, AXA_P_OP_WATCH };
462 	char *out = NULL;
463 	axa_json_res_t res;
464 	res = axa_body_to_json(&emsg, nmsg_input, &hdr, (axa_p_body_t*)&watch, watch_len, &out);
465 	ck_assert_int_eq(res, AXA_JSON_RES_SUCCESS);
466 	ck_assert_str_eq(out, expected);
467 	free(out);
468 }
469 END_TEST
470 
START_TEST(test_watch_dns_wildcard_all)471 START_TEST(test_watch_dns_wildcard_all)
472 {
473 	const char *expected = "{\"tag\":1,\"op\":\"WATCH\",\"watch_type\":\"dns\",\"watch\":\"dns=*.\"}";
474 	axa_emsg_t emsg;
475 	axa_p_watch_t watch = { AXA_P_WATCH_DNS, 0, AXA_P_WATCH_FG_WILD, 0, { .dns="" } };
476 	size_t watch_len = offsetof(axa_p_watch_t, pat) + strlen((const char*)watch.pat.dns) + 1;
477 	axa_p_hdr_t hdr = { AXA_H2P32(sizeof(axa_p_hdr_t) + watch_len), 1, AXA_P_PVERS, AXA_P_OP_WATCH };
478 	char *out = NULL;
479 	axa_json_res_t res;
480 	res = axa_body_to_json(&emsg, nmsg_input, &hdr, (axa_p_body_t*)&watch, watch_len, &out);
481 	ck_assert_int_eq(res, AXA_JSON_RES_SUCCESS);
482 	ck_assert_str_eq(out, expected);
483 	free(out);
484 }
485 END_TEST
486 
START_TEST(test_watch_dns_shared)487 START_TEST(test_watch_dns_shared)
488 {
489 	const char *expected = "{\"tag\":1,\"op\":\"WATCH\",\"watch_type\":\"dns\",\"watch\":\"dns=fsi.io(shared)\"}";
490 	axa_emsg_t emsg;
491 	axa_p_watch_t watch = { AXA_P_WATCH_DNS, 0, AXA_P_WATCH_FG_SHARED, 0, { .dns="\x03""fsi\x02io" } };
492 	size_t watch_len = offsetof(axa_p_watch_t, pat) + strlen((const char*)watch.pat.dns) + 1;
493 	axa_p_hdr_t hdr = { AXA_H2P32(sizeof(axa_p_hdr_t) + watch_len), 1, AXA_P_PVERS, AXA_P_OP_WATCH };
494 	char *out = NULL;
495 	axa_json_res_t res;
496 	res = axa_body_to_json(&emsg, nmsg_input, &hdr, (axa_p_body_t*)&watch, watch_len, &out);
497 	ck_assert_int_eq(res, AXA_JSON_RES_SUCCESS);
498 	ck_assert_str_eq(out, expected);
499 	free(out);
500 }
501 END_TEST
502 
START_TEST(test_watch_ch)503 START_TEST(test_watch_ch)
504 {
505 	const char *expected = "{\"tag\":1,\"op\":\"WATCH\",\"watch_type\":\"channel\",\"watch\":\"ch=ch123\"}";
506 	axa_emsg_t emsg;
507 	axa_p_watch_t watch = { AXA_P_WATCH_CH, 0, 0, 0, { .ch=123 } };
508 	size_t watch_len = offsetof(axa_p_watch_t, pat) + sizeof(axa_p_ch_t);
509 	axa_p_hdr_t hdr = { AXA_H2P32(sizeof(axa_p_hdr_t) + watch_len), 1, AXA_P_PVERS, AXA_P_OP_WATCH };
510 	char *out = NULL;
511 	axa_json_res_t res;
512 	res = axa_body_to_json(&emsg, nmsg_input, &hdr, (axa_p_body_t*)&watch, watch_len, &out);
513 	ck_assert_int_eq(res, AXA_JSON_RES_SUCCESS);
514 	ck_assert_str_eq(out, expected);
515 	free(out);
516 }
517 END_TEST
518 
START_TEST(test_watch_errors)519 START_TEST(test_watch_errors)
520 {
521 	const char *expected = "{\"tag\":1,\"op\":\"WATCH\",\"watch_type\":\"errors\",\"watch\":\"ERRORS\"}";
522 	axa_emsg_t emsg;
523 	axa_p_watch_t watch = { AXA_P_WATCH_ERRORS, 0, 0, 0, { } };
524 	size_t watch_len = offsetof(axa_p_watch_t, pat);
525 	axa_p_hdr_t hdr = { AXA_H2P32(sizeof(axa_p_hdr_t) + watch_len), 1, AXA_P_PVERS, AXA_P_OP_WATCH };
526 	char *out = NULL;
527 	axa_json_res_t res;
528 	res = axa_body_to_json(&emsg, nmsg_input, &hdr, (axa_p_body_t*)&watch, watch_len, &out);
529 	ck_assert_int_eq(res, AXA_JSON_RES_SUCCESS);
530 	ck_assert_str_eq(out, expected);
531 	free(out);
532 }
533 END_TEST
534 
START_TEST(test_watch_trunc)535 START_TEST(test_watch_trunc)
536 {
537 	truncated_test(AXA_P_OP_OPT, axa_p_opt_t, offsetof(axa_p_watch_t, pat));
538 }
539 END_TEST
540 
START_TEST(test_anom)541 START_TEST(test_anom)
542 {
543 	const char *expected = "{\"tag\":1,\"op\":\"ANOMALY\",\"an\":\"test_anom\",\"parms\":\"param1 param2\"}";
544 	axa_emsg_t emsg;
545 	axa_p_anom_t anom = { {"test_anom"}, "param1 param2" };
546 	size_t anom_len = offsetof(axa_p_anom_t, parms) + strlen(anom.parms) + 1;
547 	axa_p_hdr_t hdr = { AXA_H2P32(sizeof(axa_p_hdr_t) + anom_len), 1, AXA_P_PVERS, AXA_P_OP_ANOM };
548 	char *out = NULL;
549 	axa_json_res_t res = axa_body_to_json(&emsg, nmsg_input, &hdr, (axa_p_body_t*)&anom, anom_len, &out);
550 	ck_assert_int_eq(res, AXA_JSON_RES_SUCCESS);
551 	ck_assert_str_eq(out, expected);
552 	free(out);
553 }
554 END_TEST
555 
START_TEST(test_anom_empty)556 START_TEST(test_anom_empty)
557 {
558 	const char *expected = "{\"tag\":1,\"op\":\"ANOMALY\",\"an\":\"test_anom\"}";
559 	axa_emsg_t emsg;
560 	axa_p_anom_t anom = { {"test_anom"}, {} };
561 	size_t anom_len = offsetof(axa_p_anom_t, parms) + offsetof(axa_p_anom_t, parms);
562 	axa_p_hdr_t hdr = { AXA_H2P32(sizeof(axa_p_hdr_t) + anom_len), 1, AXA_P_PVERS, AXA_P_OP_ANOM };
563 	char *out = NULL;
564 	axa_json_res_t res = axa_body_to_json(&emsg, nmsg_input, &hdr, (axa_p_body_t*)&anom, anom_len, &out);
565 	ck_assert_int_eq(res, AXA_JSON_RES_SUCCESS);
566 	ck_assert_str_eq(out, expected);
567 	free(out);
568 }
569 END_TEST
570 
START_TEST(test_anom_trunc)571 START_TEST(test_anom_trunc)
572 {
573 	truncated_test(AXA_P_OP_ANOM, axa_p_anom_t, offsetof(axa_p_anom_t, parms) - 1);
574 }
575 END_TEST
576 
START_TEST(test_channel_on)577 START_TEST(test_channel_on)
578 {
579 	const char *expected = "{\"tag\":1,\"op\":\"CHANNEL ON/OFF\",\"channel\":\"ch123\",\"on\":true}";
580 	axa_emsg_t emsg;
581 	axa_p_hdr_t hdr = { AXA_H2P32(sizeof(axa_p_hdr_t) + sizeof(axa_p_channel_t)), 1, AXA_P_PVERS, AXA_P_OP_CHANNEL };
582 	axa_p_channel_t channel = { 123, true };
583 	char *out = NULL;
584 	axa_json_res_t res = axa_body_to_json(&emsg, nmsg_input, &hdr, (axa_p_body_t*)&channel, sizeof(channel), &out);
585 	ck_assert_int_eq(res, AXA_JSON_RES_SUCCESS);
586 	ck_assert_str_eq(out, expected);
587 	free(out);
588 }
589 END_TEST
590 
START_TEST(test_channel_off)591 START_TEST(test_channel_off)
592 {
593 	const char *expected = "{\"tag\":1,\"op\":\"CHANNEL ON/OFF\",\"channel\":\"ch123\",\"on\":false}";
594 	axa_emsg_t emsg;
595 	axa_p_hdr_t hdr = { AXA_H2P32(sizeof(axa_p_hdr_t) + sizeof(axa_p_channel_t)), 1, AXA_P_PVERS, AXA_P_OP_CHANNEL };
596 	axa_p_channel_t channel = { 123, false };
597 	char *out = NULL;
598 	axa_json_res_t res = axa_body_to_json(&emsg, nmsg_input, &hdr, (axa_p_body_t*)&channel, sizeof(channel), &out);
599 	ck_assert_int_eq(res, AXA_JSON_RES_SUCCESS);
600 	ck_assert_str_eq(out, expected);
601 	free(out);
602 }
603 END_TEST
604 
START_TEST(test_channel_all)605 START_TEST(test_channel_all)
606 {
607 	const char *expected = "{\"tag\":1,\"op\":\"CHANNEL ON/OFF\",\"channel\":\"all\",\"on\":true}";
608 	axa_emsg_t emsg;
609 	axa_p_hdr_t hdr = { AXA_H2P32(sizeof(axa_p_hdr_t) + sizeof(axa_p_channel_t)), 1, AXA_P_PVERS, AXA_P_OP_CHANNEL };
610 	axa_p_channel_t channel = { AXA_OP_CH_ALL, true };
611 	char *out = NULL;
612 	axa_json_res_t res = axa_body_to_json(&emsg, nmsg_input, &hdr, (axa_p_body_t*)&channel, sizeof(channel), &out);
613 	ck_assert_int_eq(res, AXA_JSON_RES_SUCCESS);
614 	ck_assert_str_eq(out, expected);
615 	free(out);
616 }
617 END_TEST
618 
START_TEST(test_channel_trunc)619 START_TEST(test_channel_trunc)
620 {
621 	truncated_test(AXA_P_OP_CHANNEL, axa_p_channel_t, sizeof(axa_p_channel_t) - 1);
622 }
623 END_TEST
624 
START_TEST(test_wlist)625 START_TEST(test_wlist)
626 {
627 	const char *expected = "{\"tag\":1,\"op\":\"WATCH LIST\",\"cur_tag\":1,\"watch_type\":\"ipv4\",\"watch\":\"IP=12.34.56.0/24\"}";
628 	axa_emsg_t emsg;
629 	axa_p_wlist_t wlist = { 1, {0,0}, { AXA_P_WATCH_IPV4, 24, 0, 0, {} }};
630 	size_t wlist_len = offsetof(axa_p_wlist_t, w) + offsetof(axa_p_watch_t, pat) + sizeof(struct in_addr);
631 	axa_p_hdr_t hdr = { AXA_H2P32(sizeof(axa_p_hdr_t) + wlist_len), 1, AXA_P_PVERS, AXA_P_OP_WLIST };
632 	char *out = NULL;
633 	axa_json_res_t res;
634 	struct in_addr addr;
635 
636 	ck_assert(inet_aton("12.34.56.0", &addr));
637 	memcpy(&(wlist.w.pat.addr), &addr, sizeof(wlist.w.pat.addr));
638 
639 	res = axa_body_to_json(&emsg, nmsg_input, &hdr, (axa_p_body_t*)&wlist, wlist_len, &out);
640 	ck_assert_int_eq(res, AXA_JSON_RES_SUCCESS);
641 	ck_assert_str_eq(out, expected);
642 	free(out);
643 }
644 END_TEST
645 
START_TEST(test_wlist_trunc)646 START_TEST(test_wlist_trunc)
647 {
648 	truncated_test(AXA_P_OP_OPT, axa_p_opt_t, offsetof(axa_p_wlist_t, w) + offsetof(axa_p_watch_t, pat) - 1);
649 }
650 END_TEST
651 
START_TEST(test_ahit)652 START_TEST(test_ahit)
653 {
654 	const char *expected = "{\"tag\":1,\"op\":\"ANOMALY HIT\",\"an\":\"test_anom\",\"channel\":\"ch123\",\"time\":\"1970-01-01 00:00:01.000002\",\"af\":\"IPv4\",\"src\":\"1.2.3.4\",\"dst\":\"5.6.7.8\",\"ttl\":255,\"proto\":\"UDP\",\"src_port\":123,\"dst_port\":456,\"payload\":\"3q2+7w==\"}";
655 	axa_emsg_t emsg;
656 	uint8_t packet[] = "\x45\x00\x00\x20\x12\x34\x40\x00\xff\x11\x59\x85\x01\x02\x03\x04\x05\x06\x07\x08\x00\x7b\x01\xc8\x00\x0c\x4f\xe2\xde\xad\xbe\xef";
657 	size_t ahit_len = offsetof(axa_p_ahit_t, whit) + offsetof(axa_p_whit_ip_t, b) + sizeof(packet) - 1;
658 	axa_p_ahit_t *ahit = alloca(ahit_len);
659 	axa_p_ahit_t ahit_data = { .an={"test_anom"} };
660 	axa_p_whit_ip_t whit_data = { .hdr={
661 		.hdr = { .ch=123, .type=AXA_P_WHIT_IP },
662 		.tv = { 1, 2 },
663 		.ip_len = sizeof(packet),
664 	}};
665 	axa_p_hdr_t hdr = { AXA_H2P32(sizeof(axa_p_hdr_t) + ahit_len), 1, AXA_P_PVERS, AXA_P_OP_AHIT };
666 	char *out = NULL;
667 	axa_json_res_t res;
668 
669 	ahit_data.whit.ip = whit_data;
670 	*ahit = ahit_data;
671 	memcpy(&(ahit->whit.ip.b), packet, sizeof(packet) - 1);
672 
673 	res = axa_body_to_json(&emsg, nmsg_input, &hdr, (axa_p_body_t*)ahit, ahit_len, &out);
674 	ck_assert_int_eq(res, AXA_JSON_RES_SUCCESS);
675 	ck_assert_str_eq(out, expected);
676 	free(out);
677 }
678 END_TEST
679 
START_TEST(test_ahit_trunc)680 START_TEST(test_ahit_trunc)
681 {
682 	truncated_test(AXA_P_OP_AHIT, axa_p_ahit_t, offsetof(axa_p_ahit_t, whit) + sizeof(axa_p_whit_hdr_t) - 1);
683 }
684 END_TEST
685 
START_TEST(test_alist)686 START_TEST(test_alist)
687 {
688 	const char *expected = "{\"tag\":1,\"op\":\"ANOMALY LIST\",\"cur_tag\":1,\"an\":\"test_anom\",\"parms\":\"param1 param2\"}";
689 	axa_emsg_t emsg;
690 	axa_p_alist_t alist = { .cur_tag=1, .anom={ {"test_anom"}, "param1 param2" } };
691 	size_t alist_len = offsetof(axa_p_alist_t, anom) + offsetof(axa_p_anom_t, parms) + strlen(alist.anom.parms) + 1;
692 	axa_p_hdr_t hdr = { AXA_H2P32(sizeof(axa_p_hdr_t) + alist_len), 1, AXA_P_PVERS, AXA_P_OP_ALIST };
693 	char *out = NULL;
694 	axa_json_res_t res = axa_body_to_json(&emsg, nmsg_input, &hdr, (axa_p_body_t*)&alist, alist_len, &out);
695 	ck_assert_int_eq(res, AXA_JSON_RES_SUCCESS);
696 	ck_assert_str_eq(out, expected);
697 	free(out);
698 }
699 END_TEST
700 
START_TEST(test_alist_trunc)701 START_TEST(test_alist_trunc)
702 {
703 	truncated_test(AXA_P_OP_ALIST, axa_p_alist_t, offsetof(axa_p_alist_t, anom) + offsetof(axa_p_anom_t, parms) - 1);
704 }
705 END_TEST
706 
START_TEST(test_clist)707 START_TEST(test_clist)
708 {
709 	const char *expected = "{\"tag\":1,\"op\":\"CHANNEL LIST\",\"channel\":\"ch123\",\"on\":true,\"spec\":\"test channel\"}";
710 	axa_emsg_t emsg;
711 	axa_p_hdr_t hdr = { AXA_H2P32(sizeof(axa_p_hdr_t) + sizeof(axa_p_clist_t)), 1, AXA_P_PVERS, AXA_P_OP_CLIST };
712 	axa_p_clist_t clist = { 123, true, {"test channel"} };
713 	char *out = NULL;
714 	axa_json_res_t res = axa_body_to_json(&emsg, nmsg_input, &hdr, (axa_p_body_t*)&clist, sizeof(clist), &out);
715 	ck_assert_int_eq(res, AXA_JSON_RES_SUCCESS);
716 	ck_assert_str_eq(out, expected);
717 	free(out);
718 }
719 END_TEST
720 
START_TEST(test_clist_trunc)721 START_TEST(test_clist_trunc)
722 {
723 	truncated_test(AXA_P_OP_CLIST, axa_p_clist_t, sizeof(axa_p_clist_t) - 1);
724 }
725 END_TEST
726 
START_TEST(test_user)727 START_TEST(test_user)
728 {
729 	const char *expected = "{\"tag\":1,\"op\":\"USER\",\"name\":\"test user\"}";
730 	axa_emsg_t emsg;
731 	axa_p_hdr_t hdr = { AXA_H2P32(sizeof(axa_p_hdr_t) + sizeof(axa_p_user_t)), 1, AXA_P_PVERS, AXA_P_OP_USER };
732 	axa_p_user_t user = { {"test user"} };
733 	char *out = NULL;
734 	axa_json_res_t res = axa_body_to_json(&emsg, nmsg_input, &hdr, (axa_p_body_t*)&user, sizeof(user), &out);
735 	ck_assert_int_eq(res, AXA_JSON_RES_SUCCESS);
736 	ck_assert_str_eq(out, expected);
737 	free(out);
738 }
739 END_TEST
740 
START_TEST(test_user_trunc)741 START_TEST(test_user_trunc)
742 {
743 	truncated_test(AXA_P_OP_USER, axa_p_user_t, 0);
744 }
745 END_TEST
746 
START_TEST(test_opt_trace)747 START_TEST(test_opt_trace)
748 {
749 	const char *expected = "{\"tag\":1,\"op\":\"OPTION\",\"type\":\"TRACE\",\"trace\":3}";
750 	axa_emsg_t emsg;
751 	axa_p_opt_t opt = { AXA_P_OPT_TRACE, {}, { .trace=AXA_H2P32(AXA_DEBUG_TRACE) } };
752 	size_t watch_len = offsetof(axa_p_opt_t, u) + sizeof(opt.u.trace);
753 	axa_p_hdr_t hdr = { AXA_H2P32(sizeof(axa_p_hdr_t) + watch_len), 1, AXA_P_PVERS, AXA_P_OP_OPT };
754 	char *out = NULL;
755 	axa_json_res_t res = axa_body_to_json(&emsg, nmsg_input, &hdr, (axa_p_body_t*)&opt, watch_len, &out);
756 	ck_assert_int_eq(res, AXA_JSON_RES_SUCCESS);
757 	ck_assert_str_eq(out, expected);
758 	free(out);
759 }
760 END_TEST
761 
START_TEST(test_opt_trace_req)762 START_TEST(test_opt_trace_req)
763 {
764 	const char *expected = "{\"tag\":1,\"op\":\"OPTION\",\"type\":\"TRACE\",\"trace\":\"REQUEST TRACE VALUE\"}";
765 	axa_emsg_t emsg;
766 	axa_p_opt_t opt = { AXA_P_OPT_TRACE, {}, { .trace=AXA_H2P32(AXA_P_OPT_TRACE_REQ) } };
767 	size_t watch_len = offsetof(axa_p_opt_t, u) + sizeof(opt.u.trace);
768 	axa_p_hdr_t hdr = { AXA_H2P32(sizeof(axa_p_hdr_t) + watch_len), 1, AXA_P_PVERS, AXA_P_OP_OPT };
769 	char *out = NULL;
770 	axa_json_res_t res = axa_body_to_json(&emsg, nmsg_input, &hdr, (axa_p_body_t*)&opt, watch_len, &out);
771 	ck_assert_int_eq(res, AXA_JSON_RES_SUCCESS);
772 	ck_assert_str_eq(out, expected);
773 	free(out);
774 }
775 END_TEST
776 
START_TEST(test_opt_rlimit_num)777 START_TEST(test_opt_rlimit_num)
778 {
779 	const char *expected = "{\"tag\":1,\"op\":\"OPTION\",\"type\":\"RATE LIMIT\",\"max_pkts_per_sec\":123,\"cur_pkts_per_sec\":456,\"report_secs\":60}";
780 	axa_emsg_t emsg;
781 	axa_p_opt_t opt = { AXA_P_OPT_RLIMIT, {}, { .rlimit={
782 		.max_pkts_per_sec=AXA_H2P64(123),
783 		.cur_pkts_per_sec=AXA_H2P64(456),
784 		.report_secs=AXA_H2P64(60),
785 	} } };
786 	size_t watch_len = offsetof(axa_p_opt_t, u) + sizeof(opt.u.rlimit);
787 	axa_p_hdr_t hdr = { AXA_H2P32(sizeof(axa_p_hdr_t) + watch_len), 1, AXA_P_PVERS, AXA_P_OP_OPT };
788 	char *out = NULL;
789 	axa_json_res_t res = axa_body_to_json(&emsg, nmsg_input, &hdr, (axa_p_body_t*)&opt, watch_len, &out);
790 	ck_assert_int_eq(res, AXA_JSON_RES_SUCCESS);
791 	ck_assert_str_eq(out, expected);
792 	free(out);
793 }
794 END_TEST
795 
START_TEST(test_opt_rlimit_max)796 START_TEST(test_opt_rlimit_max)
797 {
798 	const char *expected = "{\"tag\":1,\"op\":\"OPTION\",\"type\":\"RATE LIMIT\",\"max_pkts_per_sec\":1000000000,\"cur_pkts_per_sec\":123,\"report_secs\":60}";
799 	axa_emsg_t emsg;
800 	axa_p_opt_t opt = { AXA_P_OPT_RLIMIT, {}, { .rlimit={
801 		.max_pkts_per_sec=AXA_H2P64(AXA_RLIMIT_MAX),
802 		.cur_pkts_per_sec=AXA_H2P64(123),
803 		.report_secs=AXA_H2P64(60),
804 	} } };
805 	size_t watch_len = offsetof(axa_p_opt_t, u) + sizeof(opt.u.rlimit);
806 	axa_p_hdr_t hdr = { AXA_H2P32(sizeof(axa_p_hdr_t) + watch_len), 1, AXA_P_PVERS, AXA_P_OP_OPT };
807 	char *out = NULL;
808 	axa_json_res_t res = axa_body_to_json(&emsg, nmsg_input, &hdr, (axa_p_body_t*)&opt, watch_len, &out);
809 	ck_assert_int_eq(res, AXA_JSON_RES_SUCCESS);
810 	ck_assert_str_eq(out, expected);
811 	free(out);
812 }
813 END_TEST
814 
START_TEST(test_opt_rlimit_off)815 START_TEST(test_opt_rlimit_off)
816 {
817 	const char *expected = "{\"tag\":1,\"op\":\"OPTION\",\"type\":\"RATE LIMIT\",\"max_pkts_per_sec\":\"off\",\"cur_pkts_per_sec\":123,\"report_secs\":60}";
818 	axa_emsg_t emsg;
819 	axa_p_opt_t opt = { AXA_P_OPT_RLIMIT, {}, { .rlimit={
820 		.max_pkts_per_sec=AXA_H2P64(AXA_RLIMIT_OFF),
821 		.cur_pkts_per_sec=AXA_H2P64(123),
822 		.report_secs=AXA_H2P64(60),
823 	} } };
824 	size_t watch_len = offsetof(axa_p_opt_t, u) + sizeof(opt.u.rlimit);
825 	axa_p_hdr_t hdr = { AXA_H2P32(sizeof(axa_p_hdr_t) + watch_len), 1, AXA_P_PVERS, AXA_P_OP_OPT };
826 	char *out = NULL;
827 	axa_json_res_t res = axa_body_to_json(&emsg, nmsg_input, &hdr, (axa_p_body_t*)&opt, watch_len, &out);
828 	ck_assert_int_eq(res, AXA_JSON_RES_SUCCESS);
829 	ck_assert_str_eq(out, expected);
830 	free(out);
831 }
832 END_TEST
833 
START_TEST(test_opt_rlimit_na)834 START_TEST(test_opt_rlimit_na)
835 {
836 	const char *expected = "{\"tag\":1,\"op\":\"OPTION\",\"type\":\"RATE LIMIT\",\"max_pkts_per_sec\":null,\"cur_pkts_per_sec\":123,\"report_secs\":null}";
837 	axa_emsg_t emsg;
838 	axa_p_opt_t opt = { AXA_P_OPT_RLIMIT, {}, { .rlimit={
839 		.max_pkts_per_sec=AXA_H2P64(AXA_RLIMIT_NA),
840 		.cur_pkts_per_sec=AXA_H2P64(123),
841 		.report_secs=AXA_H2P64(AXA_RLIMIT_NA),
842 	} } };
843 	size_t watch_len = offsetof(axa_p_opt_t, u) + sizeof(opt.u.rlimit);
844 	axa_p_hdr_t hdr = { AXA_H2P32(sizeof(axa_p_hdr_t) + watch_len), 1, AXA_P_PVERS, AXA_P_OP_OPT };
845 	char *out = NULL;
846 	axa_json_res_t res = axa_body_to_json(&emsg, nmsg_input, &hdr, (axa_p_body_t*)&opt, watch_len, &out);
847 	ck_assert_int_eq(res, AXA_JSON_RES_SUCCESS);
848 	ck_assert_str_eq(out, expected);
849 	free(out);
850 }
851 END_TEST
852 
853 
START_TEST(test_opt_sample)854 START_TEST(test_opt_sample)
855 {
856 	const char *expected = "{\"tag\":1,\"op\":\"OPTION\",\"type\":\"SAMPLE\",\"sample\":0.000123}";
857 	axa_emsg_t emsg;
858 	axa_p_opt_t opt = { AXA_P_OPT_SAMPLE, {}, { .sample=AXA_H2P32(123) } };
859 	size_t watch_len = offsetof(axa_p_opt_t, u) + sizeof(opt.u.sample);
860 	axa_p_hdr_t hdr = { AXA_H2P32(sizeof(axa_p_hdr_t) + watch_len), 1, AXA_P_PVERS, AXA_P_OP_OPT };
861 	char *out = NULL;
862 	axa_json_res_t res = axa_body_to_json(&emsg, nmsg_input, &hdr, (axa_p_body_t*)&opt, watch_len, &out);
863 	ck_assert_int_eq(res, AXA_JSON_RES_SUCCESS);
864 	ck_assert_str_eq(out, expected);
865 	free(out);
866 }
867 END_TEST
868 
START_TEST(test_opt_sndbuf)869 START_TEST(test_opt_sndbuf)
870 {
871 	const char *expected = "{\"tag\":1,\"op\":\"OPTION\",\"type\":\"SNDBUF\",\"bufsize\":123}";
872 	axa_emsg_t emsg;
873 	axa_p_opt_t opt = { AXA_P_OPT_SNDBUF, {}, { .bufsize=AXA_H2P32(123) } };
874 	size_t watch_len = offsetof(axa_p_opt_t, u) + sizeof(opt.u.bufsize);
875 	axa_p_hdr_t hdr = { AXA_H2P32(sizeof(axa_p_hdr_t) + watch_len), 1, AXA_P_PVERS, AXA_P_OP_OPT };
876 	char *out = NULL;
877 	axa_json_res_t res = axa_body_to_json(&emsg, nmsg_input, &hdr, (axa_p_body_t*)&opt, watch_len, &out);
878 	ck_assert_int_eq(res, AXA_JSON_RES_SUCCESS);
879 	ck_assert_str_eq(out, expected);
880 	free(out);
881 }
882 END_TEST
883 
START_TEST(test_opt_trunc)884 START_TEST(test_opt_trunc)
885 {
886 	truncated_test(AXA_P_OP_OPT, axa_p_opt_t, offsetof(axa_p_opt_t, u));
887 }
888 END_TEST
889 
START_TEST(test_join)890 START_TEST(test_join)
891 {
892 	axa_p_join_t join = { 0 };
893 	size_t watch_len = sizeof(axa_p_join_t);
894 	axa_p_hdr_t hdr = { AXA_H2P32(sizeof(axa_p_hdr_t) + watch_len), AXA_H2P_TAG(0), AXA_P_PVERS, AXA_P_OP_JOIN };
895 	char *out = NULL;
896 	axa_json_res_t res;
897 	axa_emsg_t emsg;
898 	res = axa_body_to_json(&emsg, nmsg_input, &hdr, (axa_p_body_t*)&join, watch_len, &out);
899 	ck_assert_int_eq(res, AXA_JSON_RES_SUCCESS);
900 	ck_assert_str_eq(out, "{\"tag\":\"*\",\"op\":\"JOIN\",\"id\":0}");
901 	free(out);
902 }
903 END_TEST
904 
START_TEST(test_join_trunc)905 START_TEST(test_join_trunc)
906 {
907 	truncated_test(AXA_P_OP_JOIN, axa_p_join_t, sizeof(axa_p_join_t) - 1);
908 }
909 END_TEST
910 
START_TEST(test_pause)911 START_TEST(test_pause)
912 {
913 	empty_test(AXA_P_OP_PAUSE, "PAUSE");
914 }
915 END_TEST
916 
START_TEST(test_go)917 START_TEST(test_go)
918 {
919 	empty_test(AXA_P_OP_GO, "GO");
920 }
921 END_TEST
922 
START_TEST(test_wget)923 START_TEST(test_wget)
924 {
925 	empty_test(AXA_P_OP_WGET, "WATCH GET");
926 }
927 END_TEST
928 
START_TEST(test_aget)929 START_TEST(test_aget)
930 {
931 	empty_test(AXA_P_OP_AGET, "ANOMALY GET");
932 }
933 END_TEST
934 
START_TEST(test_stop)935 START_TEST(test_stop)
936 {
937 	empty_test(AXA_P_OP_STOP, "STOP");
938 }
939 END_TEST
940 
START_TEST(test_all_stop)941 START_TEST(test_all_stop)
942 {
943 	empty_test(AXA_P_OP_ALL_STOP, "ALL STOP");
944 }
945 END_TEST
946 
START_TEST(test_cget)947 START_TEST(test_cget)
948 {
949 	empty_test(AXA_P_OP_CGET, "CHANNEL GET");
950 }
951 END_TEST
952 
START_TEST(test_acct)953 START_TEST(test_acct)
954 {
955 	empty_test(AXA_P_OP_ACCT, "ACCOUNTING");
956 }
957 END_TEST
958 
START_TEST(test_radu)959 START_TEST(test_radu)
960 {
961 	empty_test(AXA_P_OP_RADU, "RAD UNITS GET");
962 }
963 END_TEST
964 
START_TEST(test_stats_req)965 START_TEST(test_stats_req)
966 {
967 	const char *expected ="{\"tag\":\"*\",\"op\":\"STATS REQ\",\"version\":1,\"type\":\"all\"}";
968 	axa_emsg_t emsg;
969 	axa_p_hdr_t hdr;
970 	_axa_p_stats_req_t stats_req;
971 	uint8_t stats[sizeof(_axa_p_stats_req_t)];
972 	axa_json_res_t res;
973 	char *out = NULL;
974 
975 	memset(&hdr, 0, sizeof (hdr));
976 	memset(&stats_req, 0, sizeof (stats_req));
977 
978 	hdr.len = AXA_H2P32(sizeof(axa_p_hdr_t) + sizeof (stats_req));
979 	hdr.tag = AXA_H2P_TAG(0);
980 	hdr.pvers = AXA_P_PVERS;
981 	hdr.op = _AXA_P_OP_STATS_REQ;
982 
983 	stats_req.version = _AXA_STATS_VERSION_ONE;
984 	stats_req.type = AXA_P_STATS_M_M_ALL;
985 
986 	memcpy(stats, (uint8_t *)&stats_req, sizeof (stats_req));
987 
988 	res = axa_body_to_json(&emsg, nmsg_input, &hdr,
989 			(axa_p_body_t *)&stats_req, sizeof (stats_req), &out);
990 	ck_assert_int_eq(res, AXA_JSON_RES_SUCCESS);
991 	ck_assert_str_eq(out, expected);
992 	free(out);
993 }
994 END_TEST
995 
START_TEST(test_stats_rsp_sra_one_user)996 START_TEST(test_stats_rsp_sra_one_user)
997 {
998 	const char *expected = "{\"tag\":\"*\",\"op\":\"STATS RSP\",\"version\":1,\"result\":\"success\",\"load\":[6700,7900,8300],\"cpu_usage\":5144,\"uptime\":19287627,\"starttime\":19279187,\"vmsize\":1428819968,\"vmrss\":21204992,\"thread_cnt\":145,\"user_cnt\":1,\"server_type\":\"sra\",\"fd_sockets\":13,\"fd_pipes\":3,\"fd_anon_inodes\":0,\"fd_other\":5,\"rchar\":17362446,\"wchar\":755982917,\"sra_ipv4_watch_cnt\":0,\"sra_ipv6_watch_cnt\":0,\"sra_dns_watch_cnt\":0,\"sra_ch_watch_cnt\":0,\"sra_err_watch_cnt\":0,\"sra_channels\":[\"ch213\",\"ch255\"],\"users\":[\"user_obj\",{\"server_type\":\"sra\",\"user\":\"mschiffm\",\"is_admin\":true,\"io_type\":\"apikey\",\"address\":\"73.170.71.223\",\"sn\":251,\"connected_since\":\"2018-01-03T23:50:00Z\",\"ratelimit\":0,\"sample\":100.00,\"last_count_update\":\"2018-01-03T23:50:00Z\",\"filtered\":0,\"missed\":0,\"collected\":0,\"sent\":0,\"rlimit\":0,\"congested\":0,\"ipv4_watch_cnt\":0,\"ipv6_watch_cnt\":0,\"dns_watch_cnt\":0,\"ch_watch_cnt\":0,\"err_watch_cnt\":0,\"channels\":[\"ch255\"]}]}";
999 	axa_emsg_t emsg;
1000 	axa_p_hdr_t hdr;
1001 	_axa_p_stats_rsp_t stats_rsp;
1002 	_axa_p_stats_sys_t stats_sys;
1003 	_axa_p_stats_user_t stats_users[1];
1004 	size_t stats_len = sizeof (stats_rsp) + sizeof (stats_sys)
1005 		+ sizeof (stats_users);
1006 	uint8_t stats[stats_len];
1007 	axa_json_res_t res;
1008 	char *out = NULL;
1009 
1010 	memset(&hdr, 0, sizeof (hdr));
1011 	memset(&stats_rsp, 0, sizeof (stats_rsp));
1012 	memset(&stats_sys, 0, sizeof (stats_sys));
1013 	memset(&stats_users, 0, sizeof (stats_users));
1014 
1015 	hdr.len = AXA_H2P32(sizeof(axa_p_hdr_t) + stats_len);
1016 	hdr.tag = AXA_H2P_TAG(0);
1017 	hdr.pvers = AXA_P_PVERS;
1018 	hdr.op = _AXA_P_OP_STATS_RSP;
1019 
1020 	stats_rsp.version = _AXA_STATS_VERSION_ONE;
1021 	stats_rsp.sys_objs_cnt = 1;
1022 	stats_rsp.user_objs_cnt = 1;
1023 	stats_rsp.result = AXA_P_STATS_R_SUCCESS;
1024 
1025 	stats_sys.type = _AXA_P_STATS_TYPE_SYS;
1026 	stats_sys.server_type = _AXA_STATS_SRVR_TYPE_SRA;
1027 	stats_sys.load[0] = 6700;
1028 	stats_sys.load[1] = 7900;
1029 	stats_sys.load[2] = 8300;
1030 	stats_sys.cpu_usage = 5144;
1031 	stats_sys.uptime = 19287627;
1032 	stats_sys.starttime = 19279187;
1033 	stats_sys.fd_sockets = 13;
1034 	stats_sys.fd_pipes = 3;
1035 	stats_sys.fd_anon_inodes = 0;
1036 	stats_sys.fd_other = 5;
1037 	stats_sys.vmsize = 1428819968;
1038 	stats_sys.vmrss = 21204992;
1039 	stats_sys.rchar = 17362446;
1040 	stats_sys.wchar = 755982917;
1041 	stats_sys.thread_cnt = 145;
1042 	stats_sys.user_cnt = 1;
1043 	stats_sys.srvr.sra.watches.ipv4_cnt = 0;
1044 	stats_sys.srvr.sra.watches.ipv6_cnt = 0;
1045 	stats_sys.srvr.sra.watches.dns_cnt = 0;
1046 	stats_sys.srvr.sra.watches.ch_cnt = 0;
1047 	stats_sys.srvr.sra.watches.err_cnt = 0;
1048 	axa_set_bitwords(stats_sys.srvr.sra.ch_mask.m, 213);
1049 	axa_set_bitwords(stats_sys.srvr.sra.ch_mask.m, 255);
1050 
1051 	stats_users[0].type = _AXA_P_STATS_TYPE_USER;
1052 	stats_users[0].server_type = _AXA_STATS_SRVR_TYPE_SRA;
1053 	strcpy(stats_users[0].user.name, "mschiffm");
1054 	stats_users[0].is_admin = 1;
1055 	stats_users[0].io_type = AXA_IO_TYPE_APIKEY;
1056 	stats_users[0].addr_type = AXA_AF_INET;
1057 	stats_users[0].ip.ipv4 = inet_addr("73.170.71.223");
1058 	stats_users[0].sn = 251;
1059 	stats_users[0].connected_since.tv_sec = 1515023400;
1060 	stats_users[0].ratelimit = 0;
1061 	stats_users[0].sample = 100;
1062 	stats_users[0].last_cnt_update.tv_sec = 1515023400;
1063 	stats_users[0].filtered = 0;
1064 	stats_users[0].missed = 0;
1065 	stats_users[0].collected = 0;
1066 	stats_users[0].sent = 0;
1067 	stats_users[0].rlimit = 0;
1068 	stats_users[0].congested = 0;
1069 	axa_set_bitwords(stats_users[0].srvr.sra.ch_mask.m, 255);
1070 	stats_users[0].srvr.sra.watches.ipv4_cnt = 0;
1071 	stats_users[0].srvr.sra.watches.ipv6_cnt = 0;
1072 	stats_users[0].srvr.sra.watches.dns_cnt = 0;
1073 	stats_users[0].srvr.sra.watches.ch_cnt = 0;
1074 	stats_users[0].srvr.sra.watches.err_cnt = 0;
1075 
1076 	memcpy((uint8_t *)stats, (uint8_t *)&stats_rsp, sizeof (stats_rsp));
1077 	memcpy((uint8_t *)stats + sizeof (stats_rsp), (uint8_t *)&stats_sys,
1078 			sizeof (stats_sys));
1079 	memcpy((uint8_t *)stats + sizeof (stats_rsp) + sizeof (stats_sys),
1080 			(uint8_t *)&stats_users, sizeof (stats_users));
1081 
1082 	res = axa_body_to_json(&emsg, nmsg_input, &hdr,
1083 			(axa_p_body_t *)stats, stats_len, &out);
1084 	ck_assert_int_eq(res, AXA_JSON_RES_SUCCESS);
1085 	ck_assert_str_eq(out, expected);
1086 	free(out);
1087 }
1088 END_TEST
1089 
START_TEST(test_stats_rsp_rad_one_user)1090 START_TEST(test_stats_rsp_rad_one_user)
1091 {
1092 	const char *expected = "{\"tag\":\"*\",\"op\":\"STATS RSP\",\"version\":1,\"result\":\"success\",\"load\":[6300,6200,7100],\"cpu_usage\":0,\"uptime\":19449048,\"starttime\":19373104,\"vmsize\":91680768,\"vmrss\":4968448,\"thread_cnt\":2,\"user_cnt\":1,\"server_type\":\"rad\",\"rad_anomaly_cnt\":0,\"users\":[\"user_obj\",{\"server_type\":\"rad\",\"user\":\"mschiffm\",\"is_admin\":true,\"io_type\":\"apikey\",\"address\":\"73.170.71.223\",\"sn\":2,\"connected_since\":\"2018-01-05T20:40:31Z\",\"ratelimit\":0,\"sample\":100.00,\"last_count_update\":\"2018-01-05T20:40:31Z\",\"filtered\":0,\"missed\":0,\"collected\":0,\"sent\":0,\"rlimit\":0,\"congested\":0,\"anomaly_count_in_flight\":0,\"anomaly_count_total\":0}]}";
1093 	axa_emsg_t emsg;
1094 	axa_p_hdr_t hdr;
1095 	_axa_p_stats_rsp_t stats_rsp;
1096 	_axa_p_stats_sys_t stats_sys;
1097 	_axa_p_stats_user_t stats_users[1];
1098 	size_t stats_len = sizeof (stats_rsp) + sizeof (stats_sys)
1099 		+ sizeof (stats_users);
1100 	uint8_t stats[stats_len];
1101 	axa_json_res_t res;
1102 	char *out = NULL;
1103 
1104 	memset(&hdr, 0, sizeof (hdr));
1105 	memset(&stats_rsp, 0, sizeof (stats_rsp));
1106 	memset(&stats_sys, 0, sizeof (stats_sys));
1107 	memset(&stats_users, 0, sizeof (stats_users));
1108 
1109 	hdr.len = AXA_H2P32(sizeof(axa_p_hdr_t) + stats_len);
1110 	hdr.tag = AXA_H2P_TAG(0);
1111 	hdr.pvers = AXA_P_PVERS;
1112 	hdr.op = _AXA_P_OP_STATS_RSP;
1113 
1114 	stats_rsp.version = _AXA_STATS_VERSION_ONE;
1115 	stats_rsp.sys_objs_cnt = 1;
1116 	stats_rsp.user_objs_cnt = 1;
1117 	stats_rsp.result = AXA_P_STATS_R_SUCCESS;
1118 
1119 	stats_sys.type = _AXA_P_STATS_TYPE_SYS;
1120 	stats_sys.server_type = _AXA_STATS_SRVR_TYPE_RAD;
1121 	stats_sys.load[0] = 6300;
1122 	stats_sys.load[1] = 6200;
1123 	stats_sys.load[2] = 7100;
1124 	stats_sys.cpu_usage = 0;
1125 	stats_sys.uptime = 19449048;
1126 	stats_sys.starttime = 19373104;
1127 	stats_sys.fd_sockets = 91680768;
1128 	stats_sys.fd_pipes = 4968448;
1129 	stats_sys.vmsize = 91680768;
1130 	stats_sys.vmrss = 4968448;
1131 	stats_sys.thread_cnt = 2;
1132 	stats_sys.user_cnt = 1;
1133 	stats_sys.srvr.rad.an_cnt = 0;
1134 
1135 	stats_users[0].type = _AXA_P_STATS_TYPE_USER;
1136 	stats_users[0].server_type = _AXA_STATS_SRVR_TYPE_RAD;
1137 	strcpy(stats_users[0].user.name, "mschiffm");
1138 	stats_users[0].is_admin = 1;
1139 	stats_users[0].io_type = AXA_IO_TYPE_APIKEY;
1140 	stats_users[0].addr_type = AXA_AF_INET;
1141 	stats_users[0].ip.ipv4 = inet_addr("73.170.71.223");
1142 	stats_users[0].sn = 2;
1143 	stats_users[0].connected_since.tv_sec = 1515184831;
1144 	stats_users[0].ratelimit = 0;
1145 	stats_users[0].sample = 100;
1146 	stats_users[0].last_cnt_update.tv_sec = 1515184831;
1147 	stats_users[0].filtered = 0;
1148 	stats_users[0].missed = 0;
1149 	stats_users[0].collected = 0;
1150 	stats_users[0].sent = 0;
1151 	stats_users[0].rlimit = 0;
1152 	stats_users[0].congested = 0;
1153 	stats_users[0].srvr.rad.an_obj_cnt = 0;
1154 	stats_users[0].srvr.rad.an_obj_cnt_total = 0;
1155 
1156 	memcpy((uint8_t *)stats, (uint8_t *)&stats_rsp, sizeof (stats_rsp));
1157 	memcpy((uint8_t *)stats + sizeof (stats_rsp), (uint8_t *)&stats_sys,
1158 			sizeof (stats_sys));
1159 	memcpy((uint8_t *)stats + sizeof (stats_rsp) + sizeof (stats_sys),
1160 			(uint8_t *)&stats_users, sizeof (stats_users));
1161 
1162 	res = axa_body_to_json(&emsg, nmsg_input, &hdr,
1163 			(axa_p_body_t *)stats, stats_len, &out);
1164 	ck_assert_int_eq(res, AXA_JSON_RES_SUCCESS);
1165 	ck_assert_str_eq(out, expected);
1166 	free(out);
1167 }
1168 END_TEST
1169 
START_TEST(test_stats_rsp_rad_one_user_one_anomaly)1170 START_TEST(test_stats_rsp_rad_one_user_one_anomaly)
1171 {
1172 	const char *expected = "{\"tag\":\"*\",\"op\":\"STATS RSP\",\"version\":1,\"result\":\"success\",\"load\":[6300,6200,7100],\"cpu_usage\":0,\"uptime\":19449048,\"starttime\":19373104,\"vmsize\":91680768,\"vmrss\":4968448,\"thread_cnt\":2,\"user_cnt\":1,\"server_type\":\"rad\",\"rad_anomaly_cnt\":1,\"users\":[\"user_obj\",{\"server_type\":\"rad\",\"user\":\"mschiffm\",\"is_admin\":true,\"io_type\":\"apikey\",\"address\":\"73.170.71.223\",\"sn\":2,\"connected_since\":\"2018-01-05T20:40:31Z\",\"ratelimit\":0,\"sample\":100.00,\"last_count_update\":\"2018-01-05T20:40:31Z\",\"filtered\":0,\"missed\":0,\"collected\":0,\"sent\":0,\"rlimit\":0,\"congested\":0,\"anomaly_count_in_flight\":1,\"anomaly_count_total\":1,\"anomalies\":[\"an_obj\",{\"name\":\"brand_sentry\",\"options\":\"b=farsight,fsi;m=hgl,lit\",\"ru_original\":\"unlimited\",\"ru_current\":\"unlimited\",\"ru_cost\":0,\"channels\":[\"ch204\"]}]}]}";
1173 	axa_emsg_t emsg;
1174 	axa_p_hdr_t hdr;
1175 	_axa_p_stats_rsp_t stats_rsp;
1176 	_axa_p_stats_sys_t stats_sys;
1177 	_axa_p_stats_user_t stats_users[1];
1178 	_axa_p_stats_user_rad_an_t an_obj;
1179 	size_t stats_len = sizeof (stats_rsp) + sizeof (stats_sys)
1180 		+ sizeof (stats_users) + sizeof (an_obj);
1181 	uint8_t stats[stats_len];
1182 	axa_json_res_t res;
1183 	char *out = NULL;
1184 
1185 	memset(&hdr, 0, sizeof (hdr));
1186 	memset(&stats_rsp, 0, sizeof (stats_rsp));
1187 	memset(&stats_sys, 0, sizeof (stats_sys));
1188 	memset(&stats_users, 0, sizeof (stats_users));
1189 	memset(&an_obj, 0, sizeof (an_obj));
1190 
1191 	hdr.len = AXA_H2P32(sizeof(axa_p_hdr_t) + stats_len);
1192 	hdr.tag = AXA_H2P_TAG(0);
1193 	hdr.pvers = AXA_P_PVERS;
1194 	hdr.op = _AXA_P_OP_STATS_RSP;
1195 
1196 	stats_rsp.version = _AXA_STATS_VERSION_ONE;
1197 	stats_rsp.sys_objs_cnt = 1;
1198 	stats_rsp.user_objs_cnt = 1;
1199 	stats_rsp.result = AXA_P_STATS_R_SUCCESS;
1200 
1201 	stats_sys.type = _AXA_P_STATS_TYPE_SYS;
1202 	stats_sys.server_type = _AXA_STATS_SRVR_TYPE_RAD;
1203 	stats_sys.load[0] = 6300;
1204 	stats_sys.load[1] = 6200;
1205 	stats_sys.load[2] = 7100;
1206 	stats_sys.cpu_usage = 0;
1207 	stats_sys.uptime = 19449048;
1208 	stats_sys.starttime = 19373104;
1209 	stats_sys.vmsize = 91680768;
1210 	stats_sys.vmrss = 4968448;
1211 	stats_sys.thread_cnt = 2;
1212 	stats_sys.user_cnt = 1;
1213 	stats_sys.srvr.rad.an_cnt = 1;
1214 
1215 	stats_users[0].type = _AXA_P_STATS_TYPE_USER;
1216 	stats_users[0].server_type = _AXA_STATS_SRVR_TYPE_RAD;
1217 	strcpy(stats_users[0].user.name, "mschiffm");
1218 	stats_users[0].is_admin = 1;
1219 	stats_users[0].io_type = AXA_IO_TYPE_APIKEY;
1220 	stats_users[0].addr_type = AXA_AF_INET;
1221 	stats_users[0].ip.ipv4 = inet_addr("73.170.71.223");
1222 	stats_users[0].sn = 2;
1223 	stats_users[0].connected_since.tv_sec = 1515184831;
1224 	stats_users[0].ratelimit = 0;
1225 	stats_users[0].sample = 100;
1226 	stats_users[0].last_cnt_update.tv_sec = 1515184831;
1227 	stats_users[0].filtered = 0;
1228 	stats_users[0].missed = 0;
1229 	stats_users[0].collected = 0;
1230 	stats_users[0].sent = 0;
1231 	stats_users[0].rlimit = 0;
1232 	stats_users[0].congested = 0;
1233 	stats_users[0].srvr.rad.an_obj_cnt = 1;
1234 	stats_users[0].srvr.rad.an_obj_cnt_total = 1;
1235 
1236 	strcpy(an_obj.name, "brand_sentry");
1237 	strcpy(an_obj.opt, "b=farsight,fsi;m=hgl,lit");
1238 	an_obj.ru_original = INT_MAX;
1239 	an_obj.ru_current = INT_MAX;
1240 	an_obj.ru_cost = 0;
1241 	axa_set_bitwords(an_obj.ch_mask.m, 204);
1242 
1243 	memcpy((uint8_t *)stats, (uint8_t *)&stats_rsp, sizeof (stats_rsp));
1244 	memcpy((uint8_t *)stats + sizeof (stats_rsp), (uint8_t *)&stats_sys,
1245 			sizeof (stats_sys));
1246 	memcpy((uint8_t *)stats + sizeof (stats_rsp) + sizeof (stats_sys),
1247 			(uint8_t *)&stats_users, sizeof (stats_users));
1248 	memcpy((uint8_t *)stats + sizeof (stats_rsp) + sizeof (stats_sys) +
1249 			sizeof (stats_users), (uint8_t *)&an_obj,
1250 			sizeof (an_obj));
1251 
1252 	res = axa_body_to_json(&emsg, nmsg_input, &hdr,
1253 			(axa_p_body_t *)stats, stats_len, &out);
1254 	ck_assert_int_eq(res, AXA_JSON_RES_SUCCESS);
1255 	ck_assert_str_eq(out, expected);
1256 	free(out);
1257 }
1258 END_TEST
START_TEST(test_stats_rsp_sra_no_users)1259 START_TEST(test_stats_rsp_sra_no_users)
1260 {
1261 	const char *expected = "{\"tag\":\"*\",\"op\":\"STATS RSP\",\"version\":1,\"result\":\"success\",\"load\":[6700,7900,8300],\"cpu_usage\":5144,\"uptime\":19287627,\"starttime\":19279187,\"vmsize\":1428819968,\"vmrss\":21204992,\"thread_cnt\":145,\"user_cnt\":0,\"server_type\":\"sra\",\"fd_sockets\":13,\"fd_pipes\":3,\"fd_anon_inodes\":0,\"fd_other\":5,\"rchar\":17362446,\"wchar\":755982917,\"sra_ipv4_watch_cnt\":0,\"sra_ipv6_watch_cnt\":0,\"sra_dns_watch_cnt\":0,\"sra_ch_watch_cnt\":0,\"sra_err_watch_cnt\":0,\"sra_channels\":[\"ch213\",\"ch255\"]}";
1262 	axa_emsg_t emsg;
1263 	axa_p_hdr_t hdr;
1264 	_axa_p_stats_rsp_t stats_rsp;
1265 	_axa_p_stats_sys_t stats_sys;
1266 	size_t stats_len = sizeof (stats_rsp) + sizeof (stats_sys);
1267 	uint8_t stats[stats_len];
1268 	axa_json_res_t res;
1269 	char *out = NULL;
1270 
1271 	memset(&hdr, 0, sizeof (hdr));
1272 	memset(&stats_rsp, 0, sizeof (stats_rsp));
1273 	memset(&stats_sys, 0, sizeof (stats_sys));
1274 
1275 	hdr.len = AXA_H2P32(sizeof(axa_p_hdr_t) + stats_len);
1276 	hdr.tag = AXA_H2P_TAG(0);
1277 	hdr.pvers = AXA_P_PVERS;
1278 	hdr.op = _AXA_P_OP_STATS_RSP;
1279 
1280 	stats_rsp.version = _AXA_STATS_VERSION_ONE;
1281 	stats_rsp.sys_objs_cnt = 1;
1282 	stats_rsp.user_objs_cnt = 0;
1283 	stats_rsp.result = AXA_P_STATS_R_SUCCESS;
1284 
1285 	stats_sys.type = _AXA_P_STATS_TYPE_SYS;
1286 	stats_sys.server_type = _AXA_STATS_SRVR_TYPE_SRA;
1287 	stats_sys.load[0] = 6700;
1288 	stats_sys.load[1] = 7900;
1289 	stats_sys.load[2] = 8300;
1290 	stats_sys.cpu_usage = 5144;
1291 	stats_sys.uptime = 19287627;
1292 	stats_sys.starttime = 19279187;
1293 	stats_sys.fd_sockets = 13;
1294 	stats_sys.fd_pipes = 3;
1295 	stats_sys.fd_anon_inodes = 0;
1296 	stats_sys.fd_other = 5;
1297 	stats_sys.vmsize = 1428819968;
1298 	stats_sys.vmrss = 21204992;
1299 	stats_sys.rchar = 17362446;
1300 	stats_sys.wchar = 755982917;
1301 	stats_sys.thread_cnt = 145;
1302 	stats_sys.user_cnt = 0;
1303 	stats_sys.srvr.sra.watches.ipv4_cnt = 0;
1304 	stats_sys.srvr.sra.watches.ipv6_cnt = 0;
1305 	stats_sys.srvr.sra.watches.dns_cnt = 0;
1306 	stats_sys.srvr.sra.watches.ch_cnt = 0;
1307 	stats_sys.srvr.sra.watches.err_cnt = 0;
1308 	axa_set_bitwords(stats_sys.srvr.sra.ch_mask.m, 213);
1309 	axa_set_bitwords(stats_sys.srvr.sra.ch_mask.m, 255);
1310 
1311 	memcpy((uint8_t *)stats, (uint8_t *)&stats_rsp, sizeof (stats_rsp));
1312 	memcpy((uint8_t *)stats + sizeof (stats_rsp), (uint8_t *)&stats_sys,
1313 			sizeof (stats_sys));
1314 
1315 	res = axa_body_to_json(&emsg, nmsg_input, &hdr,
1316 			(axa_p_body_t *)stats, stats_len, &out);
1317 	ck_assert_int_eq(res, AXA_JSON_RES_SUCCESS);
1318 	ck_assert_str_eq(out, expected);
1319 	free(out);
1320 }
1321 END_TEST
1322 
START_TEST(test_stats_rsp_rad_no_users)1323 START_TEST(test_stats_rsp_rad_no_users)
1324 {
1325 	const char *expected = "{\"tag\":\"*\",\"op\":\"STATS RSP\",\"version\":1,\"result\":\"success\",\"load\":[6300,6200,7100],\"cpu_usage\":0,\"uptime\":19449048,\"starttime\":19373104,\"vmsize\":91680768,\"vmrss\":4968448,\"thread_cnt\":2,\"user_cnt\":0,\"server_type\":\"rad\",\"rad_anomaly_cnt\":0}";
1326 	axa_emsg_t emsg;
1327 	axa_p_hdr_t hdr;
1328 	_axa_p_stats_rsp_t stats_rsp;
1329 	_axa_p_stats_sys_t stats_sys;
1330 	size_t stats_len = sizeof (stats_rsp) + sizeof (stats_sys);
1331 	uint8_t stats[stats_len];
1332 	axa_json_res_t res;
1333 	char *out = NULL;
1334 
1335 	memset(&hdr, 0, sizeof (hdr));
1336 	memset(&stats_rsp, 0, sizeof (stats_rsp));
1337 	memset(&stats_sys, 0, sizeof (stats_sys));
1338 
1339 	hdr.len = AXA_H2P32(sizeof(axa_p_hdr_t) + stats_len);
1340 	hdr.tag = AXA_H2P_TAG(0);
1341 	hdr.pvers = AXA_P_PVERS;
1342 	hdr.op = _AXA_P_OP_STATS_RSP;
1343 
1344 	stats_rsp.version = _AXA_STATS_VERSION_ONE;
1345 	stats_rsp.sys_objs_cnt = 1;
1346 	stats_rsp.user_objs_cnt = 0;
1347 	stats_rsp.result = AXA_P_STATS_R_SUCCESS;
1348 
1349 	stats_sys.type = _AXA_P_STATS_TYPE_SYS;
1350 	stats_sys.server_type = _AXA_STATS_SRVR_TYPE_RAD;
1351 	stats_sys.load[0] = 6300;
1352 	stats_sys.load[1] = 6200;
1353 	stats_sys.load[2] = 7100;
1354 	stats_sys.cpu_usage = 0;
1355 	stats_sys.uptime = 19449048;
1356 	stats_sys.starttime = 19373104;
1357 	stats_sys.vmsize = 91680768;
1358 	stats_sys.vmrss = 4968448;
1359 	stats_sys.thread_cnt = 2;
1360 	stats_sys.user_cnt = 0;
1361 	stats_sys.srvr.rad.an_cnt = 0;
1362 
1363 	memcpy((uint8_t *)stats, (uint8_t *)&stats_rsp, sizeof (stats_rsp));
1364 	memcpy((uint8_t *)stats + sizeof (stats_rsp), (uint8_t *)&stats_sys,
1365 			sizeof (stats_sys));
1366 
1367 	res = axa_body_to_json(&emsg, nmsg_input, &hdr,
1368 			(axa_p_body_t *)stats, stats_len, &out);
1369 	ck_assert_int_eq(res, AXA_JSON_RES_SUCCESS);
1370 	ck_assert_str_eq(out, expected);
1371 	free(out);
1372 }
1373 END_TEST
1374 
START_TEST(test_kill_req)1375 START_TEST(test_kill_req)
1376 {
1377 	const char *expected = "{\"tag\":\"*\",\"op\":\"KILL REQ\",\"mode\":1,\"user\":\"wink\",\"sn\":0,\"result\":0}";
1378 	axa_emsg_t emsg;
1379 	axa_p_hdr_t hdr;
1380 	_axa_p_kill_t kill;
1381 	size_t kill_len = sizeof(_axa_p_kill_t);
1382 	char *out = NULL;
1383 	axa_json_res_t res;
1384 
1385 	memset(&kill, 0, sizeof (kill));
1386 
1387 	hdr.len = AXA_H2P32(sizeof(axa_p_hdr_t) + kill_len);
1388 	hdr.tag = AXA_H2P_TAG(0);
1389 	hdr.pvers = AXA_P_PVERS;
1390 	hdr.op = _AXA_P_OP_KILL_REQ;
1391 
1392 	kill.mode = AXA_P_KILL_M_SN;
1393 	strcpy(kill.user.name, "wink");
1394 	kill.sn = 0;
1395 
1396 	res = axa_body_to_json(&emsg, nmsg_input, &hdr, (axa_p_body_t *)&kill,
1397 			kill_len, &out);
1398 	ck_assert_int_eq(res, AXA_JSON_RES_SUCCESS);
1399 	ck_assert_str_eq(out, expected);
1400 	free(out);
1401 }
1402 END_TEST
1403 
START_TEST(test_kill_rsp)1404 START_TEST(test_kill_rsp)
1405 {
1406 	const char *expected = "{\"tag\":\"*\",\"op\":\"KILL RSP\",\"mode\":2,\"user\":\"wink\",\"sn\":10,\"result\":2}";
1407 	axa_emsg_t emsg;
1408 	_axa_p_kill_t kill;
1409 	size_t kill_len = sizeof(_axa_p_kill_t);
1410 	axa_p_hdr_t hdr;
1411 	char *out = NULL;
1412 	axa_json_res_t res;
1413 
1414 	memset(&kill, 0, sizeof (kill));
1415 
1416 	hdr.len = AXA_H2P32(sizeof(axa_p_hdr_t) + kill_len);
1417 	hdr.tag = AXA_H2P_TAG(0);
1418 	hdr.pvers = AXA_P_PVERS;
1419 	hdr.op = _AXA_P_OP_KILL_RSP;
1420 
1421 	kill.mode = AXA_P_KILL_M_U;
1422 	strcpy(kill.user.name, "wink");
1423 	kill.sn = 10;
1424 	kill.result = AXA_P_KILL_R_FAIL_NF;
1425 
1426 	res = axa_body_to_json(&emsg, nmsg_input, &hdr, (axa_p_body_t *)&kill,
1427 			kill_len, &out);
1428 	ck_assert_int_eq(res, AXA_JSON_RES_SUCCESS);
1429 	ck_assert_str_eq(out, expected);
1430 	free(out);
1431 }
1432 END_TEST
1433 
main(void)1434 int main(void) {
1435 	int number_failed;
1436 	Suite *s;
1437 	TCase *tc_core;
1438 	SRunner *sr;
1439 
1440 	if (nmsg_init() != nmsg_res_success) {
1441 		fprintf (stderr, "unable to initialize libnmsg\n");
1442 		return 1;
1443 	}
1444 
1445 	nmsg_input = nmsg_input_open_null();
1446 	assert(nmsg_input != NULL);
1447 
1448 	s = suite_create("axa_json");
1449 	tc_core = tcase_create("core");
1450 	tcase_add_test(tc_core, test_nop);
1451 	tcase_add_test(tc_core, test_hello);
1452 	tcase_add_test(tc_core, test_hello_empty);
1453 	tcase_add_test(tc_core, test_hello_trunc);
1454 	tcase_add_test(tc_core, test_ok);
1455 	tcase_add_test(tc_core, test_ok_trunc);
1456 	tcase_add_test(tc_core, test_error);
1457 	tcase_add_test(tc_core, test_error_trunc);
1458 	tcase_add_test(tc_core, test_missed);
1459 	tcase_add_test(tc_core, test_missed_trunc);
1460 	tcase_add_test(tc_core, test_missed_rad);
1461 	tcase_add_test(tc_core, test_missed_rad_trunc);
1462 	tcase_add_test(tc_core, test_whit_nmsg);
1463 	tcase_add_test(tc_core, test_whit_nmsg_trunc);
1464 	tcase_add_test(tc_core, test_whit_ip4_udp);
1465 	tcase_add_test(tc_core, test_whit_ip4_tcp);
1466 	tcase_add_test(tc_core, test_whit_ip4_trunc);
1467 	tcase_add_test(tc_core, test_whit_ip6);
1468 	tcase_add_test(tc_core, test_whit_ip6_trunc);
1469 	tcase_add_test(tc_core, test_whit_trunc);
1470 	tcase_add_test(tc_core, test_watch_ip4);
1471 	tcase_add_test(tc_core, test_watch_ip4_trunc);
1472 	tcase_add_test(tc_core, test_watch_ip4_overflow);
1473 	tcase_add_test(tc_core, test_watch_ip6);
1474 	tcase_add_test(tc_core, test_watch_dns);
1475 	tcase_add_test(tc_core, test_watch_dns_wildcard);
1476 	tcase_add_test(tc_core, test_watch_dns_wildcard_all);
1477 	tcase_add_test(tc_core, test_watch_dns_shared);
1478 	tcase_add_test(tc_core, test_watch_ch);
1479 	tcase_add_test(tc_core, test_watch_errors);
1480 	tcase_add_test(tc_core, test_watch_trunc);
1481 	tcase_add_test(tc_core, test_anom);
1482 	tcase_add_test(tc_core, test_anom_empty);
1483 	tcase_add_test(tc_core, test_anom_trunc);
1484 	tcase_add_test(tc_core, test_channel_on);
1485 	tcase_add_test(tc_core, test_channel_off);
1486 	tcase_add_test(tc_core, test_channel_all);
1487 	tcase_add_test(tc_core, test_channel_trunc);
1488 	tcase_add_test(tc_core, test_wlist);
1489 	tcase_add_test(tc_core, test_wlist_trunc);
1490 	tcase_add_test(tc_core, test_ahit);
1491 	tcase_add_test(tc_core, test_ahit_trunc);
1492 	tcase_add_test(tc_core, test_alist);
1493 	tcase_add_test(tc_core, test_alist_trunc);
1494 	tcase_add_test(tc_core, test_clist);
1495 	tcase_add_test(tc_core, test_clist_trunc);
1496 	tcase_add_test(tc_core, test_user);
1497 	tcase_add_test(tc_core, test_user_trunc);
1498 	tcase_add_test(tc_core, test_opt_trace);
1499 	tcase_add_test(tc_core, test_opt_trace_req);
1500 	tcase_add_test(tc_core, test_opt_rlimit_num);
1501 	tcase_add_test(tc_core, test_opt_rlimit_max);
1502 	tcase_add_test(tc_core, test_opt_rlimit_off);
1503 	tcase_add_test(tc_core, test_opt_rlimit_na);
1504 	tcase_add_test(tc_core, test_opt_sample);
1505 	tcase_add_test(tc_core, test_opt_sndbuf);
1506 	tcase_add_test(tc_core, test_opt_trunc);
1507 	tcase_add_test(tc_core, test_join);
1508 	tcase_add_test(tc_core, test_join_trunc);
1509 	tcase_add_test(tc_core, test_pause);
1510 	tcase_add_test(tc_core, test_go);
1511 	tcase_add_test(tc_core, test_wget);
1512 	tcase_add_test(tc_core, test_aget);
1513 	tcase_add_test(tc_core, test_stop);
1514 	tcase_add_test(tc_core, test_all_stop);
1515 	tcase_add_test(tc_core, test_cget);
1516 	tcase_add_test(tc_core, test_acct);
1517 	tcase_add_test(tc_core, test_radu);
1518 	tcase_add_test(tc_core, test_stats_req);
1519 	tcase_add_test(tc_core, test_stats_rsp_sra_one_user);
1520 	tcase_add_test(tc_core, test_stats_rsp_rad_one_user);
1521 	tcase_add_test(tc_core, test_stats_rsp_rad_one_user_one_anomaly);
1522 	tcase_add_test(tc_core, test_stats_rsp_sra_no_users);
1523 	tcase_add_test(tc_core, test_stats_rsp_rad_no_users);
1524 	tcase_add_test(tc_core, test_kill_req);
1525 	tcase_add_test(tc_core, test_kill_rsp);
1526 	suite_add_tcase(s, tc_core);
1527 
1528 	sr = srunner_create(s);
1529 
1530 	srunner_run_all(sr, CK_NORMAL);
1531 	number_failed = srunner_ntests_failed(sr);
1532 	srunner_free(sr);
1533 	return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
1534 }
1535