1 /* -*- mode: c; c-file-style: "openbsd" -*- */
3 * Copyright (c) 2012 Vincent Bernat <bernat@luffy.cx>
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.
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.
22 #include "../marshal.h"
24 #include "../lldpd-structs.h"
27 lldpctl_atom_get_connection(lldpctl_atom_t
*atom
)
35 lldpctl_atom_inc_ref(lldpctl_atom_t
*atom
)
41 lldpctl_atom_dec_ref(lldpctl_atom_t
*atom
)
43 struct atom_buffer
*buffer
, *buffer_next
;
44 if (atom
&& (--atom
->count
== 0)) {
48 /* Remove special allocated buffers */
49 for (buffer
= TAILQ_FIRST(&atom
->buffers
);
51 buffer
= buffer_next
) {
52 buffer_next
= TAILQ_NEXT(buffer
, next
);
61 lldpctl_atom_get(lldpctl_atom_t
*atom
, lldpctl_key_t key
)
63 if (atom
== NULL
) return NULL
;
64 RESET_ERROR(atom
->conn
);
66 if (atom
->get
== NULL
) {
67 SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
70 return atom
->get(atom
, key
);
74 lldpctl_atom_set(lldpctl_atom_t
*atom
, lldpctl_key_t key
,
75 lldpctl_atom_t
*value
)
77 if (atom
== NULL
) return NULL
;
78 RESET_ERROR(atom
->conn
);
80 if (atom
->set
== NULL
) {
81 SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
84 return atom
->set(atom
, key
, value
);
88 lldpctl_atom_get_str(lldpctl_atom_t
*atom
, lldpctl_key_t key
)
90 char *strresult
= NULL
;
91 const uint8_t *bufresult
= NULL
;
92 long int intresult
= -1;
96 if (atom
== NULL
) return NULL
;
97 RESET_ERROR(atom
->conn
);
99 if (atom
->get_str
!= NULL
) {
100 strresult
= (char *)atom
->get_str(atom
, key
);
101 if (strresult
) return strresult
;
102 if (lldpctl_last_error(atom
->conn
) != LLDPCTL_ERR_NOT_EXIST
)
106 RESET_ERROR(atom
->conn
);
107 if (atom
->get_int
!= NULL
) {
108 intresult
= atom
->get_int(atom
, key
);
109 if (lldpctl_last_error(atom
->conn
) != LLDPCTL_ERR_NOT_EXIST
) {
110 strresult
= _lldpctl_alloc_in_atom(atom
, 21);
111 if (!strresult
) return NULL
;
112 n1
= snprintf(strresult
, 21, "%ld", intresult
);
113 if (n1
> -1 && n1
< 21)
115 SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOMEM
); /* Not really true... */
120 RESET_ERROR(atom
->conn
);
121 if (atom
->get_buffer
!= NULL
) {
122 bufresult
= atom
->get_buffer(atom
, key
, &n2
);
124 return _lldpctl_dump_in_atom(atom
, bufresult
, n2
, ' ', 0);
125 if (lldpctl_last_error(atom
->conn
) != LLDPCTL_ERR_NOT_EXIST
)
129 SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
134 lldpctl_atom_set_str(lldpctl_atom_t
*atom
, lldpctl_key_t key
,
137 lldpctl_atom_t
*result
= NULL
;
143 if (atom
== NULL
) return NULL
;
144 RESET_ERROR(atom
->conn
);
146 if (atom
->set_str
!= NULL
) {
147 result
= atom
->set_str(atom
, key
, value
);
148 if (result
) return result
;
149 if (lldpctl_last_error(atom
->conn
) != LLDPCTL_ERR_NOT_EXIST
&&
150 lldpctl_last_error(atom
->conn
) != LLDPCTL_ERR_BAD_VALUE
)
152 bad
= bad
|| (lldpctl_last_error(atom
->conn
) == LLDPCTL_ERR_BAD_VALUE
);
155 converted
= strtol(value
, &end
, 0);
156 isint
= (end
!= value
&& *end
== '\0');
158 RESET_ERROR(atom
->conn
);
159 if (atom
->set_int
!= NULL
&& isint
) {
160 result
= atom
->set_int(atom
, key
, converted
);
161 if (result
) return result
;
162 if (lldpctl_last_error(atom
->conn
) != LLDPCTL_ERR_NOT_EXIST
&&
163 lldpctl_last_error(atom
->conn
) != LLDPCTL_ERR_BAD_VALUE
)
165 bad
= bad
|| (lldpctl_last_error(atom
->conn
) == LLDPCTL_ERR_BAD_VALUE
);
168 RESET_ERROR(atom
->conn
);
169 if (atom
->set_buffer
!= NULL
) {
170 result
= atom
->set_buffer(atom
, key
, (u_int8_t
*)value
, strlen(value
));
171 if (result
) return result
;
172 if (lldpctl_last_error(atom
->conn
) != LLDPCTL_ERR_NOT_EXIST
&&
173 lldpctl_last_error(atom
->conn
) != LLDPCTL_ERR_BAD_VALUE
)
175 bad
= bad
|| (lldpctl_last_error(atom
->conn
) == LLDPCTL_ERR_BAD_VALUE
);
178 SET_ERROR(atom
->conn
, bad
?LLDPCTL_ERR_BAD_VALUE
:LLDPCTL_ERR_NOT_EXIST
);
183 lldpctl_atom_get_buffer(lldpctl_atom_t
*atom
, lldpctl_key_t key
,
186 if (atom
== NULL
) return NULL
;
187 RESET_ERROR(atom
->conn
);
189 if (atom
->get_buffer
== NULL
) {
190 SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
193 return atom
->get_buffer(atom
, key
, length
);
197 lldpctl_atom_set_buffer(lldpctl_atom_t
*atom
, lldpctl_key_t key
,
198 const u_int8_t
* value
, size_t length
)
200 if (atom
== NULL
) return NULL
;
201 RESET_ERROR(atom
->conn
);
203 if (atom
->set_buffer
== NULL
) {
204 SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
207 return atom
->set_buffer(atom
, key
, value
, length
);
211 lldpctl_atom_get_int(lldpctl_atom_t
*atom
, lldpctl_key_t key
)
213 if (atom
== NULL
) return LLDPCTL_ERR_NOT_EXIST
;
214 RESET_ERROR(atom
->conn
);
216 if (atom
->get_int
== NULL
)
217 return SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
218 return atom
->get_int(atom
, key
);
222 lldpctl_atom_set_int(lldpctl_atom_t
*atom
, lldpctl_key_t key
,
225 if (atom
== NULL
) return NULL
;
226 RESET_ERROR(atom
->conn
);
228 if (atom
->set_int
== NULL
) {
229 SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
232 return atom
->set_int(atom
, key
, value
);
236 lldpctl_atom_iter(lldpctl_atom_t
*atom
)
238 if (atom
== NULL
) return NULL
;
239 RESET_ERROR(atom
->conn
);
242 SET_ERROR(atom
->conn
, LLDPCTL_ERR_CANNOT_ITERATE
);
245 return atom
->iter(atom
);
249 lldpctl_atom_iter_next(lldpctl_atom_t
*atom
, lldpctl_atom_iter_t
*iter
)
251 if (atom
== NULL
) return NULL
;
252 RESET_ERROR(atom
->conn
);
255 SET_ERROR(atom
->conn
, LLDPCTL_ERR_CANNOT_ITERATE
);
258 return atom
->next(atom
, iter
);
262 lldpctl_atom_iter_value(lldpctl_atom_t
*atom
, lldpctl_atom_iter_t
*iter
)
264 if (atom
== NULL
) return NULL
;
265 RESET_ERROR(atom
->conn
);
268 SET_ERROR(atom
->conn
, LLDPCTL_ERR_CANNOT_ITERATE
);
271 return atom
->value(atom
, iter
);
275 lldpctl_atom_create(lldpctl_atom_t
*atom
)
277 if (atom
== NULL
) return NULL
;
278 RESET_ERROR(atom
->conn
);
281 SET_ERROR(atom
->conn
, LLDPCTL_ERR_CANNOT_CREATE
);
284 return atom
->create(atom
);
288 * Get somethin with IO.
290 * @param conn The connection to lldpd.
291 * @param state_send State to be when "sending"
292 * @param state_recv State to be when "receiving"
293 * @param type Type of message to send (and receive)
294 * @param to_send Data to send.
295 * @param mi_send Marshalling info for data to send.
296 * @param to_recv Data to receive.
297 * @param mi_recv Marshalling info for data to recive.
298 * @return 0 in case of success, a negative integer in case of failure.
301 _lldpctl_do_something(lldpctl_conn_t
*conn
,
302 int state_send
, int state_recv
, void *state_data
,
304 void *to_send
, struct marshal_info
*mi_send
,
305 void **to_recv
, struct marshal_info
*mi_recv
)
309 if (conn
->state
== CONN_STATE_IDLE
) {
310 /* We need to build the message to send, then send
312 if (ctl_msg_send_unserialized(&conn
->output_buffer
, &conn
->output_buffer_len
,
313 type
, to_send
, mi_send
) != 0)
314 return SET_ERROR(conn
, LLDPCTL_ERR_SERIALIZATION
);
315 conn
->state
= state_send
;
316 conn
->state_data
= state_data
;
318 if (conn
->state
== state_send
&& conn
->state_data
== state_data
) {
319 /* We need to send the currently built message */
320 rc
= lldpctl_send(conn
);
322 return SET_ERROR(conn
, rc
);
323 conn
->state
= state_recv
;
325 if (conn
->state
== state_recv
&& conn
->state_data
== state_data
) {
326 /* We need to receive the answer */
327 while ((rc
= ctl_msg_recv_unserialized(&conn
->input_buffer
, &conn
->input_buffer_len
,
329 to_recv
, mi_recv
)) > 0) {
330 /* We need more bytes */
331 rc
= _lldpctl_needs(conn
, rc
);
333 return SET_ERROR(conn
, rc
);
336 return SET_ERROR(conn
, LLDPCTL_ERR_SERIALIZATION
);
338 conn
->state
= CONN_STATE_IDLE
;
339 conn
->state_data
= NULL
;
342 return SET_ERROR(conn
, LLDPCTL_ERR_INVALID_STATE
);
346 lldpctl_get_interfaces(lldpctl_conn_t
*conn
)
348 struct lldpd_interface_list
*ifs
;
353 rc
= _lldpctl_do_something(conn
,
354 CONN_STATE_GET_INTERFACES_SEND
, CONN_STATE_GET_INTERFACES_RECV
, NULL
,
357 (void **)&ifs
, &MARSHAL_INFO(lldpd_interface_list
));
359 return _lldpctl_new_atom(conn
, atom_interfaces_list
, ifs
);
364 lldpctl_get_port(lldpctl_atom_t
*atom
)
367 lldpctl_conn_t
*conn
= atom
->conn
;
368 struct lldpd_hardware
*hardware
;
369 struct _lldpctl_atom_interface_t
*iface
=
370 (struct _lldpctl_atom_interface_t
*)atom
;
374 if (atom
->type
!= atom_interface
) {
375 SET_ERROR(conn
, LLDPCTL_ERR_INCORRECT_ATOM_TYPE
);
378 rc
= _lldpctl_do_something(conn
,
379 CONN_STATE_GET_PORT_SEND
, CONN_STATE_GET_PORT_RECV
, iface
->name
,
380 GET_INTERFACE
, (void*)iface
->name
, &MARSHAL_INFO(string
),
381 (void**)&hardware
, &MARSHAL_INFO(lldpd_hardware
));
383 return _lldpctl_new_atom(conn
, atom_port
,
384 hardware
, &hardware
->h_lport
, NULL
);