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