summaryrefslogtreecommitdiffstats
path: root/src/lib/atoms/config.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/atoms/config.c')
-rw-r--r--src/lib/atoms/config.c338
1 files changed, 338 insertions, 0 deletions
diff --git a/src/lib/atoms/config.c b/src/lib/atoms/config.c
new file mode 100644
index 0000000..8a4af2e
--- /dev/null
+++ b/src/lib/atoms/config.c
@@ -0,0 +1,338 @@
+/* -*- mode: c; c-file-style: "openbsd" -*- */
+/*
+ * Copyright (c) 2015 Vincent Bernat <vincent@bernat.im>
+ *
+ * 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 <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <arpa/inet.h>
+
+#include "../lldpctl.h"
+#include "../../log.h"
+#include "../atom.h"
+#include "../helpers.h"
+
+static struct atom_map bond_slave_src_mac_map = {
+ .key = lldpctl_k_config_bond_slave_src_mac_type,
+ .map = {
+ { LLDP_BOND_SLAVE_SRC_MAC_TYPE_REAL, "real"},
+ { LLDP_BOND_SLAVE_SRC_MAC_TYPE_ZERO, "zero"},
+ { LLDP_BOND_SLAVE_SRC_MAC_TYPE_FIXED, "fixed"},
+ { LLDP_BOND_SLAVE_SRC_MAC_TYPE_LOCALLY_ADMINISTERED, "local" },
+ { LLDP_BOND_SLAVE_SRC_MAC_TYPE_UNKNOWN, NULL},
+ },
+};
+
+static struct atom_map lldp_portid_map = {
+ .key = lldpctl_k_config_lldp_portid_type,
+ .map = {
+ { LLDP_PORTID_SUBTYPE_IFNAME, "ifname"},
+ { LLDP_PORTID_SUBTYPE_LLADDR, "macaddress"},
+ { LLDP_PORTID_SUBTYPE_LOCAL, "local"},
+ { LLDP_PORTID_SUBTYPE_UNKNOWN, NULL},
+ },
+};
+
+static struct atom_map lldp_agent_map = {
+ .key = lldpctl_k_config_lldp_agent_type,
+ .map = {
+ { LLDP_AGENT_TYPE_NEAREST_BRIDGE, "nearest bridge"},
+ { LLDP_AGENT_TYPE_NEAREST_NONTPMR_BRIDGE, "nearest non-TPMR bridge"},
+ { LLDP_AGENT_TYPE_NEAREST_CUSTOMER_BRIDGE, "nearest customer bridge"},
+ { LLDP_AGENT_TYPE_UNKNOWN, NULL},
+ },
+};
+
+ATOM_MAP_REGISTER(bond_slave_src_mac_map, 1);
+ATOM_MAP_REGISTER(lldp_portid_map, 2);
+ATOM_MAP_REGISTER(lldp_agent_map, 3);
+
+static int
+_lldpctl_atom_new_config(lldpctl_atom_t *atom, va_list ap)
+{
+ struct _lldpctl_atom_config_t *c = (struct _lldpctl_atom_config_t *)atom;
+ c->config = va_arg(ap, struct lldpd_config *);
+ return 1;
+}
+
+static void
+_lldpctl_atom_free_config(lldpctl_atom_t *atom)
+{
+ struct _lldpctl_atom_config_t *c = (struct _lldpctl_atom_config_t *)atom;
+ lldpd_config_cleanup(c->config);
+ free(c->config);
+}
+
+static const char *
+_lldpctl_atom_get_str_config(lldpctl_atom_t *atom, lldpctl_key_t key)
+{
+ char *res = NULL;
+ struct _lldpctl_atom_config_t *c = (struct _lldpctl_atom_config_t *)atom;
+ switch (key) {
+ case lldpctl_k_config_mgmt_pattern:
+ res = c->config->c_mgmt_pattern;
+ break;
+ case lldpctl_k_config_iface_pattern:
+ res = c->config->c_iface_pattern;
+ break;
+ case lldpctl_k_config_perm_iface_pattern:
+ res = c->config->c_perm_ifaces;
+ break;
+ case lldpctl_k_config_cid_pattern:
+ res = c->config->c_cid_pattern;
+ break;
+ case lldpctl_k_config_cid_string:
+ res = c->config->c_cid_string;
+ break;
+ case lldpctl_k_config_description:
+ res = c->config->c_description;
+ break;
+ case lldpctl_k_config_platform:
+ res = c->config->c_platform;
+ break;
+ case lldpctl_k_config_hostname:
+ res = c->config->c_hostname;
+ break;
+ case lldpctl_k_config_bond_slave_src_mac_type:
+ return map_lookup(bond_slave_src_mac_map.map,
+ c->config->c_bond_slave_src_mac_type);
+ case lldpctl_k_config_lldp_portid_type:
+ return map_lookup(lldp_portid_map.map, c->config->c_lldp_portid_type);
+ case lldpctl_k_config_lldp_agent_type:
+ return map_lookup(lldp_agent_map.map, c->config->c_lldp_agent_type);
+ default:
+ SET_ERROR(atom->conn, LLDPCTL_ERR_NOT_EXIST);
+ return NULL;
+ }
+ return res ? res : "";
+}
+
+static struct _lldpctl_atom_config_t *
+__lldpctl_atom_set_str_config(struct _lldpctl_atom_config_t *c, char **local,
+ char **global, const char *value)
+{
+ if (value) {
+ char *aval = NULL;
+ size_t len = strlen(value) + 1;
+ aval = _lldpctl_alloc_in_atom((lldpctl_atom_t *)c, len);
+ if (!aval) return NULL;
+ memcpy(aval, value, len);
+ *local = aval;
+ free(*global);
+ *global = strdup(aval);
+ } else {
+ free(*global);
+ *local = *global = NULL;
+ }
+ return c;
+}
+
+static lldpctl_atom_t *
+_lldpctl_atom_set_str_config(lldpctl_atom_t *atom, lldpctl_key_t key, const char *value)
+{
+ struct _lldpctl_atom_config_t *c = (struct _lldpctl_atom_config_t *)atom;
+ struct lldpd_config config;
+ memcpy(&config, c->config, sizeof(struct lldpd_config));
+ char *canary = NULL;
+ int rc;
+
+ switch (key) {
+ case lldpctl_k_config_perm_iface_pattern:
+ if (!__lldpctl_atom_set_str_config(c, &config.c_perm_ifaces,
+ &c->config->c_perm_ifaces, value))
+ return NULL;
+ break;
+ case lldpctl_k_config_iface_pattern:
+ if (!__lldpctl_atom_set_str_config(c, &config.c_iface_pattern,
+ &c->config->c_iface_pattern, value))
+ return NULL;
+ break;
+ case lldpctl_k_config_mgmt_pattern:
+ if (!__lldpctl_atom_set_str_config(c, &config.c_mgmt_pattern,
+ &c->config->c_mgmt_pattern, value))
+ return NULL;
+ break;
+ case lldpctl_k_config_cid_string:
+ if (!__lldpctl_atom_set_str_config(c, &config.c_cid_string,
+ &c->config->c_cid_string, value))
+ return NULL;
+ break;
+ case lldpctl_k_config_description:
+ if (!__lldpctl_atom_set_str_config(c, &config.c_description,
+ &c->config->c_description, value))
+ return NULL;
+ break;
+ case lldpctl_k_config_platform:
+ if (!__lldpctl_atom_set_str_config(c, &config.c_platform,
+ &c->config->c_platform, value))
+ return NULL;
+ break;
+ case lldpctl_k_config_hostname:
+ if (!__lldpctl_atom_set_str_config(c, &config.c_hostname,
+ &c->config->c_hostname, value))
+ return NULL;
+ break;
+ default:
+ SET_ERROR(atom->conn, LLDPCTL_ERR_NOT_EXIST);
+ return NULL;
+ }
+
+ if (asprintf(&canary, "%d%s", key, value ? value : "(NULL)") == -1) {
+ SET_ERROR(atom->conn, LLDPCTL_ERR_NOMEM);
+ return NULL;
+ }
+ rc = _lldpctl_do_something(atom->conn, CONN_STATE_SET_CONFIG_SEND,
+ CONN_STATE_SET_CONFIG_RECV, canary, SET_CONFIG, &config,
+ &MARSHAL_INFO(lldpd_config), NULL, NULL);
+ free(canary);
+ if (rc == 0) return atom;
+
+#undef SET_STR
+
+ return NULL;
+}
+
+static long int
+_lldpctl_atom_get_int_config(lldpctl_atom_t *atom, lldpctl_key_t key)
+{
+ struct _lldpctl_atom_config_t *c = (struct _lldpctl_atom_config_t *)atom;
+ switch (key) {
+ case lldpctl_k_config_paused:
+ return c->config->c_paused;
+ case lldpctl_k_config_tx_interval:
+ return (c->config->c_tx_interval + 999) / 1000; /* s units */
+ case lldpctl_k_config_tx_interval_ms:
+ return c->config->c_tx_interval; /* ms units */
+ case lldpctl_k_config_receiveonly:
+ return c->config->c_receiveonly;
+ case lldpctl_k_config_advertise_version:
+ return c->config->c_advertise_version;
+ case lldpctl_k_config_ifdescr_update:
+ return c->config->c_set_ifdescr;
+ case lldpctl_k_config_iface_promisc:
+ return c->config->c_promisc;
+ case lldpctl_k_config_chassis_cap_advertise:
+ return c->config->c_cap_advertise;
+ case lldpctl_k_config_chassis_cap_override:
+ return c->config->c_cap_override;
+ case lldpctl_k_config_chassis_mgmt_advertise:
+ return c->config->c_mgmt_advertise;
+#ifdef ENABLE_LLDPMED
+ case lldpctl_k_config_lldpmed_noinventory:
+ return c->config->c_noinventory;
+ case lldpctl_k_config_fast_start_enabled:
+ return c->config->c_enable_fast_start;
+ case lldpctl_k_config_fast_start_interval:
+ return c->config->c_tx_fast_interval;
+#endif
+ case lldpctl_k_config_tx_hold:
+ return c->config->c_tx_hold;
+ case lldpctl_k_config_max_neighbors:
+ return c->config->c_max_neighbors;
+ default:
+ return SET_ERROR(atom->conn, LLDPCTL_ERR_NOT_EXIST);
+ }
+}
+
+static lldpctl_atom_t *
+_lldpctl_atom_set_int_config(lldpctl_atom_t *atom, lldpctl_key_t key, long int value)
+{
+ int rc;
+ char *canary = NULL;
+ struct _lldpctl_atom_config_t *c = (struct _lldpctl_atom_config_t *)atom;
+ struct lldpd_config config;
+ memcpy(&config, c->config, sizeof(struct lldpd_config));
+
+ switch (key) {
+ case lldpctl_k_config_paused:
+ config.c_paused = c->config->c_paused = value;
+ break;
+ case lldpctl_k_config_tx_interval:
+ config.c_tx_interval = value * 1000;
+ if (value > 0) c->config->c_tx_interval = value * 1000;
+ break;
+ case lldpctl_k_config_tx_interval_ms:
+ config.c_tx_interval = value;
+ if (value > 0) c->config->c_tx_interval = value;
+ break;
+ case lldpctl_k_config_ifdescr_update:
+ config.c_set_ifdescr = c->config->c_set_ifdescr = value;
+ break;
+ case lldpctl_k_config_iface_promisc:
+ config.c_promisc = c->config->c_promisc = value;
+ break;
+ case lldpctl_k_config_chassis_cap_advertise:
+ config.c_cap_advertise = c->config->c_cap_advertise = value;
+ break;
+ case lldpctl_k_config_chassis_cap_override:
+ config.c_cap_override = c->config->c_cap_override = value;
+ break;
+ case lldpctl_k_config_chassis_mgmt_advertise:
+ config.c_mgmt_advertise = c->config->c_mgmt_advertise = value;
+ break;
+#ifdef ENABLE_LLDPMED
+ case lldpctl_k_config_fast_start_enabled:
+ config.c_enable_fast_start = c->config->c_enable_fast_start = value;
+ break;
+ case lldpctl_k_config_fast_start_interval:
+ config.c_tx_fast_interval = c->config->c_tx_fast_interval = value;
+ break;
+#endif
+ case lldpctl_k_config_tx_hold:
+ config.c_tx_hold = value;
+ if (value > 0) c->config->c_tx_hold = value;
+ break;
+ case lldpctl_k_config_max_neighbors:
+ config.c_max_neighbors = value;
+ if (value > 0) c->config->c_max_neighbors = value;
+ break;
+ case lldpctl_k_config_bond_slave_src_mac_type:
+ config.c_bond_slave_src_mac_type = value;
+ c->config->c_bond_slave_src_mac_type = value;
+ break;
+ case lldpctl_k_config_lldp_portid_type:
+ config.c_lldp_portid_type = value;
+ c->config->c_lldp_portid_type = value;
+ break;
+ case lldpctl_k_config_lldp_agent_type:
+ config.c_lldp_agent_type = value;
+ c->config->c_lldp_agent_type = value;
+ break;
+ default:
+ SET_ERROR(atom->conn, LLDPCTL_ERR_NOT_EXIST);
+ return NULL;
+ }
+
+ if (asprintf(&canary, "%d%ld", key, value) == -1) {
+ SET_ERROR(atom->conn, LLDPCTL_ERR_NOMEM);
+ return NULL;
+ }
+ rc = _lldpctl_do_something(atom->conn, CONN_STATE_SET_CONFIG_SEND,
+ CONN_STATE_SET_CONFIG_RECV, canary, SET_CONFIG, &config,
+ &MARSHAL_INFO(lldpd_config), NULL, NULL);
+ free(canary);
+ if (rc == 0) return atom;
+ return NULL;
+}
+
+static struct atom_builder config = { atom_config,
+ sizeof(struct _lldpctl_atom_config_t), .init = _lldpctl_atom_new_config,
+ .free = _lldpctl_atom_free_config, .get_str = _lldpctl_atom_get_str_config,
+ .set_str = _lldpctl_atom_set_str_config,
+ .get_int = _lldpctl_atom_get_int_config,
+ .set_int = _lldpctl_atom_set_int_config };
+
+ATOM_BUILDER_REGISTER(config, 1);