1 /*****
2 *
3 * Copyright (C) 2003-2015 CS-SI. All Rights Reserved.
4 * Author: Nicolas Delon <nicolas.delon@prelude-ids.com>
5 * Author: Yoann Vandoorselaere <yoann.v@prelude-ids.com>
6 *
7 * This file is part of the Prelude library.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2, or (at your option)
12 * any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 *
23 *****/
24 
25 #include "config.h"
26 
27 #include <sys/types.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <stdio.h>
31 #include <ctype.h>
32 #include <assert.h>
33 
34 #include "prelude-list.h"
35 #include "prelude-log.h"
36 #include "prelude-inttypes.h"
37 #include "prelude-string.h"
38 #include "prelude-error.h"
39 #include "common.h"
40 
41 #include "idmef.h"
42 #include "idmef-value-type.h"
43 
44 #define CHUNK_SIZE 16
45 #define FLOAT_TOLERANCE 0.0001
46 
47 
48 #ifndef MAX
49 # define MAX(x, y) ((x) > (y) ? (x) : (y))
50 #endif
51 
52 #ifndef ABS
53 # define ABS(x) (((x) < 0) ? -(x) : (x))
54 #endif
55 
56 
57 #define idmef_value_new_decl(mtype, vname, vtype)                    \
58 int idmef_value_new_ ## vname (idmef_value_t **value, vtype val) {   \
59         int ret;                                                     \
60                                                                      \
61         ret = idmef_value_create(value, IDMEF_VALUE_TYPE_ ## mtype); \
62         if ( ret < 0 )                                               \
63                 return ret;                                          \
64                                                                      \
65         (*value)->type.data. vname ## _val = val;                    \
66                                                                      \
67         return 0;                                                    \
68 }
69 
70 
71 #define idmef_value_set_decl(mtype, vname, vtype)                    \
72 int idmef_value_set_ ## vname (idmef_value_t *value, vtype val)      \
73 {                                                                    \
74         prelude_return_val_if_fail(value, prelude_error(PRELUDE_ERROR_ASSERTION)); \
75                                                                      \
76         if ( value->own_data )                                       \
77                 idmef_value_type_destroy(&value->type);              \
78                                                                      \
79         value->type.id = IDMEF_VALUE_TYPE_ ## mtype;                 \
80         value->type.data. vname ## _val = val;                       \
81         value->own_data = TRUE;                                      \
82                                                                      \
83         return 0;                                                    \
84 }
85 
86 #define idmef_value_get_decl(mtype, vname, vtype)                \
87 vtype idmef_value_get_ ## vname (const idmef_value_t *val)       \
88 {                                                                \
89         prelude_return_val_if_fail(val, (vtype) 0);              \
90                                                                  \
91         if ( val->type.id != IDMEF_VALUE_TYPE_ ## mtype )        \
92                 return (vtype) 0;                                \
93                                                                  \
94         return val->type.data. vname ## _val;                    \
95 }
96 
97 
98 #define idmef_value_decl(mtype, vname, vtype)     \
99         idmef_value_new_decl(mtype, vname, vtype) \
100         idmef_value_get_decl(mtype, vname, vtype) \
101         idmef_value_set_decl(mtype, vname, vtype)
102 
103 
104 
105 #define CASTCHK(ntype, fval, src, dst)                                             \
106   if ( ! (src == dst && (src < 1) == (dst < 1)) )                                  \
107                 return prelude_error_verbose(PRELUDE_ERROR_GENERIC,                \
108                         "Value '%" fval "' is incompatible with output type '%s'", \
109                         src, idmef_value_type_to_string(ntype))
110 
111 
112 
113 #define FLOATCHK(ntype, fval, src, dst)                                            \
114         if ( reldif(src, dst) > FLOAT_TOLERANCE )                                  \
115                 return prelude_error_verbose(PRELUDE_ERROR_GENERIC,                \
116                         "Value '%" fval "' is incompatible with output type '%s'", \
117                         src, idmef_value_type_to_string(ntype))
118 
119 
120 #define VALUE_CAST_CHECK(v, itype_t, itype, iformat, ntype) do {      \
121         itype_t src = idmef_value_get_ ##itype(value);                \
122                                                                       \
123         if ( ntype == IDMEF_VALUE_TYPE_INT8 ) {                       \
124                 CASTCHK(ntype, iformat, src, (int8_t) src);           \
125                 idmef_value_set_int8(value, src);                     \
126                                                                       \
127         } else if ( ntype == IDMEF_VALUE_TYPE_UINT8 ) {               \
128                 CASTCHK(ntype, iformat, src, (uint8_t) src);          \
129                 idmef_value_set_uint8(value, src);                    \
130                                                                       \
131         } else if ( ntype == IDMEF_VALUE_TYPE_INT16 ) {               \
132                 CASTCHK(ntype, iformat, src, (int16_t) src);          \
133                 idmef_value_set_int16(value, src);                    \
134                                                                       \
135         } else if ( ntype == IDMEF_VALUE_TYPE_UINT16 ) {              \
136                 CASTCHK(ntype, iformat, src, (uint16_t) src);         \
137                 idmef_value_set_uint16(value, src);                   \
138                                                                       \
139         } else if ( ntype == IDMEF_VALUE_TYPE_INT32 ) {               \
140                 CASTCHK(ntype, iformat, src, (int32_t) src);          \
141                 idmef_value_set_int32(value, src);                    \
142                                                                       \
143         } else if ( ntype == IDMEF_VALUE_TYPE_UINT32 ) {              \
144                 CASTCHK(ntype, iformat, src, (uint32_t) src);         \
145                 idmef_value_set_uint32(value, src);                   \
146                                                                       \
147         } else if ( ntype == IDMEF_VALUE_TYPE_INT64 ) {               \
148                 CASTCHK(ntype, iformat, src, (int64_t) src);          \
149                 idmef_value_set_int64(value, src);                    \
150                                                                       \
151         } else if ( ntype == IDMEF_VALUE_TYPE_UINT64 ) {              \
152                 CASTCHK(ntype, iformat, src, (uint64_t) src);         \
153                 idmef_value_set_uint64(value, src);                   \
154                                                                       \
155         } else if ( ntype == IDMEF_VALUE_TYPE_FLOAT ) {               \
156                 FLOATCHK(ntype, iformat, src, (float) src);           \
157                 idmef_value_set_float(value, src);                    \
158                                                                       \
159         } else if ( ntype == IDMEF_VALUE_TYPE_DOUBLE ) {              \
160                 FLOATCHK(ntype, iformat, src, (double) src);          \
161                 idmef_value_set_double(value, src);                   \
162                                                                       \
163         } else return prelude_error_verbose(PRELUDE_ERROR_GENERIC,    \
164                                           "Unable to handle output type '%s' for integer cast", \
165                                            idmef_value_type_to_string(ntype));                  \
166 } while(0)
167 
168 
169 
170 typedef struct compare {
171         unsigned int match;
172         idmef_value_t *val2;
173         idmef_criterion_operator_t operator;
174 } compare_t;
175 
176 
177 
178 struct idmef_value {
179         int list_elems;
180         int list_max;
181         int refcount;
182         prelude_bool_t own_data;
183         idmef_value_t **list;
184         idmef_value_type_t type;
185 };
186 
187 
188 /*
189  * Returns the relative difference of two real numbers: 0.0 if they are
190  * exactly the same, otherwise, the ratio of the difference to the
191  * larger of the two.
192  */
reldif(double a,double b)193 static double reldif(double a, double b)
194 {
195         double c = ABS(a);
196         double d = ABS(b);
197 
198         d = MAX(c, d);
199 
200         return d == 0.0 ? 0.0 : ABS(a - b) / d;
201 }
202 
203 
string_isdigit(const char * s)204 static int string_isdigit(const char *s)
205 {
206         while ( *s ) {
207                 if ( ! isdigit((int) *s) )
208                         return -1;
209                 s++;
210         }
211 
212         return 0;
213 }
214 
215 
idmef_value_create(idmef_value_t ** ret,idmef_value_type_id_t type_id)216 static int idmef_value_create(idmef_value_t **ret, idmef_value_type_id_t type_id)
217 {
218         *ret = calloc(1, sizeof(**ret));
219         if ( ! *ret )
220                 return prelude_error_from_errno(errno);
221 
222         (*ret)->refcount = 1;
223         (*ret)->own_data = TRUE;
224         (*ret)->type.id = type_id;
225 
226         return 0;
227 }
228 
229 
230 
idmef_value_decl(INT8,int8,int8_t)231 idmef_value_decl(INT8, int8, int8_t)
232 idmef_value_decl(UINT8, uint8, uint8_t)
233 idmef_value_decl(INT16, int16, int16_t)
234 idmef_value_decl(UINT16, uint16, uint16_t)
235 idmef_value_decl(INT32, int32, int32_t)
236 idmef_value_decl(UINT32, uint32, uint32_t)
237 idmef_value_decl(INT64, int64, int64_t)
238 idmef_value_decl(UINT64, uint64, uint64_t)
239 idmef_value_decl(FLOAT, float, float)
240 idmef_value_decl(DOUBLE, double, double)
241 idmef_value_decl(STRING, string, prelude_string_t *)
242 idmef_value_decl(DATA, data, idmef_data_t *)
243 idmef_value_decl(TIME, time, idmef_time_t *)
244 
245 
246 
247 int idmef_value_get_enum(const idmef_value_t *value)
248 {
249         prelude_return_val_if_fail(value, prelude_error(PRELUDE_ERROR_ASSERTION));
250 
251         if ( value->type.id != IDMEF_VALUE_TYPE_ENUM )
252                 return 0;
253 
254         return value->type.data.enum_val.value;
255 }
256 
257 
idmef_value_set_class(idmef_value_t * value,idmef_class_id_t class,void * object)258 int idmef_value_set_class(idmef_value_t *value, idmef_class_id_t class, void *object)
259 {
260         prelude_return_val_if_fail(value, prelude_error(PRELUDE_ERROR_ASSERTION));
261         prelude_return_val_if_fail(object, prelude_error(PRELUDE_ERROR_ASSERTION));
262 
263         if ( value->own_data )
264                 idmef_value_type_destroy(&value->type);
265 
266         value->own_data = TRUE;
267         value->type.data.class_val.object = object;
268         value->type.data.class_val.class_id = class;
269 
270         return 0;
271 }
272 
273 
idmef_value_new_class(idmef_value_t ** value,idmef_class_id_t class,void * object)274 int idmef_value_new_class(idmef_value_t **value, idmef_class_id_t class, void *object)
275 {
276         int ret;
277 
278         prelude_return_val_if_fail(object, prelude_error(PRELUDE_ERROR_ASSERTION));
279 
280         ret = idmef_value_create(value, IDMEF_VALUE_TYPE_CLASS);
281         if ( ret < 0 )
282                 return ret;
283 
284         (*value)->type.data.class_val.object = object;
285         (*value)->type.data.class_val.class_id = class;
286 
287         return ret;
288 }
289 
290 
idmef_value_set_enum_from_numeric(idmef_value_t * value,idmef_class_id_t class,int val)291 int idmef_value_set_enum_from_numeric(idmef_value_t *value, idmef_class_id_t class, int val)
292 {
293         prelude_return_val_if_fail(value, prelude_error(PRELUDE_ERROR_ASSERTION));
294 
295         if ( value->own_data )
296                 idmef_value_type_destroy(&value->type);
297 
298         value->own_data = TRUE;
299         value->type.id = IDMEF_VALUE_TYPE_ENUM;
300         value->type.data.enum_val.value = val;
301         value->type.data.enum_val.class_id = class;
302 
303         return 0;
304 }
305 
306 
idmef_value_set_enum_from_string(idmef_value_t * value,idmef_class_id_t class,const char * buf)307 int idmef_value_set_enum_from_string(idmef_value_t *value, idmef_class_id_t class, const char *buf)
308 {
309         int ret;
310 
311         prelude_return_val_if_fail(value, prelude_error(PRELUDE_ERROR_ASSERTION));
312         prelude_return_val_if_fail(buf, prelude_error(PRELUDE_ERROR_ASSERTION));
313 
314         ret = idmef_class_enum_to_numeric(class, buf);
315         if ( ret < 0 )
316                 return ret;
317 
318         return idmef_value_set_enum_from_numeric(value, class, ret);
319 }
320 
321 
idmef_value_set_enum(idmef_value_t * value,idmef_class_id_t class,const char * buf)322 int idmef_value_set_enum(idmef_value_t *value, idmef_class_id_t class, const char *buf)
323 {
324         int ret;
325 
326         prelude_return_val_if_fail(value, prelude_error(PRELUDE_ERROR_ASSERTION));
327         prelude_return_val_if_fail(buf, prelude_error(PRELUDE_ERROR_ASSERTION));
328 
329         if ( string_isdigit(buf) == 0 )
330                 ret = idmef_value_set_enum_from_numeric(value, class, atoi(buf));
331         else
332                 ret = idmef_value_set_enum_from_string(value, class, buf);
333 
334         return ret;
335 }
336 
337 
idmef_value_new_enum_from_numeric(idmef_value_t ** value,idmef_class_id_t class,int val)338 int idmef_value_new_enum_from_numeric(idmef_value_t **value, idmef_class_id_t class, int val)
339 {
340         int ret;
341 
342         ret = idmef_value_create(value, IDMEF_VALUE_TYPE_ENUM);
343         if ( ret < 0 )
344                 return ret;
345 
346         (*value)->type.data.enum_val.value = val;
347         (*value)->type.data.enum_val.class_id = class;
348 
349         return ret;
350 }
351 
352 
idmef_value_new_enum_from_string(idmef_value_t ** value,idmef_class_id_t class,const char * buf)353 int idmef_value_new_enum_from_string(idmef_value_t **value, idmef_class_id_t class, const char *buf)
354 {
355         int ret;
356 
357         prelude_return_val_if_fail(buf, prelude_error(PRELUDE_ERROR_ASSERTION));
358 
359         ret = idmef_class_enum_to_numeric(class, buf);
360         if ( ret < 0 )
361                 return ret;
362 
363         return idmef_value_new_enum_from_numeric(value, class, ret);
364 }
365 
366 
367 
idmef_value_new_enum(idmef_value_t ** value,idmef_class_id_t class,const char * buf)368 int idmef_value_new_enum(idmef_value_t **value, idmef_class_id_t class, const char *buf)
369 {
370         int ret;
371 
372         prelude_return_val_if_fail(buf, prelude_error(PRELUDE_ERROR_ASSERTION));
373 
374         if ( string_isdigit(buf) == 0 )
375                 ret = idmef_value_new_enum_from_numeric(value, class, atoi(buf));
376         else
377                 ret = idmef_value_new_enum_from_string(value, class, buf);
378 
379         return ret;
380 }
381 
382 
idmef_value_new_list(idmef_value_t ** value)383 int idmef_value_new_list(idmef_value_t **value)
384 {
385         int ret;
386 
387         ret = idmef_value_create(value, IDMEF_VALUE_TYPE_LIST);
388         if ( ret < 0 )
389                 return ret;
390 
391         (*value)->list = malloc(CHUNK_SIZE * sizeof(idmef_value_t *));
392         if ( ! (*value)->list ) {
393                 free(*value);
394                     return prelude_error_from_errno(errno);
395         }
396 
397         (*value)->list_elems = 0;
398         (*value)->list_max = CHUNK_SIZE - 1;
399 
400         return 0;
401 }
402 
403 
404 
idmef_value_list_add(idmef_value_t * list,idmef_value_t * item)405 int idmef_value_list_add(idmef_value_t *list, idmef_value_t *item)
406 {
407         prelude_return_val_if_fail(list, prelude_error(PRELUDE_ERROR_ASSERTION));
408 
409         if ( list->list_elems == list->list_max ) {
410 
411                 list->list = realloc(list->list, (list->list_max + 1 + CHUNK_SIZE) * sizeof(idmef_value_t *));
412                 if ( ! list->list )
413                         return prelude_error_from_errno(errno);
414 
415                 list->list_max += CHUNK_SIZE;
416         }
417 
418         list->list[list->list_elems++] = item;
419 
420         return 0;
421 }
422 
423 
424 
idmef_value_is_list(const idmef_value_t * list)425 prelude_bool_t idmef_value_is_list(const idmef_value_t *list)
426 {
427         prelude_return_val_if_fail(list, FALSE);
428         return (list->list) ? TRUE : FALSE;
429 }
430 
431 
432 
idmef_value_list_is_empty(const idmef_value_t * list)433 prelude_bool_t idmef_value_list_is_empty(const idmef_value_t *list)
434 {
435         prelude_return_val_if_fail(list, TRUE);
436         return (list->list_elems) ? FALSE : TRUE;
437 }
438 
439 
440 
441 
idmef_value_new(idmef_value_t ** value,idmef_value_type_id_t type,void * ptr)442 int idmef_value_new(idmef_value_t **value, idmef_value_type_id_t type, void *ptr)
443 {
444         int ret;
445 
446         prelude_return_val_if_fail(ptr, prelude_error(PRELUDE_ERROR_ASSERTION));
447 
448         ret = idmef_value_create(value, type);
449         if ( ret < 0 )
450                 return ret;
451 
452         (*value)->type.data.data_val = ptr;
453 
454         return 0;
455 }
456 
457 
458 
idmef_value_new_from_string(idmef_value_t ** value,idmef_value_type_id_t type,const char * buf)459 int idmef_value_new_from_string(idmef_value_t **value, idmef_value_type_id_t type, const char *buf)
460 {
461         int ret;
462 
463         prelude_return_val_if_fail(buf, prelude_error(PRELUDE_ERROR_ASSERTION));
464 
465         ret = idmef_value_create(value, type);
466         if ( ret < 0 )
467                 return ret;
468 
469         ret = idmef_value_type_read(&(*value)->type, buf);
470         if ( ret < 0 ) {
471                 free(*value);
472                 return ret;
473         }
474 
475         return 0;
476 }
477 
478 
479 
idmef_value_new_from_path(idmef_value_t ** value,idmef_path_t * path,const char * buf)480 int idmef_value_new_from_path(idmef_value_t **value, idmef_path_t *path, const char *buf)
481 {
482         int ret;
483         idmef_class_id_t class;
484         idmef_value_type_id_t value_type;
485 
486         prelude_return_val_if_fail(path, prelude_error(PRELUDE_ERROR_ASSERTION));
487         prelude_return_val_if_fail(buf, prelude_error(PRELUDE_ERROR_ASSERTION));
488 
489         value_type = idmef_path_get_value_type(path, -1);
490         if ( value_type < 0 )
491                 return value_type;
492 
493         if ( value_type != IDMEF_VALUE_TYPE_ENUM )
494                 ret = idmef_value_new_from_string(value, value_type, buf);
495         else {
496                 class = idmef_path_get_class(path, -1);
497                 if ( class < 0 )
498                         return class;
499 
500                 ret = idmef_value_new_enum(value, class, buf);
501         }
502 
503         return ret;
504 }
505 
506 
507 
idmef_value_set_own_data(idmef_value_t * value,prelude_bool_t own_data)508 static int idmef_value_set_own_data(idmef_value_t *value, prelude_bool_t own_data)
509 {
510         int cnt;
511 
512         if ( ! value->list )
513                 value->own_data = own_data;
514 
515         else for ( cnt = 0 ; cnt < value->list_elems; cnt++ ) {
516                 if ( value->list[cnt] )
517                         idmef_value_set_own_data(value->list[cnt], own_data);
518         }
519 
520         return 0;
521 }
522 
523 
524 
525 
idmef_value_have_own_data(idmef_value_t * value)526 int idmef_value_have_own_data(idmef_value_t *value)
527 {
528         prelude_return_val_if_fail(value, prelude_error(PRELUDE_ERROR_ASSERTION));
529         return idmef_value_set_own_data(value, TRUE);
530 }
531 
532 
533 
idmef_value_dont_have_own_data(idmef_value_t * value)534 int idmef_value_dont_have_own_data(idmef_value_t *value)
535 {
536         prelude_return_val_if_fail(value, prelude_error(PRELUDE_ERROR_ASSERTION));
537         return idmef_value_set_own_data(value, FALSE);
538 }
539 
540 
541 
idmef_value_get_type(const idmef_value_t * value)542 idmef_value_type_id_t idmef_value_get_type(const idmef_value_t *value)
543 {
544         prelude_return_val_if_fail(value, prelude_error(PRELUDE_ERROR_ASSERTION));
545         return value->type.id;
546 }
547 
548 
549 
idmef_value_get_class(const idmef_value_t * value)550 idmef_class_id_t idmef_value_get_class(const idmef_value_t *value)
551 {
552         prelude_return_val_if_fail(value, prelude_error(PRELUDE_ERROR_ASSERTION));
553 
554         if ( value->type.id == IDMEF_VALUE_TYPE_CLASS )
555                 return value->type.data.class_val.class_id;
556 
557         else if ( value->type.id == IDMEF_VALUE_TYPE_ENUM )
558                 return value->type.data.enum_val.class_id;
559 
560         return -1;
561 }
562 
563 
564 
idmef_value_get_object(const idmef_value_t * value)565 void *idmef_value_get_object(const idmef_value_t *value)
566 {
567         prelude_return_val_if_fail(value, NULL);
568         return (value->type.id == IDMEF_VALUE_TYPE_CLASS) ? value->type.data.class_val.object : NULL;
569 }
570 
571 
value_ro2rw(const idmef_value_t * value)572 inline static idmef_value_t *value_ro2rw(const idmef_value_t *value)
573 {
574         union {
575                 idmef_value_t *rw;
576                 const idmef_value_t *ro;
577         } val;
578 
579         val.ro = value;
580 
581         return val.rw;
582 }
583 
584 
idmef_value_iterate(const idmef_value_t * value,int (* callback)(idmef_value_t * ptr,void * extra),void * extra)585 int idmef_value_iterate(const idmef_value_t *value,
586                         int (*callback)(idmef_value_t *ptr, void *extra), void *extra)
587 {
588         int i, ret;
589 
590         prelude_return_val_if_fail(value, prelude_error(PRELUDE_ERROR_ASSERTION));
591         prelude_return_val_if_fail(callback, prelude_error(PRELUDE_ERROR_ASSERTION));
592 
593         if ( ! value->list )
594                 return callback(value_ro2rw(value), extra);
595 
596         for ( i = 0; i < value->list_elems; i++ ) {
597 
598                 ret = callback(value->list[i], extra);
599                 if ( ret < 0 )
600                         return ret;
601         }
602 
603         return 0;
604 }
605 
606 
607 
idmef_value_iterate_reversed(const idmef_value_t * value,int (* callback)(idmef_value_t * ptr,void * extra),void * extra)608 int idmef_value_iterate_reversed(const idmef_value_t *value,
609                                  int (*callback)(idmef_value_t *ptr, void *extra), void *extra)
610 {
611         int i, ret;
612 
613         prelude_return_val_if_fail(value, prelude_error(PRELUDE_ERROR_ASSERTION));
614         prelude_return_val_if_fail(callback, prelude_error(PRELUDE_ERROR_ASSERTION));
615 
616         if ( ! value->list )
617                 return callback(value_ro2rw(value), extra);
618 
619         for ( i = value->list_elems - 1; i >= 0; i-- ) {
620 
621                 ret = callback(value->list[i], extra);
622                 if ( ret < 0 )
623                         return ret;
624         }
625 
626         return 0;
627 }
628 
629 
630 
idmef_value_get_nth2(const idmef_value_t * val,int index,idmef_value_t ** ret)631 int idmef_value_get_nth2(const idmef_value_t *val, int index, idmef_value_t **ret)
632 {
633         prelude_return_val_if_fail(val, prelude_error(PRELUDE_ERROR_ASSERTION));
634         prelude_return_val_if_fail(index <= val->list_elems, prelude_error(PRELUDE_ERROR_ASSERTION));
635 
636         if ( index == 0 && ! val->list ) {
637                 *ret = value_ro2rw(val);
638                 return 1;
639         }
640 
641         else if ( index >= 0 && index < val->list_elems ) {
642                 *ret = val->list[index];
643                 return 1;
644         }
645 
646         else if ( index >= val->list_elems )
647                 return 0;
648 
649         else return -1;
650 }
651 
652 
653 
idmef_value_get_nth(const idmef_value_t * val,int n)654 idmef_value_t *idmef_value_get_nth(const idmef_value_t *val, int n)
655 {
656         int ret;
657         idmef_value_t *rv;
658 
659         prelude_return_val_if_fail(val, NULL);
660 
661         ret = idmef_value_get_nth2(val, n, &rv);
662         if ( ret != 1 )
663                 return NULL;
664 
665         return rv;
666 }
667 
668 
669 
idmef_value_get_count(const idmef_value_t * val)670 int idmef_value_get_count(const idmef_value_t *val)
671 {
672         prelude_return_val_if_fail(val, prelude_error(PRELUDE_ERROR_ASSERTION));
673         return val->list ? val->list_elems : 1;
674 }
675 
676 
677 
678 
idmef_value_list_clone(const idmef_value_t * val,idmef_value_t ** dst)679 static int idmef_value_list_clone(const idmef_value_t *val, idmef_value_t **dst)
680 {
681         int cnt, ret;
682 
683         ret = idmef_value_create(dst, val->type.id);
684         if ( ret < 0 )
685                 return ret;
686 
687         (*dst)->list_elems = val->list_elems;
688         (*dst)->list_max = val->list_max;
689         (*dst)->list = malloc(((*dst)->list_elems + 1) * sizeof((*dst)->list));
690 
691         for ( cnt = 0; cnt < (*dst)->list_elems; cnt++ ) {
692                 if ( ! val->list[cnt] ) {
693                         (*dst)->list[cnt] = NULL;
694                         continue;
695                 }
696 
697                 ret = idmef_value_clone(val->list[cnt], &((*dst)->list[cnt]));
698                 if ( ret < 0 ) {
699                         while ( --cnt >= 0 ) {
700                                 if ( (*dst)->list[cnt] )
701                                         idmef_value_destroy((*dst)->list[cnt]);
702                         }
703                 }
704 
705                 free((*dst)->list);
706                 free(*dst);
707 
708                 return -1;
709         }
710 
711         return 0;
712 }
713 
714 
715 
idmef_value_clone(const idmef_value_t * val,idmef_value_t ** dst)716 int idmef_value_clone(const idmef_value_t *val, idmef_value_t **dst)
717 {
718         int ret;
719 
720         prelude_return_val_if_fail(val, prelude_error(PRELUDE_ERROR_ASSERTION));
721 
722         if ( val->list )
723                 return idmef_value_list_clone(val, dst);
724 
725         ret = idmef_value_create(dst, val->type.id);
726         if ( ret < 0 )
727                 return ret;
728 
729         ret = idmef_value_type_clone(&val->type, &(*dst)->type);
730         if ( ret < 0 )
731                 free(*dst);
732 
733         return ret;
734 }
735 
736 
737 
idmef_value_ref(idmef_value_t * val)738 idmef_value_t *idmef_value_ref(idmef_value_t *val)
739 {
740         prelude_return_val_if_fail(val, NULL);
741 
742         val->refcount++;
743 
744         return val;
745 }
746 
747 
748 
idmef_value_to_string(const idmef_value_t * value,prelude_string_t * out)749 int idmef_value_to_string(const idmef_value_t *value, prelude_string_t *out)
750 {
751         int i, ret;
752         idmef_value_t *val;
753 
754         prelude_return_val_if_fail(value, prelude_error(PRELUDE_ERROR_ASSERTION));
755         prelude_return_val_if_fail(out, prelude_error(PRELUDE_ERROR_ASSERTION));
756 
757         if ( idmef_value_is_list(value) ) {
758                 ret = prelude_string_cat(out, "(");
759                 if ( ret < 0 )
760                         return ret;
761         }
762 
763         for ( i = 0; i < idmef_value_get_count(value); i++ ) {
764                 val = idmef_value_get_nth(value, i);
765 
766                 if ( idmef_value_is_list(val) ) {
767                         ret = prelude_string_cat(out, "(");
768                         if ( ret < 0 )
769                                 return ret;
770 
771                         ret = idmef_value_to_string(val, out);
772                         if ( ret < 0 )
773                                 return ret;
774 
775                         ret = prelude_string_cat(out, ")");
776                         if ( ret < 0 )
777                                 return ret;
778                 } else {
779                         if ( i ) {
780                                 ret = prelude_string_cat(out, ", ");
781                                 if ( ret < 0 )
782                                         return ret;
783                         }
784 
785                         ret = idmef_value_type_write(&val->type, out);
786                         if ( ret < 0 )
787                                 return ret;
788                 }
789         }
790 
791         if ( idmef_value_is_list(value) ) {
792                 ret = prelude_string_cat(out, ")");
793                 if ( ret < 0 )
794                         return ret;
795         }
796 
797         return 0;
798 }
799 
800 
801 
idmef_value_print(const idmef_value_t * val,prelude_io_t * fd)802 int idmef_value_print(const idmef_value_t *val, prelude_io_t *fd)
803 {
804         int ret;
805         prelude_string_t *out;
806 
807         prelude_return_val_if_fail(val, prelude_error(PRELUDE_ERROR_ASSERTION));
808         prelude_return_val_if_fail(fd, prelude_error(PRELUDE_ERROR_ASSERTION));
809 
810         ret = prelude_string_new(&out);
811         if ( ret < 0 )
812                 return ret;
813 
814         ret = idmef_value_type_write(&val->type, out);
815         if ( ret < 0 ) {
816                 prelude_string_destroy(out);
817                 return ret;
818         }
819 
820         return prelude_io_write(fd, prelude_string_get_string(out), prelude_string_get_len(out));
821 }
822 
823 
824 
idmef_value_get(const idmef_value_t * val,void * res)825 int idmef_value_get(const idmef_value_t *val, void *res)
826 {
827         prelude_return_val_if_fail(val, prelude_error(PRELUDE_ERROR_ASSERTION));
828         prelude_return_val_if_fail(res, prelude_error(PRELUDE_ERROR_ASSERTION));
829 
830         return idmef_value_type_copy(&val->type, res);
831 }
832 
833 
834 
idmef_value_match_internal(idmef_value_t * val1,void * extra)835 static int idmef_value_match_internal(idmef_value_t *val1, void *extra)
836 {
837         int ret;
838         compare_t *compare = extra;
839 
840         if ( idmef_value_is_list(val1) )
841                 ret = idmef_value_iterate(val1, idmef_value_match_internal, extra);
842 
843         else if ( compare->val2 && idmef_value_is_list(compare->val2) ) {
844                 ret = idmef_value_match(compare->val2, val1, compare->operator);
845                 if ( ret < 0 )
846                         return ret;
847 
848                 compare->match += ret;
849         }
850 
851         else {
852                 ret = idmef_value_type_compare(&val1->type, &compare->val2->type, compare->operator);
853                 if ( ret == 0 )
854                         compare->match++;
855         }
856 
857         return ret;
858 }
859 
860 
861 
862 /**
863  * idmef_value_match:
864  * @val1: Pointer to a #idmef_value_t object.
865  * @val2: Pointer to a #idmef_value_t object.
866  * @op: operator to use for matching.
867  *
868  * Match @val1 and @val2 using @op.
869  *
870  * Returns: the number of match, 0 for none, a negative value if an error occured.
871  */
idmef_value_match(idmef_value_t * val1,idmef_value_t * val2,idmef_criterion_operator_t op)872 int idmef_value_match(idmef_value_t *val1, idmef_value_t *val2, idmef_criterion_operator_t op)
873 {
874         int ret;
875         compare_t compare;
876 
877         prelude_return_val_if_fail(val1, prelude_error(PRELUDE_ERROR_ASSERTION));
878         prelude_return_val_if_fail(val2, prelude_error(PRELUDE_ERROR_ASSERTION));
879 
880         compare.match = 0;
881         compare.val2 = val2;
882         compare.operator = op;
883 
884         ret = idmef_value_iterate(val1, idmef_value_match_internal, &compare);
885         if ( ret < 0 )
886                 return ret;
887 
888         return compare.match;
889 }
890 
891 
892 
893 /**
894  * idmef_value_check_operator:
895  * @value: Pointer to a #idmef_value_t object.
896  * @op: Type of operator to check @value for.
897  *
898  * Check whether @op can apply to @value.
899  *
900  * Returns: 0 on success, a negative value if an error occured.
901  */
idmef_value_check_operator(const idmef_value_t * value,idmef_criterion_operator_t op)902 int idmef_value_check_operator(const idmef_value_t *value, idmef_criterion_operator_t op)
903 {
904         prelude_return_val_if_fail(value, prelude_error(PRELUDE_ERROR_ASSERTION));
905         return idmef_value_type_check_operator(value->type.id, op);
906 }
907 
908 
909 
910 /**
911  * idmef_value_get_applicable_operators:
912  * @value: Pointer to a #idmef_value_t object.
913  * @result: Pointer where the result will be stored.
914  *
915  * Store all operator supported by @value in @result.
916  *
917  * Returns: 0 on success, a negative value if an error occured.
918  */
919 
idmef_value_get_applicable_operators(const idmef_value_t * value,idmef_criterion_operator_t * result)920 int idmef_value_get_applicable_operators(const idmef_value_t *value, idmef_criterion_operator_t *result)
921 {
922         prelude_return_val_if_fail(value, prelude_error(PRELUDE_ERROR_ASSERTION));
923 
924         return idmef_value_type_get_applicable_operators(value->type.id, result);
925 }
926 
927 
928 
929 /**
930  * idmef_value_destroy:
931  * @val: Pointer to a #idmef_value_t object.
932  *
933  * Decrement refcount and destroy @value if it reach 0.
934  */
idmef_value_destroy(idmef_value_t * val)935 void idmef_value_destroy(idmef_value_t *val)
936 {
937         int i;
938 
939         prelude_return_if_fail(val);
940 
941         if ( --val->refcount )
942                 return;
943 
944         if ( val->list ) {
945                 for ( i = 0; i < val->list_elems; i++ ) {
946                         if ( val->list[i] )
947                                 idmef_value_destroy(val->list[i]);
948                 }
949 
950                 free(val->list);
951         }
952 
953         /*
954          * Actual destructor starts here
955          */
956         if ( val->own_data )
957                 idmef_value_type_destroy(&val->type);
958 
959         free(val);
960 }
961 
962 
cast_to_data(idmef_value_t * input)963 static int cast_to_data(idmef_value_t *input)
964 {
965         int ret;
966         idmef_data_t *data;
967         idmef_value_type_id_t vtype = idmef_value_get_type(input);
968 
969         if ( vtype == IDMEF_VALUE_TYPE_STRING ) {
970                 prelude_string_t *str = idmef_value_get_string(input);
971 
972                 ret = idmef_data_new_char_string_dup_fast(&data, prelude_string_get_string(str), prelude_string_get_len(str));
973                 if ( ret < 0 )
974                         return ret;
975 
976                 return idmef_value_set_data(input, data);
977         }
978 
979         else if ( vtype == IDMEF_VALUE_TYPE_INT8 ) {
980                 ret = idmef_data_new_int(&data, idmef_value_get_int8(input));
981                 if ( ret < 0 )
982                         return ret;
983 
984                 return idmef_value_set_data(input, data);
985         }
986 
987         else if ( vtype == IDMEF_VALUE_TYPE_UINT8 ) {
988                 ret = idmef_data_new_int(&data, idmef_value_get_uint8(input));
989                 if ( ret < 0 )
990                         return ret;
991 
992                 return idmef_value_set_data(input, data);
993         }
994 
995         else if ( vtype == IDMEF_VALUE_TYPE_INT16 ) {
996                 ret = idmef_data_new_int(&data, idmef_value_get_int16(input));
997                 if ( ret < 0 )
998                         return ret;
999 
1000                 return idmef_value_set_data(input, data);
1001         }
1002 
1003         else if ( vtype == IDMEF_VALUE_TYPE_UINT16 ) {
1004                 ret = idmef_data_new_int(&data, idmef_value_get_uint16(input));
1005                 if ( ret < 0 )
1006                         return ret;
1007 
1008                 return idmef_value_set_data(input, data);
1009         }
1010 
1011         else if ( vtype == IDMEF_VALUE_TYPE_INT32 ) {
1012                 ret = idmef_data_new_int(&data, idmef_value_get_int32(input));
1013                 if ( ret < 0 )
1014                         return ret;
1015 
1016                 return idmef_value_set_data(input, data);
1017         }
1018 
1019         else if ( vtype == IDMEF_VALUE_TYPE_UINT32 ) {
1020                 ret = idmef_data_new_int(&data, idmef_value_get_uint32(input));
1021                 if ( ret < 0 )
1022                         return ret;
1023 
1024                 return idmef_value_set_data(input, data);
1025         }
1026 
1027         else if ( vtype == IDMEF_VALUE_TYPE_INT64 ) {
1028                 ret = idmef_data_new_int(&data, idmef_value_get_int64(input));
1029                 if ( ret < 0 )
1030                         return ret;
1031 
1032                 return idmef_value_set_data(input, data);
1033         }
1034 
1035         else if ( vtype == IDMEF_VALUE_TYPE_UINT64 ) {
1036                 ret = idmef_data_new_int(&data, idmef_value_get_uint64(input));
1037                 if ( ret < 0 )
1038                         return ret;
1039 
1040                 return idmef_value_set_data(input, data);
1041         }
1042 
1043         else if ( vtype == IDMEF_VALUE_TYPE_TIME ) {
1044                 ret = idmef_data_new_time(&data, idmef_time_ref(idmef_value_get_time(input)));
1045                 if ( ret < 0 )
1046                         return ret;
1047 
1048                 return idmef_value_set_data(input, data);
1049         }
1050 
1051         else if ( vtype == IDMEF_VALUE_TYPE_FLOAT ) {
1052                 int64_t v = idmef_value_get_float(input);
1053 
1054                 if ( v == idmef_value_get_float(input) )
1055                         ret = idmef_data_new_int(&data, v);
1056                 else
1057                         ret = idmef_data_new_float(&data, idmef_value_get_float(input));
1058 
1059                 if ( ret < 0 )
1060                         return ret;
1061 
1062                 return idmef_value_set_data(input, data);
1063         }
1064 
1065         else if ( vtype == IDMEF_VALUE_TYPE_DOUBLE ) {
1066                 int64_t v = idmef_value_get_double(input);
1067 
1068                 if ( v == idmef_value_get_double(input) )
1069                         ret = idmef_data_new_int(&data, v);
1070                 else
1071                         ret = idmef_data_new_float(&data, idmef_value_get_double(input));
1072 
1073                 if ( ret < 0 )
1074                         return ret;
1075 
1076                 return idmef_value_set_data(input, data);
1077         }
1078 
1079         return prelude_error_verbose(PRELUDE_ERROR_GENERIC,
1080                                      "Unable to cast input type '%s' to 'data'",
1081                                      idmef_value_type_to_string(vtype));
1082 }
1083 
1084 
cast_to_time(idmef_value_t * value)1085 static int cast_to_time(idmef_value_t *value)
1086 {
1087         int ret = -1;
1088         idmef_time_t *time;
1089 
1090         if ( idmef_value_get_type(value) == IDMEF_VALUE_TYPE_STRING ) {
1091                 ret = idmef_time_new_from_string(&time, prelude_string_get_string(idmef_value_get_string(value)));
1092                 if ( ret < 0 )
1093                         return ret;
1094 
1095                 idmef_value_set_time(value, time);
1096         }
1097 
1098         else if ( idmef_value_get_type(value) == IDMEF_VALUE_TYPE_INT32 ) {
1099                 time_t val = idmef_value_get_int32(value);
1100 
1101                 ret = idmef_time_new_from_time(&time, &val);
1102                 if ( ret < 0 )
1103                         return ret;
1104 
1105                 idmef_value_set_time(value, time);
1106         }
1107 
1108         else if ( idmef_value_get_type(value) == IDMEF_VALUE_TYPE_UINT32 ) {
1109                 time_t val = idmef_value_get_uint32(value);
1110 
1111                 ret = idmef_time_new_from_time(&time, &val);
1112                 if ( ret < 0 )
1113                         return ret;
1114 
1115                 idmef_value_set_time(value, time);
1116         }
1117 
1118         else if ( idmef_value_get_type(value) == IDMEF_VALUE_TYPE_INT64 ) {
1119                 time_t val = idmef_value_get_int64(value);
1120 
1121                 ret = idmef_time_new_from_time(&time, &val);
1122                 if ( ret < 0 )
1123                         return ret;
1124 
1125                 idmef_value_set_time(value, time);
1126         }
1127 
1128         else if ( idmef_value_get_type(value) == IDMEF_VALUE_TYPE_UINT64 ) {
1129                 time_t val = idmef_value_get_uint64(value);
1130 
1131                 ret = idmef_time_new_from_time(&time, &val);
1132                 if ( ret < 0 )
1133                         return ret;
1134 
1135                 idmef_value_set_time(value, time);
1136         }
1137 
1138         return ret;
1139 }
1140 
1141 
1142 
cast_to_string(idmef_value_t * value)1143 static int cast_to_string(idmef_value_t *value)
1144 {
1145         int ret;
1146         prelude_string_t *out;
1147 
1148         ret = prelude_string_new(&out);
1149         if ( ret < 0 )
1150                 return ret;
1151 
1152         ret = idmef_value_type_write(&value->type, out);
1153         if ( ret < 0 ) {
1154                 prelude_string_destroy(out);
1155                 return ret;
1156         }
1157 
1158         idmef_value_set_string(value, out);
1159 
1160         return 0;
1161 }
1162 
1163 
1164 
cast_from_string(idmef_value_t * value,idmef_value_type_id_t ntype)1165 static int cast_from_string(idmef_value_t *value, idmef_value_type_id_t ntype)
1166 {
1167         int ret;
1168         idmef_value_type_t vt;
1169         prelude_string_t *str = idmef_value_get_string(value);
1170 
1171         vt.id = ntype;
1172 
1173         ret = idmef_value_type_read(&vt, prelude_string_get_string(str));
1174         if ( ret < 0 )
1175                 return ret;
1176 
1177         if ( value->own_data )
1178                 idmef_value_type_destroy(&value->type);
1179 
1180         memcpy(&value->type, &vt, sizeof(value->type));
1181 
1182         return 0;
1183 }
1184 
1185 
1186 
_idmef_value_cast(idmef_value_t * value,idmef_value_type_id_t ntype,idmef_class_id_t id)1187 int _idmef_value_cast(idmef_value_t *value, idmef_value_type_id_t ntype, idmef_class_id_t id)
1188 {
1189         idmef_value_type_id_t otype;
1190 
1191         prelude_return_val_if_fail(value, prelude_error(PRELUDE_ERROR_ASSERTION));
1192 
1193         otype = idmef_value_get_type(value);
1194         prelude_log_debug(3, "converting '%s' to '%s'.\n",
1195                           idmef_value_type_to_string(otype),
1196                           idmef_value_type_to_string(ntype));
1197 
1198         if ( ntype == IDMEF_VALUE_TYPE_DATA )
1199                 return cast_to_data(value);
1200 
1201         else if ( ntype == IDMEF_VALUE_TYPE_TIME )
1202                 return cast_to_time(value);
1203 
1204         else if ( ntype == IDMEF_VALUE_TYPE_STRING )
1205                 return cast_to_string(value);
1206 
1207         else if ( ntype == IDMEF_VALUE_TYPE_ENUM && idmef_value_get_type(value) == IDMEF_VALUE_TYPE_STRING ) {
1208                 prelude_string_t *str = idmef_value_get_string(value);
1209                 return idmef_value_set_enum_from_string(value, id, prelude_string_get_string(str));
1210         }
1211 
1212         else if ( otype == IDMEF_VALUE_TYPE_INT8 )
1213                 VALUE_CAST_CHECK(value, int8_t, int8, PRELUDE_PRId8, ntype);
1214 
1215         else if ( otype == IDMEF_VALUE_TYPE_UINT8 )
1216                 VALUE_CAST_CHECK(value, uint8_t, uint8, PRELUDE_PRIu8, ntype);
1217 
1218         else if ( otype == IDMEF_VALUE_TYPE_INT16 )
1219                 VALUE_CAST_CHECK(value, int16_t, int16, PRELUDE_PRId16, ntype);
1220 
1221         else if ( otype == IDMEF_VALUE_TYPE_UINT16 )
1222                 VALUE_CAST_CHECK(value, uint16_t, uint16, PRELUDE_PRIu16, ntype);
1223 
1224         else if ( otype == IDMEF_VALUE_TYPE_INT32 )
1225                 VALUE_CAST_CHECK(value, int32_t, int32, PRELUDE_PRId32, ntype);
1226 
1227         else if ( otype == IDMEF_VALUE_TYPE_UINT32 )
1228                 VALUE_CAST_CHECK(value, uint32_t, uint32, PRELUDE_PRIu32, ntype);
1229 
1230         else if ( otype == IDMEF_VALUE_TYPE_INT64 )
1231                 VALUE_CAST_CHECK(value, int64_t, int64, PRELUDE_PRId64, ntype);
1232 
1233         else if ( otype == IDMEF_VALUE_TYPE_UINT64 )
1234                 VALUE_CAST_CHECK(value, uint64_t, uint64, PRELUDE_PRIu64, ntype);
1235 
1236         else if ( otype == IDMEF_VALUE_TYPE_FLOAT )
1237                 VALUE_CAST_CHECK(value, float, float, "f", ntype);
1238 
1239         else if ( otype == IDMEF_VALUE_TYPE_DOUBLE )
1240                 VALUE_CAST_CHECK(value, double, double, "f", ntype);
1241 
1242         else if ( otype == IDMEF_VALUE_TYPE_STRING )
1243                 return cast_from_string(value, ntype);
1244 
1245         else return prelude_error_verbose(PRELUDE_ERROR_GENERIC,
1246                                           "Unable to cast input type '%s' to '%s'",
1247                                            idmef_value_type_to_string(value->type.id),
1248                                            idmef_value_type_to_string(ntype));
1249 
1250         return 0;
1251 }
1252 
1253 
1254 
_idmef_value_copy_internal(const idmef_value_t * val,idmef_value_type_id_t res_type,idmef_class_id_t res_id,void * res)1255 int _idmef_value_copy_internal(const idmef_value_t *val,
1256                                idmef_value_type_id_t res_type, idmef_class_id_t res_id, void *res)
1257 {
1258         int ret;
1259 
1260         prelude_return_val_if_fail(val, prelude_error(PRELUDE_ERROR_ASSERTION));
1261         prelude_return_val_if_fail(res, prelude_error(PRELUDE_ERROR_ASSERTION));
1262 
1263         if ( res_type == val->type.id )
1264                 ret = idmef_value_type_copy(&val->type, res);
1265         else {
1266                 idmef_value_t copy;
1267 
1268                 memcpy(&copy, val, sizeof(copy));
1269                 idmef_value_dont_have_own_data(&copy);
1270 
1271                 ret = _idmef_value_cast(&copy, res_type, res_id);
1272                 if ( ret < 0 )
1273                         return ret;
1274 
1275                 ret = idmef_value_type_copy(&copy.type, res);
1276                 if ( val->own_data )
1277                         idmef_value_type_destroy(&copy.type);
1278         }
1279 
1280         return ret;
1281 }
1282