summaryrefslogtreecommitdiffstats
path: root/src/lib/atom.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/lib/atom.h344
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); \
+ }