diff options
Diffstat (limited to '')
-rw-r--r-- | src/lib/atom.h | 344 |
1 files changed, 344 insertions, 0 deletions
diff --git a/src/lib/atom.h b/src/lib/atom.h new file mode 100644 index 0000000..0dfc85b --- /dev/null +++ b/src/lib/atom.h @@ -0,0 +1,344 @@ +/* -*- mode: c; c-file-style: "openbsd" -*- */ +/* + * Copyright (c) 2012 Vincent Bernat <bernat@luffy.cx> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/queue.h> +#include "../lldpd-structs.h" +#include "../compat/compat.h" +#include "../marshal.h" +#include "../ctl.h" + +/* connection.c */ +struct lldpctl_conn_t { + /* the Unix-domain socket to connect to lldpd */ + char *ctlname; + + /* Callback handling */ + lldpctl_recv_callback recv; /* Receive callback */ + lldpctl_send_callback send; /* Send callback */ + void *user_data; /* Callback user data */ + + /* IO state handling. */ + uint8_t *input_buffer; /* Current input/output buffer */ + uint8_t *output_buffer; /* Current input/output buffer */ + size_t input_buffer_len; + size_t output_buffer_len; + +#define CONN_STATE_IDLE 0 +#define CONN_STATE_GET_INTERFACES_SEND 1 +#define CONN_STATE_GET_INTERFACES_RECV 2 +#define CONN_STATE_GET_PORT_SEND 3 +#define CONN_STATE_GET_PORT_RECV 4 +#define CONN_STATE_SET_PORT_SEND 5 +#define CONN_STATE_SET_PORT_RECV 6 +#define CONN_STATE_SET_WATCH_SEND 7 +#define CONN_STATE_SET_WATCH_RECV 8 +#define CONN_STATE_GET_CONFIG_SEND 9 +#define CONN_STATE_GET_CONFIG_RECV 10 +#define CONN_STATE_SET_CONFIG_SEND 11 +#define CONN_STATE_SET_CONFIG_RECV 12 +#define CONN_STATE_GET_CHASSIS_SEND 13 +#define CONN_STATE_GET_CHASSIS_RECV 14 +#define CONN_STATE_GET_DEFAULT_PORT_SEND 15 +#define CONN_STATE_GET_DEFAULT_PORT_RECV 16 +#define CONN_STATE_WATCHING 17 +#define CONN_STATE_SET_CHASSIS_SEND 18 +#define CONN_STATE_SET_CHASSIS_RECV 19 + + int state; /* Current state */ + /* Data attached to the state. It is used to check that we are using the + * same data as a previous call until the state machine goes to + * CONN_STATE_IDLE. */ + char state_data[IFNAMSIZ + 64]; + /* Error handling */ + lldpctl_error_t error; /* Last error */ + + /* Handling notifications */ + lldpctl_change_callback watch_cb; + lldpctl_change_callback2 watch_cb2; + void *watch_data; + int watch_triggered; +}; + +/* User data for synchronous callbacks. */ +struct lldpctl_conn_sync_t { + int fd; /* File descriptor to the socket. */ +}; + +ssize_t _lldpctl_needs(lldpctl_conn_t *lldpctl, size_t length); +int _lldpctl_do_something(lldpctl_conn_t *conn, int state_send, int state_recv, + const char *state_data, enum hmsg_type type, void *to_send, + struct marshal_info *mi_send, void **to_recv, struct marshal_info *mi_recv); + +/* errors.c */ +#define SET_ERROR(conn, x) ((conn)->error = x) +#define RESET_ERROR(conn) SET_ERROR((conn), LLDPCTL_NO_ERROR) + +/* atom.c and atom-private.c */ +typedef enum { + atom_config, + atom_interfaces_list, + atom_interface, + atom_ports_list, + atom_port, + atom_mgmts_list, + atom_mgmt, +#ifdef ENABLE_DOT3 + atom_dot3_power, +#endif +#ifdef ENABLE_DOT1 + atom_vlans_list, + atom_vlan, + atom_ppvids_list, + atom_ppvid, + atom_pis_list, + atom_pi, +#endif +#ifdef ENABLE_LLDPMED + atom_med_policies_list, + atom_med_policy, + atom_med_locations_list, + atom_med_location, + atom_med_caelements_list, + atom_med_caelement, + atom_med_power, +#endif +#ifdef ENABLE_CUSTOM + atom_custom_list, + atom_custom, +#endif + atom_chassis, +} atom_t; + +void *_lldpctl_alloc_in_atom(lldpctl_atom_t *, size_t); +const char *_lldpctl_dump_in_atom(lldpctl_atom_t *, const uint8_t *, size_t, char, + size_t); + +struct atom_buffer { + TAILQ_ENTRY(atom_buffer) next; + u_int8_t data[0]; +}; + +struct lldpctl_atom_t { + int count; + atom_t type; + lldpctl_conn_t *conn; + TAILQ_HEAD(, atom_buffer) buffers; /* List of buffers */ + + /* Destructor */ + void (*free)(lldpctl_atom_t *); + + /* Iterators */ + lldpctl_atom_iter_t *(*iter)(lldpctl_atom_t *); + lldpctl_atom_iter_t *(*next)(lldpctl_atom_t *, lldpctl_atom_iter_t *); + lldpctl_atom_t *(*value)(lldpctl_atom_t *, lldpctl_atom_iter_t *); + + /* Getters */ + lldpctl_atom_t *(*get)(lldpctl_atom_t *, lldpctl_key_t); + const char *(*get_str)(lldpctl_atom_t *, lldpctl_key_t); + const u_int8_t *(*get_buffer)(lldpctl_atom_t *, lldpctl_key_t, size_t *); + long int (*get_int)(lldpctl_atom_t *, lldpctl_key_t); + + /* Setters */ + lldpctl_atom_t *(*set)(lldpctl_atom_t *, lldpctl_key_t, lldpctl_atom_t *); + lldpctl_atom_t *(*set_str)(lldpctl_atom_t *, lldpctl_key_t, const char *); + lldpctl_atom_t *( + *set_buffer)(lldpctl_atom_t *, lldpctl_key_t, const u_int8_t *, size_t); + lldpctl_atom_t *(*set_int)(lldpctl_atom_t *, lldpctl_key_t, long int); + lldpctl_atom_t *(*create)(lldpctl_atom_t *); +}; + +struct _lldpctl_atom_config_t { + lldpctl_atom_t base; + struct lldpd_config *config; +}; + +struct _lldpctl_atom_interfaces_list_t { + lldpctl_atom_t base; + struct lldpd_interface_list *ifs; +}; + +struct _lldpctl_atom_interface_t { + lldpctl_atom_t base; + char *name; +}; + +struct _lldpctl_atom_chassis_t { + lldpctl_atom_t base; + struct lldpd_chassis *chassis; + struct _lldpctl_atom_port_t + *parent; /* Optional: parent of this atom (owning our reference) */ + int embedded; /* This atom is "embedded" (not refcounted) */ +}; + +struct _lldpctl_atom_port_t { + lldpctl_atom_t base; + int local; /* Local or remote port? */ + struct lldpd_hardware *hardware; /* Local port only (but optional) */ + struct lldpd_port *port; /* Local and remote */ + struct _lldpctl_atom_port_t *parent; /* Local port if we are a remote port */ + lldpctl_atom_t *chassis; /* Internal atom for chassis */ +}; + +/* Can represent any simple list holding just a reference to a port. */ +struct _lldpctl_atom_any_list_t { + lldpctl_atom_t base; + struct _lldpctl_atom_port_t *parent; +}; + +struct _lldpctl_atom_mgmts_list_t { + lldpctl_atom_t base; + lldpctl_atom_t *parent; + struct lldpd_chassis *chassis; /* Chassis containing the list of IP addresses */ +}; + +struct _lldpctl_atom_mgmt_t { + lldpctl_atom_t base; + lldpctl_atom_t *parent; + struct lldpd_mgmt *mgmt; +}; + +#ifdef ENABLE_DOT3 +struct _lldpctl_atom_dot3_power_t { + lldpctl_atom_t base; + struct _lldpctl_atom_port_t *parent; +}; +#endif + +#ifdef ENABLE_DOT1 +struct _lldpctl_atom_vlan_t { + lldpctl_atom_t base; + struct _lldpctl_atom_port_t *parent; + struct lldpd_vlan *vlan; +}; + +struct _lldpctl_atom_ppvid_t { + lldpctl_atom_t base; + struct _lldpctl_atom_port_t *parent; + struct lldpd_ppvid *ppvid; +}; + +struct _lldpctl_atom_pi_t { + lldpctl_atom_t base; + struct _lldpctl_atom_port_t *parent; + struct lldpd_pi *pi; +}; +#endif + +#ifdef ENABLE_LLDPMED +struct _lldpctl_atom_med_policy_t { + lldpctl_atom_t base; + struct _lldpctl_atom_port_t *parent; + struct lldpd_med_policy *policy; +}; + +struct _lldpctl_atom_med_location_t { + lldpctl_atom_t base; + struct _lldpctl_atom_port_t *parent; + struct lldpd_med_loc *location; +}; + +/* This list should have the same structure than _llpdctl_atom_any_list_t */ +struct _lldpctl_atom_med_caelements_list_t { + lldpctl_atom_t base; + struct _lldpctl_atom_med_location_t *parent; +}; + +struct _lldpctl_atom_med_caelement_t { + lldpctl_atom_t base; + struct _lldpctl_atom_med_location_t *parent; + int type; + uint8_t *value; + size_t len; +}; + +struct _lldpctl_atom_med_power_t { + lldpctl_atom_t base; + struct _lldpctl_atom_port_t *parent; +}; +#endif + +#ifdef ENABLE_CUSTOM +struct _lldpctl_atom_custom_list_t { + lldpctl_atom_t base; + struct _lldpctl_atom_port_t *parent; + struct lldpd_custom_list *list; +}; + +struct _lldpctl_atom_custom_t { + lldpctl_atom_t base; + struct _lldpctl_atom_port_t *parent; + int op; + struct lldpd_custom *tlv; +}; +#endif + +struct lldpctl_atom_t *_lldpctl_new_atom(lldpctl_conn_t *conn, atom_t type, ...); + +struct atom_map { + int key; + struct atom_map *next; + lldpctl_map_t map[]; +}; + +void atom_map_register(struct atom_map *map, int); +void init_atom_map(void); + +#define ATOM_MAP_REGISTER(NAME, PRIO) \ + void init_atom_map_##NAME(void); \ + void init_atom_map_##NAME(void) \ + { \ + atom_map_register(&NAME, PRIO); \ + } + +struct atom_builder { + atom_t type; /* Atom type */ + size_t size; /* Size of structure to allocate */ + int (*init)(lldpctl_atom_t *, va_list); /* Optional additional init steps */ + void (*free)(lldpctl_atom_t *); /* Optional deallocation steps */ + + lldpctl_atom_iter_t *(*iter)( + lldpctl_atom_t *); /* Optional, return an iterator for this object */ + lldpctl_atom_iter_t *(*next)(lldpctl_atom_t *, + lldpctl_atom_iter_t + *); /* Return the next object for the provided iterator */ + lldpctl_atom_t *(*value)(lldpctl_atom_t *, + lldpctl_atom_iter_t + *); /* Return the current object for the provided iterator */ + + lldpctl_atom_t *(*get)(lldpctl_atom_t *, lldpctl_key_t); + const char *(*get_str)(lldpctl_atom_t *, lldpctl_key_t); + const u_int8_t *(*get_buffer)(lldpctl_atom_t *, lldpctl_key_t, size_t *); + long int (*get_int)(lldpctl_atom_t *, lldpctl_key_t); + + lldpctl_atom_t *(*set)(lldpctl_atom_t *, lldpctl_key_t, lldpctl_atom_t *); + lldpctl_atom_t *(*set_str)(lldpctl_atom_t *, lldpctl_key_t, const char *); + lldpctl_atom_t *( + *set_buffer)(lldpctl_atom_t *, lldpctl_key_t, const u_int8_t *, size_t); + lldpctl_atom_t *(*set_int)(lldpctl_atom_t *, lldpctl_key_t, long int); + lldpctl_atom_t *(*create)(lldpctl_atom_t *); + struct atom_builder *nextb; +}; + +void atom_builder_register(struct atom_builder *builder, int); +void init_atom_builder(void); + +#define ATOM_BUILDER_REGISTER(NAME, PRIO) \ + void init_atom_builder_##NAME(void); \ + void init_atom_builder_##NAME(void) \ + { \ + atom_builder_register(&NAME, PRIO); \ + } |