]> git.ipfire.org Git - thirdparty/lldpd.git/blob - src/lib/atom.h
lib: fix memory leak when handling I/O
[thirdparty/lldpd.git] / src / lib / atom.h
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 #include <sys/queue.h>
19 #include "../lldpd-structs.h"
20 #include "../compat/compat.h"
21 #include "../marshal.h"
22 #include "../ctl.h"
23
24 /* connection.c */
25 struct lldpctl_conn_t {
26 /* the Unix-domain socket to connect to lldpd */
27 char *ctlname;
28
29 /* Callback handling */
30 lldpctl_recv_callback recv; /* Receive callback */
31 lldpctl_send_callback send; /* Send callback */
32 void *user_data; /* Callback user data */
33
34 /* IO state handling. */
35 uint8_t *input_buffer; /* Current input/output buffer */
36 uint8_t *output_buffer; /* Current input/output buffer */
37 size_t input_buffer_len;
38 size_t output_buffer_len;
39
40 #define CONN_STATE_IDLE 0
41 #define CONN_STATE_GET_INTERFACES_SEND 1
42 #define CONN_STATE_GET_INTERFACES_RECV 2
43 #define CONN_STATE_GET_PORT_SEND 3
44 #define CONN_STATE_GET_PORT_RECV 4
45 #define CONN_STATE_SET_PORT_SEND 5
46 #define CONN_STATE_SET_PORT_RECV 6
47 #define CONN_STATE_SET_WATCH_SEND 7
48 #define CONN_STATE_SET_WATCH_RECV 8
49 #define CONN_STATE_GET_CONFIG_SEND 9
50 #define CONN_STATE_GET_CONFIG_RECV 10
51 #define CONN_STATE_SET_CONFIG_SEND 11
52 #define CONN_STATE_SET_CONFIG_RECV 12
53 #define CONN_STATE_GET_CHASSIS_SEND 13
54 #define CONN_STATE_GET_CHASSIS_RECV 14
55 #define CONN_STATE_GET_DEFAULT_PORT_SEND 15
56 #define CONN_STATE_GET_DEFAULT_PORT_RECV 16
57 int state; /* Current state */
58 /* Data attached to the state. It is used to check that we are using the
59 * same data as a previous call until the state machine goes to
60 * CONN_STATE_IDLE. */
61 char state_data[IFNAMSIZ + 64];
62 /* Error handling */
63 lldpctl_error_t error; /* Last error */
64
65 /* Handling notifications */
66 lldpctl_change_callback watch_cb;
67 void *watch_data;
68 int watch_triggered;
69 };
70
71 /* User data for synchronous callbacks. */
72 struct lldpctl_conn_sync_t {
73 int fd; /* File descriptor to the socket. */
74 };
75
76 ssize_t _lldpctl_needs(lldpctl_conn_t *lldpctl, size_t length);
77 int _lldpctl_do_something(lldpctl_conn_t *conn,
78 int state_send, int state_recv, const char *state_data,
79 enum hmsg_type type,
80 void *to_send, struct marshal_info *mi_send,
81 void **to_recv, struct marshal_info *mi_recv);
82
83 /* errors.c */
84 #define SET_ERROR(conn, x) ((conn)->error = x)
85 #define RESET_ERROR(conn) SET_ERROR((conn), LLDPCTL_NO_ERROR)
86
87
88 /* atom.c and atom-private.c */
89 typedef enum {
90 atom_config,
91 atom_interfaces_list,
92 atom_interface,
93 atom_ports_list,
94 atom_port,
95 atom_mgmts_list,
96 atom_mgmt,
97 #ifdef ENABLE_DOT3
98 atom_dot3_power,
99 #endif
100 #ifdef ENABLE_DOT1
101 atom_vlans_list,
102 atom_vlan,
103 atom_ppvids_list,
104 atom_ppvid,
105 atom_pis_list,
106 atom_pi,
107 #endif
108 #ifdef ENABLE_LLDPMED
109 atom_med_policies_list,
110 atom_med_policy,
111 atom_med_locations_list,
112 atom_med_location,
113 atom_med_caelements_list,
114 atom_med_caelement,
115 atom_med_power,
116 #endif
117 #ifdef ENABLE_CUSTOM
118 atom_custom_list,
119 atom_custom,
120 #endif
121 atom_chassis,
122 } atom_t;
123
124 void *_lldpctl_alloc_in_atom(lldpctl_atom_t *, size_t);
125 const char *_lldpctl_dump_in_atom(lldpctl_atom_t *, const uint8_t *, size_t, char, size_t);
126
127 struct atom_buffer {
128 TAILQ_ENTRY(atom_buffer) next;
129 u_int8_t data[0];
130 };
131
132 struct lldpctl_atom_t {
133 int count;
134 atom_t type;
135 lldpctl_conn_t *conn;
136 TAILQ_HEAD(, atom_buffer) buffers; /* List of buffers */
137
138 /* Destructor */
139 void (*free)(lldpctl_atom_t *);
140
141 /* Iterators */
142 lldpctl_atom_iter_t *(*iter)(lldpctl_atom_t *);
143 lldpctl_atom_iter_t *(*next)(lldpctl_atom_t *, lldpctl_atom_iter_t *);
144 lldpctl_atom_t *(*value)(lldpctl_atom_t *, lldpctl_atom_iter_t *);
145
146 /* Getters */
147 lldpctl_atom_t *(*get)(lldpctl_atom_t *, lldpctl_key_t);
148 const char *(*get_str)(lldpctl_atom_t *, lldpctl_key_t);
149 const u_int8_t *(*get_buffer)(lldpctl_atom_t *, lldpctl_key_t, size_t *);
150 long int (*get_int)(lldpctl_atom_t *, lldpctl_key_t);
151
152 /* Setters */
153 lldpctl_atom_t *(*set)(lldpctl_atom_t *, lldpctl_key_t, lldpctl_atom_t *);
154 lldpctl_atom_t *(*set_str)(lldpctl_atom_t *, lldpctl_key_t, const char *);
155 lldpctl_atom_t *(*set_buffer)(lldpctl_atom_t *, lldpctl_key_t, const u_int8_t *, size_t);
156 lldpctl_atom_t *(*set_int)(lldpctl_atom_t *, lldpctl_key_t, long int);
157 lldpctl_atom_t *(*create)(lldpctl_atom_t *);
158 };
159
160 struct _lldpctl_atom_config_t {
161 lldpctl_atom_t base;
162 struct lldpd_config *config;
163 };
164
165 struct _lldpctl_atom_interfaces_list_t {
166 lldpctl_atom_t base;
167 struct lldpd_interface_list *ifs;
168 };
169
170 struct _lldpctl_atom_interface_t {
171 lldpctl_atom_t base;
172 char *name;
173 };
174
175 struct _lldpctl_atom_chassis_t {
176 lldpctl_atom_t base;
177 struct lldpd_chassis *chassis;
178 struct _lldpctl_atom_port_t *parent; /* Optional: parent of this atom (owning our reference) */
179 int embedded; /* This atom is "embedded" (not refcounted) */
180 };
181
182 struct _lldpctl_atom_port_t {
183 lldpctl_atom_t base;
184 int local; /* Local or remote port? */
185 struct lldpd_hardware *hardware; /* Local port only (but optional) */
186 struct lldpd_port *port; /* Local and remote */
187 struct _lldpctl_atom_port_t *parent; /* Local port if we are a remote port */
188 lldpctl_atom_t *chassis; /* Internal atom for chassis */
189 };
190
191 /* Can represent any simple list holding just a reference to a port. */
192 struct _lldpctl_atom_any_list_t {
193 lldpctl_atom_t base;
194 struct _lldpctl_atom_port_t *parent;
195 };
196
197 struct _lldpctl_atom_mgmts_list_t {
198 lldpctl_atom_t base;
199 lldpctl_atom_t *parent;
200 struct lldpd_chassis *chassis; /* Chassis containing the list of IP addresses */
201 };
202
203 struct _lldpctl_atom_mgmt_t {
204 lldpctl_atom_t base;
205 lldpctl_atom_t *parent;
206 struct lldpd_mgmt *mgmt;
207 };
208
209 #ifdef ENABLE_DOT3
210 struct _lldpctl_atom_dot3_power_t {
211 lldpctl_atom_t base;
212 struct _lldpctl_atom_port_t *parent;
213 };
214 #endif
215
216 #ifdef ENABLE_DOT1
217 struct _lldpctl_atom_vlan_t {
218 lldpctl_atom_t base;
219 struct _lldpctl_atom_port_t *parent;
220 struct lldpd_vlan *vlan;
221 };
222
223 struct _lldpctl_atom_ppvid_t {
224 lldpctl_atom_t base;
225 struct _lldpctl_atom_port_t *parent;
226 struct lldpd_ppvid *ppvid;
227 };
228
229 struct _lldpctl_atom_pi_t {
230 lldpctl_atom_t base;
231 struct _lldpctl_atom_port_t *parent;
232 struct lldpd_pi *pi;
233 };
234 #endif
235
236 #ifdef ENABLE_LLDPMED
237 struct _lldpctl_atom_med_policy_t {
238 lldpctl_atom_t base;
239 struct _lldpctl_atom_port_t *parent;
240 struct lldpd_med_policy *policy;
241 };
242
243 struct _lldpctl_atom_med_location_t {
244 lldpctl_atom_t base;
245 struct _lldpctl_atom_port_t *parent;
246 struct lldpd_med_loc *location;
247 };
248
249 /* This list should have the same structure than _llpdctl_atom_any_list_t */
250 struct _lldpctl_atom_med_caelements_list_t {
251 lldpctl_atom_t base;
252 struct _lldpctl_atom_med_location_t *parent;
253 };
254
255 struct _lldpctl_atom_med_caelement_t {
256 lldpctl_atom_t base;
257 struct _lldpctl_atom_med_location_t *parent;
258 int type;
259 uint8_t *value;
260 size_t len;
261 };
262
263 struct _lldpctl_atom_med_power_t {
264 lldpctl_atom_t base;
265 struct _lldpctl_atom_port_t *parent;
266 };
267 #endif
268
269 #ifdef ENABLE_CUSTOM
270 struct _lldpctl_atom_custom_list_t {
271 lldpctl_atom_t base;
272 struct _lldpctl_atom_port_t *parent;
273 struct lldpd_custom_list *list;
274 };
275
276 struct _lldpctl_atom_custom_t {
277 lldpctl_atom_t base;
278 struct _lldpctl_atom_port_t *parent;
279 int op;
280 struct lldpd_custom *tlv;
281 };
282 #endif
283
284 struct lldpctl_atom_t *_lldpctl_new_atom(lldpctl_conn_t *conn, atom_t type, ...);
285
286 struct atom_map {
287 int key;
288 struct atom_map *next;
289 lldpctl_map_t map[];
290 };
291
292 void atom_map_register(struct atom_map *map, int);
293 void init_atom_map(void);
294
295 #define ATOM_MAP_REGISTER(NAME, PRIO) void init_atom_map_ ## NAME() { atom_map_register(& NAME, PRIO); }
296
297 struct atom_builder {
298 atom_t type; /* Atom type */
299 size_t size; /* Size of structure to allocate */
300 int (*init)(lldpctl_atom_t *, va_list); /* Optional additional init steps */
301 void (*free)(lldpctl_atom_t *); /* Optional deallocation steps */
302
303 lldpctl_atom_iter_t* (*iter)(lldpctl_atom_t *); /* Optional, return an iterator for this object */
304 lldpctl_atom_iter_t* (*next)(lldpctl_atom_t *, lldpctl_atom_iter_t *); /* Return the next object for the provided iterator */
305 lldpctl_atom_t* (*value)(lldpctl_atom_t *, lldpctl_atom_iter_t *); /* Return the current object for the provided iterator */
306
307 lldpctl_atom_t* (*get)(lldpctl_atom_t *, lldpctl_key_t);
308 const char* (*get_str)(lldpctl_atom_t *, lldpctl_key_t);
309 const u_int8_t* (*get_buffer)(lldpctl_atom_t *, lldpctl_key_t, size_t *);
310 long int (*get_int)(lldpctl_atom_t *, lldpctl_key_t);
311
312 lldpctl_atom_t* (*set)(lldpctl_atom_t *, lldpctl_key_t, lldpctl_atom_t *);
313 lldpctl_atom_t* (*set_str)(lldpctl_atom_t *, lldpctl_key_t, const char *);
314 lldpctl_atom_t* (*set_buffer)(lldpctl_atom_t *, lldpctl_key_t, const u_int8_t *, size_t);
315 lldpctl_atom_t* (*set_int)(lldpctl_atom_t *, lldpctl_key_t, long int);
316 lldpctl_atom_t* (*create)(lldpctl_atom_t *);
317 struct atom_builder *nextb;
318 };
319
320 void atom_builder_register(struct atom_builder *builder, int);
321 void init_atom_builder(void);
322
323 #define ATOM_BUILDER_REGISTER(NAME, PRIO) void init_atom_builder_ ## NAME() { atom_builder_register(& NAME, PRIO); }