1 /*
2 * Copyright (C) 2003-2015 FreeIPMI Core Team
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *
17 */
18
19 #ifdef HAVE_CONFIG_H
20 #include <config.h>
21 #endif /* HAVE_CONFIG_H */
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #ifdef STDC_HEADERS
26 #include <string.h>
27 #include <stdarg.h>
28 #endif /* STDC_HEADERS */
29 #include <limits.h>
30 #include <assert.h>
31 #include <errno.h>
32
33 #include "freeipmi/fiid/fiid.h"
34
35 #include "libcommon/ipmi-bit-ops.h"
36
37 #include "freeipmi-portability.h"
38 #include "hash.h"
39 #include "secure.h"
40
41 #define FIID_OBJ_MAGIC 0xf00fd00d
42 #define FIID_ITERATOR_MAGIC 0xd00df00f
43
44 struct fiid_field_data
45 {
46 unsigned int max_field_len;
47 char key[FIID_FIELD_MAX_KEY_LEN + 1];
48 unsigned int set_field_len;
49 unsigned int flags;
50 unsigned int index; /* for lookup */
51 unsigned int start; /* for lookup */
52 unsigned int end; /* for lookup */
53 };
54
55 struct fiid_obj
56 {
57 uint32_t magic;
58 fiid_err_t errnum;
59 uint8_t *data;
60 unsigned int data_len;
61 struct fiid_field_data *field_data;
62 unsigned int field_data_len;
63 hash_t lookup;
64 int makes_packet_sufficient; /* flag for internal use */
65 int secure_memset_on_clear; /* flag for internal use */
66 };
67
68 struct fiid_iterator
69 {
70 uint32_t magic;
71 fiid_err_t errnum;
72 unsigned int current_index;
73 unsigned int last_index;
74 struct fiid_obj *obj;
75 };
76
77 static char * fiid_errmsg[] =
78 {
79 "success",
80 "fiid object null",
81 "fiid object invalid",
82 "fiid iterator null",
83 "fiid iterator invalid",
84 "invalid parameter",
85 "invalid template specified",
86 "field not found",
87 "template key invalid",
88 "template flags invalid",
89 "template not byte aligned",
90 "field not byte aligned",
91 "block not byte aligned",
92 "buffer too small to hold result",
93 "template max field length mismatch",
94 "template key mismatch",
95 "template flags mismatch",
96 "template length mismatch",
97 "data not byte aligned",
98 "required field missing",
99 "fixed length field invalid",
100 "data not available",
101 "not identical",
102 "out of memory",
103 "internal error",
104 "errnum out of range",
105 };
106
107 #ifndef NDEBUG
108 static int
_fiid_template_check_valid_keys(fiid_template_t tmpl)109 _fiid_template_check_valid_keys (fiid_template_t tmpl)
110 {
111 unsigned int i;
112
113 assert (tmpl);
114
115 for (i = 0; tmpl[i].max_field_len; i++)
116 {
117 unsigned int len;
118
119 len = strlen (tmpl[i].key);
120 if (!len || len > FIID_FIELD_MAX_KEY_LEN)
121 return (-1);
122 }
123
124 return (0);
125 }
126 #endif /* NDEBUG */
127
128 static int
_fiid_template_check_valid_flags(fiid_template_t tmpl)129 _fiid_template_check_valid_flags (fiid_template_t tmpl)
130 {
131 unsigned int i;
132
133 assert (tmpl);
134
135 for (i = 0; tmpl[i].max_field_len; i++)
136 {
137 if (!FIID_FIELD_REQUIRED_FLAG_VALID (tmpl[i].flags)
138 || !FIID_FIELD_LENGTH_FLAG_VALID (tmpl[i].flags))
139 return (-1);
140 }
141
142 return (0);
143 }
144
145 static int
_fiid_template_len(fiid_template_t tmpl,unsigned int * tmpl_field_count)146 _fiid_template_len (fiid_template_t tmpl,
147 unsigned int *tmpl_field_count)
148 {
149 unsigned int i, len = 0;
150
151 assert (tmpl);
152 assert (tmpl_field_count);
153
154 for (i = 0; tmpl[i].max_field_len; i++)
155 {
156 if (tmpl[i].max_field_len > INT_MAX)
157 {
158 /* FIID_ERR_OVERFLOW */
159 errno = EINVAL;
160 return (-1);
161 }
162
163 len += tmpl[i].max_field_len;
164
165 /* check for integer overflow */
166 if (len < tmpl[i].max_field_len)
167 {
168 /* FIID_ERR_OVERFLOW */
169 errno = EINVAL;
170 return (-1);
171 }
172 }
173
174 if (len > INT_MAX)
175 {
176 /* FIID_ERR_OVERFLOW */
177 errno = EINVAL;
178 return (-1);
179 }
180
181 if (len % 8)
182 {
183 /* FIID_ERR_TEMPLATE_NOT_BYTE_ALIGNED */
184 errno = EINVAL;
185 return (-1);
186 }
187
188 *tmpl_field_count = (i + 1);
189 return (len);
190 }
191
192 static int
_fiid_template_len_bytes(fiid_template_t tmpl,unsigned int * tmpl_field_count)193 _fiid_template_len_bytes (fiid_template_t tmpl,
194 unsigned int *tmpl_field_count)
195 {
196 int len;
197
198 assert (tmpl);
199 assert (tmpl_field_count);
200
201 if ((len = _fiid_template_len (tmpl,
202 tmpl_field_count)) < 0)
203 return (-1);
204
205 return (BITS_ROUND_BYTES (len));
206 }
207
208 int
fiid_template_field_lookup(fiid_template_t tmpl,const char * field)209 fiid_template_field_lookup (fiid_template_t tmpl,
210 const char *field)
211 {
212 unsigned int i;
213
214 if (!(tmpl && field))
215 {
216 /* FIID_ERR_PARAMETERS */
217 errno = EINVAL;
218 return (-1);
219 }
220
221 #ifndef NDEBUG
222 if (_fiid_template_check_valid_keys (tmpl) < 0)
223 {
224 /* FIID_ERR_PARAMETERS */
225 errno = EINVAL;
226 return (-1);
227 }
228 #endif /* NDEBUG */
229
230 for (i = 0; tmpl[i].max_field_len; i++)
231 {
232 if (!strcmp (tmpl[i].key, field))
233 return (1);
234 }
235
236 return (0);
237 }
238
239 int
FIID_TEMPLATE_FIELD_LOOKUP(fiid_template_t tmpl,const char * field)240 FIID_TEMPLATE_FIELD_LOOKUP (fiid_template_t tmpl,
241 const char *field)
242 {
243 int ret;
244
245 if ((ret = fiid_template_field_lookup (tmpl, field)) < 0)
246 return (ret);
247
248 if (!ret)
249 {
250 errno = EINVAL;
251 return (-1);
252 }
253
254 return (ret);
255 }
256
257 int
fiid_template_len(fiid_template_t tmpl)258 fiid_template_len (fiid_template_t tmpl)
259 {
260 unsigned int temp;
261 int len = 0;
262
263 if (!tmpl)
264 {
265 /* FIID_ERR_PARAMETERS */
266 errno = EINVAL;
267 return (-1);
268 }
269
270 if ((len = _fiid_template_len (tmpl,
271 &temp)) < 0)
272 return (-1);
273
274 return (len);
275 }
276
277 int
fiid_template_len_bytes(fiid_template_t tmpl)278 fiid_template_len_bytes (fiid_template_t tmpl)
279 {
280 int len;
281
282 if (!tmpl)
283 {
284 /* FIID_ERR_PARAMETERS */
285 errno = EINVAL;
286 return (-1);
287 }
288
289 if ((len = fiid_template_len (tmpl)) < 0)
290 return (-1);
291
292 if (len % 8)
293 {
294 /* FIID_ERR_TEMPLATE_NOT_BYTE_ALIGNED */
295 errno = EINVAL;
296 return (-1);
297 }
298
299 return (BITS_ROUND_BYTES (len));
300 }
301
302 static int
_fiid_template_field_start_end(fiid_template_t tmpl,const char * field,unsigned int * start,unsigned int * end)303 _fiid_template_field_start_end (fiid_template_t tmpl,
304 const char *field,
305 unsigned int *start,
306 unsigned int *end)
307 {
308 unsigned int i = 0;
309 unsigned int _start = 0;
310 unsigned int _end = 0;
311
312 assert (tmpl);
313 assert (field);
314 assert (start);
315 assert (end);
316
317 for (i = 0; tmpl[i].max_field_len; i++)
318 {
319 if (strcmp (tmpl[i].key, field) == 0)
320 {
321 if (tmpl[i].max_field_len > INT_MAX)
322 {
323 /* FIID_ERR_OVERFLOW */
324 errno = EINVAL;
325 return (-1);
326 }
327
328 _end = _start + tmpl[i].max_field_len;
329
330 /* check for integer overflow */
331 if (_end < tmpl[i].max_field_len)
332 {
333 /* FIID_ERR_OVERFLOW */
334 errno = EINVAL;
335 return (-1);
336 }
337
338 *start = _start;
339 *end = _end;
340 return (tmpl[i].max_field_len);
341 }
342
343 _start += tmpl[i].max_field_len;
344
345 /* check for integer overflow */
346 if (_start < tmpl[i].max_field_len)
347 {
348 /* FIID_ERR_OVERFLOW */
349 errno = EINVAL;
350 return (-1);
351 }
352 }
353
354 /* FIID_ERR_FIELD_NOT_FOUND */
355 errno = EINVAL;
356 return (-1);
357 }
358
359 static int
_fiid_template_field_start(fiid_template_t tmpl,const char * field)360 _fiid_template_field_start (fiid_template_t tmpl,
361 const char *field)
362 {
363 unsigned int start = 0;
364 unsigned int end = 0;
365
366 assert (tmpl);
367 assert (field);
368
369 if (_fiid_template_field_start_end (tmpl,
370 field,
371 &start,
372 &end) < 0)
373 return (-1);
374
375 if (start > INT_MAX)
376 {
377 /* FIID_ERR_OVERFLOW */
378 errno = EINVAL;
379 return (-1);
380 }
381
382 return (start);
383 }
384
385 int
fiid_template_field_start(fiid_template_t tmpl,const char * field)386 fiid_template_field_start (fiid_template_t tmpl,
387 const char *field)
388 {
389 if (!tmpl || !field)
390 {
391 /* FIID_ERR_PARAMETERS */
392 errno = EINVAL;
393 return (-1);
394 }
395
396 #ifndef NDEBUG
397 if (_fiid_template_check_valid_keys (tmpl) < 0)
398 {
399 /* FIID_ERR_PARAMETERS */
400 errno = EINVAL;
401 return (-1);
402 }
403 #endif /* NDEBUG */
404
405 return (_fiid_template_field_start (tmpl, field));
406 }
407
408 int
fiid_template_field_start_bytes(fiid_template_t tmpl,const char * field)409 fiid_template_field_start_bytes (fiid_template_t tmpl,
410 const char *field)
411 {
412 int start = 0;
413
414 if (!tmpl || !field)
415 {
416 /* FIID_ERR_PARAMETERS */
417 errno = EINVAL;
418 return (-1);
419 }
420
421 #ifndef NDEBUG
422 if (_fiid_template_check_valid_keys (tmpl) < 0)
423 {
424 /* FIID_ERR_PARAMETERS */
425 errno = EINVAL;
426 return (-1);
427 }
428 #endif /* NDEBUG */
429
430 if ((start = _fiid_template_field_start (tmpl,
431 field)) < 0)
432 return (-1);
433
434 if (start % 8)
435 {
436 /* FIID_ERR_FIELD_NOT_BYTE_ALIGNED */
437 errno = EINVAL;
438 return (-1);
439 }
440
441 return (BITS_ROUND_BYTES (start));
442 }
443
444 static int
_fiid_template_field_end(fiid_template_t tmpl,const char * field)445 _fiid_template_field_end (fiid_template_t tmpl,
446 const char *field)
447 {
448 unsigned int start = 0;
449 unsigned int end = 0;
450
451 assert (tmpl);
452 assert (field);
453
454 if (_fiid_template_field_start_end (tmpl,
455 field,
456 &start,
457 &end) < 0)
458 return (-1);
459
460 if (end > INT_MAX)
461 {
462 /* FIID_ERR_OVERFLOW */
463 errno = EINVAL;
464 return (-1);
465 }
466
467 return (end);
468 }
469
470 int
fiid_template_field_end(fiid_template_t tmpl,const char * field)471 fiid_template_field_end (fiid_template_t tmpl,
472 const char *field)
473 {
474 if (!tmpl || !field)
475 {
476 /* FIID_ERR_PARAMETERS */
477 errno = EINVAL;
478 return (-1);
479 }
480
481 #ifndef NDEBUG
482 if (_fiid_template_check_valid_keys (tmpl) < 0)
483 {
484 /* FIID_ERR_PARAMETERS */
485 errno = EINVAL;
486 return (-1);
487 }
488 #endif /* NDEBUG */
489
490 return (_fiid_template_field_end (tmpl, field));
491 }
492
493 int
fiid_template_field_end_bytes(fiid_template_t tmpl,const char * field)494 fiid_template_field_end_bytes (fiid_template_t tmpl,
495 const char *field)
496 {
497 int end = 0;
498
499 if (!tmpl || !field)
500 {
501 /* FIID_ERR_PARAMETERS */
502 errno = EINVAL;
503 return (-1);
504 }
505
506 #ifndef NDEBUG
507 if (_fiid_template_check_valid_keys (tmpl) < 0)
508 {
509 /* FIID_ERR_PARAMETERS */
510 errno = EINVAL;
511 return (-1);
512 }
513 #endif /* NDEBUG */
514
515 if ((end = _fiid_template_field_end (tmpl,
516 field)) < 0)
517 return (-1);
518
519 if (end % 8)
520 {
521 /* FIID_ERR_FIELD_NOT_BYTE_ALIGNED */
522 errno = EINVAL;
523 return (-1);
524 }
525
526 return (BITS_ROUND_BYTES (end));
527 }
528
529 static int
_fiid_template_field_len(fiid_template_t tmpl,const char * field)530 _fiid_template_field_len (fiid_template_t tmpl,
531 const char *field)
532 {
533 unsigned int i;
534
535 assert (tmpl);
536 assert (field);
537
538 for (i = 0; tmpl[i].max_field_len; i++)
539 {
540 if (!strcmp (tmpl[i].key, field))
541 {
542 if (tmpl[i].max_field_len > INT_MAX)
543 {
544 /* FIID_ERR_OVERFLOW */
545 errno = EINVAL;
546 return (-1);
547 }
548
549 return (tmpl[i].max_field_len);
550 }
551 }
552
553 /* FIID_ERR_FIELD_NOT_FOUND */
554 errno = EINVAL;
555 return (-1);
556 }
557
558 int
fiid_template_field_len(fiid_template_t tmpl,const char * field)559 fiid_template_field_len (fiid_template_t tmpl,
560 const char *field)
561 {
562 if (!tmpl || !field)
563 {
564 /* FIID_ERR_PARAMETERS */
565 errno = EINVAL;
566 return (-1);
567 }
568
569 #ifndef NDEBUG
570 if (_fiid_template_check_valid_keys (tmpl) < 0)
571 {
572 /* FIID_ERR_PARAMETERS */
573 errno = EINVAL;
574 return (-1);
575 }
576 #endif /* NDEBUG */
577
578 return (_fiid_template_field_len (tmpl, field));
579 }
580
581 int
fiid_template_field_len_bytes(fiid_template_t tmpl,const char * field)582 fiid_template_field_len_bytes (fiid_template_t tmpl,
583 const char *field)
584 {
585 int len;
586
587 if (!tmpl || !field)
588 {
589 /* FIID_ERR_PARAMETERS */
590 errno = EINVAL;
591 return (-1);
592 }
593
594 #ifndef NDEBUG
595 if (_fiid_template_check_valid_keys (tmpl) < 0)
596 {
597 /* FIID_ERR_PARAMETERS */
598 errno = EINVAL;
599 return (-1);
600 }
601 #endif /* NDEBUG */
602
603 if ((len = _fiid_template_field_len (tmpl,
604 field)) < 0)
605 return (-1);
606
607 if (len % 8)
608 {
609 /* FIID_ERR_FIELD_NOT_BYTE_ALIGNED */
610 errno = EINVAL;
611 return (-1);
612 }
613
614 return (BITS_ROUND_BYTES (len));
615 }
616
617 static int
_fiid_template_block_len(fiid_template_t tmpl,const char * field_start,const char * field_end)618 _fiid_template_block_len (fiid_template_t tmpl,
619 const char *field_start,
620 const char *field_end)
621 {
622 int start;
623 int end;
624
625 assert (tmpl);
626 assert (field_start);
627 assert (field_end);
628
629 if ((end = _fiid_template_field_end (tmpl,
630 field_end)) < 0)
631 return (-1);
632
633 if ((start = _fiid_template_field_start (tmpl,
634 field_start)) < 0)
635 return (-1);
636
637 if (start > end)
638 {
639 /* FIID_ERR_PARAMETERS */
640 errno = EINVAL;
641 return (-1);
642 }
643
644 return (end - start);
645 }
646
647 int
fiid_template_block_len(fiid_template_t tmpl,const char * field_start,const char * field_end)648 fiid_template_block_len (fiid_template_t tmpl,
649 const char *field_start,
650 const char *field_end)
651 {
652 if (!tmpl || !field_start || !field_end)
653 {
654 /* FIID_ERR_PARAMETERS */
655 errno = EINVAL;
656 return (-1);
657 }
658
659 #ifndef NDEBUG
660 if (_fiid_template_check_valid_keys (tmpl) < 0)
661 {
662 /* FIID_ERR_PARAMETERS */
663 errno = EINVAL;
664 return (-1);
665 }
666 #endif /* NDEBUG */
667
668 return (_fiid_template_block_len (tmpl, field_start, field_end));
669 }
670
671 int
fiid_template_block_len_bytes(fiid_template_t tmpl,const char * field_start,const char * field_end)672 fiid_template_block_len_bytes (fiid_template_t tmpl,
673 const char *field_start,
674 const char *field_end)
675 {
676 int len;
677
678 if (!tmpl || !field_start || !field_end)
679 {
680 /* FIID_ERR_PARAMETERS */
681 errno = EINVAL;
682 return (-1);
683 }
684
685 #ifndef NDEBUG
686 if (_fiid_template_check_valid_keys (tmpl) < 0)
687 {
688 /* FIID_ERR_PARAMETERS */
689 errno = EINVAL;
690 return (-1);
691 }
692 #endif /* NDEBUG */
693
694 if ((len = _fiid_template_block_len (tmpl,
695 field_start,
696 field_end)) < 0)
697 return (-1);
698
699 if (len % 8)
700 {
701 /* FIID_ERR_BLOCK_NOT_BYTE_ALIGNED */
702 errno = EINVAL;
703 return (-1);
704 }
705
706 return (BITS_ROUND_BYTES (len));
707 }
708
709 int
fiid_template_compare(fiid_template_t tmpl1,fiid_template_t tmpl2)710 fiid_template_compare (fiid_template_t tmpl1,
711 fiid_template_t tmpl2)
712 {
713 unsigned int i;
714
715 if (!tmpl1 || !tmpl2)
716 {
717 /* FIID_ERR_PARAMETERS */
718 errno = EINVAL;
719 return (-1);
720 }
721
722 #ifndef NDEBUG
723 if (_fiid_template_check_valid_keys (tmpl1) < 0)
724 {
725 /* FIID_ERR_PARAMETERS */
726 errno = EINVAL;
727 return (-1);
728 }
729 #endif /* NDEBUG */
730
731 #ifndef NDEBUG
732 if (_fiid_template_check_valid_keys (tmpl2) < 0)
733 {
734 /* FIID_ERR_PARAMETERS */
735 errno = EINVAL;
736 return (-1);
737 }
738 #endif /* NDEBUG */
739
740 for (i = 0; tmpl1[i].max_field_len; i++)
741 {
742 if (tmpl1[i].max_field_len != tmpl2[i].max_field_len)
743 return (0);
744
745 if (strcmp (tmpl1[i].key, tmpl2[i].key))
746 return (0);
747
748 if (tmpl1[i].flags != tmpl2[i].flags)
749 return (0);
750 }
751
752 if (tmpl2[i].max_field_len)
753 return (0);
754
755 return (1);
756 }
757
758 int
FIID_TEMPLATE_COMPARE(fiid_template_t tmpl1,fiid_template_t tmpl2)759 FIID_TEMPLATE_COMPARE (fiid_template_t tmpl1,
760 fiid_template_t tmpl2)
761 {
762 int ret;
763
764 if ((ret = fiid_template_compare (tmpl1, tmpl2)) < 0)
765 return (ret);
766
767 if (!ret)
768 {
769 errno = EINVAL;
770 return (-1);
771 }
772
773 return (ret);
774 }
775
776 void
fiid_template_free(fiid_field_t * tmpl_dynamic)777 fiid_template_free (fiid_field_t *tmpl_dynamic)
778 {
779 free (tmpl_dynamic);
780 }
781
782 static int
_fiid_obj_field_start_end(fiid_obj_t obj,const char * field,unsigned int * start,unsigned int * end)783 _fiid_obj_field_start_end (fiid_obj_t obj,
784 const char *field,
785 unsigned int *start,
786 unsigned int *end)
787 {
788 struct fiid_field_data *ffdptr;
789 unsigned int i;
790
791 assert (obj);
792 assert (obj->magic == FIID_OBJ_MAGIC);
793 assert (field);
794 assert (start);
795 assert (end);
796
797 if ((ffdptr = hash_find (obj->lookup, field)))
798 {
799 *start = ffdptr->start;
800 *end = ffdptr->end;
801 return (ffdptr->max_field_len);
802 }
803
804 /* integer overflow conditions checked during object creation */
805 for (i = 0; obj->field_data[i].max_field_len; i++)
806 {
807 if (!strcmp (obj->field_data[i].key, field))
808 {
809 if (!hash_insert (obj->lookup,
810 obj->field_data[i].key,
811 &(obj->field_data[i])))
812 {
813 obj->errnum = FIID_ERR_INTERNAL_ERROR;
814 return (-1);
815 }
816
817 *start = obj->field_data[i].start;
818 *end = obj->field_data[i].end;
819 return (obj->field_data[i].max_field_len);
820 }
821 }
822
823 obj->errnum = FIID_ERR_FIELD_NOT_FOUND;
824 return (-1);
825 }
826
827 static int
_fiid_obj_field_start(fiid_obj_t obj,const char * field)828 _fiid_obj_field_start (fiid_obj_t obj, const char *field)
829 {
830 unsigned int start = 0;
831 unsigned int end = 0; /* excluded always */
832
833 assert (obj);
834 assert (obj->magic == FIID_OBJ_MAGIC);
835 assert (field);
836
837 if (_fiid_obj_field_start_end (obj, field, &start, &end) < 0)
838 return (-1);
839
840 return (start);
841 }
842
843 static int
_fiid_obj_field_end(fiid_obj_t obj,const char * field)844 _fiid_obj_field_end (fiid_obj_t obj, const char *field)
845 {
846 unsigned int start = 0;
847 unsigned int end = 0; /* excluded always */
848
849 assert (obj);
850 assert (obj->magic == FIID_OBJ_MAGIC);
851 assert (field);
852
853 if (_fiid_obj_field_start_end (obj, field, &start, &end) < 0)
854 return (-1);
855
856 return (end);
857 }
858
859 static int
_fiid_obj_field_len(fiid_obj_t obj,const char * field)860 _fiid_obj_field_len (fiid_obj_t obj, const char *field)
861 {
862 struct fiid_field_data *ffdptr;
863 unsigned int i;
864
865 assert (obj);
866 assert (obj->magic == FIID_OBJ_MAGIC);
867 assert (field);
868
869 if ((ffdptr = hash_find (obj->lookup, field)))
870 return (ffdptr->max_field_len);
871
872 for (i = 0; obj->field_data[i].max_field_len; i++)
873 {
874 if (!strcmp (obj->field_data[i].key, field))
875 {
876 if (!hash_insert (obj->lookup,
877 obj->field_data[i].key,
878 &(obj->field_data[i])))
879 {
880 obj->errnum = FIID_ERR_INTERNAL_ERROR;
881 return (-1);
882 }
883
884 return (obj->field_data[i].max_field_len);
885 }
886 }
887
888 obj->errnum = FIID_ERR_FIELD_NOT_FOUND;
889 return (-1);
890 }
891
892 char *
fiid_strerror(fiid_err_t errnum)893 fiid_strerror (fiid_err_t errnum)
894 {
895 if (errnum >= FIID_ERR_SUCCESS && errnum <= FIID_ERR_ERRNUMRANGE)
896 return (fiid_errmsg[errnum]);
897 else
898 return (fiid_errmsg[FIID_ERR_ERRNUMRANGE]);
899 }
900
901 fiid_obj_t
fiid_obj_create(fiid_template_t tmpl)902 fiid_obj_create (fiid_template_t tmpl)
903 {
904 fiid_obj_t obj = NULL;
905 unsigned int max_pkt_len = 0;
906 unsigned int i;
907 unsigned int start = 0;
908 int data_len;
909
910 if (!tmpl)
911 {
912 /* FIID_ERR_PARAMETERS */
913 errno = EINVAL;
914 goto cleanup;
915 }
916
917 #ifndef NDEBUG
918 if (_fiid_template_check_valid_keys (tmpl) < 0)
919 {
920 /* FIID_ERR_TEMPLATE_INVALID */
921 errno = EINVAL;
922 goto cleanup;
923 }
924 #endif /* NDEBUG */
925
926 if (_fiid_template_check_valid_flags (tmpl) < 0)
927 {
928 /* FIID_ERR_TEMPLATE_INVALID */
929 errno = EINVAL;
930 goto cleanup;
931 }
932
933 if (!(obj = (fiid_obj_t)malloc (sizeof (struct fiid_obj))))
934 {
935 /* FIID_ERR_OUT_OF_MEMORY */
936 errno = ENOMEM;
937 goto cleanup;
938 }
939 memset (obj, '\0', sizeof (struct fiid_obj));
940 obj->magic = FIID_OBJ_MAGIC;
941
942 /* after call to _fiid_template_len_bytes, we know each field length
943 * and total field length won't overflow an int.
944 */
945 if ((data_len = _fiid_template_len_bytes (tmpl,
946 &obj->field_data_len)) < 0)
947 goto cleanup;
948 obj->data_len = data_len;
949
950 if (!obj->field_data_len)
951 {
952 /* FIID_ERR_TEMPLATE_INVALID */
953 errno = EINVAL;
954 goto cleanup;
955 }
956
957 if (!(obj->data = malloc (obj->data_len)))
958 {
959 /* FIID_ERR_OUT_OF_MEMORY */
960 errno = ENOMEM;
961 goto cleanup;
962 }
963 memset (obj->data, '\0', obj->data_len);
964
965 if (!(obj->field_data = malloc (obj->field_data_len * sizeof (struct fiid_field_data))))
966 {
967 /* FIID_ERR_OUT_OF_MEMORY */
968 errno = ENOMEM;
969 goto cleanup;
970 }
971 memset (obj->field_data, '\0', obj->field_data_len * sizeof (struct fiid_field_data));
972
973 if (!(obj->lookup = hash_create (obj->field_data_len,
974 (hash_key_f)hash_key_string,
975 (hash_cmp_f)strcmp,
976 NULL)))
977 {
978 errno = ENOMEM;
979 goto cleanup;
980 }
981
982 for (i = 0; i < obj->field_data_len; i++)
983 {
984 #ifndef NDEBUG
985 if (tmpl[i].max_field_len)
986 {
987 unsigned int j;
988
989 for (j = 0; j < i; j++)
990 {
991 if (!strncmp (obj->field_data[j].key, tmpl[i].key, FIID_FIELD_MAX_KEY_LEN))
992 {
993 /* FIID_ERR_TEMPLATE_INVALID */
994 errno = EINVAL;
995 goto cleanup;
996 }
997 }
998 }
999 #endif /* !NDEBUG */
1000 obj->field_data[i].max_field_len = tmpl[i].max_field_len;
1001 memset (obj->field_data[i].key, '\0', FIID_FIELD_MAX_KEY_LEN + 1);
1002 strncpy (obj->field_data[i].key, tmpl[i].key, FIID_FIELD_MAX_KEY_LEN);
1003 obj->field_data[i].set_field_len = 0;
1004 obj->field_data[i].flags = tmpl[i].flags;
1005 obj->field_data[i].index = i;
1006 obj->field_data[i].start = start;
1007 obj->field_data[i].end = start + obj->field_data[i].max_field_len;
1008 max_pkt_len += tmpl[i].max_field_len;
1009
1010 if (obj->field_data[i].flags & FIID_FIELD_MAKES_PACKET_SUFFICIENT)
1011 obj->makes_packet_sufficient = 1;
1012
1013 if (obj->field_data[i].flags & FIID_FIELD_SECURE_MEMSET_ON_CLEAR)
1014 obj->secure_memset_on_clear = 1;
1015
1016 start += obj->field_data[i].max_field_len;
1017 }
1018
1019 if (max_pkt_len % 8)
1020 {
1021 /* FIID_ERR_TEMPLATE_NOT_BYTE_ALIGNED */
1022 errno = EINVAL;
1023 goto cleanup;
1024 }
1025
1026 obj->errnum = FIID_ERR_SUCCESS;
1027 return (obj);
1028
1029 cleanup:
1030 if (obj)
1031 {
1032 free (obj->data);
1033 free (obj->field_data);
1034 hash_destroy (obj->lookup);
1035 free (obj);
1036 }
1037
1038 return (NULL);
1039 }
1040
1041 void
fiid_obj_destroy(fiid_obj_t obj)1042 fiid_obj_destroy (fiid_obj_t obj)
1043 {
1044 if (!(obj && obj->magic == FIID_OBJ_MAGIC))
1045 return;
1046
1047 obj->magic = ~FIID_OBJ_MAGIC;
1048 obj->errnum = FIID_ERR_SUCCESS;
1049 free (obj->data);
1050 free (obj->field_data);
1051 hash_destroy (obj->lookup);
1052 free (obj);
1053 }
1054
1055 fiid_obj_t
fiid_obj_dup(fiid_obj_t src_obj)1056 fiid_obj_dup (fiid_obj_t src_obj)
1057 {
1058 fiid_obj_t dest_obj = NULL;
1059
1060 if (!src_obj || src_obj->magic != FIID_OBJ_MAGIC)
1061 goto cleanup;
1062
1063 if (!(dest_obj = malloc (sizeof (struct fiid_obj))))
1064 {
1065 src_obj->errnum = FIID_ERR_OUT_OF_MEMORY;
1066 goto cleanup;
1067 }
1068 memset (dest_obj, '\0', sizeof (struct fiid_obj));
1069 dest_obj->magic = src_obj->magic;
1070 dest_obj->data_len = src_obj->data_len;
1071 dest_obj->field_data_len = src_obj->field_data_len;
1072
1073 if (!(dest_obj->data = malloc (src_obj->data_len)))
1074 {
1075 src_obj->errnum = FIID_ERR_OUT_OF_MEMORY;
1076 goto cleanup;
1077 }
1078 memcpy (dest_obj->data, src_obj->data, src_obj->data_len);
1079
1080 if (!(dest_obj->field_data = malloc (dest_obj->field_data_len * sizeof (struct fiid_field_data))))
1081 {
1082 src_obj->errnum = FIID_ERR_OUT_OF_MEMORY;
1083 goto cleanup;
1084 }
1085
1086 memcpy (dest_obj->field_data,
1087 src_obj->field_data,
1088 src_obj->field_data_len * sizeof (struct fiid_field_data));
1089
1090 if (!(dest_obj->lookup = hash_create (dest_obj->field_data_len,
1091 (hash_key_f)hash_key_string,
1092 (hash_cmp_f)strcmp,
1093 NULL)))
1094 {
1095 src_obj->errnum = FIID_ERR_OUT_OF_MEMORY;
1096 goto cleanup;
1097 }
1098
1099 src_obj->errnum = FIID_ERR_SUCCESS;
1100 dest_obj->errnum = FIID_ERR_SUCCESS;
1101 return (dest_obj);
1102
1103 cleanup:
1104 if (dest_obj)
1105 {
1106 free (dest_obj->data);
1107 free (dest_obj->field_data);
1108 hash_destroy (dest_obj->lookup);
1109 free (dest_obj);
1110 }
1111 return (NULL);
1112 }
1113
1114 fiid_obj_t
fiid_obj_copy(fiid_obj_t src_obj,fiid_template_t alt_tmpl)1115 fiid_obj_copy (fiid_obj_t src_obj, fiid_template_t alt_tmpl)
1116 {
1117 fiid_obj_t dest_obj = NULL;
1118 int data_len;
1119 unsigned int field_data_len = 0;
1120 uint8_t *databuf = NULL;
1121
1122 if (!src_obj || src_obj->magic != FIID_OBJ_MAGIC)
1123 goto cleanup;
1124
1125 if ((data_len = _fiid_template_len_bytes (alt_tmpl, &field_data_len)) < 0)
1126 goto cleanup;
1127
1128 if (src_obj->data_len != data_len)
1129 {
1130 src_obj->errnum = FIID_ERR_PARAMETERS;
1131 goto cleanup;
1132 }
1133
1134 if (!(dest_obj = fiid_obj_create (alt_tmpl)))
1135 goto cleanup;
1136
1137 if (!(databuf = (uint8_t *)malloc (src_obj->data_len)))
1138 {
1139 src_obj->errnum = FIID_ERR_OUT_OF_MEMORY;
1140 goto cleanup;
1141 }
1142
1143 if ((data_len = fiid_obj_get_all (src_obj, databuf, src_obj->data_len)) < 0)
1144 goto cleanup;
1145
1146 if (fiid_obj_set_all (dest_obj, databuf, data_len) < 0)
1147 {
1148 src_obj->errnum = dest_obj->errnum;
1149 goto cleanup;
1150 }
1151
1152 free (databuf);
1153 return (dest_obj);
1154
1155 cleanup:
1156 if (dest_obj)
1157 fiid_obj_destroy (dest_obj);
1158 free (databuf);
1159 return (NULL);
1160 }
1161
1162 int
fiid_obj_valid(fiid_obj_t obj)1163 fiid_obj_valid (fiid_obj_t obj)
1164 {
1165 if (!obj || obj->magic != FIID_OBJ_MAGIC)
1166 return (0);
1167 return (1);
1168 }
1169
1170 static int
_fiid_obj_packet_valid(fiid_obj_t obj,int makes_packet_sufficient_checks)1171 _fiid_obj_packet_valid (fiid_obj_t obj, int makes_packet_sufficient_checks)
1172 {
1173 unsigned int total_set_bits_counter = 0, max_bits_counter = 0,
1174 set_bits_counter = 0, optional_bits_counter = 0;
1175 unsigned int i;
1176
1177 assert (obj);
1178 assert (obj->magic == FIID_OBJ_MAGIC);
1179 assert (!makes_packet_sufficient_checks || obj->makes_packet_sufficient);
1180
1181 for (i = 0; i < obj->field_data_len; i++)
1182 {
1183 unsigned int required_flag = FIID_FIELD_REQUIRED_FLAG (obj->field_data[i].flags);
1184 unsigned int length_flag = FIID_FIELD_LENGTH_FLAG (obj->field_data[i].flags);
1185 unsigned int max_field_len = obj->field_data[i].max_field_len;
1186 unsigned int set_field_len = obj->field_data[i].set_field_len;
1187 unsigned int makes_packet_sufficient_flag = obj->field_data[i].flags & FIID_FIELD_MAKES_PACKET_SUFFICIENT;
1188
1189 if (makes_packet_sufficient_checks)
1190 {
1191 /* Each field w/ MAKES_PACKET_SUFFICIENT must have the field set. */
1192 if (makes_packet_sufficient_flag)
1193 {
1194 if (!set_field_len)
1195 return (0);
1196
1197 if (length_flag == FIID_FIELD_LENGTH_FIXED && max_field_len != set_field_len)
1198 return (0);
1199 }
1200 }
1201 else
1202 {
1203 if (required_flag == FIID_FIELD_REQUIRED && !set_field_len)
1204 {
1205 obj->errnum = FIID_ERR_REQUIRED_FIELD_MISSING;
1206 return (0);
1207 }
1208
1209 if ((length_flag == FIID_FIELD_LENGTH_FIXED && max_field_len != set_field_len)
1210 && (required_flag == FIID_FIELD_REQUIRED
1211 || (required_flag == FIID_FIELD_OPTIONAL && set_field_len)))
1212
1213 {
1214 obj->errnum = FIID_ERR_FIXED_LENGTH_FIELD_INVALID;
1215 return (0);
1216 }
1217 }
1218
1219 max_bits_counter += max_field_len;
1220 total_set_bits_counter += set_field_len;
1221
1222 if (set_field_len)
1223 {
1224 if (optional_bits_counter)
1225 {
1226 obj->errnum = FIID_ERR_DATA_NOT_BYTE_ALIGNED;
1227 return (0);
1228 }
1229
1230 if (set_field_len != max_field_len)
1231 {
1232 /* If there is an optional or variable length
1233 * field, it cannot have only partial data.
1234 */
1235 if ((set_bits_counter + set_field_len) % 8)
1236 {
1237 obj->errnum = FIID_ERR_DATA_NOT_BYTE_ALIGNED;
1238 return (0);
1239 }
1240 }
1241
1242 set_bits_counter += set_field_len;
1243 if (!(set_bits_counter % 8))
1244 {
1245 set_bits_counter = 0;
1246 max_bits_counter = 0;
1247 }
1248 }
1249 else
1250 {
1251 /* All information must be collected in byte sized
1252 * chunks
1253 */
1254 if (set_bits_counter)
1255 {
1256 obj->errnum = FIID_ERR_DATA_NOT_BYTE_ALIGNED;
1257 return (0);
1258 }
1259
1260 /* Likewise, optional data should be aligned across
1261 * bytes
1262 */
1263 optional_bits_counter += max_field_len;
1264 if (optional_bits_counter && !(optional_bits_counter % 8))
1265 {
1266 /* an "assert" */
1267 if (optional_bits_counter != max_bits_counter)
1268 {
1269 obj->errnum = FIID_ERR_DATA_NOT_BYTE_ALIGNED;
1270 return (0);
1271 }
1272
1273 optional_bits_counter = 0;
1274 max_bits_counter = 0;
1275 }
1276 }
1277 }
1278
1279 /* There shouldn't be anything left over */
1280 if (set_bits_counter)
1281 {
1282 obj->errnum = FIID_ERR_DATA_NOT_BYTE_ALIGNED;
1283 return (0);
1284 }
1285
1286 /* And the bits set should align across a byte */
1287 if (total_set_bits_counter % 8)
1288 {
1289 obj->errnum = FIID_ERR_DATA_NOT_BYTE_ALIGNED;
1290 return (0);
1291 }
1292
1293 obj->errnum = FIID_ERR_SUCCESS;
1294 return (1);
1295 }
1296
1297 int
fiid_obj_packet_valid(fiid_obj_t obj)1298 fiid_obj_packet_valid (fiid_obj_t obj)
1299 {
1300 if (!obj || obj->magic != FIID_OBJ_MAGIC)
1301 return (-1);
1302
1303 return _fiid_obj_packet_valid (obj, 0);
1304 }
1305
1306 int
FIID_OBJ_PACKET_VALID(fiid_obj_t obj)1307 FIID_OBJ_PACKET_VALID (fiid_obj_t obj)
1308 {
1309 int ret;
1310
1311 if ((ret = fiid_obj_packet_valid (obj)) < 0)
1312 return (ret);
1313
1314 /* errnum set in fiid_obj_packet_valid() */
1315 if (!ret)
1316 return (-1);
1317
1318 return (ret);
1319 }
1320
1321 int
fiid_obj_packet_sufficient(fiid_obj_t obj)1322 fiid_obj_packet_sufficient (fiid_obj_t obj)
1323 {
1324 int ret;
1325
1326 if (!obj || obj->magic != FIID_OBJ_MAGIC)
1327 return (-1);
1328
1329 if (!obj->makes_packet_sufficient)
1330 return _fiid_obj_packet_valid (obj, 0);
1331
1332 if (!(ret = _fiid_obj_packet_valid (obj, 0)))
1333 {
1334 fiid_err_t save_errnum = obj->errnum;
1335
1336 if (_fiid_obj_packet_valid (obj, 1) == 1)
1337 return (1);
1338
1339 obj->errnum = save_errnum;
1340 }
1341 return (ret);
1342 }
1343
1344 int
FIID_OBJ_PACKET_SUFFICIENT(fiid_obj_t obj)1345 FIID_OBJ_PACKET_SUFFICIENT (fiid_obj_t obj)
1346 {
1347 int ret;
1348
1349 if ((ret = fiid_obj_packet_sufficient (obj)) < 0)
1350 return (ret);
1351
1352 /* errnum set in fiid_obj_packet_sufficient() */
1353 if (!ret)
1354 return (-1);
1355
1356 return (ret);
1357 }
1358
1359 fiid_field_t *
fiid_obj_template(fiid_obj_t obj)1360 fiid_obj_template (fiid_obj_t obj)
1361 {
1362 fiid_field_t *tmpl;
1363 unsigned int i;
1364
1365 if (!obj || obj->magic != FIID_OBJ_MAGIC)
1366 return (NULL);
1367
1368 if (!(tmpl = (fiid_field_t *)malloc (sizeof (fiid_field_t) * obj->field_data_len)))
1369 {
1370 obj->errnum = FIID_ERR_OUT_OF_MEMORY;
1371 return (NULL);
1372 }
1373 memset (tmpl, '\0', sizeof (fiid_field_t) * obj->field_data_len);
1374
1375 for (i = 0; i < obj->field_data_len; i++)
1376 {
1377 tmpl[i].max_field_len = obj->field_data[i].max_field_len;
1378 /* not FIID_FIELD_MAX_KEY_LEN + 1, template does not have + 1 */
1379 memcpy (tmpl[i].key, obj->field_data[i].key, FIID_FIELD_MAX_KEY_LEN);
1380 tmpl[i].flags = obj->field_data[i].flags;
1381 }
1382
1383 obj->errnum = FIID_ERR_SUCCESS;
1384 return (tmpl);
1385 }
1386
1387 int
fiid_obj_template_compare(fiid_obj_t obj,fiid_template_t tmpl)1388 fiid_obj_template_compare (fiid_obj_t obj, fiid_template_t tmpl)
1389 {
1390 unsigned int i;
1391
1392 if (!obj || obj->magic != FIID_OBJ_MAGIC)
1393 return (-1);
1394
1395 if (!tmpl)
1396 {
1397 obj->errnum = FIID_ERR_PARAMETERS;
1398 return (-1);
1399 }
1400
1401 #ifndef NDEBUG
1402 if (_fiid_template_check_valid_keys (tmpl) < 0)
1403 {
1404 obj->errnum = FIID_ERR_TEMPLATE_INVALID;
1405 return (-1);
1406 }
1407 #endif /* NDEBUG */
1408
1409 for (i = 0; obj->field_data[i].max_field_len; i++)
1410 {
1411 if (obj->field_data[i].max_field_len != tmpl[i].max_field_len)
1412 {
1413 obj->errnum = FIID_ERR_MAX_FIELD_LEN_MISMATCH;
1414 return (0);
1415 }
1416
1417 if (strcmp (obj->field_data[i].key, tmpl[i].key))
1418 {
1419 obj->errnum = FIID_ERR_KEY_FIELD_MISMATCH;
1420 return (0);
1421 }
1422
1423 if (obj->field_data[i].flags != tmpl[i].flags)
1424 {
1425 obj->errnum = FIID_ERR_FLAGS_FIELD_MISMATCH;
1426 return (0);
1427 }
1428 }
1429
1430 if (tmpl[i].max_field_len)
1431 {
1432 obj->errnum = FIID_ERR_TEMPLATE_LENGTH_MISMATCH;
1433 return (0);
1434 }
1435
1436 obj->errnum = FIID_ERR_SUCCESS;
1437 return (1);
1438 }
1439
1440 int
FIID_OBJ_TEMPLATE_COMPARE(fiid_obj_t obj,fiid_template_t tmpl)1441 FIID_OBJ_TEMPLATE_COMPARE (fiid_obj_t obj, fiid_template_t tmpl)
1442 {
1443 int ret;
1444
1445 if ((ret = fiid_obj_template_compare (obj, tmpl)) < 0)
1446 return (ret);
1447
1448 if (!ret)
1449 {
1450 obj->errnum = FIID_ERR_NOT_IDENTICAL;
1451 return (-1);
1452 }
1453
1454 return (ret);
1455 }
1456
1457 fiid_err_t
fiid_obj_errnum(fiid_obj_t obj)1458 fiid_obj_errnum (fiid_obj_t obj)
1459 {
1460 if (!obj)
1461 return (FIID_ERR_OBJ_NULL);
1462 else if (obj->magic != FIID_OBJ_MAGIC)
1463 return (FIID_ERR_OBJ_INVALID);
1464 else
1465 return (obj->errnum);
1466 }
1467
1468 char *
fiid_obj_errormsg(fiid_obj_t obj)1469 fiid_obj_errormsg (fiid_obj_t obj)
1470 {
1471 return (fiid_strerror (fiid_obj_errnum (obj)));
1472 }
1473
1474 static int
_fiid_obj_lookup_field_index(fiid_obj_t obj,const char * field,unsigned int * index)1475 _fiid_obj_lookup_field_index (fiid_obj_t obj, const char *field, unsigned int *index)
1476 {
1477 struct fiid_field_data *ffdptr;
1478 unsigned int i;
1479
1480 assert (obj);
1481 assert (obj->magic == FIID_OBJ_MAGIC);
1482 assert (field);
1483 assert (index);
1484
1485 if ((ffdptr = hash_find (obj->lookup, field)))
1486 {
1487 (*index) = ffdptr->index;
1488 return (0);
1489 }
1490
1491 for (i = 0; obj->field_data[i].max_field_len; i++)
1492 {
1493 if (!strcmp (obj->field_data[i].key, field))
1494 {
1495 if (!hash_insert (obj->lookup,
1496 obj->field_data[i].key,
1497 &(obj->field_data[i])))
1498 {
1499 obj->errnum = FIID_ERR_INTERNAL_ERROR;
1500 return (-1);
1501 }
1502
1503 (*index) = obj->field_data[i].index;
1504 return (0);
1505 }
1506 }
1507
1508 obj->errnum = FIID_ERR_FIELD_NOT_FOUND;
1509 return (-1);
1510 }
1511
1512 int
fiid_obj_len(fiid_obj_t obj)1513 fiid_obj_len (fiid_obj_t obj)
1514 {
1515 unsigned int counter = 0;
1516 unsigned int i;
1517
1518 if (!obj || obj->magic != FIID_OBJ_MAGIC)
1519 return (-1);
1520
1521 /* integer overflow conditions checked during object creation */
1522 for (i = 0; obj->field_data[i].max_field_len; i++)
1523 counter += obj->field_data[i].set_field_len;
1524
1525 obj->errnum = FIID_ERR_SUCCESS;
1526 return (counter);
1527 }
1528
1529 int
fiid_obj_len_bytes(fiid_obj_t obj)1530 fiid_obj_len_bytes (fiid_obj_t obj)
1531 {
1532 int len;
1533
1534 if (!obj || obj->magic != FIID_OBJ_MAGIC)
1535 return (-1);
1536
1537 if ((len = fiid_obj_len (obj)) < 0)
1538 return (-1);
1539
1540 if (len % 8)
1541 {
1542 obj->errnum = FIID_ERR_DATA_NOT_BYTE_ALIGNED;
1543 return (-1);
1544 }
1545
1546 obj->errnum = FIID_ERR_SUCCESS;
1547 return (BITS_ROUND_BYTES (len));
1548 }
1549
1550 int
fiid_obj_field_len(fiid_obj_t obj,const char * field)1551 fiid_obj_field_len (fiid_obj_t obj, const char *field)
1552 {
1553 unsigned int key_index;
1554
1555 if (!obj || obj->magic != FIID_OBJ_MAGIC)
1556 return (-1);
1557
1558 if (!field)
1559 {
1560 obj->errnum = FIID_ERR_PARAMETERS;
1561 return (-1);
1562 }
1563
1564 if (_fiid_obj_lookup_field_index (obj, field, &key_index) < 0)
1565 return (-1);
1566
1567 obj->errnum = FIID_ERR_SUCCESS;
1568 return (obj->field_data[key_index].set_field_len);
1569 }
1570
1571 int
fiid_obj_field_len_bytes(fiid_obj_t obj,const char * field)1572 fiid_obj_field_len_bytes (fiid_obj_t obj, const char *field)
1573 {
1574 int len;
1575
1576 if (!obj || obj->magic != FIID_OBJ_MAGIC)
1577 return (-1);
1578
1579 if (!field)
1580 {
1581 obj->errnum = FIID_ERR_PARAMETERS;
1582 return (-1);
1583 }
1584
1585 if ((len = fiid_obj_field_len (obj, field)) < 0)
1586 return (-1);
1587
1588 if (len % 8)
1589 {
1590 obj->errnum = FIID_ERR_DATA_NOT_BYTE_ALIGNED;
1591 return (-1);
1592 }
1593
1594 obj->errnum = FIID_ERR_SUCCESS;
1595 return (BITS_ROUND_BYTES (len));
1596 }
1597
1598 int
fiid_obj_block_len(fiid_obj_t obj,const char * field_start,const char * field_end)1599 fiid_obj_block_len (fiid_obj_t obj, const char *field_start, const char *field_end)
1600 {
1601 unsigned int key_index_start, key_index_end;
1602 unsigned int counter = 0;
1603 unsigned int i;
1604
1605 if (!obj || obj->magic != FIID_OBJ_MAGIC)
1606 return (-1);
1607
1608 if (!field_start || !field_end)
1609 {
1610 obj->errnum = FIID_ERR_PARAMETERS;
1611 return (-1);
1612 }
1613
1614 if (_fiid_obj_lookup_field_index (obj, field_start, &key_index_start) < 0)
1615 return (-1);
1616
1617 if (_fiid_obj_lookup_field_index (obj, field_end, &key_index_end) < 0)
1618 return (-1);
1619
1620 if (key_index_start > key_index_end)
1621 {
1622 obj->errnum = FIID_ERR_PARAMETERS;
1623 return (-1);
1624 }
1625
1626 /* integer overflow conditions checked during object creation */
1627 for (i = key_index_start; i <= key_index_end; i++)
1628 counter += obj->field_data[i].set_field_len;
1629
1630 obj->errnum = FIID_ERR_SUCCESS;
1631 return (counter);
1632 }
1633
1634 int
fiid_obj_block_len_bytes(fiid_obj_t obj,const char * field_start,const char * field_end)1635 fiid_obj_block_len_bytes (fiid_obj_t obj, const char *field_start, const char *field_end)
1636 {
1637 int len;
1638
1639 if (!obj || obj->magic != FIID_OBJ_MAGIC)
1640 return (-1);
1641
1642 if (!field_start || !field_end)
1643 {
1644 obj->errnum = FIID_ERR_PARAMETERS;
1645 return (-1);
1646 }
1647
1648 if ((len = fiid_obj_block_len (obj, field_start, field_end)) < 0)
1649 return (-1);
1650
1651 if (len % 8)
1652 {
1653 obj->errnum = FIID_ERR_DATA_NOT_BYTE_ALIGNED;
1654 return (-1);
1655 }
1656
1657 obj->errnum = FIID_ERR_SUCCESS;
1658 return (BITS_ROUND_BYTES (len));
1659 }
1660
1661 int
fiid_obj_clear(fiid_obj_t obj)1662 fiid_obj_clear (fiid_obj_t obj)
1663 {
1664 unsigned int i;
1665
1666 if (!obj || obj->magic != FIID_OBJ_MAGIC)
1667 return (-1);
1668
1669 if (obj->secure_memset_on_clear)
1670 secure_memset (obj->data, '\0', obj->data_len);
1671 else
1672 memset (obj->data, '\0', obj->data_len);
1673
1674 for (i =0; i < obj->field_data_len; i++)
1675 obj->field_data[i].set_field_len = 0;
1676
1677 obj->errnum = FIID_ERR_SUCCESS;
1678 return (0);
1679 }
1680
1681 int
fiid_obj_clear_field(fiid_obj_t obj,const char * field)1682 fiid_obj_clear_field (fiid_obj_t obj, const char *field)
1683 {
1684 unsigned int key_index;
1685 int bits_len;
1686
1687 if (!obj || obj->magic != FIID_OBJ_MAGIC)
1688 return (-1);
1689
1690 if (!field)
1691 {
1692 obj->errnum = FIID_ERR_PARAMETERS;
1693 return (-1);
1694 }
1695
1696 if (_fiid_obj_lookup_field_index (obj, field, &key_index) < 0)
1697 return (-1);
1698
1699 if (!obj->field_data[key_index].set_field_len)
1700 return (0);
1701
1702 if ((bits_len = _fiid_obj_field_len (obj, field)) < 0)
1703 return (-1);
1704
1705 if (bits_len <= 64)
1706 {
1707 uint64_t val = 0;
1708
1709 if (fiid_obj_set (obj, field, val) < 0)
1710 return (-1);
1711 }
1712 else
1713 {
1714 int field_start;
1715 unsigned int field_offset, bytes_len;
1716
1717 /* achu: We assume the field must start on a byte boundary and end
1718 * on a byte boundary.
1719 */
1720
1721 if (bits_len % 8)
1722 {
1723 obj->errnum = FIID_ERR_DATA_NOT_BYTE_ALIGNED;
1724 return (-1);
1725 }
1726
1727 bytes_len = BITS_ROUND_BYTES (bits_len);
1728
1729 if ((field_start = _fiid_obj_field_start (obj, field)) < 0)
1730 return (-1);
1731
1732 if (field_start % 8)
1733 {
1734 obj->errnum = FIID_ERR_DATA_NOT_BYTE_ALIGNED;
1735 return (-1);
1736 }
1737
1738 field_offset = BITS_ROUND_BYTES (field_start);
1739 if (obj->field_data[key_index].flags & FIID_FIELD_SECURE_MEMSET_ON_CLEAR)
1740 secure_memset (obj->data + field_offset, '\0', bytes_len);
1741 else
1742 memset (obj->data + field_offset, '\0', bytes_len);
1743 }
1744
1745 obj->field_data[key_index].set_field_len = 0;
1746 obj->errnum = FIID_ERR_SUCCESS;
1747 return (0);
1748 }
1749
1750 int
fiid_obj_field_lookup(fiid_obj_t obj,const char * field)1751 fiid_obj_field_lookup (fiid_obj_t obj, const char *field)
1752 {
1753 unsigned int start = 0;
1754 unsigned int end = 0; /* excluded always */
1755
1756 if (!obj || obj->magic != FIID_OBJ_MAGIC)
1757 return (-1);
1758
1759 if (!field)
1760 {
1761 obj->errnum = FIID_ERR_PARAMETERS;
1762 return (-1);
1763 }
1764
1765 if (_fiid_obj_field_start_end (obj, field, &start, &end) != -1)
1766 {
1767 obj->errnum = FIID_ERR_SUCCESS;
1768 return (1);
1769 }
1770
1771 obj->errnum = FIID_ERR_FIELD_NOT_FOUND;
1772 return (0);
1773 }
1774
1775 int
FIID_OBJ_FIELD_LOOKUP(fiid_obj_t obj,const char * field)1776 FIID_OBJ_FIELD_LOOKUP (fiid_obj_t obj, const char *field)
1777 {
1778 int ret;
1779
1780 if ((ret = fiid_obj_field_lookup (obj, field)) < 0)
1781 return (ret);
1782
1783 if (!ret)
1784 {
1785 obj->errnum = FIID_ERR_FIELD_NOT_FOUND;
1786 return (-1);
1787 }
1788
1789 return (ret);
1790 }
1791
1792 int
fiid_obj_set(fiid_obj_t obj,const char * field,uint64_t val)1793 fiid_obj_set (fiid_obj_t obj,
1794 const char *field,
1795 uint64_t val)
1796 {
1797 unsigned int start_bit_pos = 0;
1798 unsigned int end_bit_pos = 0; /* excluded always */
1799 int byte_pos = 0;
1800 int start_bit_in_byte_pos = 0;
1801 int end_bit_in_byte_pos = 0;
1802 int field_len = 0;
1803 int bytes_used = 0;
1804 unsigned int key_index;
1805 uint64_t merged_val = 0;
1806 uint8_t *temp_data = NULL;
1807
1808 if (!obj || obj->magic != FIID_OBJ_MAGIC)
1809 goto cleanup;
1810
1811 if (!field)
1812 {
1813 obj->errnum = FIID_ERR_PARAMETERS;
1814 goto cleanup;
1815 }
1816
1817 if (_fiid_obj_lookup_field_index (obj, field, &key_index) < 0)
1818 return (-1);
1819
1820 if ((field_len = _fiid_obj_field_start_end (obj,
1821 field,
1822 &start_bit_pos,
1823 &end_bit_pos)) < 0)
1824 return (-1);
1825
1826 if (field_len > 64)
1827 field_len = 64;
1828
1829 byte_pos = start_bit_pos / 8;
1830
1831 /* in byte_pos, start_bit_pos is */
1832 start_bit_in_byte_pos = start_bit_pos - (byte_pos * 8);
1833
1834 /* and it spans into... */
1835 if (start_bit_in_byte_pos + field_len > 8)
1836 {
1837 int field_len_temp = field_len;
1838
1839 if (start_bit_in_byte_pos)
1840 bytes_used++;
1841
1842 field_len_temp -= start_bit_in_byte_pos;
1843
1844 bytes_used += (field_len_temp / 8);
1845
1846 field_len_temp -= (bytes_used * 8);
1847
1848 if (field_len_temp)
1849 bytes_used++;
1850 }
1851 else
1852 {
1853 end_bit_in_byte_pos = start_bit_in_byte_pos + field_len;
1854 bytes_used++;
1855 }
1856
1857 if (bytes_used > 1)
1858 {
1859 int start_val_pos = 0;
1860 int end_val_pos = 0;
1861 uint64_t extracted_val = 0;
1862 int field_len_left = field_len;
1863 unsigned int i;
1864
1865 if (!(temp_data = malloc (obj->data_len)))
1866 {
1867 obj->errnum = FIID_ERR_OUT_OF_MEMORY;
1868 goto cleanup;
1869 }
1870 memcpy (temp_data, obj->data, obj->data_len);
1871
1872 for (i = 0; i < bytes_used; i++)
1873 {
1874 if (i == 0)
1875 {
1876 end_val_pos = 8 - start_bit_in_byte_pos;
1877 field_len_left -= end_val_pos;
1878 }
1879 else if (i != (bytes_used - 1))
1880 {
1881 end_val_pos += 8;
1882 field_len_left -= 8;
1883 }
1884 else
1885 end_val_pos += field_len_left;
1886
1887 if (i != (bytes_used - 1))
1888 end_bit_in_byte_pos = 8;
1889 else
1890 end_bit_in_byte_pos = field_len_left;
1891
1892 if (bits_extract (val,
1893 start_val_pos,
1894 end_val_pos,
1895 &extracted_val) < 0)
1896 {
1897 obj->errnum = FIID_ERR_INTERNAL_ERROR;
1898 goto cleanup;
1899 }
1900
1901 if (bits_merge (temp_data[byte_pos + i],
1902 start_bit_in_byte_pos,
1903 end_bit_in_byte_pos,
1904 extracted_val,
1905 &merged_val) < 0)
1906 {
1907 obj->errnum = FIID_ERR_INTERNAL_ERROR;
1908 goto cleanup;
1909 }
1910
1911 temp_data[byte_pos + i] = merged_val;
1912 start_bit_in_byte_pos = 0;
1913 start_val_pos = end_val_pos;
1914 }
1915
1916 memcpy (obj->data, temp_data, obj->data_len);
1917 obj->field_data[key_index].set_field_len = field_len;
1918 }
1919 else
1920 {
1921 if (bits_merge (obj->data[byte_pos],
1922 start_bit_in_byte_pos,
1923 end_bit_in_byte_pos,
1924 val,
1925 &merged_val) < 0)
1926 {
1927 obj->errnum = FIID_ERR_INTERNAL_ERROR;
1928 goto cleanup;
1929 }
1930 obj->data[byte_pos] = merged_val;
1931 obj->field_data[key_index].set_field_len = field_len;
1932 }
1933
1934 free (temp_data);
1935 obj->errnum = FIID_ERR_SUCCESS;
1936 return (0);
1937
1938 cleanup:
1939 free (temp_data);
1940 return (-1);
1941 }
1942
1943 int
fiid_obj_get(fiid_obj_t obj,const char * field,uint64_t * val)1944 fiid_obj_get (fiid_obj_t obj,
1945 const char *field,
1946 uint64_t *val)
1947 {
1948 unsigned int start_bit_pos = 0;
1949 unsigned int end_bit_pos = 0; /* excluded always */
1950 int byte_pos = 0;
1951 int start_bit_in_byte_pos = 0;
1952 int end_bit_in_byte_pos = 0;
1953 int field_len = 0;
1954 int bytes_used = 0;
1955 unsigned int key_index;
1956 uint64_t merged_val = 0;
1957
1958 if (!obj || obj->magic != FIID_OBJ_MAGIC)
1959 return (-1);
1960
1961 if (!field || !val)
1962 {
1963 obj->errnum = FIID_ERR_PARAMETERS;
1964 return (-1);
1965 }
1966
1967 if (_fiid_obj_lookup_field_index (obj, field, &key_index) < 0)
1968 return (-1);
1969
1970 if (!obj->field_data[key_index].set_field_len)
1971 {
1972 obj->errnum = FIID_ERR_SUCCESS;
1973 return (0);
1974 }
1975
1976 if ((field_len = _fiid_obj_field_start_end (obj,
1977 field,
1978 &start_bit_pos,
1979 &end_bit_pos)) < 0)
1980 return (-1);
1981
1982 if (field_len > 64)
1983 field_len = 64;
1984
1985 if (field_len > obj->field_data[key_index].set_field_len)
1986 field_len = obj->field_data[key_index].set_field_len;
1987
1988 byte_pos = start_bit_pos / 8;
1989
1990 /* in byte_pos, start_bit_pos is */
1991 start_bit_in_byte_pos = start_bit_pos - (byte_pos * 8);
1992
1993 /* and it spans into... */
1994 if (start_bit_in_byte_pos + field_len > 8)
1995 {
1996 int field_len_temp = field_len;
1997
1998 if (start_bit_in_byte_pos)
1999 bytes_used++;
2000
2001 field_len_temp -= start_bit_in_byte_pos;
2002
2003 bytes_used += (field_len_temp / 8);
2004
2005 field_len_temp -= (bytes_used * 8);
2006
2007 if (field_len_temp)
2008 bytes_used++;
2009 }
2010 else
2011 {
2012 end_bit_in_byte_pos = start_bit_in_byte_pos + field_len;
2013 bytes_used++;
2014 }
2015
2016 if (bytes_used > 1)
2017 {
2018 int start_val_pos = 0;
2019 int end_val_pos = 0;
2020 uint64_t extracted_val = 0;
2021 uint64_t final_val = 0x0;
2022 int field_len_left = field_len;
2023 unsigned int i;
2024
2025 for (i = 0; i < bytes_used; i++)
2026 {
2027 if (i == 0)
2028 {
2029 end_val_pos = 8 - start_bit_in_byte_pos;
2030 field_len_left -= end_val_pos;
2031 }
2032 else if (i != (bytes_used - 1))
2033 {
2034 end_val_pos += 8;
2035 field_len_left -= 8;
2036 }
2037 else
2038 end_val_pos += field_len_left;
2039
2040 if (i != (bytes_used - 1))
2041 end_bit_in_byte_pos = 8;
2042 else
2043 end_bit_in_byte_pos = field_len_left;
2044
2045 if (bits_extract (obj->data[byte_pos + i],
2046 start_bit_in_byte_pos,
2047 end_bit_in_byte_pos,
2048 &extracted_val) < 0)
2049 {
2050 obj->errnum = FIID_ERR_INTERNAL_ERROR;
2051 return (-1);
2052 }
2053
2054 if (bits_merge (final_val,
2055 start_val_pos,
2056 end_val_pos,
2057 extracted_val,
2058 &merged_val) < 0)
2059 {
2060 obj->errnum = FIID_ERR_INTERNAL_ERROR;
2061 return (-1);
2062 }
2063
2064 final_val = merged_val;
2065 start_bit_in_byte_pos = 0;
2066 start_val_pos = end_val_pos;
2067 }
2068
2069 *val = 0;
2070 *val = final_val;
2071 }
2072 else
2073 {
2074 if (bits_extract (obj->data[byte_pos],
2075 start_bit_in_byte_pos,
2076 end_bit_in_byte_pos,
2077 &merged_val) < 0)
2078 {
2079 obj->errnum = FIID_ERR_INTERNAL_ERROR;
2080 return (-1);
2081 }
2082
2083 *val = 0;
2084 *val = merged_val;
2085 }
2086
2087 obj->errnum = FIID_ERR_SUCCESS;
2088 return (1);
2089 }
2090
2091 int
FIID_OBJ_GET(fiid_obj_t obj,const char * field,uint64_t * val)2092 FIID_OBJ_GET (fiid_obj_t obj,
2093 const char *field,
2094 uint64_t *val)
2095 {
2096 uint64_t lval;
2097 int ret;
2098
2099 if ((ret = fiid_obj_get (obj, field, &lval)) < 0)
2100 return (ret);
2101
2102 if (!ret)
2103 {
2104 obj->errnum = FIID_ERR_DATA_NOT_AVAILABLE;
2105 return (-1);
2106 }
2107
2108 *val = lval;
2109 return (ret);
2110 }
2111
2112 int
fiid_obj_set_data(fiid_obj_t obj,const char * field,const void * data,unsigned int data_len)2113 fiid_obj_set_data (fiid_obj_t obj,
2114 const char *field,
2115 const void *data,
2116 unsigned int data_len)
2117 {
2118 unsigned int field_offset, bytes_len, key_index;
2119 int bits_len, field_start;
2120
2121 if (!obj || obj->magic != FIID_OBJ_MAGIC)
2122 return (-1);
2123
2124 if (!field || !data)
2125 {
2126 obj->errnum = FIID_ERR_PARAMETERS;
2127 return (-1);
2128 }
2129
2130 if (_fiid_obj_lookup_field_index (obj, field, &key_index) < 0)
2131 return (-1);
2132
2133 /* achu: We assume the field must start on a byte boundary and end
2134 * on a byte boundary.
2135 */
2136
2137 if ((field_start = _fiid_obj_field_start (obj, field)) < 0)
2138 return (-1);
2139
2140 if (field_start % 8)
2141 {
2142 obj->errnum = FIID_ERR_DATA_NOT_BYTE_ALIGNED;
2143 return (-1);
2144 }
2145
2146 if ((bits_len = _fiid_obj_field_len (obj, field)) < 0)
2147 return (-1);
2148
2149 if (bits_len % 8)
2150 {
2151 obj->errnum = FIID_ERR_DATA_NOT_BYTE_ALIGNED;
2152 return (-1);
2153 }
2154
2155 bytes_len = BITS_ROUND_BYTES (bits_len);
2156 if (data_len > bytes_len)
2157 data_len = bytes_len;
2158
2159 field_offset = BITS_ROUND_BYTES (field_start);
2160 memcpy ((obj->data + field_offset), data, data_len);
2161 obj->field_data[key_index].set_field_len = (data_len * 8);
2162
2163 obj->errnum = FIID_ERR_SUCCESS;
2164 return (data_len);
2165 }
2166
2167 int
fiid_obj_get_data(fiid_obj_t obj,const char * field,void * data,unsigned int data_len)2168 fiid_obj_get_data (fiid_obj_t obj,
2169 const char *field,
2170 void *data,
2171 unsigned int data_len)
2172 {
2173 unsigned int field_offset, bytes_len, key_index;
2174 int bits_len, field_start;
2175
2176 if (!obj || obj->magic != FIID_OBJ_MAGIC)
2177 return (-1);
2178
2179 if (!field || !data)
2180 {
2181 obj->errnum = FIID_ERR_PARAMETERS;
2182 return (-1);
2183 }
2184
2185 if (_fiid_obj_lookup_field_index (obj, field, &key_index) < 0)
2186 return (-1);
2187
2188 if (!obj->field_data[key_index].set_field_len)
2189 return (0);
2190
2191 /* achu: We assume the field must start on a byte boundary and end
2192 * on a byte boundary.
2193 */
2194
2195 if ((field_start = _fiid_obj_field_start (obj, field)) < 0)
2196 return (-1);
2197
2198 if (field_start % 8)
2199 {
2200 obj->errnum = FIID_ERR_DATA_NOT_BYTE_ALIGNED;
2201 return (-1);
2202 }
2203
2204 if ((bits_len = _fiid_obj_field_len (obj, field)) < 0)
2205 return (-1);
2206
2207 if (obj->field_data[key_index].set_field_len < bits_len)
2208 bits_len = obj->field_data[key_index].set_field_len;
2209
2210 if (bits_len % 8)
2211 {
2212 obj->errnum = FIID_ERR_DATA_NOT_BYTE_ALIGNED;
2213 return (-1);
2214 }
2215
2216 bytes_len = BITS_ROUND_BYTES (bits_len);
2217
2218 if (bytes_len > data_len)
2219 {
2220 obj->errnum = FIID_ERR_OVERFLOW;
2221 return (-1);
2222 }
2223
2224 field_offset = BITS_ROUND_BYTES (field_start);
2225
2226 memcpy (data, (obj->data + field_offset), bytes_len);
2227
2228 obj->errnum = FIID_ERR_SUCCESS;
2229 return (bytes_len);
2230 }
2231
2232 int
fiid_obj_set_all(fiid_obj_t obj,const void * data,unsigned int data_len)2233 fiid_obj_set_all (fiid_obj_t obj,
2234 const void *data,
2235 unsigned int data_len)
2236 {
2237 unsigned int bits_counter, data_bits_len;
2238 unsigned int key_index_end;
2239 unsigned int i;
2240
2241 if (!obj || obj->magic != FIID_OBJ_MAGIC)
2242 return (-1);
2243
2244 if (!data)
2245 {
2246 obj->errnum = FIID_ERR_PARAMETERS;
2247 return (-1);
2248 }
2249
2250 if (data_len > obj->data_len)
2251 data_len = obj->data_len;
2252
2253 /* achu: Find index of last field */
2254 data_bits_len = data_len * 8;
2255 if (data_len < obj->data_len)
2256 {
2257 /* integer overflow conditions checked during object creation */
2258 bits_counter = 0;
2259 for (i = 0; obj->field_data[i].max_field_len; i++)
2260 {
2261 bits_counter += obj->field_data[i].max_field_len;
2262 if (bits_counter >= data_bits_len)
2263 {
2264 /* achu: We assume the data must end on a byte boundary. */
2265 if (bits_counter % 8)
2266 {
2267 obj->errnum = FIID_ERR_DATA_NOT_BYTE_ALIGNED;
2268 return (-1);
2269 }
2270 else
2271 break;
2272 }
2273
2274 }
2275 key_index_end = i;
2276 }
2277 else
2278 key_index_end = (obj->field_data_len - 1);
2279
2280 memcpy (obj->data, data, data_len);
2281
2282 /* integer overflow conditions checked during object creation */
2283 bits_counter = 0;
2284 for (i = 0; i < key_index_end; i++)
2285 {
2286 obj->field_data[i].set_field_len = obj->field_data[i].max_field_len;
2287 bits_counter += obj->field_data[i].set_field_len;
2288 }
2289 if (data_bits_len < bits_counter + obj->field_data[key_index_end].max_field_len)
2290 {
2291 int data_bits_left = data_bits_len - bits_counter;
2292 obj->field_data[i].set_field_len = data_bits_left;
2293 }
2294 else
2295 obj->field_data[i].set_field_len = obj->field_data[i].max_field_len;
2296
2297 obj->errnum = FIID_ERR_SUCCESS;
2298 return (data_len);
2299 }
2300
2301 int
fiid_obj_get_all(fiid_obj_t obj,void * data,unsigned int data_len)2302 fiid_obj_get_all (fiid_obj_t obj,
2303 void *data,
2304 unsigned int data_len)
2305 {
2306 unsigned int bytes_len;
2307 int bits_len;
2308
2309 if (!obj || obj->magic != FIID_OBJ_MAGIC)
2310 return (-1);
2311
2312 if (!data)
2313 {
2314 obj->errnum = FIID_ERR_PARAMETERS;
2315 return (-1);
2316 }
2317
2318 if ((bits_len = fiid_obj_len (obj)) < 0)
2319 return (-1);
2320
2321 if (bits_len == (obj->data_len * 8))
2322 bytes_len = obj->data_len;
2323 else
2324 bytes_len = BITS_ROUND_BYTES (bits_len);
2325
2326 if (data_len < bytes_len)
2327 {
2328 obj->errnum = FIID_ERR_OVERFLOW;
2329 return (-1);
2330 }
2331
2332 if (bytes_len == obj->data_len)
2333 memcpy (data, obj->data, bytes_len);
2334 else
2335 {
2336 unsigned int bytes_written = 0, max_bits_counter = 0, set_bits_counter = 0,
2337 optional_bits_counter = 0, data_index = 0, obj_data_index = 0;
2338 unsigned int i;
2339
2340 /* integer overflow conditions checked during object creation */
2341 for (i = 0; i < obj->field_data_len; i++)
2342 {
2343 unsigned int max_field_len = obj->field_data[i].max_field_len;
2344 unsigned int set_field_len = obj->field_data[i].set_field_len;
2345
2346 max_bits_counter += max_field_len;
2347
2348 if (set_field_len)
2349 {
2350 if (optional_bits_counter)
2351 {
2352 obj->errnum = FIID_ERR_DATA_NOT_BYTE_ALIGNED;
2353 goto cleanup;
2354 }
2355
2356 if (set_field_len != max_field_len)
2357 {
2358 /* If there is an optional or variable length
2359 * field, it cannot have only partial data.
2360 */
2361 if ((set_bits_counter + set_field_len) % 8)
2362 {
2363 obj->errnum = FIID_ERR_DATA_NOT_BYTE_ALIGNED;
2364 goto cleanup;
2365 }
2366 }
2367
2368 set_bits_counter += set_field_len;
2369 if (!(set_bits_counter % 8))
2370 {
2371 unsigned int max_bytes_count = BITS_ROUND_BYTES (max_bits_counter);
2372 unsigned int set_bytes_count = BITS_ROUND_BYTES (set_bits_counter);
2373
2374 memcpy (data + data_index,
2375 obj->data + obj_data_index,
2376 set_bytes_count);
2377
2378 bytes_written += set_bytes_count;
2379 data_index += set_bytes_count;
2380 obj_data_index += max_bytes_count;
2381 set_bits_counter = 0;
2382 max_bits_counter = 0;
2383 }
2384 }
2385 else
2386 {
2387 /* All information must be collected in byte sized
2388 * chunks
2389 */
2390 if (set_bits_counter)
2391 {
2392 obj->errnum = FIID_ERR_DATA_NOT_BYTE_ALIGNED;
2393 goto cleanup;
2394 }
2395
2396 /* Likewise, optional data should be aligned across
2397 * bytes
2398 */
2399 optional_bits_counter += max_field_len;
2400 if (optional_bits_counter && !(optional_bits_counter % 8))
2401 {
2402 /* an "assert" */
2403 if (optional_bits_counter != max_bits_counter)
2404 {
2405 obj->errnum = FIID_ERR_DATA_NOT_BYTE_ALIGNED;
2406 goto cleanup;
2407 }
2408
2409 obj_data_index += BITS_ROUND_BYTES (optional_bits_counter);
2410 optional_bits_counter = 0;
2411 max_bits_counter = 0;
2412 }
2413 }
2414 }
2415
2416 /* There shouldn't be anything left over */
2417 if (set_bits_counter)
2418 {
2419 obj->errnum = FIID_ERR_DATA_NOT_BYTE_ALIGNED;
2420 goto cleanup;
2421 }
2422
2423 if (bytes_written != bytes_len)
2424 {
2425 obj->errnum = FIID_ERR_DATA_NOT_BYTE_ALIGNED;
2426 goto cleanup;
2427 }
2428 }
2429
2430 obj->errnum = FIID_ERR_SUCCESS;
2431 return (bytes_len);
2432
2433 cleanup:
2434 return (-1);
2435 }
2436
2437 static int
_fiid_obj_max_block_len(fiid_obj_t obj,const char * field_start,const char * field_end)2438 _fiid_obj_max_block_len (fiid_obj_t obj,
2439 const char *field_start,
2440 const char *field_end)
2441 {
2442 int end;
2443 int start;
2444
2445 assert (obj);
2446 assert (obj->magic == FIID_OBJ_MAGIC);
2447 assert (field_start);
2448 assert (field_end);
2449
2450 if ((start = _fiid_obj_field_start (obj, field_start)) < 0)
2451 return (-1);
2452
2453 if ((end = _fiid_obj_field_end (obj, field_end)) < 0)
2454 return (-1);
2455
2456 if (start > end)
2457 {
2458 obj->errnum = FIID_ERR_PARAMETERS;
2459 return (-1);
2460 }
2461
2462 return (end - start);
2463 }
2464
2465 int
fiid_obj_set_block(fiid_obj_t obj,const char * field_start,const char * field_end,const void * data,unsigned int data_len)2466 fiid_obj_set_block (fiid_obj_t obj,
2467 const char *field_start,
2468 const char *field_end,
2469 const void *data,
2470 unsigned int data_len)
2471 {
2472 int block_bits_start, block_bits_len;
2473 unsigned int key_index_start, key_index_end;
2474 unsigned int block_bytes_len, bits_counter, data_bits_len, field_offset;
2475 unsigned int i;
2476
2477 if (!obj || obj->magic != FIID_OBJ_MAGIC)
2478 return (-1);
2479
2480 if (!field_start || !field_end || !data)
2481 {
2482 obj->errnum = FIID_ERR_PARAMETERS;
2483 return (-1);
2484 }
2485
2486 if (_fiid_obj_lookup_field_index (obj, field_start, &key_index_start) < 0)
2487 return (-1);
2488
2489 if (_fiid_obj_lookup_field_index (obj, field_end, &key_index_end) < 0)
2490 return (-1);
2491
2492 if (key_index_start > key_index_end)
2493 {
2494 obj->errnum = FIID_ERR_PARAMETERS;
2495 return (-1);
2496 }
2497
2498 /* achu: We assume the field must start on a byte boundary and end
2499 * on a byte boundary.
2500 */
2501
2502 if ((block_bits_start = _fiid_obj_field_start (obj, field_start)) < 0)
2503 return (-1);
2504
2505 if (block_bits_start % 8)
2506 {
2507 obj->errnum = FIID_ERR_DATA_NOT_BYTE_ALIGNED;
2508 return (-1);
2509 }
2510
2511 if ((block_bits_len = _fiid_obj_max_block_len (obj,
2512 field_start,
2513 field_end)) < 0)
2514 return (-1);
2515
2516 if (block_bits_len % 8)
2517 {
2518 obj->errnum = FIID_ERR_DATA_NOT_BYTE_ALIGNED;
2519 return (-1);
2520 }
2521
2522 block_bytes_len = BITS_ROUND_BYTES (block_bits_len);
2523
2524 if (data_len > block_bytes_len)
2525 data_len = block_bytes_len;
2526
2527 /* achu: Potentially adjust index of last field */
2528 /* integer overflow conditions checked during object creation */
2529 data_bits_len = data_len * 8;
2530 if (data_len < block_bits_len)
2531 {
2532 bits_counter = 0;
2533
2534 for (i = key_index_start; i <= key_index_end; i++)
2535 {
2536 bits_counter += obj->field_data[i].max_field_len;
2537 if (bits_counter >= data_bits_len)
2538 {
2539 /* achu: We assume the data must end on a byte boundary. */
2540 if (bits_counter % 8)
2541 {
2542 obj->errnum = FIID_ERR_DATA_NOT_BYTE_ALIGNED;
2543 return (-1);
2544 }
2545 else
2546 break;
2547 }
2548
2549 }
2550 key_index_end = i;
2551 }
2552
2553 field_offset = BITS_ROUND_BYTES (block_bits_start);
2554 memcpy ((obj->data + field_offset), data, data_len);
2555
2556 /* integer overflow conditions checked during object creation */
2557 bits_counter = 0;
2558 for (i = key_index_start; i < key_index_end; i++)
2559 {
2560 obj->field_data[i].set_field_len = obj->field_data[i].max_field_len;
2561 bits_counter += obj->field_data[i].set_field_len;
2562 }
2563 if (data_bits_len < bits_counter + obj->field_data[key_index_end].max_field_len)
2564 {
2565 int data_bits_left = data_bits_len - bits_counter;
2566 obj->field_data[i].set_field_len = data_bits_left;
2567 }
2568 else
2569 obj->field_data[i].set_field_len = obj->field_data[i].max_field_len;
2570
2571 obj->errnum = FIID_ERR_SUCCESS;
2572 return (data_len);
2573 }
2574
2575 int
fiid_obj_get_block(fiid_obj_t obj,const char * field_start,const char * field_end,void * data,unsigned int data_len)2576 fiid_obj_get_block (fiid_obj_t obj,
2577 const char *field_start,
2578 const char *field_end,
2579 void *data,
2580 unsigned int data_len)
2581 {
2582 int block_bits_start, block_bits_max_len, block_bits_set_len;
2583 unsigned int block_bytes_max_len, block_bytes_set_len, field_offset;
2584 unsigned int key_index_start, key_index_end;
2585
2586 if (!obj || obj->magic != FIID_OBJ_MAGIC)
2587 return (-1);
2588
2589 if (!field_start || !field_end || !data)
2590 {
2591 obj->errnum = FIID_ERR_PARAMETERS;
2592 return (-1);
2593 }
2594
2595 if (_fiid_obj_lookup_field_index (obj, field_start, &key_index_start) < 0)
2596 return (-1);
2597
2598 if (_fiid_obj_lookup_field_index (obj, field_end, &key_index_end) < 0)
2599 return (-1);
2600
2601 if (key_index_start > key_index_end)
2602 {
2603 obj->errnum = FIID_ERR_PARAMETERS;
2604 return (-1);
2605 }
2606
2607 /* achu: We assume the field must start on a byte boundary and ends
2608 * on a byte boundary.
2609 */
2610
2611 if ((block_bits_start = _fiid_obj_field_start (obj, field_start)) < 0)
2612 return (-1);
2613
2614 if (block_bits_start % 8)
2615 {
2616 obj->errnum = FIID_ERR_DATA_NOT_BYTE_ALIGNED;
2617 return (-1);
2618 }
2619
2620 if ((block_bits_max_len = _fiid_obj_max_block_len (obj, field_start, field_end)) < 0)
2621 return (-1);
2622
2623 if (block_bits_max_len % 8)
2624 {
2625 obj->errnum = FIID_ERR_DATA_NOT_BYTE_ALIGNED;
2626 return (-1);
2627 }
2628
2629 if ((block_bits_set_len = fiid_obj_block_len (obj, field_start, field_end)) < 0)
2630 return (-1);
2631
2632 if (block_bits_set_len % 8)
2633 {
2634 obj->errnum = FIID_ERR_DATA_NOT_BYTE_ALIGNED;
2635 return (-1);
2636 }
2637
2638 block_bytes_max_len = BITS_ROUND_BYTES (block_bits_max_len);
2639 block_bytes_set_len = BITS_ROUND_BYTES (block_bits_set_len);
2640
2641 if (data_len < block_bytes_set_len)
2642 {
2643 obj->errnum = FIID_ERR_OVERFLOW;
2644 return (-1);
2645 }
2646
2647 field_offset = BITS_ROUND_BYTES (block_bits_start);
2648
2649 memset (data, '\0', data_len);
2650
2651 if (block_bytes_set_len == block_bytes_max_len)
2652 memcpy (data, (obj->data + field_offset), block_bytes_set_len);
2653 else
2654 {
2655 unsigned int bytes_written = 0, max_bits_counter = 0, set_bits_counter = 0,
2656 optional_bits_counter = 0, data_index = 0, obj_data_index = field_offset;
2657 unsigned int i;
2658
2659 /* integer overflow conditions checked during object creation */
2660 for (i = key_index_start; i <= key_index_end; i++)
2661 {
2662 unsigned int max_field_len = obj->field_data[i].max_field_len;
2663 unsigned int set_field_len = obj->field_data[i].set_field_len;
2664
2665 max_bits_counter += max_field_len;
2666
2667 if (set_field_len)
2668 {
2669 if (optional_bits_counter)
2670 {
2671 obj->errnum = FIID_ERR_DATA_NOT_BYTE_ALIGNED;
2672 goto cleanup;
2673 }
2674
2675 if (set_field_len != max_field_len)
2676 {
2677 /* If there is an optional or variable length
2678 * field, it cannot have only partial data.
2679 */
2680 if ((set_bits_counter + set_field_len) % 8)
2681 {
2682 obj->errnum = FIID_ERR_DATA_NOT_BYTE_ALIGNED;
2683 goto cleanup;
2684 }
2685 }
2686
2687 set_bits_counter += set_field_len;
2688 if (!(set_bits_counter % 8))
2689 {
2690 unsigned int max_bytes_count = BITS_ROUND_BYTES (max_bits_counter);
2691 unsigned int set_bytes_count = BITS_ROUND_BYTES (set_bits_counter);
2692
2693 memcpy (data + data_index,
2694 obj->data + obj_data_index,
2695 set_bytes_count);
2696
2697 bytes_written += set_bytes_count;
2698 data_index += set_bytes_count;
2699 obj_data_index += max_bytes_count;
2700 set_bits_counter = 0;
2701 max_bits_counter = 0;
2702 }
2703 }
2704 else
2705 {
2706 /* All information must be collected in byte sized
2707 * chunks
2708 */
2709 if (set_bits_counter)
2710 {
2711 obj->errnum = FIID_ERR_DATA_NOT_BYTE_ALIGNED;
2712 goto cleanup;
2713 }
2714
2715 /* Likewise, optional data should be aligned across
2716 * bytes
2717 */
2718 optional_bits_counter += max_field_len;
2719 if (optional_bits_counter && !(optional_bits_counter % 8))
2720 {
2721 /* an "assert" */
2722 if (optional_bits_counter != max_bits_counter)
2723 {
2724 obj->errnum = FIID_ERR_DATA_NOT_BYTE_ALIGNED;
2725 goto cleanup;
2726 }
2727
2728 obj_data_index += BITS_ROUND_BYTES (optional_bits_counter);
2729 optional_bits_counter = 0;
2730 max_bits_counter = 0;
2731 }
2732 }
2733
2734 }
2735
2736 /* There shouldn't be anything left over */
2737 if (set_bits_counter)
2738 {
2739 obj->errnum = FIID_ERR_DATA_NOT_BYTE_ALIGNED;
2740 goto cleanup;
2741 }
2742
2743 if (bytes_written != block_bytes_set_len)
2744 {
2745 obj->errnum = FIID_ERR_DATA_NOT_BYTE_ALIGNED;
2746 goto cleanup;
2747 }
2748 }
2749
2750 obj->errnum = FIID_ERR_SUCCESS;
2751 return (block_bytes_set_len);
2752
2753 cleanup:
2754 if (data)
2755 memset (data, '\0', data_len);
2756 return (-1);
2757 }
2758
2759 fiid_iterator_t
fiid_iterator_create(fiid_obj_t obj)2760 fiid_iterator_create (fiid_obj_t obj)
2761 {
2762 fiid_iterator_t iter = NULL;
2763
2764 if (!obj || obj->magic != FIID_OBJ_MAGIC)
2765 goto cleanup;
2766
2767 if (!(iter = (fiid_iterator_t)malloc (sizeof (struct fiid_iterator))))
2768 {
2769 obj->errnum = FIID_ERR_OUT_OF_MEMORY;
2770 goto cleanup;
2771 }
2772 memset (iter, '\0', sizeof (struct fiid_iterator));
2773 iter->magic = FIID_ITERATOR_MAGIC;
2774 iter->current_index = 0;
2775
2776 /* The - 1 below is because field_data_len is length of the array.
2777 * The iterator is concerned about array indexes.
2778 */
2779 iter->last_index = obj->field_data_len - 1;
2780
2781 if (!(iter->obj = fiid_obj_dup (obj)))
2782 goto cleanup;
2783
2784 obj->errnum = FIID_ERR_SUCCESS;
2785 return (iter);
2786
2787 cleanup:
2788 if (iter)
2789 {
2790 if (iter->obj)
2791 fiid_obj_destroy (iter->obj);
2792 free (iter);
2793 }
2794
2795 return (NULL);
2796 }
2797
2798 void
fiid_iterator_destroy(fiid_iterator_t iter)2799 fiid_iterator_destroy (fiid_iterator_t iter)
2800 {
2801 if (!(iter && iter->magic == FIID_ITERATOR_MAGIC))
2802 return;
2803
2804 iter->magic = ~FIID_ITERATOR_MAGIC;
2805 iter->errnum = FIID_ERR_SUCCESS;
2806 fiid_obj_destroy (iter->obj);
2807 free (iter);
2808 }
2809
2810 fiid_err_t
fiid_iterator_errnum(fiid_iterator_t iter)2811 fiid_iterator_errnum (fiid_iterator_t iter)
2812 {
2813 if (!iter)
2814 return (FIID_ERR_ITERATOR_NULL);
2815 else if (iter->magic != FIID_ITERATOR_MAGIC)
2816 return (FIID_ERR_ITERATOR_INVALID);
2817 else
2818 return (iter->errnum);
2819 }
2820
2821 char *
fiid_iterator_errormsg(fiid_iterator_t iter)2822 fiid_iterator_errormsg (fiid_iterator_t iter)
2823 {
2824 return (fiid_strerror (fiid_iterator_errnum (iter)));
2825 }
2826
2827 int
fiid_iterator_reset(fiid_iterator_t iter)2828 fiid_iterator_reset (fiid_iterator_t iter)
2829 {
2830 if (!(iter && iter->magic == FIID_ITERATOR_MAGIC))
2831 return (-1);
2832
2833 iter->current_index = 0;
2834 iter->errnum = FIID_ERR_SUCCESS;
2835 return (0);
2836 }
2837
2838 int
fiid_iterator_next(fiid_iterator_t iter)2839 fiid_iterator_next (fiid_iterator_t iter)
2840 {
2841 if (!(iter && iter->magic == FIID_ITERATOR_MAGIC))
2842 return (-1);
2843
2844 if (iter->current_index != iter->last_index)
2845 iter->current_index++;
2846
2847 iter->errnum = FIID_ERR_SUCCESS;
2848 return (0);
2849 }
2850
2851 int
fiid_iterator_end(fiid_iterator_t iter)2852 fiid_iterator_end (fiid_iterator_t iter)
2853 {
2854 if (!(iter && iter->magic == FIID_ITERATOR_MAGIC))
2855 return (-1);
2856
2857 iter->errnum = FIID_ERR_SUCCESS;
2858 return ((iter->current_index == iter->last_index) ? 1 : 0);
2859 }
2860
2861 int
fiid_iterator_field_len(fiid_iterator_t iter)2862 fiid_iterator_field_len (fiid_iterator_t iter)
2863 {
2864 if (!(iter && iter->magic == FIID_ITERATOR_MAGIC))
2865 return (-1);
2866
2867 iter->errnum = FIID_ERR_SUCCESS;
2868 /* integer overflow conditions checked during object creation */
2869 return (iter->obj->field_data[iter->current_index].set_field_len);
2870 }
2871
2872 char *
fiid_iterator_key(fiid_iterator_t iter)2873 fiid_iterator_key (fiid_iterator_t iter)
2874 {
2875 if (!(iter && iter->magic == FIID_ITERATOR_MAGIC))
2876 return (NULL);
2877
2878 iter->errnum = FIID_ERR_SUCCESS;
2879 return (iter->obj->field_data[iter->current_index].key);
2880 }
2881
2882 int
fiid_iterator_get(fiid_iterator_t iter,uint64_t * val)2883 fiid_iterator_get (fiid_iterator_t iter, uint64_t *val)
2884 {
2885 char *key;
2886 int rv;
2887
2888 if (!(iter && iter->magic == FIID_ITERATOR_MAGIC))
2889 return (-1);
2890
2891 key = iter->obj->field_data[iter->current_index].key;
2892 rv = fiid_obj_get (iter->obj, key, val);
2893 iter->errnum = (iter->obj->errnum);
2894 return (rv);
2895 }
2896
2897 int
fiid_iterator_get_data(fiid_iterator_t iter,void * data,unsigned int data_len)2898 fiid_iterator_get_data (fiid_iterator_t iter,
2899 void *data,
2900 unsigned int data_len)
2901 {
2902 char *key;
2903 int rv;
2904
2905 if (!(iter && iter->magic == FIID_ITERATOR_MAGIC))
2906 return (-1);
2907
2908 key = iter->obj->field_data[iter->current_index].key;
2909 rv = fiid_obj_get_data (iter->obj, key, data, data_len);
2910 iter->errnum = (iter->obj->errnum);
2911 return (rv);
2912 }
2913