summaryrefslogtreecommitdiffstats
path: root/src/lldpd-structs.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lldpd-structs.c')
-rw-r--r--src/lldpd-structs.c232
1 files changed, 232 insertions, 0 deletions
diff --git a/src/lldpd-structs.c b/src/lldpd-structs.c
new file mode 100644
index 0000000..6b42713
--- /dev/null
+++ b/src/lldpd-structs.c
@@ -0,0 +1,232 @@
+/* -*- mode: c; c-file-style: "openbsd" -*- */
+/*
+ * Copyright (c) 2008 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 <stdlib.h>
+#include <unistd.h>
+#include <time.h>
+#include "lldpd-structs.h"
+#include "log.h"
+
+void
+lldpd_chassis_mgmt_cleanup(struct lldpd_chassis *chassis)
+{
+ struct lldpd_mgmt *mgmt, *mgmt_next;
+
+ log_debug("alloc", "cleanup management addresses for chassis %s",
+ chassis->c_name ? chassis->c_name : "(unknown)");
+
+ for (mgmt = TAILQ_FIRST(&chassis->c_mgmt); mgmt != NULL; mgmt = mgmt_next) {
+ mgmt_next = TAILQ_NEXT(mgmt, m_entries);
+ free(mgmt);
+ }
+ TAILQ_INIT(&chassis->c_mgmt);
+}
+
+void
+lldpd_chassis_cleanup(struct lldpd_chassis *chassis, int all)
+{
+ lldpd_chassis_mgmt_cleanup(chassis);
+ log_debug("alloc", "cleanup chassis %s",
+ chassis->c_name ? chassis->c_name : "(unknown)");
+#ifdef ENABLE_LLDPMED
+ free(chassis->c_med_hw);
+ free(chassis->c_med_sw);
+ free(chassis->c_med_fw);
+ free(chassis->c_med_sn);
+ free(chassis->c_med_manuf);
+ free(chassis->c_med_model);
+ free(chassis->c_med_asset);
+#endif
+ free(chassis->c_id);
+ free(chassis->c_name);
+ free(chassis->c_descr);
+ if (all) free(chassis);
+}
+
+#ifdef ENABLE_DOT1
+void
+lldpd_vlan_cleanup(struct lldpd_port *port)
+{
+ struct lldpd_vlan *vlan, *vlan_next;
+ for (vlan = TAILQ_FIRST(&port->p_vlans); vlan != NULL; vlan = vlan_next) {
+ free(vlan->v_name);
+ vlan_next = TAILQ_NEXT(vlan, v_entries);
+ free(vlan);
+ }
+ TAILQ_INIT(&port->p_vlans);
+ port->p_pvid = 0;
+}
+
+void
+lldpd_ppvid_cleanup(struct lldpd_port *port)
+{
+ struct lldpd_ppvid *ppvid, *ppvid_next;
+ for (ppvid = TAILQ_FIRST(&port->p_ppvids); ppvid != NULL; ppvid = ppvid_next) {
+ ppvid_next = TAILQ_NEXT(ppvid, p_entries);
+ free(ppvid);
+ }
+ TAILQ_INIT(&port->p_ppvids);
+}
+
+void
+lldpd_pi_cleanup(struct lldpd_port *port)
+{
+ struct lldpd_pi *pi, *pi_next;
+ for (pi = TAILQ_FIRST(&port->p_pids); pi != NULL; pi = pi_next) {
+ free(pi->p_pi);
+ pi_next = TAILQ_NEXT(pi, p_entries);
+ free(pi);
+ }
+ TAILQ_INIT(&port->p_pids);
+}
+#endif
+
+#ifdef ENABLE_CUSTOM
+void
+lldpd_custom_tlv_add(struct lldpd_port *port, struct lldpd_custom *curr)
+{
+ struct lldpd_custom *custom;
+
+ if ((custom = malloc(sizeof(struct lldpd_custom)))) {
+ memcpy(custom, curr, sizeof(struct lldpd_custom));
+ if ((custom->oui_info = malloc(custom->oui_info_len))) {
+ memcpy(custom->oui_info, curr->oui_info, custom->oui_info_len);
+ TAILQ_INSERT_TAIL(&port->p_custom_list, custom, next);
+ } else {
+ free(custom);
+ log_warn("rpc",
+ "could not allocate memory for custom TLV info");
+ }
+ }
+}
+
+void
+lldpd_custom_tlv_cleanup(struct lldpd_port *port, struct lldpd_custom *curr)
+{
+ struct lldpd_custom *custom, *custom_next;
+ for (custom = TAILQ_FIRST(&port->p_custom_list); custom != NULL;
+ custom = custom_next) {
+ custom_next = TAILQ_NEXT(custom, next);
+ if (!memcmp(curr->oui, custom->oui, sizeof(curr->oui)) &&
+ curr->subtype == custom->subtype) {
+ TAILQ_REMOVE(&port->p_custom_list, custom, next);
+ free(custom->oui_info);
+ free(custom);
+ }
+ }
+}
+
+void
+lldpd_custom_list_cleanup(struct lldpd_port *port)
+{
+ struct lldpd_custom *custom, *custom_next;
+ for (custom = TAILQ_FIRST(&port->p_custom_list); custom != NULL;
+ custom = custom_next) {
+ custom_next = TAILQ_NEXT(custom, next);
+ free(custom->oui_info);
+ free(custom);
+ }
+ TAILQ_INIT(&port->p_custom_list);
+}
+#endif
+
+/* Cleanup a remote port. The before last argument, `expire` is a function that
+ * should be called when a remote port is removed. If the last argument is 1,
+ * all remote ports are removed.
+ */
+void
+lldpd_remote_cleanup(struct lldpd_hardware *hardware,
+ void (*expire)(struct lldpd_hardware *, struct lldpd_port *), int all)
+{
+ struct lldpd_port *port, *port_next;
+ int del;
+ time_t now = time(NULL);
+
+ log_debug("alloc", "cleanup remote port on %s", hardware->h_ifname);
+ for (port = TAILQ_FIRST(&hardware->h_rports); port != NULL; port = port_next) {
+ port_next = TAILQ_NEXT(port, p_entries);
+ del = all;
+ if (!all && expire && (now >= port->p_lastupdate + port->p_ttl)) {
+ if (port->p_ttl > 0) hardware->h_ageout_cnt++;
+ del = 1;
+ }
+ if (del) {
+ if (expire) expire(hardware, port);
+ /* This TAILQ_REMOVE is dangerous. It should not be
+ * called while in liblldpctl because we don't have a
+ * real list. It is only needed to be called when we
+ * don't delete the entire list. */
+ if (!all) TAILQ_REMOVE(&hardware->h_rports, port, p_entries);
+
+ hardware->h_delete_cnt++;
+ /* Register last removal to be able to report
+ * lldpStatsRemTablesLastChangeTime */
+ hardware->h_lport.p_lastremove = time(NULL);
+ lldpd_port_cleanup(port, 1);
+ free(port);
+ }
+ }
+ if (all) TAILQ_INIT(&hardware->h_rports);
+}
+
+/* If `all' is true, clear all information, including information that
+ are not refreshed periodically. Port should be freed manually. */
+void
+lldpd_port_cleanup(struct lldpd_port *port, int all)
+{
+#ifdef ENABLE_LLDPMED
+ int i;
+ if (all)
+ for (i = 0; i < LLDP_MED_LOCFORMAT_LAST; i++)
+ free(port->p_med_location[i].data);
+#endif
+#ifdef ENABLE_DOT1
+ lldpd_vlan_cleanup(port);
+ lldpd_ppvid_cleanup(port);
+ lldpd_pi_cleanup(port);
+#endif
+ /* will set these to NULL so we don't free wrong memory */
+
+ if (all) {
+ free(port->p_id);
+ port->p_id = NULL;
+ free(port->p_descr);
+ port->p_descr = NULL;
+ free(port->p_lastframe);
+ if (port->p_chassis) { /* chassis may not have been attributed, yet */
+ port->p_chassis->c_refcount--;
+ port->p_chassis = NULL;
+ }
+#ifdef ENABLE_CUSTOM
+ lldpd_custom_list_cleanup(port);
+#endif
+ }
+}
+
+void
+lldpd_config_cleanup(struct lldpd_config *config)
+{
+ log_debug("alloc", "general configuration cleanup");
+ free(config->c_mgmt_pattern);
+ free(config->c_cid_pattern);
+ free(config->c_cid_string);
+ free(config->c_iface_pattern);
+ free(config->c_perm_ifaces);
+ free(config->c_hostname);
+ free(config->c_platform);
+ free(config->c_description);
+}