1 /*****
2 *
3 * Copyright (C) 2003-2015 CS-SI. All Rights Reserved.
4 * Author: Yoann Vandoorselaere <yoann.v@prelude-ids.com>
5 *
6 * This file is part of the Prelude library.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2, or (at your option)
11 * any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 *
22 *****/
23 
24 #include "libmissing.h"
25 
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <ctype.h>
30 #include <assert.h>
31 
32 #include "prelude-inttypes.h"
33 #include "prelude-string.h"
34 
35 #define PRELUDE_ERROR_SOURCE_DEFAULT PRELUDE_ERROR_SOURCE_IDMEF_VALUE_TYPE
36 #include "prelude-error.h"
37 #include "prelude-inttypes.h"
38 #include "prelude-linked-object.h"
39 #include "idmef-object-prv.h"
40 
41 #include "idmef-time.h"
42 #include "idmef-data.h"
43 #include "idmef-value-type.h"
44 
45 
46 #define CLASS_OPERATOR  IDMEF_CRITERION_OPERATOR_NULL|IDMEF_CRITERION_OPERATOR_NOT| \
47                         IDMEF_CRITERION_OPERATOR_EQUAL
48 
49 #define DATA_OPERATOR    IDMEF_CRITERION_OPERATOR_EQUAL|IDMEF_CRITERION_OPERATOR_NOT| \
50                          IDMEF_CRITERION_OPERATOR_LESSER|IDMEF_CRITERION_OPERATOR_GREATER|IDMEF_CRITERION_OPERATOR_SUBSTR
51 
52 #define TIME_OPERATOR    IDMEF_CRITERION_OPERATOR_LESSER|IDMEF_CRITERION_OPERATOR_GREATER| \
53                          IDMEF_CRITERION_OPERATOR_EQUAL|IDMEF_CRITERION_OPERATOR_NOT
54 
55 #define STRING_OPERATOR  IDMEF_CRITERION_OPERATOR_SUBSTR|IDMEF_CRITERION_OPERATOR_EQUAL| \
56                          IDMEF_CRITERION_OPERATOR_NOT|IDMEF_CRITERION_OPERATOR_NOCASE
57 
58 #define INTEGER_OPERATOR IDMEF_CRITERION_OPERATOR_LESSER|IDMEF_CRITERION_OPERATOR_GREATER|\
59                          IDMEF_CRITERION_OPERATOR_EQUAL|IDMEF_CRITERION_OPERATOR_NOT
60 
61 #define ENUM_OPERATOR    STRING_OPERATOR|INTEGER_OPERATOR
62 
63 
64 #define GENERIC_ONE_BASE_RW_FUNC(scanfmt, printfmt, name, type)                            \
65         static int name ## _read(idmef_value_type_t *dst, const char *buf)                 \
66         {                                                                                  \
67                 char *endptr;                                                              \
68                                                                                            \
69                 (dst)->data. name ##_val = strtod(buf, &endptr);                           \
70                 if ( buf == endptr || *endptr != '\0' || errno == ERANGE )                 \
71                         return prelude_error_verbose(PRELUDE_ERROR_IDMEF_VALUE_TYPE_PARSE, \
72                         "Reading " #name " value failed with '%s'", buf);                  \
73                 return 1;                                                                  \
74         }                                                                                  \
75                                                                                            \
76         static int name ## _write(const idmef_value_type_t *src, prelude_string_t *out)    \
77         {                                                                                  \
78                 return prelude_string_sprintf(out, (printfmt), src->data.name ##_val);     \
79         }
80 
81 
82 #define GENERIC_TWO_BASES_RW_FUNC(rfunc, fmt_dec, name, type, min, max)                              \
83         static int name ## _read(idmef_value_type_t *dst, const char *buf)                           \
84         {                                                                                            \
85                 type tmp;                                                                            \
86                 char *endptr;                                                                        \
87                                                                                                      \
88                 tmp = rfunc(buf, &endptr, 0);                                                        \
89                 if ( buf == endptr || *endptr != '\0' || tmp < min || tmp > max || errno == ERANGE ) \
90                         return prelude_error_verbose(PRELUDE_ERROR_IDMEF_VALUE_TYPE_PARSE,           \
91                         "Value out of range, required: [" # min " - " # max "], got '%s'", buf);     \
92                                                                                                      \
93                 dst->data.name ##_val = tmp;                                                         \
94                 return 0;                                                                            \
95         }                                                                                            \
96                                                                                                      \
97         static int name ## _write(const idmef_value_type_t *src, prelude_string_t *out)              \
98         {                                                                                            \
99                 return prelude_string_sprintf(out, (fmt_dec), src->data.name ##_val);                \
100         }
101 
102 
103 
104 typedef struct {
105         const char *name;
106 
107         size_t len;
108 
109         idmef_criterion_operator_t operator;
110 
111         int (*copy)(const idmef_value_type_t *src, void *dst, size_t size);
112         int (*clone)(const idmef_value_type_t *src, idmef_value_type_t *dst, size_t size);
113         int (*ref)(const idmef_value_type_t *src);
114 
115         void (*destroy)(idmef_value_type_t *type);
116         int (*compare)(const idmef_value_type_t *t1, const idmef_value_type_t *t2, size_t size, idmef_criterion_operator_t op);
117 
118         int (*read)(idmef_value_type_t *dst, const char *buf);
119         int (*write)(const idmef_value_type_t *src, prelude_string_t *out);
120 
121 } idmef_value_type_operation_t;
122 
123 
124 
125 /*
126  * We specify a type bigger than the one handled, in order to catch min/max error.
127  */
128 GENERIC_TWO_BASES_RW_FUNC(strtol, "%d", int8, int, PRELUDE_INT8_MIN, PRELUDE_INT8_MAX)
129 GENERIC_TWO_BASES_RW_FUNC(strtol, "%d", uint8, unsigned int, 0, PRELUDE_UINT8_MAX)
130 GENERIC_TWO_BASES_RW_FUNC(strtol, "%hd", int16, int, PRELUDE_INT16_MIN, PRELUDE_INT16_MAX)
131 GENERIC_TWO_BASES_RW_FUNC(strtoul, "%hu", uint16, unsigned int, 0, PRELUDE_UINT16_MAX)
132 GENERIC_TWO_BASES_RW_FUNC(strtol, "%d", int32, int64_t, PRELUDE_INT32_MIN, PRELUDE_INT32_MAX)
133 GENERIC_TWO_BASES_RW_FUNC(strtoul, "%u", uint32, uint64_t, 0, PRELUDE_UINT32_MAX)
134 GENERIC_TWO_BASES_RW_FUNC(strtoll, "%" PRELUDE_PRId64, int64, int64_t, PRELUDE_INT64_MIN, PRELUDE_INT64_MAX)
135 GENERIC_TWO_BASES_RW_FUNC(strtoull, "%" PRELUDE_PRIu64, uint64, uint64_t, 0, PRELUDE_UINT64_MAX)
136 
137 GENERIC_ONE_BASE_RW_FUNC("%f", "%f", float, float)
138 GENERIC_ONE_BASE_RW_FUNC("%lf", "%f", double, double)
139 
140 
141 
142 
143 /*
144  * generic functions.
145  */
charstring_compare(const char * s1,const char * s2,idmef_criterion_operator_t op)146 static int charstring_compare(const char *s1, const char *s2, idmef_criterion_operator_t op)
147 {
148         if ( ! s1 || ! s2 )
149                 return (s1) ? 1 : -1;
150 
151         if ( op == (IDMEF_CRITERION_OPERATOR_EQUAL|IDMEF_CRITERION_OPERATOR_NOCASE) && strcasecmp(s1, s2) == 0 )
152                 return 0;
153 
154         else if ( op == IDMEF_CRITERION_OPERATOR_EQUAL && strcmp(s1, s2) == 0 )
155                 return 0;
156 
157         else if ( op == (IDMEF_CRITERION_OPERATOR_SUBSTR|IDMEF_CRITERION_OPERATOR_NOCASE) && strcasestr(s1, s2) )
158                 return 0;
159 
160         else if ( op == IDMEF_CRITERION_OPERATOR_SUBSTR && strstr(s1, s2) )
161                 return 0;
162 
163         return -1;
164 }
165 
166 
167 
generic_copy(const idmef_value_type_t * src,void * dst,size_t size)168 static int generic_copy(const idmef_value_type_t *src, void *dst, size_t size)
169 {
170         memcpy(dst, &src->data, size);
171         return 0;
172 }
173 
174 
175 
176 
generic_clone(const idmef_value_type_t * src,idmef_value_type_t * dst,size_t size)177 static int generic_clone(const idmef_value_type_t *src, idmef_value_type_t *dst, size_t size)
178 {
179         memcpy(&dst->data, &src->data, size);
180         return 0;
181 }
182 
183 
184 
generic_compare(const idmef_value_type_t * t1,const idmef_value_type_t * t2,size_t size,idmef_criterion_operator_t op)185 static int generic_compare(const idmef_value_type_t *t1, const idmef_value_type_t *t2,
186                            size_t size, idmef_criterion_operator_t op)
187 {
188         int ret;
189 
190         ret = memcmp(&t1->data, &t2->data, size);
191 
192         if ( ret == 0 && op & IDMEF_CRITERION_OPERATOR_EQUAL )
193                 return 0;
194 
195         if ( ret < 0 && op & IDMEF_CRITERION_OPERATOR_LESSER )
196                 return 0;
197 
198         if ( ret > 0 && op & IDMEF_CRITERION_OPERATOR_GREATER )
199                 return 0;
200 
201         return -1;
202 }
203 
204 
205 
206 /*
207  * Enum specific
208  */
enum_copy(const idmef_value_type_t * src,void * dst,size_t size)209 static int enum_copy(const idmef_value_type_t *src, void *dst, size_t size)
210 {
211         *(int *)dst = src->data.enum_val.value;
212         return 0;
213 }
214 
215 
enum_read(idmef_value_type_t * dst,const char * buf)216 static int enum_read(idmef_value_type_t *dst, const char *buf)
217 {
218         int ret;
219 
220         ret = sscanf(buf, "%d", &(dst)->data.enum_val.value);
221 
222         return (ret == 1) ? 0 : prelude_error_verbose(PRELUDE_ERROR_IDMEF_VALUE_TYPE_PARSE, "Reading enum value failed");
223 }
224 
225 
226 
enum_write(const idmef_value_type_t * src,prelude_string_t * out)227 static int enum_write(const idmef_value_type_t *src, prelude_string_t *out)
228 {
229         const char *str;
230 
231         str = idmef_class_enum_to_string(src->data.enum_val.class_id, src->data.enum_val.value);
232         if ( ! str )
233                 return prelude_error_verbose(PRELUDE_ERROR_IDMEF_VALUE_TYPE_PARSE, "Enumeration conversion from numeric to string failed");
234 
235         return prelude_string_cat(out, str);
236 }
237 
238 
enum_compare(const idmef_value_type_t * src,const idmef_value_type_t * dst,size_t size,idmef_criterion_operator_t op)239 static int enum_compare(const idmef_value_type_t *src, const idmef_value_type_t *dst, size_t size, idmef_criterion_operator_t op)
240 {
241         const char *s1;
242 
243         if ( dst->id == IDMEF_VALUE_TYPE_STRING ) {
244                 s1 = idmef_class_enum_to_string(src->data.enum_val.class_id, src->data.enum_val.value);
245                 if ( ! s1 )
246                         return prelude_error_verbose(PRELUDE_ERROR_IDMEF_VALUE_TYPE_PARSE, "Enumeration conversion from numeric to string failed");
247 
248                 return charstring_compare(s1, prelude_string_get_string(dst->data.string_val), op);
249         }
250 
251         return generic_compare(src, dst, size, op);
252 }
253 
254 
255 /*
256  * time specific function.
257  */
time_compare(const idmef_value_type_t * t1,const idmef_value_type_t * t2,size_t size,idmef_criterion_operator_t op)258 static int time_compare(const idmef_value_type_t *t1, const idmef_value_type_t *t2,
259                         size_t size, idmef_criterion_operator_t op)
260 {
261         int ret;
262 
263         ret = idmef_time_compare(t1->data.time_val, t2->data.time_val);
264         if ( op & IDMEF_CRITERION_OPERATOR_EQUAL && ret == 0 )
265                 return 0;
266 
267         else if ( op & IDMEF_CRITERION_OPERATOR_LESSER && ret < 0 )
268                 return 0;
269 
270         else if ( op & IDMEF_CRITERION_OPERATOR_GREATER && ret > 0 )
271                 return 0;
272 
273         return -1;
274 }
275 
276 
277 
time_read(idmef_value_type_t * dst,const char * buf)278 static int time_read(idmef_value_type_t *dst, const char *buf)
279 {
280         int ret;
281 
282         ret = idmef_time_new_from_ntpstamp(&dst->data.time_val, buf);
283         if ( ret == 0 )
284                 return 0;
285 
286         ret = idmef_time_new_from_string(&dst->data.time_val, buf);
287         if ( ret == 0 )
288                 return 0;
289 
290         return prelude_error_verbose(PRELUDE_ERROR_IDMEF_VALUE_TYPE_PARSE,
291                                      "Invalid time format specified: '%s'", buf);
292 }
293 
294 
295 
time_write(const idmef_value_type_t * src,prelude_string_t * out)296 static int time_write(const idmef_value_type_t *src, prelude_string_t *out)
297 {
298         return idmef_time_to_string(src->data.time_val, out);
299 }
300 
301 
302 
time_copy(const idmef_value_type_t * src,void * dst,size_t size)303 static int time_copy(const idmef_value_type_t *src, void *dst, size_t size)
304 {
305         return idmef_time_copy(src->data.time_val, dst);
306 }
307 
308 
309 
time_clone(const idmef_value_type_t * src,idmef_value_type_t * dst,size_t size)310 static int time_clone(const idmef_value_type_t *src, idmef_value_type_t *dst, size_t size)
311 {
312         return idmef_time_clone(src->data.time_val, &dst->data.time_val);
313 }
314 
315 
time_ref(const idmef_value_type_t * src)316 static int time_ref(const idmef_value_type_t *src)
317 {
318         idmef_time_ref(src->data.time_val);
319         return 0;
320 }
321 
322 
time_destroy(idmef_value_type_t * type)323 static void time_destroy(idmef_value_type_t *type)
324 {
325         idmef_time_destroy(type->data.time_val);
326 }
327 
328 
329 
330 /*
331  *
332  */
string_compare(const idmef_value_type_t * t1,const idmef_value_type_t * t2,size_t size,idmef_criterion_operator_t op)333 static int string_compare(const idmef_value_type_t *t1, const idmef_value_type_t *t2,
334                           size_t size, idmef_criterion_operator_t op)
335 {
336         const char *s1 = NULL, *s2 = NULL;
337 
338         if ( t1->data.string_val )
339                 s1 = prelude_string_get_string(t1->data.string_val);
340 
341         if ( t2->data.string_val )
342                 s2 = prelude_string_get_string(t2->data.string_val);
343 
344         return charstring_compare(s1, s2, op);
345 }
346 
347 
348 
string_read(idmef_value_type_t * dst,const char * buf)349 static int string_read(idmef_value_type_t *dst, const char *buf)
350 {
351         return prelude_string_new_dup(&dst->data.string_val, buf);
352 }
353 
354 
355 
string_copy(const idmef_value_type_t * src,void * dst,size_t size)356 static int string_copy(const idmef_value_type_t *src, void *dst, size_t size)
357 {
358         return prelude_string_copy_dup(src->data.string_val, dst);
359 }
360 
361 
string_ref(const idmef_value_type_t * src)362 static int string_ref(const idmef_value_type_t *src)
363 {
364         prelude_string_ref(src->data.string_val);
365         return 0;
366 }
367 
368 
string_clone(const idmef_value_type_t * src,idmef_value_type_t * dst,size_t size)369 static int string_clone(const idmef_value_type_t *src, idmef_value_type_t *dst, size_t size)
370 {
371         return prelude_string_clone(src->data.string_val, &dst->data.string_val);
372 }
373 
374 
string_destroy(idmef_value_type_t * type)375 static void string_destroy(idmef_value_type_t *type)
376 {
377         prelude_string_destroy(type->data.string_val);
378 }
379 
380 
381 
string_write(const idmef_value_type_t * src,prelude_string_t * out)382 static int string_write(const idmef_value_type_t *src, prelude_string_t *out)
383 {
384         return prelude_string_sprintf(out, "%s",
385                        prelude_string_get_string_or_default(src->data.string_val, "<empty>"));
386 }
387 
388 
389 
390 /*
391  * data specific functions
392  */
data_compare(const idmef_value_type_t * t1,const idmef_value_type_t * t2,size_t len,idmef_criterion_operator_t op)393 static int data_compare(const idmef_value_type_t *t1, const idmef_value_type_t *t2,
394                         size_t len, idmef_criterion_operator_t op)
395 {
396         int ret;
397         size_t s1_len, s2_len;
398         const void *s1 = NULL, *s2 = NULL;
399 
400         if ( t1->data.data_val )
401                 s1 = idmef_data_get_data(t1->data.data_val);
402 
403         if ( t2->data.string_val )
404                 s2 = idmef_data_get_data(t2->data.data_val);
405 
406         if ( ! s1 || ! s2 )
407                 return (s1) ? 1 : -1;
408 
409         if ( op & IDMEF_CRITERION_OPERATOR_SUBSTR ) {
410                 s1_len = idmef_data_get_len(t1->data.data_val);
411                 s2_len = idmef_data_get_len(t2->data.data_val);
412                 return ( memmem(s1, s1_len, s2, s2_len) ) ? 0 : -1;
413         }
414 
415         ret = idmef_data_compare(t1->data.data_val, t2->data.data_val);
416         if ( ret == 0 && op & IDMEF_CRITERION_OPERATOR_EQUAL )
417                 return 0;
418 
419         else if ( ret < 0 && op & IDMEF_CRITERION_OPERATOR_LESSER )
420                 return 0;
421 
422         else if ( ret > 0 && op & IDMEF_CRITERION_OPERATOR_GREATER )
423                 return 0;
424 
425 
426         return -1;
427 }
428 
429 
430 
data_read(idmef_value_type_t * dst,const char * src)431 static int data_read(idmef_value_type_t *dst, const char *src)
432 {
433         return idmef_data_new_char_string_dup_fast(&dst->data.data_val, src, strlen(src));
434 }
435 
436 
437 
data_write(const idmef_value_type_t * src,prelude_string_t * out)438 static int data_write(const idmef_value_type_t *src, prelude_string_t *out)
439 {
440         return idmef_data_to_string(src->data.data_val, out);
441 }
442 
443 
444 
data_copy(const idmef_value_type_t * src,void * dst,size_t size)445 static int data_copy(const idmef_value_type_t *src, void *dst, size_t size)
446 {
447         return idmef_data_copy_dup(src->data.data_val, dst);
448 }
449 
450 
451 
data_clone(const idmef_value_type_t * src,idmef_value_type_t * dst,size_t size)452 static int data_clone(const idmef_value_type_t *src, idmef_value_type_t *dst, size_t size)
453 {
454         return idmef_data_clone(src->data.data_val, &dst->data.data_val);
455 }
456 
457 
data_ref(const idmef_value_type_t * src)458 static int data_ref(const idmef_value_type_t *src)
459 {
460         idmef_data_ref(src->data.data_val);
461         return 0;
462 }
463 
464 
data_destroy(idmef_value_type_t * type)465 static void data_destroy(idmef_value_type_t *type)
466 {
467         idmef_data_destroy(type->data.data_val);
468 }
469 
470 
471 
472 /*
473  * class specific
474  */
class_compare(const idmef_value_type_t * c1,const idmef_value_type_t * c2,size_t len,idmef_criterion_operator_t op)475 static int class_compare(const idmef_value_type_t *c1,
476                          const idmef_value_type_t *c2, size_t len, idmef_criterion_operator_t op)
477 {
478         return idmef_class_compare(c1->data.class_val.class_id,
479                                    c1->data.class_val.object, c2->data.class_val.object);
480 }
481 
482 
class_copy(const idmef_value_type_t * src,void * dst,size_t size)483 static int class_copy(const idmef_value_type_t *src, void *dst, size_t size)
484 {
485         return idmef_class_copy(src->data.class_val.class_id, src->data.class_val.object, dst);
486 }
487 
488 
class_clone(const idmef_value_type_t * src,idmef_value_type_t * dst,size_t size)489 static int class_clone(const idmef_value_type_t *src, idmef_value_type_t *dst, size_t size)
490 {
491         dst->data.class_val.class_id = src->data.class_val.class_id;
492         return idmef_class_clone(src->data.class_val.class_id, src->data.class_val.object, &dst->data.class_val.object);
493 }
494 
495 
class_ref(const idmef_value_type_t * src)496 static int class_ref(const idmef_value_type_t *src)
497 {
498         return idmef_class_ref(src->data.class_val.class_id, src->data.class_val.object);
499 }
500 
501 
class_destroy(idmef_value_type_t * type)502 static void class_destroy(idmef_value_type_t *type)
503 {
504         idmef_class_destroy(type->data.class_val.class_id, type->data.class_val.object);
505 }
506 
507 
508 
list_to_string(const char * cname,idmef_class_id_t class,prelude_list_t * head,prelude_string_t * out,int (* item_to_string_cb)(int class,void * item,prelude_string_t * out))509 static int list_to_string(const char *cname, idmef_class_id_t class, prelude_list_t *head, prelude_string_t *out,
510                           int (*item_to_string_cb)(int class, void *item, prelude_string_t *out))
511 {
512         void *obj;
513         int ret, j;
514         prelude_list_t *tmp;
515 
516         if ( prelude_list_is_empty(head) )
517                 return 0;
518 
519         if ( cname )
520                 ret = prelude_string_sprintf(out, " %s:", cname);
521         else
522                 ret = prelude_string_cat(out, " ");
523 
524         if ( ret < 0 )
525                 return ret;
526 
527         ret = prelude_string_cat(out, "(");
528         if ( ret < 0 )
529                 return ret;
530 
531         j = 0;
532         prelude_list_for_each(head, tmp) {
533                 if ( j++ > 0 ) {
534                         ret = prelude_string_cat(out, ", ");
535                         if ( ret < 0 )
536                                 return ret;
537                 }
538 
539                 if ( ! cname )
540                         obj = idmef_linked_object_get_object(tmp);
541                 else
542                         obj = prelude_linked_object_get_object(tmp);
543 
544                 ret = item_to_string_cb(class, obj, out);
545                 if ( ret < 0 )
546                         return ret;
547         }
548 
549         return prelude_string_cat(out, ")");
550 }
551 
552 
553 
listed_str_to_string(idmef_class_id_t parent_class,void * parent,prelude_string_t * out)554 static int listed_str_to_string(idmef_class_id_t parent_class, void *parent, prelude_string_t *out)
555 {
556         return prelude_string_cat(out, prelude_string_get_string(parent));
557 }
558 
559 
class_to_string(idmef_class_id_t parent_class,void * parent,prelude_string_t * out)560 static int class_to_string(idmef_class_id_t parent_class, void *parent, prelude_string_t *out)
561 {
562         int ret, i;
563         void *childptr;
564         idmef_class_id_t childclass;
565         idmef_value_type_id_t vtype;
566         const char *pname = idmef_class_get_name(parent_class);
567 
568         ret = prelude_string_sprintf(out, "<IDMEF%c%s",  toupper(*pname), pname + 1);
569         if ( ret < 0 )
570                 return ret;
571 
572         for ( i = 0; ; i++ ) {
573                 ret = idmef_class_get_child(parent, parent_class, i, &childptr);
574                 if ( ret < 0 )
575                         break;
576 
577                 if ( ! childptr )
578                         continue;
579 
580                 vtype = idmef_class_get_child_value_type(parent_class, i);
581                 childclass = idmef_class_get_child_class(parent_class, i);
582 
583                 if ( vtype != IDMEF_VALUE_TYPE_CLASS ) {
584                         const char *cname = idmef_class_get_child_name(parent_class, i);
585 
586                         if ( ! idmef_class_is_child_list(parent_class, i) ) {
587                                 ret = prelude_string_sprintf(out, " %s:", cname);
588                                 if ( ret < 0 ) {
589                                         idmef_value_destroy(childptr);
590                                         return ret;
591                                 }
592 
593                                 ret = idmef_value_to_string(childptr, out);
594                                 idmef_value_destroy(childptr);
595                                 if ( ret < 0 )
596                                         return ret;
597                         }
598 
599                         else {
600                                 ret = list_to_string(cname, childclass, childptr, out, listed_str_to_string);
601                                 if ( ret < 0 )
602                                         return ret;
603                         }
604 
605                         continue;
606                 }
607 
608                 if ( ! idmef_class_is_child_list(parent_class, i) ) {
609                         ret = prelude_string_cat(out, " ");
610                         if ( ret < 0 )
611                                 return ret;
612 
613                         ret = class_to_string(childclass, childptr, out);
614                         if ( ret < 0 )
615                                 return ret;
616                 }
617 
618                 else {
619                         ret = list_to_string(NULL, childclass, childptr, out, class_to_string);
620                         if ( ret < 0 )
621                                 return ret;
622                 }
623         }
624 
625         return prelude_string_cat(out, ">");
626 }
627 
628 
class_write(const idmef_value_type_t * src,prelude_string_t * out)629 static int class_write(const idmef_value_type_t *src, prelude_string_t *out)
630 {
631         return class_to_string(src->data.class_val.class_id, src->data.class_val.object, out);
632 }
633 
634 
635 static const idmef_value_type_operation_t ops_tbl[] = {
636         { "unknown", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL                     },
637         { "int8", sizeof(int8_t), INTEGER_OPERATOR, generic_copy,
638           generic_clone, NULL, NULL, generic_compare, int8_read, int8_write             },
639         { "uint8", sizeof(uint8_t), INTEGER_OPERATOR, generic_copy,
640           generic_clone, NULL, NULL, generic_compare, uint8_read, uint8_write           },
641         { "int16", sizeof(int16_t), INTEGER_OPERATOR, generic_copy,
642           generic_clone, NULL, NULL, generic_compare, int16_read, int16_write           },
643         { "uint16", sizeof(uint16_t), INTEGER_OPERATOR, generic_copy,
644           generic_clone, NULL, NULL, generic_compare, uint16_read, uint16_write         },
645         { "int32", sizeof(int32_t), INTEGER_OPERATOR, generic_copy,
646           generic_clone, NULL, NULL, generic_compare, int32_read, int32_write           },
647         { "uint32", sizeof(uint32_t), INTEGER_OPERATOR, generic_copy,
648           generic_clone, NULL, NULL, generic_compare, uint32_read, uint32_write         },
649         { "int64", sizeof(int64_t), INTEGER_OPERATOR, generic_copy,
650           generic_clone, NULL, NULL, generic_compare, int64_read, int64_write           },
651         { "uint64", sizeof(uint64_t), INTEGER_OPERATOR, generic_copy,
652           generic_clone, NULL, NULL, generic_compare, uint64_read, uint64_write         },
653         { "float", sizeof(float), INTEGER_OPERATOR, generic_copy,
654           generic_clone, NULL, NULL, generic_compare, float_read, float_write           },
655         { "double", sizeof(double), INTEGER_OPERATOR, generic_copy,
656           generic_clone, NULL, NULL, generic_compare, double_read, double_write         },
657         { "string", 0, STRING_OPERATOR, string_copy, string_clone,
658           string_ref, string_destroy, string_compare, string_read, string_write         },
659         { "time", 0, TIME_OPERATOR, time_copy, time_clone,
660           time_ref, time_destroy, time_compare, time_read, time_write                   },
661         { "data", 0, DATA_OPERATOR, data_copy, data_clone,
662           data_ref, data_destroy, data_compare, data_read, data_write                   },
663         { "enum", sizeof(idmef_value_type_enum_t), ENUM_OPERATOR, enum_copy,
664           generic_clone, NULL, NULL, enum_compare, enum_read, enum_write,               },
665         { "list", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL                        },
666         { "class", 0, CLASS_OPERATOR, class_copy, class_clone,
667           class_ref, class_destroy, class_compare, NULL, class_write                    },
668 };
669 
670 
671 
is_type_valid(idmef_value_type_id_t type)672 static int is_type_valid(idmef_value_type_id_t type)
673 {
674         if ( type < 0 || (size_t) type >= (sizeof(ops_tbl) / sizeof(*ops_tbl)) )
675                 return prelude_error_verbose(PRELUDE_ERROR_IDMEF_VALUE_TYPE_UNKNOWN, "Unknown IDMEF type id: '%d'", type);
676 
677         return 0;
678 }
679 
680 
681 
idmef_value_type_to_string(idmef_value_type_id_t type)682 const char *idmef_value_type_to_string(idmef_value_type_id_t type)
683 {
684         int ret;
685 
686         ret = is_type_valid(type);
687         if ( ret < 0 )
688                 return NULL;
689 
690         return ops_tbl[type].name;
691 }
692 
693 
694 
idmef_value_type_clone(const idmef_value_type_t * src,idmef_value_type_t * dst)695 int idmef_value_type_clone(const idmef_value_type_t *src, idmef_value_type_t *dst)
696 {
697         int ret;
698 
699         assert(dst->id == src->id);
700 
701         ret = is_type_valid(dst->id);
702         if ( ret < 0 )
703                 return ret;
704 
705         if ( ! ops_tbl[dst->id].clone )
706                 return prelude_error_verbose(PRELUDE_ERROR_IDMEF_VALUE_TYPE_CLONE_UNAVAILABLE,
707                                              "Object type '%s' does not support clone operation",
708                                              idmef_value_type_to_string(dst->id));
709 
710         return ops_tbl[dst->id].clone(src, dst, ops_tbl[dst->id].len);
711 }
712 
713 
714 
715 
idmef_value_type_copy(const idmef_value_type_t * src,void * dst)716 int idmef_value_type_copy(const idmef_value_type_t *src, void *dst)
717 {
718         int ret;
719 
720         ret = is_type_valid(src->id);
721         if ( ret < 0 )
722                 return ret;
723 
724         if ( ! ops_tbl[src->id].copy )
725                 return prelude_error_verbose(PRELUDE_ERROR_IDMEF_VALUE_TYPE_COPY_UNAVAILABLE,
726                                              "Object type '%s' does not support copy operation",
727                                              idmef_value_type_to_string(src->id));
728 
729         return ops_tbl[src->id].copy(src, dst, ops_tbl[src->id].len);
730 }
731 
732 
733 
idmef_value_type_ref(const idmef_value_type_t * vt)734 int idmef_value_type_ref(const idmef_value_type_t *vt)
735 {
736         int ret;
737 
738         ret = is_type_valid(vt->id);
739         if ( ret < 0 )
740                 return ret;
741 
742         if ( ! ops_tbl[vt->id].ref )
743                 return prelude_error_verbose(PRELUDE_ERROR_IDMEF_VALUE_TYPE_REF_UNAVAILABLE,
744                                              "Object type '%s' does not support ref operation",
745                                              idmef_value_type_to_string(vt->id));
746 
747         return ops_tbl[vt->id].ref(vt);
748 }
749 
750 
idmef_value_type_compare(const idmef_value_type_t * type1,const idmef_value_type_t * type2,idmef_criterion_operator_t op)751 int idmef_value_type_compare(const idmef_value_type_t *type1,
752                              const idmef_value_type_t *type2,
753                              idmef_criterion_operator_t op)
754 {
755         int ret;
756 
757         ret = is_type_valid(type1->id);
758         if ( ret < 0 )
759                 return ret;
760 
761         if ( type1->id != type2->id ) {
762                 if ( type1->id != IDMEF_VALUE_TYPE_ENUM && type2->id != IDMEF_VALUE_TYPE_STRING )
763                         return prelude_error(PRELUDE_ERROR_IDMEF_VALUE_TYPE_COMPARE_MISMATCH);
764         }
765 
766         if ( ! (op & ops_tbl[type1->id].operator) )
767                 return prelude_error_verbose(PRELUDE_ERROR_IDMEF_VALUE_TYPE_COMPARE_UNAVAILABLE,
768                                              "Object type '%s' does not support operator '%s'",
769                                              idmef_value_type_to_string(type1->id), idmef_criterion_operator_to_string(op));
770 
771         if ( ! ops_tbl[type1->id].compare )
772                 return prelude_error_verbose(PRELUDE_ERROR_IDMEF_VALUE_TYPE_COMPARE_UNAVAILABLE,
773                                              "Object type '%s' does not support compare operation",
774                                              idmef_value_type_to_string(type1->id));
775 
776         ret = ops_tbl[type1->id].compare(type1, type2, ops_tbl[type1->id].len, op & ~IDMEF_CRITERION_OPERATOR_NOT);
777         if ( ret < 0 ) /* not an error -> no match */
778                 ret = 1;
779 
780         if ( op & IDMEF_CRITERION_OPERATOR_NOT )
781                 return (ret == 0) ? 1 : 0;
782         else
783                 return ret;
784 }
785 
786 
787 
788 
idmef_value_type_read(idmef_value_type_t * dst,const char * buf)789 int idmef_value_type_read(idmef_value_type_t *dst, const char *buf)
790 {
791         int ret;
792 
793         ret = is_type_valid(dst->id);
794         if ( ret < 0 )
795                 return ret;
796 
797         if ( ! ops_tbl[dst->id].read )
798                 return prelude_error_verbose(PRELUDE_ERROR_IDMEF_VALUE_TYPE_READ_UNAVAILABLE,
799                                              "Object type '%s' does not support read operation",
800                                              idmef_value_type_to_string(dst->id));
801 
802         ret = ops_tbl[dst->id].read(dst, buf);
803         return (ret < 0) ? ret : 0;
804 }
805 
806 
807 
808 
idmef_value_type_write(const idmef_value_type_t * src,prelude_string_t * out)809 int idmef_value_type_write(const idmef_value_type_t *src, prelude_string_t *out)
810 {
811         int ret;
812 
813         ret = is_type_valid(src->id);
814         if ( ret < 0 )
815                 return ret;
816 
817         if ( ! ops_tbl[src->id].write )
818                 return prelude_error_verbose(PRELUDE_ERROR_IDMEF_VALUE_TYPE_WRITE_UNAVAILABLE,
819                                              "Object type '%s' does not support write operation",
820                                              idmef_value_type_to_string(src->id));
821 
822         return ops_tbl[src->id].write(src, out);
823 }
824 
825 
826 
idmef_value_type_destroy(idmef_value_type_t * type)827 void idmef_value_type_destroy(idmef_value_type_t *type)
828 {
829         int ret;
830 
831         ret = is_type_valid(type->id);
832         if ( ret < 0 )
833                 return;
834 
835         if ( ! ops_tbl[type->id].destroy )
836                 return;
837 
838         ops_tbl[type->id].destroy(type);
839 }
840 
841 
842 
843 
idmef_value_type_check_operator(idmef_value_type_id_t type,idmef_criterion_operator_t op)844 int idmef_value_type_check_operator(idmef_value_type_id_t type, idmef_criterion_operator_t op)
845 {
846         int ret;
847 
848         ret = is_type_valid(type);
849         if ( ret < 0 )
850                 return ret;
851 
852         if ( (~ops_tbl[type].operator & op) == 0 )
853                 return 0;
854 
855         return prelude_error_verbose(PRELUDE_ERROR_IDMEF_CRITERION_UNSUPPORTED_OPERATOR,
856                                      "Object type '%s' does not support operator '%s'",
857                                      idmef_value_type_to_string(type), idmef_criterion_operator_to_string(op));
858 }
859 
860 
861 
idmef_value_type_get_applicable_operators(idmef_value_type_id_t type,idmef_criterion_operator_t * result)862 int idmef_value_type_get_applicable_operators(idmef_value_type_id_t type, idmef_criterion_operator_t *result)
863 {
864         int ret;
865 
866         ret = is_type_valid(type);
867         if ( ret < 0 )
868                 return ret;
869 
870         *result = ops_tbl[type].operator;
871 
872         return 0;
873 }
874