Coverage Report

Created: 2025-07-01 07:02

/src/lldpd/src/marshal.h
Line
Count
Source (jump to first uncovered line)
1
/* -*- mode: c; c-file-style: "openbsd" -*- */
2
/*
3
 * Copyright (c) 2012 Vincent Bernat <bernat@luffy.cx>
4
 *
5
 * Permission to use, copy, modify, and/or distribute this software for any
6
 * purpose with or without fee is hereby granted, provided that the above
7
 * copyright notice and this permission notice appear in all copies.
8
 *
9
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
 */
17
18
#ifndef _MARSHAL_H
19
#define _MARSHAL_H
20
21
#include <stddef.h>
22
#include <stdint.h>
23
#include <sys/types.h>
24
25
struct marshal_info;
26
enum marshal_subinfo_kind {
27
  pointer,
28
  substruct,
29
  ignore,
30
};
31
#define MARSHAL_INFO_POINTER 1
32
#define MARSHAL_INFO_SUB 2
33
struct marshal_subinfo {
34
  size_t offset;      /* Offset compared to parent structure */
35
  size_t offset2;     /* Ancillary offset (for related data) */
36
  enum marshal_subinfo_kind kind; /* Kind of substructure */
37
  struct marshal_info *mi;
38
};
39
#define MARSHAL_SUBINFO_NULL                              \
40
  {                                                       \
41
    .offset = 0, .offset2 = 0, .kind = ignore, .mi = NULL \
42
  }
43
struct marshal_info {
44
  const char *name; /* Name of structure */
45
  size_t size;    /* Size of the structure */
46
#if defined __GNUC__ && __GNUC__ < 3
47
  /* With gcc 2.96, flexible arrays are not supported, even with
48
   * -std=gnu99. And with gcc 3.x, zero-sized arrays cannot be statically
49
   * initialized (with more than one element). */
50
  struct marshal_subinfo pointers[0]; /* Pointer to other structures */
51
#else
52
  struct marshal_subinfo pointers[]; /* Pointer to other structures */
53
#endif
54
};
55
/* Special case for strings */
56
extern struct marshal_info marshal_info_string;
57
extern struct marshal_info marshal_info_fstring;
58
extern struct marshal_info marshal_info_ignore;
59
60
/* Declare a new marshal_info struct named after the type we want to
61
   marshal. The marshalled type has to be a structure. */
62
0
#define MARSHAL_INFO(type) marshal_info_##type
63
#ifdef MARSHAL_EXPORT
64
#  define MARSHAL_HELPER_FUNCTIONS(type, ttype)                               \
65
    ssize_t type##_serialize(ttype *source, void *buffer);                    \
66
    ssize_t type##_serialize(ttype *source, void *buffer)                     \
67
0
    {                                                                         \
68
0
      return marshal_serialize(type, source, buffer);                         \
69
0
    }                                                                         \
Unexecuted instantiation: lldpd_ppvid_serialize
Unexecuted instantiation: lldpd_vlan_serialize
Unexecuted instantiation: lldpd_pi_serialize
Unexecuted instantiation: lldpd_med_policy_serialize
Unexecuted instantiation: lldpd_med_loc_serialize
Unexecuted instantiation: lldpd_med_power_serialize
Unexecuted instantiation: lldpd_dot3_power_serialize
Unexecuted instantiation: lldpd_mgmt_serialize
Unexecuted instantiation: lldpd_chassis_serialize
Unexecuted instantiation: lldpd_custom_serialize
Unexecuted instantiation: lldpd_port_serialize
Unexecuted instantiation: lldpd_port_set_serialize
Unexecuted instantiation: lldpd_config_serialize
Unexecuted instantiation: lldpd_hardware_serialize
Unexecuted instantiation: lldpd_interface_serialize
Unexecuted instantiation: lldpd_interface_list_serialize
Unexecuted instantiation: lldpd_neighbor_change_serialize
70
    size_t type##_unserialize(void *buffer, size_t len, ttype **destination); \
71
    size_t type##_unserialize(void *buffer, size_t len, ttype **destination)  \
72
0
    {                                                                         \
73
0
      void *p;                                                                \
74
0
      size_t rc;                                                              \
75
0
      rc = marshal_unserialize(type, buffer, len, &p);                        \
76
0
      if (rc <= 0) return rc;                                                 \
77
0
      *destination = p;                                                       \
78
0
      return rc;                                                              \
79
0
    }
Unexecuted instantiation: lldpd_ppvid_unserialize
Unexecuted instantiation: lldpd_vlan_unserialize
Unexecuted instantiation: lldpd_pi_unserialize
Unexecuted instantiation: lldpd_med_policy_unserialize
Unexecuted instantiation: lldpd_med_loc_unserialize
Unexecuted instantiation: lldpd_med_power_unserialize
Unexecuted instantiation: lldpd_dot3_power_unserialize
Unexecuted instantiation: lldpd_mgmt_unserialize
Unexecuted instantiation: lldpd_chassis_unserialize
Unexecuted instantiation: lldpd_custom_unserialize
Unexecuted instantiation: lldpd_port_unserialize
Unexecuted instantiation: lldpd_port_set_unserialize
Unexecuted instantiation: lldpd_config_unserialize
Unexecuted instantiation: lldpd_hardware_unserialize
Unexecuted instantiation: lldpd_interface_unserialize
Unexecuted instantiation: lldpd_interface_list_unserialize
Unexecuted instantiation: lldpd_neighbor_change_unserialize
80
#  define MARSHAL_BEGIN(type)         \
81
    struct marshal_info MARSHAL_INFO( \
82
  type) = { .name = #type, .size = sizeof(struct type), .pointers = {
83
#  define MARSHAL_ADD(_kind, type, subtype, member) \
84
    { .offset = offsetof(struct type, member),      \
85
      .offset2 = 0,                           \
86
      .kind = _kind,                          \
87
      .mi = &MARSHAL_INFO(subtype) },
88
#  define MARSHAL_FSTR(type, member, len)          \
89
    { .offset = offsetof(struct type, member),     \
90
      .offset2 = offsetof(struct type, len), \
91
      .kind = pointer,                       \
92
      .mi = &marshal_info_fstring },
93
#  define MARSHAL_END(type) \
94
    MARSHAL_SUBINFO_NULL    \
95
    }                       \
96
    }                       \
97
    ;                       \
98
    MARSHAL_HELPER_FUNCTIONS(type, struct type)
99
#else
100
#  define MARSHAL_HELPER_FUNCTIONS(type, ttype) \
101
    ssize_t type##_serialize(ttype *, void *);  \
102
    size_t type##_unserialize(void *, size_t, ttype **);
103
#  define MARSHAL_BEGIN(type) extern struct marshal_info MARSHAL_INFO(type);
104
#  define MARSHAL_ADD(...)
105
#  define MARSHAL_FSTR(...)
106
#  define MARSHAL_END(type) MARSHAL_HELPER_FUNCTIONS(type, struct type)
107
#endif
108
/* Shortcuts */
109
#define MARSHAL_POINTER(...) MARSHAL_ADD(pointer, ##__VA_ARGS__)
110
#define MARSHAL_SUBSTRUCT(...) MARSHAL_ADD(substruct, ##__VA_ARGS__)
111
#define MARSHAL_STR(type, member) MARSHAL_ADD(pointer, type, string, member)
112
#define MARSHAL_IGNORE(type, member) MARSHAL_ADD(ignore, type, ignore, member)
113
#define MARSHAL_TQE(type, field)              \
114
  MARSHAL_POINTER(type, type, field.tqe_next) \
115
  MARSHAL_IGNORE(type, field.tqe_prev)
116
/* Support for TAILQ list is partial. Access to last and previous
117
   elements is not available. Some operations are therefore not
118
   possible. However, TAILQ_FOREACH is still
119
   available. */
120
#define MARSHAL_TQH(type, subtype)          \
121
  MARSHAL_POINTER(type, subtype, tqh_first) \
122
  MARSHAL_IGNORE(type, tqh_last)
123
#define MARSHAL_SUBTQ(type, subtype, field)       \
124
  MARSHAL_POINTER(type, subtype, field.tqh_first) \
125
  MARSHAL_IGNORE(type, field.tqh_last)
126
#define MARSHAL(type) \
127
  MARSHAL_BEGIN(type) \
128
  MARSHAL_END(type)
129
#define MARSHAL_TQ(type, subtype) \
130
  MARSHAL_BEGIN(type)             \
131
  MARSHAL_TQH(type, subtype)      \
132
  MARSHAL_END(type)
133
134
/* Serialization */
135
ssize_t marshal_serialize_(struct marshal_info *, void *, void **, int, void *, int)
136
    __attribute__((nonnull(1, 2, 3)));
137
#define marshal_serialize(type, o, output) \
138
0
  marshal_serialize_(&MARSHAL_INFO(type), o, output, 0, NULL, 0)
139
140
/* Unserialization */
141
size_t marshal_unserialize_(struct marshal_info *, void *, size_t, void **, void *, int,
142
    int) __attribute__((nonnull(1, 2, 4)));
143
#define marshal_unserialize(type, o, l, input) \
144
0
  marshal_unserialize_(&MARSHAL_INFO(type), o, l, input, NULL, 0, 0)
145
146
#define marshal_repair_tailq(type, head, field)                              \
147
0
  do {                                                                       \
148
0
    struct type *__item, *__item_next;                                       \
149
0
    (head)->tqh_last = &(head)->tqh_first;                                   \
150
0
    for (__item = TAILQ_FIRST(head); __item != NULL; __item = __item_next) { \
151
0
      __item_next = TAILQ_NEXT(__item, field);                               \
152
0
      __item->field.tqe_prev = (head)->tqh_last;                             \
153
0
      *(head)->tqh_last = __item;                                            \
154
0
      (head)->tqh_last = &__item->field.tqe_next;                            \
155
0
    }                                                                        \
156
0
  } while (0)
157
158
#endif