1 /*
2 * ndpi_serializer.c
3 *
4 * Copyright (C) 2011-21 - ntop.org
5 *
6 * nDPI is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * nDPI is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
18 *
19 */
20
21 #ifdef HAVE_CONFIG_H
22 #include "ndpi_config.h"
23 #endif
24
25 #include <stdlib.h>
26 #include <errno.h>
27 #include <inttypes.h>
28 #include <sys/types.h>
29
30 #include "ndpi_api.h"
31 #include "ndpi_config.h"
32
33 #include <time.h>
34 #ifndef WIN32
35 #include <unistd.h>
36 #endif
37
38 #if defined __FreeBSD__ || defined __NetBSD__ || defined __OpenBSD__ || defined __DragonFly__
39 #include <sys/endian.h>
40 #endif
41
42 #ifdef WIN32
43 #define NDPI_I64_FORMAT "%" PRId64
44 #define NDPI_U64_FORMAT "%" PRIu64
45 #else
46 #define NDPI_I64_FORMAT "%lld"
47 #define NDPI_U64_FORMAT "%llu"
48 #endif
49
50 /* ********************************** */
51
ndpi_htonll(u_int64_t v)52 u_int64_t ndpi_htonll(u_int64_t v) {
53 union { u_int32_t lv[2]; u_int64_t llv; } u;
54
55 u.lv[0] = htonl(v >> 32);
56 u.lv[1] = htonl(v & 0xFFFFFFFFULL);
57
58 return(u.llv);
59 }
60
61 /* ********************************** */
62
ndpi_ntohll(u_int64_t v)63 u_int64_t ndpi_ntohll(u_int64_t v) {
64 union { u_int32_t lv[2]; u_int64_t llv; } u;
65
66 u.llv = v;
67
68 return((u_int64_t)ntohl(u.lv[0]) << 32) | (u_int64_t)ntohl(u.lv[1]);
69 }
70
71 /* ********************************** */
72
ndpi_is_number(const char * str,u_int32_t str_len)73 static int ndpi_is_number(const char *str, u_int32_t str_len) {
74 int i;
75
76 for(i = 0; i < str_len; i++)
77 if(!isdigit(str[i])) return(0);
78
79 return(1);
80 }
81
82 /* ********************************** */
83
84 /*
85 * Escapes a string to be suitable for a JSON value, adding double quotes, and terminating the string with a null byte.
86 * It is recommended to provide a destination buffer (dst) which is as large as double the source buffer (src) at least.
87 * Upon successful return, these functions return the number of characters printed (excluding the null byte used to terminate the string).
88 */
ndpi_json_string_escape(const char * src,int src_len,char * dst,int dst_max_len)89 static int ndpi_json_string_escape(const char *src, int src_len, char *dst, int dst_max_len) {
90 char c = 0;
91 int i, j = 0;
92
93 dst[j++] = '"';
94
95 for(i = 0; i < src_len && j < dst_max_len; i++) {
96
97 c = src[i];
98
99 switch (c) {
100 case '\\':
101 case '"':
102 case '/':
103 dst[j++] = '\\';
104 dst[j++] = c;
105 break;
106 case '\b':
107 dst[j++] = '\\';
108 dst[j++] = 'b';
109 break;
110 case '\t':
111 dst[j++] = '\\';
112 dst[j++] = 't';
113 break;
114 case '\n':
115 dst[j++] = '\\';
116 dst[j++] = 'n';
117 break;
118 case '\f':
119 dst[j++] = '\\';
120 dst[j++] = 'f';
121 break;
122 case '\r':
123 dst[j++] = '\\';
124 dst[j++] = 'r';
125 break;
126 default:
127 if(c < ' ')
128 ; /* non printable */
129 else
130 dst[j++] = c;
131 }
132 }
133
134 dst[j++] = '"';
135 dst[j+1] = '\0';
136
137 return(j);
138 }
139
140 /* ********************************** */
141
142 #if UNUSED
143 /*
144 * Similar to snprintf, this returns the number of bytes actually written
145 * in any case (unlike snprintf which returns, if the output is truncated,
146 * the number of bytes which *would have been* written, and a negative
147 * value on failures)
148 */
ndpi_snappend(char * buf,size_t size,const char * fmt,...)149 static inline int ndpi_snappend(char *buf, size_t size, const char *fmt, ...) {
150 int wlen;
151 va_list va;
152
153 va_start(va, fmt);
154 wlen = snprintf(buf, size, fmt, va);
155 va_end(va);
156
157 if (wlen < 0)
158 wlen = 0;
159 else if (wlen >= size)
160 wlen = size-1;
161
162 return wlen;
163 }
164 #endif
165
166 /* ********************************** */
167
ndpi_reset_serializer(ndpi_serializer * _serializer)168 void ndpi_reset_serializer(ndpi_serializer *_serializer) {
169 ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
170
171 serializer->status.flags = 0;
172
173 if(serializer->fmt == ndpi_serialization_format_json) {
174 u_int32_t buff_diff;
175
176 serializer->status.buffer.size_used = 0;
177 buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
178
179 /* Note: please keep a space at the beginning as it is used for arrays when an end-of-record is used */
180 serializer->status.buffer.size_used += snprintf((char *) &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff, " {}");
181 } else if(serializer->fmt == ndpi_serialization_format_csv) {
182 serializer->status.header.size_used = 0;
183 serializer->status.buffer.size_used = 0;
184 } else { /* ndpi_serialization_format_tlv */
185 serializer->status.buffer.size_used = 2 * sizeof(u_int8_t);
186 }
187 }
188
189 /* ********************************** */
190
ndpi_init_serializer_buffer(ndpi_private_serializer_buffer * buffer,u_int32_t buffer_size)191 static int ndpi_init_serializer_buffer(ndpi_private_serializer_buffer *buffer, u_int32_t buffer_size) {
192 buffer->initial_size = buffer->size = buffer_size;
193 buffer->data = (u_int8_t *) calloc(buffer->size, sizeof(u_int8_t));
194 if(buffer->data == NULL)
195 return -1;
196 return 0;
197 }
198
199 /* ********************************** */
200
ndpi_init_serializer_ll(ndpi_serializer * _serializer,ndpi_serialization_format fmt,u_int32_t buffer_size)201 int ndpi_init_serializer_ll(ndpi_serializer *_serializer,
202 ndpi_serialization_format fmt,
203 u_int32_t buffer_size) {
204 ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
205
206 memset(serializer, 0, sizeof(ndpi_private_serializer));
207
208 serializer->fmt = fmt;
209
210 if (ndpi_init_serializer_buffer(&serializer->buffer, buffer_size) != 0)
211 return(-1);
212
213 if(serializer->fmt == ndpi_serialization_format_json) {
214 /* nothing to do */
215
216 } else if (fmt == ndpi_serialization_format_csv) {
217 if (ndpi_init_serializer_buffer(&serializer->header, NDPI_SERIALIZER_DEFAULT_HEADER_SIZE) != 0)
218 return(-1);
219
220 } else /* ndpi_serialization_format_tlv */ {
221 serializer->buffer.data[0] = 1; /* version */
222 serializer->buffer.data[1] = (u_int8_t) fmt;
223 }
224
225 serializer->csv_separator[0] = ',';
226 serializer->csv_separator[1] = '\0';
227
228 ndpi_reset_serializer(_serializer);
229
230 return(1);
231 }
232
233 /* ********************************** */
234
ndpi_init_serializer(ndpi_serializer * _serializer,ndpi_serialization_format fmt)235 int ndpi_init_serializer(ndpi_serializer *_serializer,
236 ndpi_serialization_format fmt) {
237 return(ndpi_init_serializer_ll(_serializer, fmt, NDPI_SERIALIZER_DEFAULT_BUFFER_SIZE));
238 }
239
240 /* ********************************** */
241
ndpi_extend_serializer_buffer(ndpi_private_serializer_buffer * buffer,u_int32_t min_len)242 static inline int ndpi_extend_serializer_buffer(ndpi_private_serializer_buffer *buffer, u_int32_t min_len) {
243 u_int32_t new_size;
244 void *r;
245
246 if(min_len < NDPI_SERIALIZER_DEFAULT_BUFFER_INCR) {
247 if(buffer->initial_size < NDPI_SERIALIZER_DEFAULT_BUFFER_INCR) {
248 if(min_len < buffer->initial_size)
249 min_len = buffer->initial_size;
250 } else {
251 min_len = NDPI_SERIALIZER_DEFAULT_BUFFER_INCR;
252 }
253 }
254
255 new_size = buffer->size + min_len;
256 new_size = ((new_size / 4) + 1) * 4; /* required by zmq encryption */
257
258 r = realloc((void *) buffer->data, new_size);
259
260 if(r == NULL)
261 return(-1);
262
263 buffer->data = r;
264 buffer->size = new_size;
265
266 return(0);
267 }
268
269 /* ********************************** */
270
ndpi_serializer_check_header_room(ndpi_private_serializer * serializer,u_int32_t needed)271 static inline int ndpi_serializer_check_header_room(ndpi_private_serializer *serializer, u_int32_t needed) {
272 u_int32_t buff_diff = serializer->header.size - serializer->status.header.size_used;
273
274 if (buff_diff < needed)
275 if (ndpi_extend_serializer_buffer(&serializer->header, needed - buff_diff) < 0)
276 return -1;
277
278 buff_diff = serializer->header.size - serializer->status.header.size_used;
279
280 return buff_diff;
281 }
282
283 /* ********************************** */
284
ndpi_serializer_header_uint32(ndpi_private_serializer * serializer,u_int32_t key)285 static inline int ndpi_serializer_header_uint32(ndpi_private_serializer *serializer, u_int32_t key) {
286 int room;
287
288 if (serializer->status.flags & NDPI_SERIALIZER_STATUS_HDR_DONE)
289 return 0;
290
291 room = ndpi_serializer_check_header_room(serializer, 12);
292
293 if (room < 0)
294 return -1;
295
296 serializer->status.header.size_used += snprintf((char *) &serializer->header.data[serializer->status.header.size_used],
297 room, "%s%u", (serializer->status.header.size_used > 0) ? serializer->csv_separator : "", key);
298
299 return 0;
300 }
301
302 /* ********************************** */
303
ndpi_serializer_header_string(ndpi_private_serializer * serializer,const char * key,u_int16_t klen)304 static inline int ndpi_serializer_header_string(ndpi_private_serializer *serializer, const char *key, u_int16_t klen) {
305 int room;
306
307 if (serializer->status.flags & NDPI_SERIALIZER_STATUS_HDR_DONE)
308 return 0;
309
310 room = ndpi_serializer_check_header_room(serializer, klen + 4);
311
312 if (room < 0)
313 return -1;
314
315 if (serializer->status.header.size_used > 0) {
316 int slen = strlen(serializer->csv_separator);
317 memcpy(&serializer->header.data[serializer->status.header.size_used], serializer->csv_separator, slen);
318 serializer->status.header.size_used += slen;
319 }
320
321 if (klen > 0) {
322 memcpy(&serializer->header.data[serializer->status.header.size_used], key, klen);
323 serializer->status.header.size_used += klen;
324 }
325
326 serializer->header.data[serializer->status.header.size_used] = '\0';
327
328 return 0;
329 }
330
331 /* ********************************** */
332
ndpi_serializer_get_buffer(ndpi_serializer * _serializer,u_int32_t * buffer_len)333 char* ndpi_serializer_get_buffer(ndpi_serializer *_serializer, u_int32_t *buffer_len) {
334 ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
335 char *buf = (char*)serializer->buffer.data;
336
337 /* NULL terminate the buffer */
338 if(serializer->buffer.size > serializer->status.buffer.size_used) /* safety check */
339 serializer->buffer.data[serializer->status.buffer.size_used] = '\0';
340
341 *buffer_len = serializer->status.buffer.size_used;
342
343 if(serializer->fmt == ndpi_serialization_format_json) {
344 while((buf[0] == '\0') || (buf[0] == ' '))
345 buf++, *buffer_len = *buffer_len - 1;
346 }
347
348 return(buf);
349 }
350
351 /* ********************************** */
352
ndpi_serializer_get_buffer_len(ndpi_serializer * _serializer)353 u_int32_t ndpi_serializer_get_buffer_len(ndpi_serializer *_serializer) {
354 return(((ndpi_private_serializer*)_serializer)->status.buffer.size_used);
355 }
356
357 /* ********************************** */
358
ndpi_serializer_get_internal_buffer_size(ndpi_serializer * _serializer)359 u_int32_t ndpi_serializer_get_internal_buffer_size(ndpi_serializer *_serializer) {
360 return(((ndpi_private_serializer*)_serializer)->buffer.size);
361 }
362
363 /* ********************************** */
364
ndpi_serializer_set_buffer_len(ndpi_serializer * _serializer,u_int32_t l)365 int ndpi_serializer_set_buffer_len(ndpi_serializer *_serializer, u_int32_t l) {
366 ndpi_private_serializer *p = (ndpi_private_serializer*)_serializer;
367
368 if(p) {
369 if(p->buffer.size <= l)
370 return(-1); /* Invalid size */
371
372 p->status.buffer.size_used = l;
373 return(0);
374 }
375
376 return(-2);
377 }
378
379 /* ********************************** */
380
381 /* Return the header automatically built from keys (CSV only) */
ndpi_serializer_get_header(ndpi_serializer * _serializer,u_int32_t * buffer_len)382 char* ndpi_serializer_get_header(ndpi_serializer *_serializer, u_int32_t *buffer_len) {
383 ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
384 char *buf = (char*)serializer->header.data;
385
386 if(buf == NULL) {
387 *buffer_len = 0;
388 return "";
389 }
390
391 /* NULL terminate the buffer */
392 if(serializer->header.size > serializer->status.header.size_used) /* safety check */
393 serializer->header.data[serializer->status.header.size_used] = '\0';
394
395 *buffer_len = serializer->status.header.size_used;
396
397 return(buf);
398 }
399
400 /* ********************************** */
401
ndpi_serializer_get_format(ndpi_serializer * _serializer)402 ndpi_serialization_format ndpi_serializer_get_format(ndpi_serializer *_serializer) {
403 ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
404 return serializer->fmt;
405 }
406
407 /* ********************************** */
408
ndpi_serializer_set_csv_separator(ndpi_serializer * _serializer,char separator)409 void ndpi_serializer_set_csv_separator(ndpi_serializer *_serializer, char separator) {
410 ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
411
412 serializer->csv_separator[0] = separator;
413 }
414
415 /* ********************************** */
416
ndpi_term_serializer(ndpi_serializer * _serializer)417 void ndpi_term_serializer(ndpi_serializer *_serializer) {
418 ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
419
420 if(serializer->buffer.data) {
421 free(serializer->buffer.data);
422 serializer->buffer.size = 0;
423 serializer->buffer.data = NULL;
424 }
425
426 if(serializer->header.data) {
427 free(serializer->header.data);
428 serializer->header.size = 0;
429 serializer->header.data = NULL;
430 }
431 }
432
433 /* ********************************** */
434
ndpi_serialize_single_uint8(ndpi_private_serializer * serializer,u_int8_t s)435 static inline void ndpi_serialize_single_uint8(ndpi_private_serializer *serializer,
436 u_int8_t s) {
437 u_int8_t v = s;
438
439 memcpy(&serializer->buffer.data[serializer->status.buffer.size_used], &v, sizeof(u_int8_t));
440 serializer->status.buffer.size_used += sizeof(u_int8_t);
441 }
442
443 /* ********************************** */
444
ndpi_serialize_single_uint16(ndpi_private_serializer * serializer,u_int16_t s)445 static inline void ndpi_serialize_single_uint16(ndpi_private_serializer *serializer,
446 u_int16_t s) {
447 u_int16_t v = htons(s);
448
449 memcpy(&serializer->buffer.data[serializer->status.buffer.size_used], &v, sizeof(u_int16_t));
450 serializer->status.buffer.size_used += sizeof(u_int16_t);
451 }
452
453 /* ********************************** */
454
ndpi_serialize_single_uint32(ndpi_private_serializer * serializer,u_int32_t s)455 static inline void ndpi_serialize_single_uint32(ndpi_private_serializer *serializer,
456 u_int32_t s) {
457 u_int32_t v = htonl(s);
458
459 memcpy(&serializer->buffer.data[serializer->status.buffer.size_used], &v, sizeof(u_int32_t));
460 serializer->status.buffer.size_used += sizeof(u_int32_t);
461 }
462
463 /* ********************************** */
464
ndpi_serialize_single_uint64(ndpi_private_serializer * serializer,u_int64_t s)465 static inline void ndpi_serialize_single_uint64(ndpi_private_serializer *serializer,
466 u_int64_t s) {
467 u_int64_t v = ndpi_htonll(s);
468
469 memcpy(&serializer->buffer.data[serializer->status.buffer.size_used], &v, sizeof(u_int64_t));
470 serializer->status.buffer.size_used += sizeof(u_int64_t);
471 }
472
473 /* ********************************** */
474
475 /* TODO: fix portability across platforms */
ndpi_serialize_single_float(ndpi_private_serializer * serializer,float s)476 static inline void ndpi_serialize_single_float(ndpi_private_serializer *serializer,
477 float s) {
478 memcpy(&serializer->buffer.data[serializer->status.buffer.size_used], &s, sizeof(s));
479 serializer->status.buffer.size_used += sizeof(float);
480 }
481
482 /* ********************************** */
483
ndpi_serialize_single_string(ndpi_private_serializer * serializer,const char * s,u_int16_t slen)484 static inline void ndpi_serialize_single_string(ndpi_private_serializer *serializer,
485 const char *s, u_int16_t slen) {
486 u_int16_t l = htons(slen);
487
488 memcpy(&serializer->buffer.data[serializer->status.buffer.size_used], &l, sizeof(u_int16_t));
489 serializer->status.buffer.size_used += sizeof(u_int16_t);
490
491 if(slen > 0)
492 memcpy(&serializer->buffer.data[serializer->status.buffer.size_used], s, slen);
493
494 serializer->status.buffer.size_used += slen;
495 }
496
497 /* ********************************** */
498
ndpi_deserialize_single_uint8(ndpi_private_deserializer * deserializer,u_int32_t offset,u_int8_t * s)499 static inline void ndpi_deserialize_single_uint8(ndpi_private_deserializer *deserializer,
500 u_int32_t offset, u_int8_t *s) {
501 *s = (*((u_int8_t *) &deserializer->buffer.data[offset]));
502 }
503
504 /* ********************************** */
505
ndpi_deserialize_single_uint16(ndpi_private_deserializer * deserializer,u_int32_t offset,u_int16_t * s)506 static inline void ndpi_deserialize_single_uint16(ndpi_private_deserializer *deserializer,
507 u_int32_t offset, u_int16_t *s) {
508 *s = ntohs(*((u_int16_t *) &deserializer->buffer.data[offset]));
509 }
510
511 /* ********************************** */
512
ndpi_deserialize_single_uint32(ndpi_private_deserializer * deserializer,u_int32_t offset,u_int32_t * s)513 static inline void ndpi_deserialize_single_uint32(ndpi_private_deserializer *deserializer,
514 u_int32_t offset, u_int32_t *s) {
515 *s = ntohl(*((u_int32_t *) &deserializer->buffer.data[offset]));
516 }
517
518 /* ********************************** */
519
ndpi_deserialize_single_int8(ndpi_private_deserializer * deserializer,u_int32_t offset,int8_t * s)520 static inline void ndpi_deserialize_single_int8(ndpi_private_deserializer *deserializer,
521 u_int32_t offset, int8_t *s) {
522 *s = (*((int8_t *) &deserializer->buffer.data[offset]));
523 }
524
525 /* ********************************** */
526
ndpi_deserialize_single_int16(ndpi_private_deserializer * deserializer,u_int32_t offset,int16_t * s)527 static inline void ndpi_deserialize_single_int16(ndpi_private_deserializer *deserializer,
528 u_int32_t offset, int16_t *s) {
529 *s = ntohs(*((int16_t *) &deserializer->buffer.data[offset]));
530 }
531
532 /* ********************************** */
533
ndpi_deserialize_single_int32(ndpi_private_deserializer * deserializer,u_int32_t offset,int32_t * s)534 static inline void ndpi_deserialize_single_int32(ndpi_private_deserializer *deserializer,
535 u_int32_t offset, int32_t *s) {
536 *s = ntohl(*((int32_t *) &deserializer->buffer.data[offset]));
537 }
538
539 /* ********************************** */
540
ndpi_deserialize_single_uint64(ndpi_private_deserializer * deserializer,u_int32_t offset,u_int64_t * s)541 static inline void ndpi_deserialize_single_uint64(ndpi_private_deserializer *deserializer,
542 u_int32_t offset, u_int64_t *s) {
543 *s = ndpi_ntohll(*(u_int64_t*)&deserializer->buffer.data[offset]);
544 }
545
546 /* ********************************** */
547
ndpi_deserialize_single_int64(ndpi_private_deserializer * deserializer,u_int32_t offset,int64_t * s)548 static inline void ndpi_deserialize_single_int64(ndpi_private_deserializer *deserializer,
549 u_int32_t offset, int64_t *s) {
550 *s = ndpi_ntohll(*(int64_t*)&deserializer->buffer.data[offset]);
551 }
552
553 /* ********************************** */
554
555 /* TODO: fix portability across platforms */
ndpi_deserialize_single_float(ndpi_private_deserializer * deserializer,u_int32_t offset,float * s)556 static inline void ndpi_deserialize_single_float(ndpi_private_deserializer *deserializer,
557 u_int32_t offset, float *s) {
558 *s = *(float*)&deserializer->buffer.data[offset];
559 }
560
561 /* ********************************** */
562
ndpi_deserialize_single_string(ndpi_private_deserializer * deserializer,u_int32_t offset,ndpi_string * v)563 static inline void ndpi_deserialize_single_string(ndpi_private_deserializer *deserializer,
564 u_int32_t offset, ndpi_string *v) {
565 v->str_len = ntohs(*((u_int16_t *) &deserializer->buffer.data[offset]));
566 v->str = (char *) &deserializer->buffer.data[offset + sizeof(u_int16_t)];
567 }
568
569 /* ********************************** */
570
571 /*
572 This function helps extending the existing serializer by adding a new
573 element in the array. This element is handled as raw without any
574 further check whatsoever
575 */
ndpi_serialize_raw_record(ndpi_serializer * _serializer,u_char * record,u_int32_t record_len)576 int ndpi_serialize_raw_record(ndpi_serializer *_serializer,
577 u_char *record, u_int32_t record_len) {
578 ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
579 u_int32_t buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
580 u_int16_t needed = record_len;
581 u_int8_t add_comma = 0;
582
583 if(serializer->fmt == ndpi_serialization_format_json) {
584 needed += 1;
585
586 if(serializer->status.buffer.size_used == 3) /* Empty buffer [{} */
587 serializer->status.buffer.size_used = 2; /* Remove {} */
588 else
589 needed += 2, add_comma = 1;
590 }
591
592 if(buff_diff < needed) {
593 if(ndpi_extend_serializer_buffer(&serializer->buffer, needed - buff_diff) < 0)
594 return(-1);
595
596 buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
597 }
598
599 if(serializer->fmt == ndpi_serialization_format_json) {
600 if(add_comma)
601 serializer->buffer.data[serializer->status.buffer.size_used-1] = ',';
602 else
603 serializer->status.buffer.size_used--;
604 }
605
606 memcpy(&serializer->buffer.data[serializer->status.buffer.size_used], record, record_len);
607 serializer->status.buffer.size_used += record_len;
608
609 if(serializer->fmt == ndpi_serialization_format_json) {
610 serializer->buffer.data[serializer->status.buffer.size_used] = ']';
611 if(add_comma) serializer->status.buffer.size_used++;
612 }
613
614 ndpi_serialize_end_of_record(_serializer);
615
616 return(0);
617 }
618
619 /* ********************************** */
620
ndpi_serialize_end_of_record(ndpi_serializer * _serializer)621 int ndpi_serialize_end_of_record(ndpi_serializer *_serializer) {
622 ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
623 u_int32_t buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
624 u_int16_t needed = sizeof(u_int8_t) /* type */;
625
626 if(serializer->fmt == ndpi_serialization_format_json ||
627 serializer->fmt == ndpi_serialization_format_csv)
628 needed += 1;
629
630 if(buff_diff < needed) {
631 if(ndpi_extend_serializer_buffer(&serializer->buffer, needed - buff_diff) < 0)
632 return(-1);
633 buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
634 }
635
636 if(serializer->fmt == ndpi_serialization_format_csv) {
637 serializer->buffer.data[serializer->status.buffer.size_used] = '\n';
638 serializer->status.buffer.size_used += 1;
639 serializer->buffer.data[serializer->status.buffer.size_used] = '\0';
640 serializer->status.flags |= NDPI_SERIALIZER_STATUS_HDR_DONE;
641 serializer->status.flags |= NDPI_SERIALIZER_STATUS_EOR;
642 } else if(serializer->fmt == ndpi_serialization_format_json) {
643 if(!(serializer->status.flags & NDPI_SERIALIZER_STATUS_ARRAY)) {
644 serializer->buffer.data[0] = '[';
645 serializer->status.buffer.size_used += snprintf((char *) &serializer->buffer.data[serializer->status.buffer.size_used],
646 buff_diff, "]");
647 }
648
649 serializer->status.flags |= NDPI_SERIALIZER_STATUS_ARRAY | NDPI_SERIALIZER_STATUS_EOR;
650 serializer->status.flags &= ~NDPI_SERIALIZER_STATUS_COMMA;
651 } else /* ndpi_serialization_format_tlv */ {
652 serializer->buffer.data[serializer->status.buffer.size_used++] = ndpi_serialization_end_of_record;
653 }
654
655 serializer->status.flags &= ~NDPI_SERIALIZER_STATUS_NOT_EMPTY;
656
657 return(0);
658 }
659
660 /* ********************************** */
661
ndpi_serialize_csv_pre(ndpi_private_serializer * serializer)662 static inline void ndpi_serialize_csv_pre(ndpi_private_serializer *serializer) {
663 if(serializer->status.flags & NDPI_SERIALIZER_STATUS_EOR) {
664 serializer->status.flags &= ~NDPI_SERIALIZER_STATUS_EOR;
665 } else if (serializer->status.buffer.size_used == 0) {
666 /* nothing to do */
667 } else {
668 u_int32_t buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
669 serializer->status.buffer.size_used += snprintf((char *)
670 &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff, "%s",
671 serializer->csv_separator);
672 }
673 }
674
675 /* ********************************** */
676
ndpi_serialize_json_pre(ndpi_serializer * _serializer)677 static inline void ndpi_serialize_json_pre(ndpi_serializer *_serializer) {
678 ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
679
680 if(serializer->status.flags & NDPI_SERIALIZER_STATUS_EOR) {
681 serializer->status.buffer.size_used--; /* Remove ']' */
682 serializer->status.flags &= ~NDPI_SERIALIZER_STATUS_EOR;
683 serializer->buffer.data[serializer->status.buffer.size_used++] = ',';
684 serializer->buffer.data[serializer->status.buffer.size_used++] = '{';
685 } else {
686 if(serializer->status.flags & NDPI_SERIALIZER_STATUS_ARRAY)
687 serializer->status.buffer.size_used--; /* Remove ']' */
688
689 serializer->status.buffer.size_used--; /* Remove '}' */
690
691 if(serializer->status.flags & NDPI_SERIALIZER_STATUS_LIST) {
692 serializer->status.buffer.size_used--; /* Remove ']' */
693 if(serializer->status.flags & NDPI_SERIALIZER_STATUS_SOL)
694 serializer->status.flags &= ~NDPI_SERIALIZER_STATUS_SOL;
695 else
696 serializer->buffer.data[serializer->status.buffer.size_used++] = ',';
697 } else {
698 if(serializer->status.flags & NDPI_SERIALIZER_STATUS_SOB)
699 serializer->status.flags &= ~NDPI_SERIALIZER_STATUS_SOB;
700 else if(serializer->status.flags & NDPI_SERIALIZER_STATUS_COMMA)
701 serializer->buffer.data[serializer->status.buffer.size_used++] = ',';
702 }
703 }
704 }
705
706 /* ********************************** */
707
ndpi_serialize_json_post(ndpi_serializer * _serializer)708 static inline void ndpi_serialize_json_post(ndpi_serializer *_serializer) {
709 ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
710
711 if(serializer->status.flags & NDPI_SERIALIZER_STATUS_LIST)
712 serializer->buffer.data[serializer->status.buffer.size_used++] = ']';
713
714 serializer->buffer.data[serializer->status.buffer.size_used++] = '}';
715
716 if(serializer->status.flags & NDPI_SERIALIZER_STATUS_ARRAY)
717 serializer->buffer.data[serializer->status.buffer.size_used++] = ']';
718
719 serializer->status.flags |= NDPI_SERIALIZER_STATUS_COMMA;
720 }
721
722 /* ********************************** */
723
ndpi_serialize_key_uint32(ndpi_private_serializer * serializer,u_int32_t key)724 static inline ndpi_serialization_type ndpi_serialize_key_uint32(ndpi_private_serializer *serializer, u_int32_t key) {
725 ndpi_serialization_type kt;
726
727 if(key <= 0xff) {
728 ndpi_serialize_single_uint8(serializer, key);
729 kt = ndpi_serialization_uint8;
730 } else if(key <= 0xffff) {
731 ndpi_serialize_single_uint16(serializer, key);
732 kt = ndpi_serialization_uint16;
733 } else {
734 ndpi_serialize_single_uint32(serializer, key);
735 kt = ndpi_serialization_uint32;
736 }
737
738 return(kt);
739 }
740
741 /* ********************************** */
742
ndpi_serialize_uint32_uint32(ndpi_serializer * _serializer,u_int32_t key,u_int32_t value)743 int ndpi_serialize_uint32_uint32(ndpi_serializer *_serializer,
744 u_int32_t key, u_int32_t value) {
745 ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
746 u_int32_t buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
747 u_int16_t needed =
748 sizeof(u_int8_t) /* type */ +
749 sizeof(u_int32_t) /* key */ +
750 sizeof(u_int32_t);
751
752 if(serializer->fmt == ndpi_serialization_format_json)
753 needed += 24;
754
755 if(buff_diff < needed) {
756 if(ndpi_extend_serializer_buffer(&serializer->buffer, needed - buff_diff) < 0)
757 return(-1);
758 buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
759 }
760
761 if(serializer->fmt == ndpi_serialization_format_json) {
762 ndpi_serialize_json_pre(_serializer);
763
764 if (!(serializer->status.flags & NDPI_SERIALIZER_STATUS_LIST)) {
765 serializer->status.buffer.size_used += snprintf((char *)
766 &serializer->buffer.data[serializer->status.buffer.size_used],
767 buff_diff, "\"%u\":", key);
768 buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
769 }
770
771 serializer->status.buffer.size_used += snprintf((char *)
772 &serializer->buffer.data[serializer->status.buffer.size_used],
773 buff_diff, "%u", value);
774
775 ndpi_serialize_json_post(_serializer);
776 } else if(serializer->fmt == ndpi_serialization_format_csv) {
777 if (ndpi_serializer_header_uint32(serializer, key) < 0) return(-1);
778 ndpi_serialize_csv_pre(serializer);
779 buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
780 serializer->status.buffer.size_used += snprintf((char *)
781 &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff,
782 "%u", value);
783 } else {
784 ndpi_serialization_type kt;
785 u_int8_t type = 0;
786 u_int32_t type_offset = serializer->status.buffer.size_used++;
787
788 kt = ndpi_serialize_key_uint32(serializer, key);
789 type = (kt << 4);
790
791 if(value <= 0xff) {
792 ndpi_serialize_single_uint8(serializer, value);
793 type |= ndpi_serialization_uint8;
794 } else if(value <= 0xffff) {
795 ndpi_serialize_single_uint16(serializer, value);
796 type |= ndpi_serialization_uint16;
797 } else {
798 ndpi_serialize_single_uint32(serializer, value);
799 type |= ndpi_serialization_uint32;
800 }
801
802 serializer->buffer.data[type_offset] = type;
803 }
804
805 serializer->status.flags |= NDPI_SERIALIZER_STATUS_NOT_EMPTY;
806 return(0);
807 }
808
809 /* ********************************** */
810
ndpi_serialize_uint32_uint64(ndpi_serializer * _serializer,u_int32_t key,u_int64_t value)811 int ndpi_serialize_uint32_uint64(ndpi_serializer *_serializer,
812 u_int32_t key, u_int64_t value) {
813 ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
814 u_int32_t buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
815 u_int16_t needed =
816 sizeof(u_int8_t) /* type */ +
817 sizeof(u_int32_t) /* key */ +
818 sizeof(u_int64_t);
819
820 if(serializer->fmt == ndpi_serialization_format_json)
821 needed += 32;
822
823 if(buff_diff < needed) {
824 if(ndpi_extend_serializer_buffer(&serializer->buffer, needed - buff_diff) < 0)
825 return(-1);
826 buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
827 }
828
829 if(serializer->fmt == ndpi_serialization_format_json) {
830 ndpi_serialize_json_pre(_serializer);
831
832 if (!(serializer->status.flags & NDPI_SERIALIZER_STATUS_LIST)) {
833 serializer->status.buffer.size_used += snprintf((char *)
834 &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff,
835 "\"%u\":", key);
836 buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
837 }
838
839 serializer->status.buffer.size_used += snprintf((char *)
840 &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff,
841 NDPI_U64_FORMAT, (unsigned long long)value);
842
843 ndpi_serialize_json_post(_serializer);
844 } else if(serializer->fmt == ndpi_serialization_format_csv) {
845 if (ndpi_serializer_header_uint32(serializer, key) < 0) return(-1);
846 ndpi_serialize_csv_pre(serializer);
847 buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
848 serializer->status.buffer.size_used += snprintf((char *)
849 &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff,
850 NDPI_U64_FORMAT, (unsigned long long)value);
851 } else {
852 if(value <= 0xffffffff) {
853 return(ndpi_serialize_uint32_uint32(_serializer, key, value));
854 } else {
855 ndpi_serialization_type kt;
856 u_int8_t type = 0;
857 u_int32_t type_offset = serializer->status.buffer.size_used++;
858
859 kt = ndpi_serialize_key_uint32(serializer, key);
860 type = (kt << 4);
861
862 ndpi_serialize_single_uint64(serializer, value);
863 type |= ndpi_serialization_uint64;
864
865 serializer->buffer.data[type_offset] = type;
866 }
867 }
868
869 serializer->status.flags |= NDPI_SERIALIZER_STATUS_NOT_EMPTY;
870 return(0);
871 }
872
873 /* ********************************** */
874
ndpi_serialize_uint32_int32(ndpi_serializer * _serializer,u_int32_t key,int32_t value)875 int ndpi_serialize_uint32_int32(ndpi_serializer *_serializer,
876 u_int32_t key, int32_t value) {
877 ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
878 u_int32_t buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
879 u_int16_t needed =
880 sizeof(u_int8_t) /* type */ +
881 sizeof(u_int32_t) /* key */ +
882 sizeof(int32_t);
883
884 if(serializer->fmt == ndpi_serialization_format_json)
885 needed += 24;
886
887 if(buff_diff < needed) {
888 if(ndpi_extend_serializer_buffer(&serializer->buffer, needed - buff_diff) < 0)
889 return(-1);
890 buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
891 }
892
893 if(serializer->fmt == ndpi_serialization_format_json) {
894 ndpi_serialize_json_pre(_serializer);
895
896 if (!(serializer->status.flags & NDPI_SERIALIZER_STATUS_LIST)) {
897 serializer->status.buffer.size_used += snprintf((char *)
898 &serializer->buffer.data[serializer->status.buffer.size_used],
899 buff_diff, "\"%u\":", key);
900 buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
901 }
902
903 serializer->status.buffer.size_used += snprintf((char *)
904 &serializer->buffer.data[serializer->status.buffer.size_used],
905 buff_diff, "%d", value);
906
907 ndpi_serialize_json_post(_serializer);
908 } else if(serializer->fmt == ndpi_serialization_format_csv) {
909 if (ndpi_serializer_header_uint32(serializer, key) < 0) return(-1);
910 ndpi_serialize_csv_pre(serializer);
911 buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
912 serializer->status.buffer.size_used += snprintf((char *)
913 &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff,
914 "%d", value);
915 } else {
916 ndpi_serialization_type kt;
917 u_int8_t type = 0;
918 u_int32_t type_offset = serializer->status.buffer.size_used++;
919
920 kt = ndpi_serialize_key_uint32(serializer, key);
921 type = (kt << 4);
922
923 if(value <= 127 && value >= -128) {
924 ndpi_serialize_single_uint8(serializer, value);
925 type |= ndpi_serialization_int8;
926 } else if(value <= 32767 && value >= -32768) {
927 ndpi_serialize_single_uint16(serializer, value);
928 type |= ndpi_serialization_int16;
929 } else {
930 ndpi_serialize_single_uint32(serializer, value);
931 type |= ndpi_serialization_int32;
932 }
933
934 serializer->buffer.data[type_offset] = type;
935 }
936
937 serializer->status.flags |= NDPI_SERIALIZER_STATUS_NOT_EMPTY;
938 return(0);
939 }
940
941 /* ********************************** */
942
ndpi_serialize_uint32_int64(ndpi_serializer * _serializer,u_int32_t key,int64_t value)943 int ndpi_serialize_uint32_int64(ndpi_serializer *_serializer,
944 u_int32_t key, int64_t value) {
945 ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
946 u_int32_t buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
947 u_int16_t needed =
948 sizeof(u_int8_t) /* type */ +
949 sizeof(u_int32_t) /* key */ +
950 sizeof(int64_t);
951
952 if(serializer->fmt == ndpi_serialization_format_json)
953 needed += 32;
954
955 if(buff_diff < needed) {
956 if(ndpi_extend_serializer_buffer(&serializer->buffer, needed - buff_diff) < 0)
957 return(-1);
958 buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
959 }
960
961 if(serializer->fmt == ndpi_serialization_format_json) {
962 ndpi_serialize_json_pre(_serializer);
963
964 if (!(serializer->status.flags & NDPI_SERIALIZER_STATUS_LIST)) {
965 serializer->status.buffer.size_used += snprintf((char *)
966 &serializer->buffer.data[serializer->status.buffer.size_used],
967 buff_diff, "\"%u\":", key);
968 buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
969 }
970
971 serializer->status.buffer.size_used += snprintf((char *)
972 &serializer->buffer.data[serializer->status.buffer.size_used],
973 buff_diff, NDPI_I64_FORMAT, (long long int)value);
974
975 ndpi_serialize_json_post(_serializer);
976 } else if(serializer->fmt == ndpi_serialization_format_csv) {
977 if (ndpi_serializer_header_uint32(serializer, key) < 0) return(-1);
978 ndpi_serialize_csv_pre(serializer);
979 buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
980 serializer->status.buffer.size_used += snprintf((char *)
981 &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff,
982 NDPI_I64_FORMAT, (long long int)value);
983 }
984 else {
985 if((value & 0xFFFFFFFF) == value) {
986 return(ndpi_serialize_uint32_int32(_serializer, key, value));
987 } else {
988 ndpi_serialization_type kt;
989 u_int8_t type = 0;
990 u_int32_t type_offset = serializer->status.buffer.size_used++;
991
992 kt = ndpi_serialize_key_uint32(serializer, key);
993 type = (kt << 4);
994
995 ndpi_serialize_single_uint64(serializer, value);
996 type |= ndpi_serialization_int64;
997
998 serializer->buffer.data[type_offset] = type;
999 }
1000 }
1001
1002 serializer->status.flags |= NDPI_SERIALIZER_STATUS_NOT_EMPTY;
1003 return(0);
1004 }
1005
1006 /* ********************************** */
1007
ndpi_serialize_uint32_float(ndpi_serializer * _serializer,u_int32_t key,float value,const char * format)1008 int ndpi_serialize_uint32_float(ndpi_serializer *_serializer,
1009 u_int32_t key, float value,
1010 const char *format /* e.f. "%.2f" */) {
1011 ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
1012 u_int32_t buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
1013 u_int16_t needed =
1014 sizeof(u_int8_t) /* type */ +
1015 sizeof(u_int32_t) /* key */ +
1016 sizeof(float);
1017
1018 if(serializer->fmt == ndpi_serialization_format_json)
1019 needed += 32;
1020
1021 if(buff_diff < needed) {
1022 if(ndpi_extend_serializer_buffer(&serializer->buffer, needed - buff_diff) < 0)
1023 return(-1);
1024 buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
1025 }
1026
1027 if(serializer->fmt == ndpi_serialization_format_json) {
1028 ndpi_serialize_json_pre(_serializer);
1029
1030 if (!(serializer->status.flags & NDPI_SERIALIZER_STATUS_LIST)) {
1031 serializer->status.buffer.size_used += snprintf((char *) &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff, "\"%u\":", key);
1032 buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
1033 }
1034
1035 serializer->status.buffer.size_used += snprintf((char *) &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff, format, value);
1036
1037 ndpi_serialize_json_post(_serializer);
1038 } else if(serializer->fmt == ndpi_serialization_format_csv) {
1039 if (ndpi_serializer_header_uint32(serializer, key) < 0) return(-1);
1040 ndpi_serialize_csv_pre(serializer);
1041 buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
1042 serializer->status.buffer.size_used += snprintf((char *) &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff, format, value);
1043
1044 } else {
1045 ndpi_serialization_type kt;
1046 u_int8_t type = 0;
1047 u_int32_t type_offset = serializer->status.buffer.size_used++;
1048
1049 kt = ndpi_serialize_key_uint32(serializer, key);
1050 type = (kt << 4);
1051
1052 ndpi_serialize_single_float(serializer, value);
1053 type |= ndpi_serialization_float;
1054
1055 serializer->buffer.data[type_offset] = type;
1056 }
1057
1058 serializer->status.flags |= NDPI_SERIALIZER_STATUS_NOT_EMPTY;
1059 return(0);
1060 }
1061
1062 /* ********************************** */
1063
ndpi_serialize_uint32_binary(ndpi_serializer * _serializer,u_int32_t key,const char * value,u_int16_t slen)1064 static int ndpi_serialize_uint32_binary(ndpi_serializer *_serializer,
1065 u_int32_t key, const char *value, u_int16_t slen) {
1066 ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
1067 u_int32_t buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
1068 u_int32_t needed =
1069 sizeof(u_int8_t) /* type */ +
1070 sizeof(u_int32_t) /* key */ +
1071 sizeof(u_int16_t) /* len */ +
1072 slen;
1073
1074 if(serializer->fmt == ndpi_serialization_format_json)
1075 needed += 24 + slen;
1076
1077 if(buff_diff < needed) {
1078 if(ndpi_extend_serializer_buffer(&serializer->buffer, needed - buff_diff) < 0)
1079 return(-1);
1080 buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
1081 }
1082
1083 if(serializer->fmt == ndpi_serialization_format_json) {
1084 ndpi_serialize_json_pre(_serializer);
1085
1086 if (!(serializer->status.flags & NDPI_SERIALIZER_STATUS_LIST)) {
1087 serializer->status.buffer.size_used += snprintf((char *) &serializer->buffer.data[serializer->status.buffer.size_used],
1088 buff_diff, "\"%u\":", key);
1089 buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
1090 }
1091 serializer->status.buffer.size_used += ndpi_json_string_escape(value, slen,
1092 (char *) &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff);
1093 buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
1094 ndpi_serialize_json_post(_serializer);
1095 } else if(serializer->fmt == ndpi_serialization_format_csv) {
1096 if (ndpi_serializer_header_uint32(serializer, key) < 0) return(-1);
1097 ndpi_serialize_csv_pre(serializer);
1098 buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
1099 serializer->status.buffer.size_used += snprintf((char *)
1100 &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff,
1101 "%s", value);
1102 } else {
1103 ndpi_serialization_type kt;
1104 u_int8_t type = 0;
1105 u_int32_t type_offset = serializer->status.buffer.size_used++;
1106
1107 kt = ndpi_serialize_key_uint32(serializer, key);
1108 type = (kt << 4);
1109
1110 ndpi_serialize_single_string(serializer, value, slen);
1111 type |= ndpi_serialization_string;
1112
1113 serializer->buffer.data[type_offset] = type;
1114 }
1115
1116 serializer->status.flags |= NDPI_SERIALIZER_STATUS_NOT_EMPTY;
1117 return(0);
1118 }
1119
1120 /* ********************************** */
1121
ndpi_serialize_uint32_string(ndpi_serializer * _serializer,u_int32_t key,const char * _value)1122 int ndpi_serialize_uint32_string(ndpi_serializer *_serializer,
1123 u_int32_t key, const char *_value) {
1124 const char *value = _value ? _value : "";
1125 return(ndpi_serialize_uint32_binary(_serializer, key, value, strlen(value)));
1126 }
1127
1128 /* ********************************** */
1129
ndpi_serialize_uint32_boolean(ndpi_serializer * _serializer,u_int32_t key,u_int8_t value)1130 int ndpi_serialize_uint32_boolean(ndpi_serializer *_serializer,
1131 u_int32_t key, u_int8_t value) {
1132 ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
1133 u_int32_t buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
1134 u_int32_t needed = 24;
1135
1136 if(serializer->fmt != ndpi_serialization_format_json &&
1137 serializer->fmt != ndpi_serialization_format_csv)
1138 return -1;
1139
1140 if(buff_diff < needed) {
1141 if(ndpi_extend_serializer_buffer(&serializer->buffer, needed - buff_diff) < 0)
1142 return(-1);
1143 buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
1144 }
1145
1146 if(serializer->fmt == ndpi_serialization_format_json) {
1147 ndpi_serialize_json_pre(_serializer);
1148
1149 if (!(serializer->status.flags & NDPI_SERIALIZER_STATUS_LIST)) {
1150 serializer->status.buffer.size_used += snprintf((char *)
1151 &serializer->buffer.data[serializer->status.buffer.size_used],
1152 buff_diff, "\"%u\":", key);
1153 buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
1154 }
1155
1156 serializer->status.buffer.size_used += snprintf((char *)
1157 &serializer->buffer.data[serializer->status.buffer.size_used],
1158 buff_diff, "%s", value ? "true" : "false");
1159
1160 ndpi_serialize_json_post(_serializer);
1161 } else if(serializer->fmt == ndpi_serialization_format_csv) {
1162 if (ndpi_serializer_header_uint32(serializer, key) < 0) return(-1);
1163 ndpi_serialize_csv_pre(serializer);
1164 buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
1165 serializer->status.buffer.size_used += snprintf((char *)
1166 &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff,
1167 "%s", value ? "true" : "false");
1168 }
1169
1170 serializer->status.flags |= NDPI_SERIALIZER_STATUS_NOT_EMPTY;
1171 return(0);
1172 }
1173
1174 /* ********************************** */
1175
ndpi_serialize_binary_int32(ndpi_serializer * _serializer,const char * key,u_int16_t klen,int32_t value)1176 int ndpi_serialize_binary_int32(ndpi_serializer *_serializer,
1177 const char *key, u_int16_t klen,
1178 int32_t value) {
1179 ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
1180 u_int32_t buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
1181 u_int32_t needed;
1182
1183 if(ndpi_is_number(key, klen))
1184 return(ndpi_serialize_uint32_int32(_serializer, atoi(key), value));
1185
1186 needed =
1187 sizeof(u_int8_t) /* type */ +
1188 sizeof(u_int16_t) /* key len */ +
1189 klen /* key */ +
1190 sizeof(u_int32_t);
1191
1192 if(serializer->fmt == ndpi_serialization_format_json)
1193 needed += 16 + klen;
1194
1195 if(buff_diff < needed) {
1196 if(ndpi_extend_serializer_buffer(&serializer->buffer, needed - buff_diff) < 0)
1197 return(-1);
1198 buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
1199 }
1200
1201 if(serializer->fmt == ndpi_serialization_format_json) {
1202 ndpi_serialize_json_pre(_serializer);
1203
1204 if (!(serializer->status.flags & NDPI_SERIALIZER_STATUS_LIST)) {
1205 serializer->status.buffer.size_used += ndpi_json_string_escape(key, klen,
1206 (char *) &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff);
1207 buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
1208 serializer->status.buffer.size_used += snprintf((char *)
1209 &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff, ":");
1210 buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
1211 }
1212
1213 serializer->status.buffer.size_used += snprintf((char *)
1214 &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff, "%d", value);
1215
1216 ndpi_serialize_json_post(_serializer);
1217 } else if(serializer->fmt == ndpi_serialization_format_csv) {
1218 if (ndpi_serializer_header_string(serializer, key, klen) < 0) return(-1);
1219 ndpi_serialize_csv_pre(serializer);
1220 buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
1221 serializer->status.buffer.size_used += snprintf((char *)
1222 &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff,
1223 "%d", value);
1224 } else {
1225 if(value <= 127 && value >= -128) {
1226 serializer->buffer.data[serializer->status.buffer.size_used++] = (ndpi_serialization_string << 4) | ndpi_serialization_int8;
1227 ndpi_serialize_single_string(serializer, key, klen);
1228 ndpi_serialize_single_uint8(serializer, value);
1229 } else if(value <= 32767 && value >= -32768) {
1230 serializer->buffer.data[serializer->status.buffer.size_used++] = (ndpi_serialization_string << 4) | ndpi_serialization_int16;
1231 ndpi_serialize_single_string(serializer, key, klen);
1232 ndpi_serialize_single_uint16(serializer, value);
1233 } else {
1234 serializer->buffer.data[serializer->status.buffer.size_used++] = (ndpi_serialization_string << 4) | ndpi_serialization_int32;
1235 ndpi_serialize_single_string(serializer, key, klen);
1236 ndpi_serialize_single_uint32(serializer, value);
1237 }
1238 }
1239
1240 serializer->status.flags |= NDPI_SERIALIZER_STATUS_NOT_EMPTY;
1241
1242 return(0);
1243 }
1244
1245 /* ********************************** */
1246
ndpi_serialize_string_int32(ndpi_serializer * _serializer,const char * key,int32_t value)1247 int ndpi_serialize_string_int32(ndpi_serializer *_serializer,
1248 const char *key, int32_t value) {
1249 return(ndpi_serialize_binary_int32(_serializer, key, strlen(key), value));
1250 }
1251
1252 /* ********************************** */
1253
ndpi_serialize_binary_int64(ndpi_serializer * _serializer,const char * key,u_int16_t klen,int64_t value)1254 int ndpi_serialize_binary_int64(ndpi_serializer *_serializer,
1255 const char *key, u_int16_t klen,
1256 int64_t value) {
1257 ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
1258 u_int32_t buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
1259 u_int32_t needed;
1260
1261 if(ndpi_is_number(key, klen))
1262 return(ndpi_serialize_uint32_int64(_serializer, atoi(key), value));
1263
1264 needed =
1265 sizeof(u_int8_t) /* type */ +
1266 sizeof(u_int16_t) /* key len */ +
1267 klen /* key */ +
1268 sizeof(u_int32_t);
1269
1270 if(serializer->fmt == ndpi_serialization_format_json)
1271 needed += 16 + klen;
1272
1273 if(buff_diff < needed) {
1274 if(ndpi_extend_serializer_buffer(&serializer->buffer, needed - buff_diff) < 0)
1275 return(-1);
1276 buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
1277 }
1278
1279 if(serializer->fmt == ndpi_serialization_format_json) {
1280 ndpi_serialize_json_pre(_serializer);
1281
1282 if (!(serializer->status.flags & NDPI_SERIALIZER_STATUS_LIST)) {
1283 serializer->status.buffer.size_used += ndpi_json_string_escape(key, klen,
1284 (char *) &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff);
1285 buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
1286 serializer->status.buffer.size_used += snprintf((char *)
1287 &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff,
1288 ":");
1289 buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
1290 }
1291
1292 serializer->status.buffer.size_used += snprintf((char *)
1293 &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff,
1294 NDPI_I64_FORMAT, (long long int)value);
1295
1296 ndpi_serialize_json_post(_serializer);
1297 } else if(serializer->fmt == ndpi_serialization_format_csv) {
1298 if (ndpi_serializer_header_string(serializer, key, klen) < 0) return(-1);
1299 ndpi_serialize_csv_pre(serializer);
1300 buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
1301 serializer->status.buffer.size_used += snprintf((char *) &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff,
1302 NDPI_I64_FORMAT, (long long int)value);
1303 } else {
1304 if ((value & 0xFFFFFFFF) == value) {
1305 return(ndpi_serialize_string_int32(_serializer, key, value));
1306 } else {
1307 serializer->buffer.data[serializer->status.buffer.size_used++] = (ndpi_serialization_string << 4) | ndpi_serialization_int64;
1308 ndpi_serialize_single_string(serializer, key, klen);
1309 ndpi_serialize_single_uint32(serializer, value);
1310 }
1311 }
1312
1313 serializer->status.flags |= NDPI_SERIALIZER_STATUS_NOT_EMPTY;
1314 return(0);
1315 }
1316
1317 /* ********************************** */
1318
ndpi_serialize_string_int64(ndpi_serializer * _serializer,const char * key,int64_t value)1319 int ndpi_serialize_string_int64(ndpi_serializer *_serializer,
1320 const char *key, int64_t value) {
1321 return(ndpi_serialize_binary_int64(_serializer, key, strlen(key), value));
1322 }
1323
1324 /* ********************************** */
1325
ndpi_serialize_binary_uint32(ndpi_serializer * _serializer,const char * key,u_int16_t klen,u_int32_t value)1326 int ndpi_serialize_binary_uint32(ndpi_serializer *_serializer,
1327 const char *key, u_int16_t klen, u_int32_t value) {
1328 ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
1329 u_int32_t buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
1330 u_int32_t needed;
1331
1332 if(ndpi_is_number(key, klen))
1333 return(ndpi_serialize_uint32_uint32(_serializer, atoi(key), value));
1334
1335 needed =
1336 sizeof(u_int8_t) /* type */ +
1337 sizeof(u_int16_t) /* key len */ +
1338 klen /* key */ +
1339 sizeof(u_int32_t);
1340
1341 if(serializer->fmt == ndpi_serialization_format_json)
1342 needed += 16 + klen;
1343
1344 if(buff_diff < needed) {
1345 if(ndpi_extend_serializer_buffer(&serializer->buffer, needed - buff_diff) < 0)
1346 return(-1);
1347 buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
1348 }
1349
1350 if(serializer->fmt == ndpi_serialization_format_json) {
1351 ndpi_serialize_json_pre(_serializer);
1352
1353 if (!(serializer->status.flags & NDPI_SERIALIZER_STATUS_LIST)) {
1354 serializer->status.buffer.size_used += ndpi_json_string_escape(key, klen,
1355 (char *) &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff);
1356 buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
1357
1358 serializer->status.buffer.size_used += snprintf((char *)
1359 &serializer->buffer.data[serializer->status.buffer.size_used],
1360 buff_diff, ":");
1361 buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
1362 }
1363
1364 serializer->status.buffer.size_used += snprintf((char *)
1365 &serializer->buffer.data[serializer->status.buffer.size_used],
1366 buff_diff, "%u", value);
1367
1368 ndpi_serialize_json_post(_serializer);
1369 } else if(serializer->fmt == ndpi_serialization_format_csv) {
1370 if (ndpi_serializer_header_string(serializer, key, klen) < 0) return(-1);
1371 ndpi_serialize_csv_pre(serializer);
1372 buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
1373 serializer->status.buffer.size_used += snprintf((char *)
1374 &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff,
1375 "%u", value);
1376 } else {
1377 if(value <= 0xff) {
1378 serializer->buffer.data[serializer->status.buffer.size_used++] = (ndpi_serialization_string << 4) | ndpi_serialization_uint8;
1379 ndpi_serialize_single_string(serializer, key, klen);
1380 ndpi_serialize_single_uint8(serializer, value);
1381 } else if(value <= 0xffff) {
1382 serializer->buffer.data[serializer->status.buffer.size_used++] = (ndpi_serialization_string << 4) | ndpi_serialization_uint16;
1383 ndpi_serialize_single_string(serializer, key, klen);
1384 ndpi_serialize_single_uint16(serializer, value);
1385 } else {
1386 serializer->buffer.data[serializer->status.buffer.size_used++] = (ndpi_serialization_string << 4) | ndpi_serialization_uint32;
1387 ndpi_serialize_single_string(serializer, key, klen);
1388 ndpi_serialize_single_uint32(serializer, value);
1389 }
1390 }
1391
1392 serializer->status.flags |= NDPI_SERIALIZER_STATUS_NOT_EMPTY;
1393 return(0);
1394 }
1395
1396 /* ********************************** */
1397
ndpi_serialize_string_uint32(ndpi_serializer * _serializer,const char * key,u_int32_t value)1398 int ndpi_serialize_string_uint32(ndpi_serializer *_serializer,
1399 const char *key, u_int32_t value) {
1400 return(ndpi_serialize_binary_uint32(_serializer, key, strlen(key), value));
1401 }
1402
1403 /* ********************************** */
1404
ndpi_serialize_string_uint32_format(ndpi_serializer * _serializer,const char * key,u_int32_t value,const char * format)1405 int ndpi_serialize_string_uint32_format(ndpi_serializer *_serializer,
1406 const char *key, u_int32_t value,
1407 const char *format) {
1408 ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
1409
1410 if(serializer->fmt == ndpi_serialization_format_json) {
1411 /*
1412 JSON supports base 10 numbers only
1413 http://cjihrig.com/blog/json-overview/
1414 */
1415
1416 return(ndpi_serialize_string_uint32(_serializer, key, value));
1417 } else {
1418 char buf[16];
1419
1420 snprintf(buf, sizeof(buf), format, value);
1421 return(ndpi_serialize_string_string(_serializer, key, buf));
1422 }
1423 }
1424
1425 /* ********************************** */
1426
ndpi_serialize_binary_uint64(ndpi_serializer * _serializer,const char * key,u_int16_t klen,u_int64_t value)1427 int ndpi_serialize_binary_uint64(ndpi_serializer *_serializer,
1428 const char *key, u_int16_t klen,
1429 u_int64_t value) {
1430 ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
1431 u_int32_t buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
1432 u_int32_t needed;
1433
1434 if(ndpi_is_number(key, klen))
1435 return(ndpi_serialize_uint32_uint64(_serializer, atoi(key), value));
1436
1437 needed =
1438 sizeof(u_int8_t) /* type */ +
1439 sizeof(u_int16_t) /* key len */ +
1440 klen /* key */ +
1441 sizeof(u_int64_t);
1442
1443 if(serializer->fmt == ndpi_serialization_format_json)
1444 needed += 32 + klen;
1445
1446 if(buff_diff < needed) {
1447 if(ndpi_extend_serializer_buffer(&serializer->buffer, needed - buff_diff) < 0)
1448 return(-1);
1449 buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
1450 }
1451
1452 if(serializer->fmt == ndpi_serialization_format_json) {
1453 ndpi_serialize_json_pre(_serializer);
1454
1455 if (!(serializer->status.flags & NDPI_SERIALIZER_STATUS_LIST)) {
1456 serializer->status.buffer.size_used += ndpi_json_string_escape(key, klen,
1457 (char *) &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff);
1458 buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
1459 serializer->status.buffer.size_used += snprintf((char *)
1460 &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff,
1461 ":");
1462 buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
1463 }
1464
1465 serializer->status.buffer.size_used += snprintf((char *)
1466 &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff,
1467 NDPI_U64_FORMAT, (unsigned long long)value);
1468
1469 ndpi_serialize_json_post(_serializer);
1470 } else if(serializer->fmt == ndpi_serialization_format_csv) {
1471 if (ndpi_serializer_header_string(serializer, key, klen) < 0) return(-1);
1472 ndpi_serialize_csv_pre(serializer);
1473 buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
1474 serializer->status.buffer.size_used += snprintf((char *)
1475 &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff,
1476 NDPI_U64_FORMAT, (unsigned long long)value);
1477 } else {
1478 if(value <= 0xffffffff) {
1479 return(ndpi_serialize_string_uint32(_serializer, key, value));
1480 } else {
1481 serializer->buffer.data[serializer->status.buffer.size_used++] = (ndpi_serialization_string << 4) | ndpi_serialization_uint64;
1482 ndpi_serialize_single_string(serializer, key, klen);
1483 ndpi_serialize_single_uint64(serializer, value);
1484 }
1485 }
1486
1487 serializer->status.flags |= NDPI_SERIALIZER_STATUS_NOT_EMPTY;
1488 return(0);
1489 }
1490
1491 /* ********************************** */
1492
ndpi_serialize_string_uint64(ndpi_serializer * _serializer,const char * key,u_int64_t value)1493 int ndpi_serialize_string_uint64(ndpi_serializer *_serializer,
1494 const char *key, u_int64_t value) {
1495 return(ndpi_serialize_binary_uint64(_serializer, key, strlen(key), value));
1496 }
1497
1498 /* ********************************** */
1499
ndpi_serialize_binary_float(ndpi_serializer * _serializer,const char * key,u_int16_t klen,float value,const char * format)1500 int ndpi_serialize_binary_float(ndpi_serializer *_serializer,
1501 const char *key,
1502 u_int16_t klen,
1503 float value,
1504 const char *format /* e.f. "%.2f" */) {
1505 ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
1506 u_int32_t buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
1507 u_int32_t needed;
1508
1509 if(ndpi_is_number(key, klen))
1510 return(ndpi_serialize_uint32_float(_serializer, atoi(key), value, format));
1511
1512 needed =
1513 sizeof(u_int8_t) /* type */ +
1514 sizeof(u_int16_t) /* key len */ +
1515 klen /* key */ +
1516 sizeof(float);
1517
1518 if(serializer->fmt == ndpi_serialization_format_json)
1519 needed += 32 + klen;
1520
1521 if(buff_diff < needed) {
1522 if(ndpi_extend_serializer_buffer(&serializer->buffer, needed - buff_diff) < 0)
1523 return(-1);
1524 buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
1525 }
1526
1527 if(serializer->fmt == ndpi_serialization_format_json) {
1528 ndpi_serialize_json_pre(_serializer);
1529
1530 if (!(serializer->status.flags & NDPI_SERIALIZER_STATUS_LIST)) {
1531 serializer->status.buffer.size_used += ndpi_json_string_escape(key, klen,
1532 (char *) &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff);
1533 buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
1534 serializer->buffer.data[serializer->status.buffer.size_used] = ':';
1535 serializer->status.buffer.size_used++;
1536 }
1537
1538 serializer->status.buffer.size_used += snprintf((char *) &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff, format, value);
1539
1540 ndpi_serialize_json_post(_serializer);
1541 } else if(serializer->fmt == ndpi_serialization_format_csv) {
1542 if (ndpi_serializer_header_string(serializer, key, klen) < 0) return(-1);
1543 ndpi_serialize_csv_pre(serializer);
1544 buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
1545 serializer->status.buffer.size_used += snprintf((char *) &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff, format, value);
1546 } else {
1547 serializer->buffer.data[serializer->status.buffer.size_used++] = (ndpi_serialization_string << 4) | ndpi_serialization_float;
1548
1549 ndpi_serialize_single_string(serializer, key, klen);
1550 ndpi_serialize_single_float(serializer, value);
1551 }
1552
1553 serializer->status.flags |= NDPI_SERIALIZER_STATUS_NOT_EMPTY;
1554 return(0);
1555 }
1556
1557 /* ********************************** */
1558
ndpi_serialize_string_float(ndpi_serializer * _serializer,const char * key,float value,const char * format)1559 int ndpi_serialize_string_float(ndpi_serializer *_serializer,
1560 const char *key,
1561 float value,
1562 const char *format /* e.f. "%.2f" */) {
1563 return(ndpi_serialize_binary_float(_serializer, key, strlen(key), value, format));
1564 }
1565
1566 /* ********************************** */
1567
1568 /* Key is a <string, len> pair, value is a raw value */
ndpi_serialize_binary_raw(ndpi_serializer * _serializer,const char * key,u_int16_t klen,const char * value,u_int16_t vlen,u_int8_t escape)1569 static int ndpi_serialize_binary_raw(ndpi_serializer *_serializer,
1570 const char *key,
1571 u_int16_t klen,
1572 const char *value,
1573 u_int16_t vlen,
1574 u_int8_t escape) {
1575 ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
1576 u_int32_t buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
1577 u_int32_t needed;
1578
1579 needed =
1580 sizeof(u_int8_t) /* type */ +
1581 sizeof(u_int16_t) /* key len */ +
1582 klen +
1583 sizeof(u_int16_t) /* len */ +
1584 vlen;
1585
1586 if(serializer->fmt == ndpi_serialization_format_json)
1587 needed += 16 + klen + vlen;
1588
1589 if(buff_diff < needed) {
1590 if(ndpi_extend_serializer_buffer(&serializer->buffer, needed - buff_diff) < 0)
1591 return(-1);
1592 buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
1593 }
1594
1595 if(serializer->fmt == ndpi_serialization_format_json) {
1596 ndpi_serialize_json_pre(_serializer);
1597
1598 if (!(serializer->status.flags & NDPI_SERIALIZER_STATUS_LIST)) {
1599 serializer->status.buffer.size_used += ndpi_json_string_escape(key, klen,
1600 (char *) &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff);
1601 buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
1602 serializer->status.buffer.size_used += snprintf((char *) &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff, ":");
1603 buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
1604 }
1605
1606 if (escape)
1607 serializer->status.buffer.size_used += ndpi_json_string_escape(value, vlen,
1608 (char *) &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff);
1609 else
1610 serializer->status.buffer.size_used += snprintf((char *) &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff,
1611 value, vlen);
1612
1613 ndpi_serialize_json_post(_serializer);
1614 } else if(serializer->fmt == ndpi_serialization_format_csv) {
1615 if (ndpi_serializer_header_string(serializer, key, klen) < 0) return(-1);
1616 ndpi_serialize_csv_pre(serializer);
1617 buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
1618 serializer->status.buffer.size_used += snprintf((char *)
1619 &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff,
1620 "%s", value);
1621 } else {
1622 serializer->buffer.data[serializer->status.buffer.size_used++] = (ndpi_serialization_string << 4) | ndpi_serialization_string;
1623
1624 ndpi_serialize_single_string(serializer, key, klen);
1625 ndpi_serialize_single_string(serializer, value, vlen);
1626 }
1627
1628 serializer->status.flags |= NDPI_SERIALIZER_STATUS_NOT_EMPTY;
1629 return(0);
1630 }
1631
1632 /* ********************************** */
1633
1634 /* Key is a <string, len> pair, value is a <string, len> pair */
ndpi_serialize_binary_binary(ndpi_serializer * _serializer,const char * key,u_int16_t klen,const char * _value,u_int16_t vlen)1635 int ndpi_serialize_binary_binary(ndpi_serializer *_serializer,
1636 const char *key,
1637 u_int16_t klen,
1638 const char *_value,
1639 u_int16_t vlen) {
1640 const char *value = _value ? _value : "";
1641
1642 if(ndpi_is_number(key, klen))
1643 return(ndpi_serialize_uint32_binary(_serializer, atoi(key), value, vlen));
1644
1645 return ndpi_serialize_binary_raw(_serializer, key, klen, value, vlen, 1 /* escape */);
1646 }
1647
1648 /* ********************************** */
1649
1650 /* Key is a string, value is a <string, len> pair */
ndpi_serialize_string_binary(ndpi_serializer * _serializer,const char * key,const char * _value,u_int16_t vlen)1651 int ndpi_serialize_string_binary(ndpi_serializer *_serializer,
1652 const char *key, const char *_value,
1653 u_int16_t vlen) {
1654 return(ndpi_serialize_binary_binary(_serializer, key, strlen(key), _value, vlen));
1655 }
1656
1657 /* ********************************** */
1658
1659 /* Key is a string, value is a string (strlen is used to compute the len) */
ndpi_serialize_string_string(ndpi_serializer * _serializer,const char * key,const char * _value)1660 int ndpi_serialize_string_string(ndpi_serializer *_serializer,
1661 const char *key, const char *_value) {
1662 const char *value = _value ? _value : "";
1663 return(ndpi_serialize_binary_binary(_serializer, key, strlen(key), value, strlen(value)));
1664 }
1665
1666 /* ********************************** */
1667
1668 /* Key is a string, value is a raw json value (it can be a number, an escaped/quoted string, an array, ..) */
ndpi_serialize_string_raw(ndpi_serializer * _serializer,const char * key,const char * _value,u_int16_t vlen)1669 int ndpi_serialize_string_raw(ndpi_serializer *_serializer,
1670 const char *key, const char *_value, u_int16_t vlen) {
1671 return(ndpi_serialize_binary_raw(_serializer, key, strlen(key), _value, vlen, 0 /* do not escape */));
1672 }
1673
1674 /* ********************************** */
1675
ndpi_serialize_binary_boolean(ndpi_serializer * _serializer,const char * key,u_int16_t klen,u_int8_t value)1676 int ndpi_serialize_binary_boolean(ndpi_serializer *_serializer,
1677 const char *key, u_int16_t klen, u_int8_t value) {
1678 ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
1679 u_int32_t buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
1680 u_int32_t needed;
1681
1682 if(serializer->fmt != ndpi_serialization_format_json &&
1683 serializer->fmt != ndpi_serialization_format_csv)
1684 return -1;
1685
1686 if(ndpi_is_number(key, klen))
1687 return(ndpi_serialize_uint32_boolean(_serializer, atoi(key), value));
1688
1689 needed = klen + 16;
1690
1691 if(buff_diff < needed) {
1692 if(ndpi_extend_serializer_buffer(&serializer->buffer, needed - buff_diff) < 0)
1693 return(-1);
1694 buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
1695 }
1696
1697 if(serializer->fmt == ndpi_serialization_format_json) {
1698 ndpi_serialize_json_pre(_serializer);
1699
1700 if (!(serializer->status.flags & NDPI_SERIALIZER_STATUS_LIST)) {
1701 serializer->status.buffer.size_used += ndpi_json_string_escape(key, klen,
1702 (char *) &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff);
1703 buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
1704 serializer->status.buffer.size_used += snprintf((char *)
1705 &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff, ":");
1706 buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
1707 }
1708
1709 serializer->status.buffer.size_used += snprintf((char *)
1710 &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff, "%s",
1711 value ? "true" : "false");
1712
1713 ndpi_serialize_json_post(_serializer);
1714 } else if(serializer->fmt == ndpi_serialization_format_csv) {
1715 if (ndpi_serializer_header_string(serializer, key, strlen(key)) < 0) return(-1);
1716 ndpi_serialize_csv_pre(serializer);
1717 buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
1718 serializer->status.buffer.size_used += snprintf((char *) &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff,
1719 "%s", value ? "true" : "false");
1720 }
1721
1722 serializer->status.flags |= NDPI_SERIALIZER_STATUS_NOT_EMPTY;
1723 return(0);
1724 }
1725
1726 /* ********************************** */
1727
ndpi_serialize_string_boolean(ndpi_serializer * _serializer,const char * key,u_int8_t value)1728 int ndpi_serialize_string_boolean(ndpi_serializer *_serializer,
1729 const char *key, u_int8_t value) {
1730 return(ndpi_serialize_binary_boolean(_serializer, key, strlen(key), value));
1731 }
1732
1733 /* ********************************** */
1734
ndpi_serialize_start_of_list_binary(ndpi_serializer * _serializer,const char * key,u_int16_t klen)1735 int ndpi_serialize_start_of_list_binary(ndpi_serializer *_serializer,
1736 const char *key, u_int16_t klen) {
1737 ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
1738 u_int32_t buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
1739 u_int32_t needed;
1740
1741 if(serializer->fmt != ndpi_serialization_format_json &&
1742 serializer->fmt != ndpi_serialization_format_tlv)
1743 return(-1);
1744
1745 needed = 16 + klen;
1746
1747 if(buff_diff < needed) {
1748 if(ndpi_extend_serializer_buffer(&serializer->buffer, needed - buff_diff) < 0)
1749 return(-1);
1750 buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
1751 }
1752
1753 if (serializer->fmt == ndpi_serialization_format_json) {
1754 ndpi_serialize_json_pre(_serializer);
1755
1756 serializer->status.buffer.size_used += ndpi_json_string_escape(key, klen,
1757 (char *) &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff);
1758
1759 buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
1760
1761 serializer->status.buffer.size_used += snprintf((char *) &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff, ": [");
1762
1763 serializer->status.flags |= NDPI_SERIALIZER_STATUS_LIST | NDPI_SERIALIZER_STATUS_SOL;
1764
1765 ndpi_serialize_json_post(_serializer);
1766 } else {
1767 serializer->buffer.data[serializer->status.buffer.size_used++] = ndpi_serialization_start_of_list;
1768 ndpi_serialize_single_string(serializer, key, klen);
1769 }
1770
1771 return(0);
1772 }
1773
1774 /* ********************************** */
1775
1776 /* Serialize start of simple values list */
ndpi_serialize_start_of_list(ndpi_serializer * _serializer,const char * _key)1777 int ndpi_serialize_start_of_list(ndpi_serializer *_serializer,
1778 const char *_key) {
1779 const char *key = _key ? _key : "";
1780 u_int16_t klen = strlen(key);
1781
1782 return ndpi_serialize_start_of_list_binary(_serializer, key, klen);
1783 }
1784
1785 /* ********************************** */
1786
1787 /* Serialize end of simple values list */
ndpi_serialize_end_of_list(ndpi_serializer * _serializer)1788 int ndpi_serialize_end_of_list(ndpi_serializer *_serializer) {
1789 ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
1790
1791 if(serializer->fmt != ndpi_serialization_format_json &&
1792 serializer->fmt != ndpi_serialization_format_tlv)
1793 return(-1);
1794
1795 if (serializer->fmt == ndpi_serialization_format_json) {
1796 if(serializer->status.flags & NDPI_SERIALIZER_STATUS_SOL) /* Empty list */
1797 serializer->status.flags &= ~NDPI_SERIALIZER_STATUS_SOL;
1798
1799 serializer->status.flags &= ~NDPI_SERIALIZER_STATUS_LIST;
1800 } else {
1801 serializer->buffer.data[serializer->status.buffer.size_used++] = ndpi_serialization_end_of_list;
1802 }
1803
1804 return(0);
1805 }
1806
1807 /* ********************************** */
1808
1809 /* Serialize start of nested block */
ndpi_serialize_start_of_block_binary(ndpi_serializer * _serializer,const char * key,u_int16_t klen)1810 int ndpi_serialize_start_of_block_binary(ndpi_serializer *_serializer,
1811 const char *key, u_int16_t klen) {
1812 ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
1813 u_int32_t buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
1814 u_int32_t needed;
1815
1816 if(serializer->fmt != ndpi_serialization_format_json &&
1817 serializer->fmt != ndpi_serialization_format_tlv)
1818 return(-1);
1819
1820 needed = 16 + klen;
1821
1822 if(buff_diff < needed) {
1823 if(ndpi_extend_serializer_buffer(&serializer->buffer, needed - buff_diff) < 0)
1824 return(-1);
1825 buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
1826 }
1827
1828 if (serializer->fmt == ndpi_serialization_format_json) {
1829 ndpi_serialize_json_pre(_serializer);
1830 serializer->status.buffer.size_used += ndpi_json_string_escape(key, klen,
1831 (char *) &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff);
1832 buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
1833 serializer->status.buffer.size_used += snprintf((char *) &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff, ": {");
1834 buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
1835 ndpi_serialize_json_post(_serializer);
1836
1837 serializer->status.flags |= NDPI_SERIALIZER_STATUS_SOB;
1838 } else /* ndpi_serialization_format_tlv */ {
1839 serializer->buffer.data[serializer->status.buffer.size_used++] = ndpi_serialization_start_of_block;
1840 ndpi_serialize_single_string(serializer, key, klen);
1841 }
1842
1843 return(0);
1844 }
1845
1846 /* ********************************** */
1847
1848 /* Serialize start of nested block */
ndpi_serialize_start_of_block(ndpi_serializer * _serializer,const char * _key)1849 int ndpi_serialize_start_of_block(ndpi_serializer *_serializer,
1850 const char *_key) {
1851 const char *key = _key ? _key : "";
1852 u_int16_t klen = strlen(key);
1853
1854 return ndpi_serialize_start_of_block_binary(_serializer, key, klen);
1855 }
1856
1857 /* ********************************** */
1858
1859 /* Serialize end of nested block (JSON only)*/
ndpi_serialize_end_of_block(ndpi_serializer * _serializer)1860 int ndpi_serialize_end_of_block(ndpi_serializer *_serializer) {
1861 ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
1862 u_int32_t buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
1863 u_int32_t needed;
1864
1865 if(serializer->fmt != ndpi_serialization_format_json &&
1866 serializer->fmt != ndpi_serialization_format_tlv)
1867 return(-1);
1868
1869 needed = 4;
1870
1871 if(buff_diff < needed) {
1872 if(ndpi_extend_serializer_buffer(&serializer->buffer, needed - buff_diff) < 0)
1873 return(-1);
1874 buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
1875 }
1876
1877 if (serializer->fmt == ndpi_serialization_format_json) {
1878
1879 if(serializer->status.flags & NDPI_SERIALIZER_STATUS_SOB) /* Empty block */
1880 serializer->status.flags &= ~NDPI_SERIALIZER_STATUS_SOB;
1881
1882 // buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
1883 ndpi_serialize_json_post(_serializer);
1884 } else {
1885 serializer->buffer.data[serializer->status.buffer.size_used++] = ndpi_serialization_end_of_block;
1886 }
1887
1888 return(0);
1889 }
1890
1891 /* ********************************** */
1892
ndpi_serializer_create_snapshot(ndpi_serializer * _serializer)1893 void ndpi_serializer_create_snapshot(ndpi_serializer *_serializer) {
1894 ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
1895
1896 #if 0
1897 printf("[NDPI] Snapshot status: %s%s%s\n",
1898 (serializer->status.flags & NDPI_SERIALIZER_STATUS_COMMA) ? " COMMA" : "",
1899 (serializer->status.flags & NDPI_SERIALIZER_STATUS_ARRAY) ? " ARRAY" : "",
1900 (serializer->status.flags & NDPI_SERIALIZER_STATUS_EOR) ? " EOR" : ""
1901 );
1902 #endif
1903
1904 memcpy(&serializer->snapshot, &serializer->status, sizeof(ndpi_private_serializer_status));
1905 serializer->has_snapshot = 1;
1906 }
1907
1908 /* ********************************** */
1909
ndpi_serializer_rollback_snapshot(ndpi_serializer * _serializer)1910 void ndpi_serializer_rollback_snapshot(ndpi_serializer *_serializer) {
1911 ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
1912
1913 if(serializer->has_snapshot) {
1914 memcpy(&serializer->status, &serializer->snapshot, sizeof(ndpi_private_serializer_status));
1915 serializer->has_snapshot = 0;
1916
1917 if(serializer->fmt == ndpi_serialization_format_json) {
1918 if(serializer->status.flags & NDPI_SERIALIZER_STATUS_ARRAY) {
1919 serializer->buffer.data[serializer->status.buffer.size_used-1] = ']';
1920 } else {
1921 serializer->buffer.data[0] = ' ';
1922 serializer->buffer.data[serializer->status.buffer.size_used-1] = '}';
1923 }
1924 }
1925 }
1926 }
1927
1928 /* ********************************** */
1929 /* ********************************** */
1930
ndpi_init_deserializer_buf(ndpi_deserializer * _deserializer,u_int8_t * serialized_buffer,u_int32_t serialized_buffer_len)1931 int ndpi_init_deserializer_buf(ndpi_deserializer *_deserializer,
1932 u_int8_t *serialized_buffer,
1933 u_int32_t serialized_buffer_len) {
1934 ndpi_private_deserializer *deserializer = (ndpi_private_deserializer*)_deserializer;
1935
1936 if(serialized_buffer_len < (2 * sizeof(u_int8_t)))
1937 return(-1);
1938
1939 deserializer->buffer.data = serialized_buffer;
1940
1941 if(deserializer->buffer.data[0] != 1)
1942 return(-2); /* Invalid version */
1943
1944 deserializer->buffer.size = serialized_buffer_len;
1945 deserializer->fmt = deserializer->buffer.data[1];
1946 ndpi_reset_serializer(_deserializer);
1947
1948 return(0);
1949 }
1950
1951 /* ********************************** */
1952
ndpi_init_deserializer(ndpi_deserializer * deserializer,ndpi_serializer * _serializer)1953 int ndpi_init_deserializer(ndpi_deserializer *deserializer,
1954 ndpi_serializer *_serializer) {
1955 ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
1956
1957 return(ndpi_init_deserializer_buf(deserializer,
1958 serializer->buffer.data,
1959 serializer->status.buffer.size_used));
1960 }
1961
1962 /* ********************************** */
1963
ndpi_deserialize_get_format(ndpi_deserializer * _deserializer)1964 ndpi_serialization_format ndpi_deserialize_get_format(ndpi_deserializer *_deserializer) {
1965 ndpi_private_deserializer *deserializer = (ndpi_private_deserializer*)_deserializer;
1966 return(deserializer->fmt);
1967 }
1968
1969 /* ********************************** */
1970
ndpi_deserialize_get_key_subtype(ndpi_private_deserializer * deserializer)1971 static inline ndpi_serialization_type ndpi_deserialize_get_key_subtype(ndpi_private_deserializer *deserializer) {
1972 u_int8_t type;
1973
1974 if(deserializer->status.buffer.size_used >= deserializer->buffer.size)
1975 return(ndpi_serialization_unknown);
1976
1977 type = deserializer->buffer.data[deserializer->status.buffer.size_used];
1978
1979 return((ndpi_serialization_type) (type >> 4));
1980 }
1981
1982 /* ********************************** */
1983
ndpi_deserialize_get_value_subtype(ndpi_private_deserializer * deserializer)1984 static inline ndpi_serialization_type ndpi_deserialize_get_value_subtype(ndpi_private_deserializer *deserializer) {
1985 u_int8_t type;
1986
1987 if(deserializer->status.buffer.size_used >= deserializer->buffer.size)
1988 return(ndpi_serialization_unknown);
1989
1990 type = deserializer->buffer.data[deserializer->status.buffer.size_used];
1991
1992 return(ndpi_serialization_type) (type & 0xf);
1993 }
1994
1995 /* ********************************** */
1996
ndpi_deserialize_get_item_type(ndpi_deserializer * _deserializer,ndpi_serialization_type * key_type)1997 ndpi_serialization_type ndpi_deserialize_get_item_type(ndpi_deserializer *_deserializer, ndpi_serialization_type *key_type) {
1998 ndpi_private_deserializer *deserializer = (ndpi_private_deserializer*)_deserializer;
1999 ndpi_serialization_type kt, et;
2000
2001 /* Note: 32/64 bit types are automatically encoded/decoded as 8/16 bit */
2002
2003 kt = ndpi_deserialize_get_key_subtype(deserializer);
2004
2005 switch(kt) {
2006 case ndpi_serialization_uint8:
2007 case ndpi_serialization_uint16:
2008 kt = ndpi_serialization_uint32;
2009 break;
2010 default:
2011 break;
2012 }
2013
2014 et = ndpi_deserialize_get_value_subtype(deserializer);
2015
2016 switch(et) {
2017 case ndpi_serialization_uint8:
2018 case ndpi_serialization_uint16:
2019 et = ndpi_serialization_uint32;
2020 break;
2021 case ndpi_serialization_int8:
2022 case ndpi_serialization_int16:
2023 et = ndpi_serialization_int32;
2024 break;
2025 default:
2026 break;
2027 }
2028
2029 *key_type = kt;
2030 return(et);
2031 }
2032
2033 /* ********************************** */
2034
ndpi_deserialize_get_single_string_size(ndpi_private_deserializer * deserializer,u_int32_t offset)2035 static inline int ndpi_deserialize_get_single_string_size(ndpi_private_deserializer *deserializer, u_int32_t offset) {
2036 u_int32_t buff_diff = deserializer->buffer.size - offset;
2037 u_int16_t expected, str_len;
2038
2039 expected = sizeof(u_int16_t) /* len */;
2040 if(buff_diff < expected) return(-2);
2041
2042 str_len = ntohs(*((u_int16_t *) &deserializer->buffer.data[offset]));
2043
2044 expected += str_len;
2045 if(buff_diff < expected) return(-2);
2046
2047 return(expected);
2048 }
2049
2050 /* ********************************** */
2051
ndpi_deserialize_get_single_size(ndpi_private_deserializer * deserializer,ndpi_serialization_type type,u_int32_t offset)2052 static inline int ndpi_deserialize_get_single_size(ndpi_private_deserializer *deserializer, ndpi_serialization_type type, u_int32_t offset) {
2053 u_int16_t size;
2054
2055 switch(type) {
2056 case ndpi_serialization_uint8:
2057 case ndpi_serialization_int8:
2058 size = sizeof(u_int8_t);
2059 break;
2060 case ndpi_serialization_uint16:
2061 case ndpi_serialization_int16:
2062 size = sizeof(u_int16_t);
2063 break;
2064 case ndpi_serialization_uint32:
2065 case ndpi_serialization_int32:
2066 size = sizeof(u_int32_t);
2067 break;
2068 case ndpi_serialization_uint64:
2069 case ndpi_serialization_int64:
2070 size = sizeof(u_int64_t);
2071 break;
2072 case ndpi_serialization_float:
2073 size = sizeof(float);
2074 break;
2075 case ndpi_serialization_string:
2076 case ndpi_serialization_start_of_block:
2077 case ndpi_serialization_start_of_list:
2078 size = ndpi_deserialize_get_single_string_size(deserializer, offset);
2079 break;
2080 case ndpi_serialization_end_of_record:
2081 case ndpi_serialization_end_of_block:
2082 case ndpi_serialization_end_of_list:
2083 case ndpi_serialization_unknown:
2084 size = 0;
2085 break;
2086 default:
2087 return(-2);
2088 break;
2089 }
2090
2091 return(size);
2092 }
2093
2094 /* ********************************** */
2095
2096 /* Move the current offset (status.buffer.size_used) to point
2097 * to the next element */
ndpi_deserialize_next(ndpi_deserializer * _deserializer)2098 int ndpi_deserialize_next(ndpi_deserializer *_deserializer) {
2099 ndpi_private_deserializer *deserializer = (ndpi_private_deserializer *) _deserializer;
2100 u_int32_t buff_diff = deserializer->buffer.size - deserializer->status.buffer.size_used;
2101 ndpi_serialization_type kt, et;
2102 u_int16_t expected;
2103 int size;
2104
2105 expected = sizeof(u_int8_t) /* type */;
2106
2107 if(buff_diff < expected) return(-2);
2108
2109 kt = ndpi_deserialize_get_key_subtype(deserializer);
2110 size = ndpi_deserialize_get_single_size(deserializer, kt, deserializer->status.buffer.size_used + expected);
2111
2112 if(size < 0) return(-2);
2113
2114 expected += size;
2115
2116 et = ndpi_deserialize_get_value_subtype(deserializer);
2117 size = ndpi_deserialize_get_single_size(deserializer, et, deserializer->status.buffer.size_used + expected);
2118
2119 if(size < 0) return(-2);
2120
2121 expected += size;
2122
2123 deserializer->status.buffer.size_used += expected;
2124
2125 return(0);
2126 }
2127
2128 /* ********************************** */
2129
ndpi_deserialize_key_uint32(ndpi_deserializer * _deserializer,u_int32_t * key)2130 int ndpi_deserialize_key_uint32(ndpi_deserializer *_deserializer,
2131 u_int32_t *key) {
2132 ndpi_private_deserializer *deserializer = (ndpi_private_deserializer*)_deserializer;
2133 u_int32_t offset, buff_diff = deserializer->buffer.size - deserializer->status.buffer.size_used;
2134 ndpi_serialization_type kt;
2135 u_int16_t expected;
2136 u_int16_t v16;
2137 u_int8_t v8;
2138 int size;
2139
2140 expected = sizeof(u_int8_t) /* type */;
2141 if(buff_diff < expected) return(-2);
2142
2143 kt = ndpi_deserialize_get_key_subtype(deserializer);
2144
2145 size = ndpi_deserialize_get_single_size(deserializer, kt, deserializer->status.buffer.size_used + expected);
2146 if(size < 0) return(-2);
2147
2148 offset = deserializer->status.buffer.size_used + expected;
2149
2150 switch(kt) {
2151 case ndpi_serialization_uint32:
2152 ndpi_deserialize_single_uint32(deserializer, offset, key);
2153 break;
2154 case ndpi_serialization_uint16:
2155 ndpi_deserialize_single_uint16(deserializer, offset, &v16);
2156 *key = v16;
2157 break;
2158 case ndpi_serialization_uint8:
2159 ndpi_deserialize_single_uint8(deserializer, offset, &v8);
2160 *key = v8;
2161 break;
2162 default:
2163 return(-1);
2164 break;
2165 }
2166
2167 return(0);
2168 }
2169
2170 /* ********************************** */
2171
2172 /* Return the string key for the current element */
ndpi_deserialize_key_string(ndpi_deserializer * _deserializer,ndpi_string * key)2173 int ndpi_deserialize_key_string(ndpi_deserializer *_deserializer,
2174 ndpi_string *key) {
2175 ndpi_private_deserializer *deserializer = (ndpi_private_deserializer*)_deserializer;
2176 ndpi_serialization_type kt;
2177 u_int32_t buff_diff = deserializer->buffer.size - deserializer->status.buffer.size_used;
2178 u_int16_t expected;
2179 int size;
2180
2181 expected = sizeof(u_int8_t) /* type */;
2182 if(buff_diff < expected) return(-2);
2183
2184 kt = ndpi_deserialize_get_key_subtype(deserializer);
2185
2186 size = ndpi_deserialize_get_single_size(deserializer, kt, deserializer->status.buffer.size_used + expected);
2187 if(size < 0) return(-2);
2188
2189 ndpi_deserialize_single_string(deserializer, deserializer->status.buffer.size_used + expected, key);
2190
2191 return(0);
2192 }
2193
2194 /* ********************************** */
2195
ndpi_deserialize_value_uint32(ndpi_deserializer * _deserializer,u_int32_t * value)2196 int ndpi_deserialize_value_uint32(ndpi_deserializer *_deserializer,
2197 u_int32_t *value) {
2198 ndpi_private_deserializer *deserializer = (ndpi_private_deserializer*)_deserializer;
2199 ndpi_serialization_type kt, et;
2200 u_int32_t offset, buff_diff = deserializer->buffer.size - deserializer->status.buffer.size_used;
2201 u_int16_t v16;
2202 u_int8_t v8;
2203 u_int16_t expected;
2204 int size;
2205
2206 expected = sizeof(u_int8_t) /* type */;
2207 if(buff_diff < expected) return(-2);
2208
2209 kt = ndpi_deserialize_get_key_subtype(deserializer);
2210 size = ndpi_deserialize_get_single_size(deserializer, kt, deserializer->status.buffer.size_used + expected);
2211 if(size < 0) return(-2);
2212
2213 expected += size;
2214
2215 et = ndpi_deserialize_get_value_subtype(deserializer);
2216 size = ndpi_deserialize_get_single_size(deserializer, et, deserializer->status.buffer.size_used + expected);
2217 if(size < 0) return(-2);
2218
2219 offset = deserializer->status.buffer.size_used + expected;
2220
2221 switch(et) {
2222 case ndpi_serialization_uint32:
2223 ndpi_deserialize_single_uint32(deserializer, offset, value);
2224 break;
2225 case ndpi_serialization_uint16:
2226 ndpi_deserialize_single_uint16(deserializer, offset, &v16);
2227 *value = v16;
2228 break;
2229 case ndpi_serialization_uint8:
2230 ndpi_deserialize_single_uint8(deserializer, offset, &v8);
2231 *value = v8;
2232 break;
2233 default:
2234 break;
2235 }
2236
2237 return(0);
2238 }
2239
2240 /* ********************************** */
2241
ndpi_deserialize_value_uint64(ndpi_deserializer * _deserializer,u_int64_t * value)2242 int ndpi_deserialize_value_uint64(ndpi_deserializer *_deserializer,
2243 u_int64_t *value) {
2244 ndpi_private_deserializer *deserializer = (ndpi_private_deserializer*)_deserializer;
2245 ndpi_serialization_type kt, et;
2246 u_int32_t buff_diff = deserializer->buffer.size - deserializer->status.buffer.size_used;
2247 u_int32_t v32;
2248 u_int16_t expected;
2249 int size;
2250 int rc;
2251
2252 expected = sizeof(u_int8_t) /* type */;
2253 if(buff_diff < expected) return(-2);
2254
2255 kt = ndpi_deserialize_get_key_subtype(deserializer);
2256 size = ndpi_deserialize_get_single_size(deserializer, kt, deserializer->status.buffer.size_used + expected);
2257 if(size < 0) return(-2);
2258
2259 expected += size;
2260
2261 et = ndpi_deserialize_get_value_subtype(deserializer);
2262 size = ndpi_deserialize_get_single_size(deserializer, et, deserializer->status.buffer.size_used + expected);
2263 if(size < 0) return(-2);
2264
2265 if(et != ndpi_serialization_uint64) {
2266 /* Try with smaller uint types */
2267 rc = ndpi_deserialize_value_uint32(_deserializer, &v32);
2268 *value = v32;
2269 return(rc);
2270 }
2271
2272 ndpi_deserialize_single_uint64(deserializer, deserializer->status.buffer.size_used + expected, value);
2273
2274 return(0);
2275 }
2276
2277 /* ********************************** */
2278
ndpi_deserialize_value_int32(ndpi_deserializer * _deserializer,int32_t * value)2279 int ndpi_deserialize_value_int32(ndpi_deserializer *_deserializer,
2280 int32_t *value) {
2281 ndpi_private_deserializer *deserializer = (ndpi_private_deserializer*)_deserializer;
2282 ndpi_serialization_type kt, et;
2283 u_int32_t offset, buff_diff = deserializer->buffer.size - deserializer->status.buffer.size_used;
2284 int16_t v16;
2285 int8_t v8;
2286 u_int16_t expected;
2287 int size;
2288
2289 expected = sizeof(u_int8_t) /* type */;
2290 if(buff_diff < expected) return(-2);
2291
2292 kt = ndpi_deserialize_get_key_subtype(deserializer);
2293 size = ndpi_deserialize_get_single_size(deserializer, kt, deserializer->status.buffer.size_used + expected);
2294 if(size < 0) return(-2);
2295
2296 expected += size;
2297
2298 et = ndpi_deserialize_get_value_subtype(deserializer);
2299 size = ndpi_deserialize_get_single_size(deserializer, et, deserializer->status.buffer.size_used + expected);
2300 if(size < 0) return(-2);
2301
2302 offset = deserializer->status.buffer.size_used + expected;
2303
2304 switch(et) {
2305 case ndpi_serialization_int32:
2306 ndpi_deserialize_single_int32(deserializer, offset, value);
2307 break;
2308 case ndpi_serialization_int16:
2309 ndpi_deserialize_single_int16(deserializer, offset, &v16);
2310 *value = v16;
2311 break;
2312 case ndpi_serialization_int8:
2313 ndpi_deserialize_single_int8(deserializer, offset, &v8);
2314 *value = v8;
2315 break;
2316 default:
2317 break;
2318 }
2319
2320 return(0);
2321 }
2322
2323 /* ********************************** */
2324
ndpi_deserialize_value_int64(ndpi_deserializer * _deserializer,int64_t * value)2325 int ndpi_deserialize_value_int64(ndpi_deserializer *_deserializer,
2326 int64_t *value) {
2327 ndpi_private_deserializer *deserializer = (ndpi_private_deserializer*)_deserializer;
2328 ndpi_serialization_type kt, et;
2329 u_int32_t buff_diff = deserializer->buffer.size - deserializer->status.buffer.size_used;
2330 int32_t v32;
2331 u_int16_t expected;
2332 int size;
2333 int rc;
2334
2335 expected = sizeof(u_int8_t) /* type */;
2336 if(buff_diff < expected) return(-2);
2337
2338 kt = ndpi_deserialize_get_key_subtype(deserializer);
2339 size = ndpi_deserialize_get_single_size(deserializer, kt, deserializer->status.buffer.size_used + expected);
2340 if(size < 0) return(-2);
2341
2342 expected += size;
2343
2344 et = ndpi_deserialize_get_value_subtype(deserializer);
2345 size = ndpi_deserialize_get_single_size(deserializer, et, deserializer->status.buffer.size_used + expected);
2346 if(size < 0) return(-2);
2347
2348 if(et != ndpi_serialization_int64) {
2349 /* Try with smaller int types */
2350 rc = ndpi_deserialize_value_int32(_deserializer, &v32);
2351 *value = v32;
2352 return(rc);
2353 }
2354
2355 ndpi_deserialize_single_int64(deserializer, deserializer->status.buffer.size_used + expected, value);
2356
2357 return(0);
2358 }
2359
2360 /* ********************************** */
2361
ndpi_deserialize_value_float(ndpi_deserializer * _deserializer,float * value)2362 int ndpi_deserialize_value_float(ndpi_deserializer *_deserializer,
2363 float *value) {
2364 ndpi_private_deserializer *deserializer = (ndpi_private_deserializer*)_deserializer;
2365 ndpi_serialization_type kt, et;
2366 u_int32_t buff_diff = deserializer->buffer.size - deserializer->status.buffer.size_used;
2367 u_int16_t expected;
2368 int size;
2369
2370 expected = sizeof(u_int8_t) /* type */;
2371 if(buff_diff < expected) return(-2);
2372
2373 kt = ndpi_deserialize_get_key_subtype(deserializer);
2374 size = ndpi_deserialize_get_single_size(deserializer, kt, deserializer->status.buffer.size_used + expected);
2375 if(size < 0) return(-2);
2376
2377 expected += size;
2378
2379 et = ndpi_deserialize_get_value_subtype(deserializer);
2380 size = ndpi_deserialize_get_single_size(deserializer, et, deserializer->status.buffer.size_used + expected);
2381 if(size < 0) return(-2);
2382
2383 if(et != ndpi_serialization_float)
2384 return(-1);
2385
2386 ndpi_deserialize_single_float(deserializer, deserializer->status.buffer.size_used + expected, value);
2387
2388 return(0);
2389 }
2390
2391 /* ********************************** */
2392
2393 /* Return the string value for the current element */
ndpi_deserialize_value_string(ndpi_deserializer * _deserializer,ndpi_string * value)2394 int ndpi_deserialize_value_string(ndpi_deserializer *_deserializer,
2395 ndpi_string *value) {
2396 ndpi_private_deserializer *deserializer = (ndpi_private_deserializer*)_deserializer;
2397 ndpi_serialization_type kt, et;
2398 u_int32_t buff_diff = deserializer->buffer.size - deserializer->status.buffer.size_used;
2399 u_int16_t expected;
2400 int size;
2401
2402 expected = sizeof(u_int8_t) /* type */;
2403 if(buff_diff < expected) return(-2);
2404
2405 kt = ndpi_deserialize_get_key_subtype(deserializer);
2406
2407 size = ndpi_deserialize_get_single_size(deserializer, kt, deserializer->status.buffer.size_used + expected);
2408 if(size < 0) return(-2);
2409
2410 expected += size;
2411
2412 et = ndpi_deserialize_get_value_subtype(deserializer);
2413
2414 size = ndpi_deserialize_get_single_size(deserializer, et, deserializer->status.buffer.size_used + expected);
2415 if(size < 0) return(-2);
2416
2417 if(et != ndpi_serialization_string)
2418 return(-1);
2419
2420 ndpi_deserialize_single_string(deserializer, deserializer->status.buffer.size_used + expected, value);
2421
2422 return(0);
2423 }
2424
2425 /* ********************************** */
2426
2427 /* Clone (with memcpy) the current item in deserializer to serializer (TLV only) */
ndpi_deserialize_clone_item(ndpi_deserializer * _deserializer,ndpi_serializer * _serializer)2428 int ndpi_deserialize_clone_item(ndpi_deserializer *_deserializer, ndpi_serializer *_serializer) {
2429 ndpi_private_deserializer *deserializer = (ndpi_private_deserializer *) _deserializer;
2430 ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
2431 u_int32_t src_buff_diff = deserializer->buffer.size - deserializer->status.buffer.size_used;
2432 u_int32_t dst_buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
2433 ndpi_serialization_type kt, et;
2434 u_int16_t expected;
2435 int size;
2436
2437 if(serializer->fmt != ndpi_serialization_format_tlv)
2438 return(-3);
2439
2440 expected = sizeof(u_int8_t) /* type */;
2441
2442 if(src_buff_diff < expected) return(-2);
2443
2444 kt = ndpi_deserialize_get_key_subtype(deserializer);
2445 size = ndpi_deserialize_get_single_size(deserializer, kt, deserializer->status.buffer.size_used + expected);
2446
2447 if(size < 0) return(-2);
2448
2449 expected += size;
2450
2451 et = ndpi_deserialize_get_value_subtype(deserializer);
2452 size = ndpi_deserialize_get_single_size(deserializer, et, deserializer->status.buffer.size_used + expected);
2453
2454 if(size < 0) return(-2);
2455
2456 expected += size;
2457
2458 if(dst_buff_diff < expected) {
2459 if(ndpi_extend_serializer_buffer(&serializer->buffer, expected - dst_buff_diff) < 0)
2460 return(-1);
2461 dst_buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
2462 }
2463
2464 memcpy(&serializer->buffer.data[serializer->status.buffer.size_used],
2465 &deserializer->buffer.data[deserializer->status.buffer.size_used],
2466 expected);
2467
2468 serializer->status.buffer.size_used += expected;
2469
2470 return(0);
2471 }
2472
2473 /* ********************************** */
2474
2475 /* Clone all elements in deserializer to serializer (this can be used to convert a TLV record to JSON) */
ndpi_deserialize_clone_all(ndpi_deserializer * deserializer,ndpi_serializer * serializer)2476 int ndpi_deserialize_clone_all(ndpi_deserializer *deserializer, ndpi_serializer *serializer) {
2477 ndpi_serialization_type kt, et;
2478 u_int32_t u32, k32;
2479 int32_t i32;
2480 u_int64_t u64;
2481 int64_t i64;
2482 float f;
2483 ndpi_string vs, ks;
2484 int key_is_string;
2485
2486 while((et = ndpi_deserialize_get_item_type(deserializer, &kt)) != ndpi_serialization_unknown) {
2487
2488 if(et == ndpi_serialization_end_of_record) {
2489 ndpi_serialize_end_of_record(serializer);
2490 goto next;
2491 } else if(et == ndpi_serialization_start_of_block) {
2492 ndpi_deserialize_key_string(deserializer, &ks);
2493 ndpi_serialize_start_of_block_binary(serializer, ks.str, ks.str_len);
2494 goto next;
2495 } else if(et == ndpi_serialization_end_of_block) {
2496 ndpi_serialize_end_of_block(serializer);
2497 goto next;
2498 } else if(et == ndpi_serialization_start_of_list) {
2499 ndpi_deserialize_key_string(deserializer, &ks);
2500 ndpi_serialize_start_of_list_binary(serializer, ks.str, ks.str_len);
2501 goto next;
2502 } else if(et == ndpi_serialization_end_of_list) {
2503 ndpi_serialize_end_of_list(serializer);
2504 goto next;
2505 }
2506
2507 key_is_string = 0;
2508 switch(kt) {
2509 case ndpi_serialization_uint32:
2510 ndpi_deserialize_key_uint32(deserializer, &k32);
2511 break;
2512 case ndpi_serialization_string:
2513 ndpi_deserialize_key_string(deserializer, &ks);
2514 key_is_string = 1;
2515 break;
2516 default:
2517 return(-1);
2518 }
2519
2520 switch(et) {
2521 case ndpi_serialization_uint32:
2522 ndpi_deserialize_value_uint32(deserializer, &u32);
2523 if(key_is_string) ndpi_serialize_binary_uint32(serializer, ks.str, ks.str_len, u32);
2524 else ndpi_serialize_uint32_uint32(serializer, k32, u32);
2525 break;
2526
2527 case ndpi_serialization_uint64:
2528 ndpi_deserialize_value_uint64(deserializer, &u64);
2529 if(key_is_string) ndpi_serialize_binary_uint64(serializer, ks.str, ks.str_len, u64);
2530 else ndpi_serialize_uint32_uint64(serializer, k32, u64);
2531 break;
2532
2533 case ndpi_serialization_int32:
2534 ndpi_deserialize_value_int32(deserializer, &i32);
2535 if(key_is_string) ndpi_serialize_binary_int32(serializer, ks.str, ks.str_len, i32);
2536 else ndpi_serialize_uint32_int32(serializer, k32, i32);
2537 break;
2538
2539 case ndpi_serialization_int64:
2540 ndpi_deserialize_value_int64(deserializer, &i64);
2541 if(key_is_string) ndpi_serialize_binary_int64(serializer, ks.str, ks.str_len, i64);
2542 else ndpi_serialize_uint32_int64(serializer, k32, i64);
2543 break;
2544
2545 case ndpi_serialization_float:
2546 ndpi_deserialize_value_float(deserializer, &f);
2547 if(key_is_string) ndpi_serialize_binary_float(serializer, ks.str, ks.str_len, f, "%.3f");
2548 else ndpi_serialize_uint32_float(serializer, k32, f, "%.3f");
2549 break;
2550
2551 case ndpi_serialization_string:
2552 ndpi_deserialize_value_string(deserializer, &vs);
2553 if(key_is_string) ndpi_serialize_binary_binary(serializer, ks.str, ks.str_len, vs.str, vs.str_len);
2554 else ndpi_serialize_uint32_binary(serializer, k32, vs.str, vs.str_len);
2555 break;
2556
2557 default:
2558 return(-2);
2559 }
2560
2561 next:
2562 ndpi_deserialize_next(deserializer);
2563 }
2564
2565 return(0);
2566 }
2567
2568 /* ********************************** */
2569