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