diff options
Diffstat (limited to 'src/lldpd-structs.c')
-rw-r--r-- | src/lldpd-structs.c | 232 |
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); +} |