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