Coverage Report

Created: 2026-08-28 06:47

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/lldpd/src/lldpd-structs.c
Line
Count
Source
1
/* -*- mode: c; c-file-style: "openbsd" -*- */
2
/*
3
 * Copyright (c) 2008 Vincent Bernat <bernat@luffy.cx>
4
 *
5
 * Permission to use, copy, modify, and/or distribute this software for any
6
 * purpose with or without fee is hereby granted, provided that the above
7
 * copyright notice and this permission notice appear in all copies.
8
 *
9
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
 */
17
18
#include <stdlib.h>
19
#include <unistd.h>
20
#include <time.h>
21
#include "lldpd-structs.h"
22
#include "log.h"
23
24
void
25
lldpd_chassis_mgmt_cleanup(struct lldpd_chassis *chassis)
26
374
{
27
374
  struct lldpd_mgmt *mgmt, *mgmt_next;
28
29
374
  log_debug("alloc", "cleanup management addresses for chassis %s",
30
374
      chassis->c_name ? chassis->c_name : "(unknown)");
31
32
743
  for (mgmt = TAILQ_FIRST(&chassis->c_mgmt); mgmt != NULL; mgmt = mgmt_next) {
33
369
    mgmt_next = TAILQ_NEXT(mgmt, m_entries);
34
369
    free(mgmt);
35
369
  }
36
374
  TAILQ_INIT(&chassis->c_mgmt);
37
374
}
38
39
void
40
lldpd_chassis_cleanup(struct lldpd_chassis *chassis, int all)
41
374
{
42
374
  lldpd_chassis_mgmt_cleanup(chassis);
43
374
  log_debug("alloc", "cleanup chassis %s",
44
374
      chassis->c_name ? chassis->c_name : "(unknown)");
45
374
#ifdef ENABLE_LLDPMED
46
374
  free(chassis->c_med_hw);
47
374
  free(chassis->c_med_sw);
48
374
  free(chassis->c_med_fw);
49
374
  free(chassis->c_med_sn);
50
374
  free(chassis->c_med_manuf);
51
374
  free(chassis->c_med_model);
52
374
  free(chassis->c_med_asset);
53
374
#endif
54
374
  free(chassis->c_id);
55
374
  free(chassis->c_name);
56
374
  free(chassis->c_descr);
57
374
  if (all) free(chassis);
58
374
}
59
60
#ifdef ENABLE_DOT1
61
void
62
lldpd_vlan_cleanup(struct lldpd_port *port)
63
374
{
64
374
  struct lldpd_vlan *vlan, *vlan_next;
65
836
  for (vlan = TAILQ_FIRST(&port->p_vlans); vlan != NULL; vlan = vlan_next) {
66
462
    free(vlan->v_name);
67
462
    vlan_next = TAILQ_NEXT(vlan, v_entries);
68
462
    free(vlan);
69
462
  }
70
374
  TAILQ_INIT(&port->p_vlans);
71
374
  port->p_pvid = 0;
72
374
}
73
74
void
75
lldpd_ppvid_cleanup(struct lldpd_port *port)
76
374
{
77
374
  struct lldpd_ppvid *ppvid, *ppvid_next;
78
374
  for (ppvid = TAILQ_FIRST(&port->p_ppvids); ppvid != NULL; ppvid = ppvid_next) {
79
0
    ppvid_next = TAILQ_NEXT(ppvid, p_entries);
80
0
    free(ppvid);
81
0
  }
82
374
  TAILQ_INIT(&port->p_ppvids);
83
374
}
84
85
void
86
lldpd_pi_cleanup(struct lldpd_port *port)
87
374
{
88
374
  struct lldpd_pi *pi, *pi_next;
89
374
  for (pi = TAILQ_FIRST(&port->p_pids); pi != NULL; pi = pi_next) {
90
0
    free(pi->p_pi);
91
0
    pi_next = TAILQ_NEXT(pi, p_entries);
92
0
    free(pi);
93
0
  }
94
374
  TAILQ_INIT(&port->p_pids);
95
374
}
96
#endif
97
98
#ifdef ENABLE_CUSTOM
99
void
100
lldpd_custom_tlv_add(struct lldpd_port *port, struct lldpd_custom *curr)
101
0
{
102
0
  struct lldpd_custom *custom;
103
104
0
  if (curr->oui_info_len < 0 ||
105
0
      curr->oui_info_len > LLDP_TLV_ORG_OUI_INFO_MAXLEN) {
106
0
    log_warnx("rpc", "invalid custom TLV info length: %d",
107
0
        curr->oui_info_len);
108
0
    return;
109
0
  }
110
0
  if ((custom = malloc(sizeof(struct lldpd_custom)))) {
111
0
    memcpy(custom, curr, sizeof(struct lldpd_custom));
112
0
    if ((custom->oui_info = malloc(custom->oui_info_len))) {
113
0
      memcpy(custom->oui_info, curr->oui_info, custom->oui_info_len);
114
0
      TAILQ_INSERT_TAIL(&port->p_custom_list, custom, next);
115
0
    } else {
116
0
      free(custom);
117
0
      log_warn("rpc",
118
0
          "could not allocate memory for custom TLV info");
119
0
    }
120
0
  }
121
0
}
122
123
void
124
lldpd_custom_tlv_cleanup(struct lldpd_port *port, struct lldpd_custom *curr)
125
0
{
126
0
  struct lldpd_custom *custom, *custom_next;
127
0
  for (custom = TAILQ_FIRST(&port->p_custom_list); custom != NULL;
128
0
       custom = custom_next) {
129
0
    custom_next = TAILQ_NEXT(custom, next);
130
0
    if (!memcmp(curr->oui, custom->oui, sizeof(curr->oui)) &&
131
0
        curr->subtype == custom->subtype) {
132
0
      TAILQ_REMOVE(&port->p_custom_list, custom, next);
133
0
      free(custom->oui_info);
134
0
      free(custom);
135
0
    }
136
0
  }
137
0
}
138
139
void
140
lldpd_custom_list_cleanup(struct lldpd_port *port)
141
374
{
142
374
  struct lldpd_custom *custom, *custom_next;
143
374
  for (custom = TAILQ_FIRST(&port->p_custom_list); custom != NULL;
144
374
       custom = custom_next) {
145
0
    custom_next = TAILQ_NEXT(custom, next);
146
0
    free(custom->oui_info);
147
0
    free(custom);
148
0
  }
149
374
  TAILQ_INIT(&port->p_custom_list);
150
374
}
151
#endif
152
153
/* Cleanup a remote port. The before last argument, `expire` is a function that
154
 * should be called when a remote port is removed. If the last argument is 1,
155
 * all remote ports are removed.
156
 */
157
void
158
lldpd_remote_cleanup(struct lldpd_hardware *hardware,
159
    void (*expire)(struct lldpd_hardware *, struct lldpd_port *), int all)
160
0
{
161
0
  struct lldpd_port *port, *port_next;
162
0
  int del;
163
0
  time_t now = time(NULL);
164
165
0
  log_debug("alloc", "cleanup remote port on %s", hardware->h_ifname);
166
0
  for (port = TAILQ_FIRST(&hardware->h_rports); port != NULL; port = port_next) {
167
0
    port_next = TAILQ_NEXT(port, p_entries);
168
0
    del = all;
169
0
    if (!all && expire && (now >= port->p_lastupdate + port->p_ttl)) {
170
0
      if (port->p_ttl > 0) hardware->h_ageout_cnt++;
171
0
      del = 1;
172
0
    }
173
0
    if (del) {
174
0
      if (expire) expire(hardware, port);
175
      /* This TAILQ_REMOVE is dangerous. It should not be
176
       * called while in liblldpctl because we don't have a
177
       * real list. It is only needed to be called when we
178
       * don't delete the entire list. */
179
0
      if (!all) TAILQ_REMOVE(&hardware->h_rports, port, p_entries);
180
181
0
      hardware->h_delete_cnt++;
182
      /* Register last removal to be able to report
183
       * lldpStatsRemTablesLastChangeTime */
184
0
      hardware->h_lport.p_lastremove = time(NULL);
185
0
      lldpd_port_cleanup(port, 1);
186
0
      free(port);
187
0
    }
188
0
  }
189
0
  if (all) TAILQ_INIT(&hardware->h_rports);
190
0
}
191
192
/* If `all' is true, clear all information, including information that
193
   are not refreshed periodically. Port should be freed manually. */
194
void
195
lldpd_port_cleanup(struct lldpd_port *port, int all)
196
374
{
197
374
#ifdef ENABLE_LLDPMED
198
374
  int i;
199
374
  if (all)
200
1.49k
    for (i = 0; i < LLDP_MED_LOCFORMAT_LAST; i++)
201
1.12k
      free(port->p_med_location[i].data);
202
374
#endif
203
374
#ifdef ENABLE_DOT1
204
374
  lldpd_vlan_cleanup(port);
205
374
  lldpd_ppvid_cleanup(port);
206
374
  lldpd_pi_cleanup(port);
207
374
#endif
208
  /* will set these to NULL so we don't free wrong memory */
209
210
374
  if (all) {
211
374
    free(port->p_id);
212
374
    port->p_id = NULL;
213
374
    free(port->p_descr);
214
374
    port->p_descr = NULL;
215
374
    free(port->p_lastframe);
216
374
    if (port->p_chassis) { /* chassis may not have been attributed, yet */
217
0
      port->p_chassis->c_refcount--;
218
0
      port->p_chassis = NULL;
219
0
    }
220
374
    free(port->p_vlan_advertise_pattern);
221
374
    port->p_vlan_advertise_pattern = NULL;
222
374
#ifdef ENABLE_CUSTOM
223
374
    lldpd_custom_list_cleanup(port);
224
374
#endif
225
374
  }
226
374
}
227
228
void
229
lldpd_config_cleanup(struct lldpd_config *config)
230
0
{
231
0
  log_debug("alloc", "general configuration cleanup");
232
0
  free(config->c_mgmt_pattern);
233
0
  free(config->c_cid_pattern);
234
0
  free(config->c_cid_string);
235
0
  free(config->c_iface_pattern);
236
0
  free(config->c_perm_ifaces);
237
0
  free(config->c_hostname);
238
0
  free(config->c_platform);
239
0
  free(config->c_description);
240
0
}