Bug Summary

File:build-scan/../src/libsystemd-network/sd-lldp.c
Warning:line 380, column 25
Potential leak of memory pointed to by 'lldp'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name sd-lldp.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -menable-no-infs -menable-no-nans -menable-unsafe-fp-math -fno-signed-zeros -mreassociate -freciprocal-math -fdenormal-fp-math=preserve-sign,preserve-sign -ffp-contract=fast -fno-rounding-math -ffast-math -ffinite-math-only -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/12.0.0 -include config.h -I src/libsystemd-network/libsystemd-network.a.p -I src/libsystemd-network -I ../src/libsystemd-network -I src/basic -I ../src/basic -I src/shared -I ../src/shared -I src/systemd -I ../src/systemd -I src/journal -I ../src/journal -I src/journal-remote -I ../src/journal-remote -I src/nspawn -I ../src/nspawn -I src/resolve -I ../src/resolve -I src/timesync -I ../src/timesync -I ../src/time-wait-sync -I src/login -I ../src/login -I src/udev -I ../src/udev -I src/libudev -I ../src/libudev -I src/core -I ../src/core -I ../src/libsystemd/sd-bus -I ../src/libsystemd/sd-device -I ../src/libsystemd/sd-hwdb -I ../src/libsystemd/sd-id128 -I ../src/libsystemd/sd-netlink -I ../src/libsystemd/sd-network -I . -I .. -D _FILE_OFFSET_BITS=64 -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/12.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wwrite-strings -Wno-unused-parameter -Wno-missing-field-initializers -Wno-unused-result -Wno-format-signedness -Wno-error=nonnull -std=gnu99 -fconst-strings -fdebug-compilation-dir /home/mrc0mmand/repos/@redhat-plumbers/systemd-rhel8/build-scan -ferror-limit 19 -fvisibility hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcolor-diagnostics -analyzer-output=html -faddrsig -o /tmp/scan-build-2021-07-16-221226-1465241-1 -x c ../src/libsystemd-network/sd-lldp.c
1/* SPDX-License-Identifier: LGPL-2.1+ */
2
3#include <arpa/inet.h>
4#include <linux1/sockios.h>
5
6#include "sd-lldp.h"
7
8#include "alloc-util.h"
9#include "fd-util.h"
10#include "lldp-internal.h"
11#include "lldp-neighbor.h"
12#include "lldp-network.h"
13#include "socket-util.h"
14#include "ether-addr-util.h"
15
16#define LLDP_DEFAULT_NEIGHBORS_MAX128U 128U
17
18static void lldp_flush_neighbors(sd_lldp *lldp) {
19 sd_lldp_neighbor *n;
20
21 assert(lldp)do { if ((__builtin_expect(!!(!(lldp)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("lldp"), "../src/libsystemd-network/sd-lldp.c"
, 21, __PRETTY_FUNCTION__); } while (0)
;
22
23 while ((n = hashmap_first(lldp->neighbor_by_id)))
24 lldp_neighbor_unlink(n);
25}
26
27static void lldp_callback(sd_lldp *lldp, sd_lldp_event event, sd_lldp_neighbor *n) {
28 assert(lldp)do { if ((__builtin_expect(!!(!(lldp)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("lldp"), "../src/libsystemd-network/sd-lldp.c"
, 28, __PRETTY_FUNCTION__); } while (0)
;
29
30 log_lldp("Invoking callback for '%c'.", event)log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((7))),
0, "../src/libsystemd-network/sd-lldp.c", 30, __func__, "LLDP: "
"Invoking callback for '%c'.", event)
;
31
32 if (!lldp->callback)
33 return;
34
35 lldp->callback(lldp, event, n, lldp->userdata);
36}
37
38static int lldp_make_space(sd_lldp *lldp, size_t extra) {
39 usec_t t = USEC_INFINITY((usec_t) -1);
40 bool_Bool changed = false0;
41
42 assert(lldp)do { if ((__builtin_expect(!!(!(lldp)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("lldp"), "../src/libsystemd-network/sd-lldp.c"
, 42, __PRETTY_FUNCTION__); } while (0)
;
43
44 /* Remove all entries that are past their TTL, and more until at least the specified number of extra entries
45 * are free. */
46
47 for (;;) {
48 _cleanup_(sd_lldp_neighbor_unrefp)__attribute__((cleanup(sd_lldp_neighbor_unrefp))) sd_lldp_neighbor *n = NULL((void*)0);
49
50 n = prioq_peek(lldp->neighbor_by_expiry);
51 if (!n)
52 break;
53
54 sd_lldp_neighbor_ref(n);
55
56 if (hashmap_size(lldp->neighbor_by_id) > LESS_BY(lldp->neighbors_max, extra)__extension__ ({ const typeof((lldp->neighbors_max)) __unique_prefix_A2
= ((lldp->neighbors_max)); const typeof((extra)) __unique_prefix_B3
= ((extra)); __unique_prefix_A2 > __unique_prefix_B3 ? __unique_prefix_A2
- __unique_prefix_B3 : 0; })
)
57 goto remove_one;
58
59 if (t == USEC_INFINITY((usec_t) -1))
60 t = now(clock_boottime_or_monotonic());
61
62 if (n->until > t)
63 break;
64
65 remove_one:
66 lldp_neighbor_unlink(n);
67 lldp_callback(lldp, SD_LLDP_EVENT_REMOVED, n);
68 changed = true1;
69 }
70
71 return changed;
72}
73
74static bool_Bool lldp_keep_neighbor(sd_lldp *lldp, sd_lldp_neighbor *n) {
75 assert(lldp)do { if ((__builtin_expect(!!(!(lldp)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("lldp"), "../src/libsystemd-network/sd-lldp.c"
, 75, __PRETTY_FUNCTION__); } while (0)
;
76 assert(n)do { if ((__builtin_expect(!!(!(n)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("n"), "../src/libsystemd-network/sd-lldp.c"
, 76, __PRETTY_FUNCTION__); } while (0)
;
77
78 /* Don't keep data with a zero TTL */
79 if (n->ttl <= 0)
80 return false0;
81
82 /* Filter out data from the filter address */
83 if (!ether_addr_is_null(&lldp->filter_address) &&
84 ether_addr_equal(&lldp->filter_address, &n->source_address))
85 return false0;
86
87 /* Only add if the neighbor has a capability we are interested in. Note that we also store all neighbors with
88 * no caps field set. */
89 if (n->has_capabilities &&
90 (n->enabled_capabilities & lldp->capability_mask) == 0)
91 return false0;
92
93 /* Keep everything else */
94 return true1;
95}
96
97static int lldp_start_timer(sd_lldp *lldp, sd_lldp_neighbor *neighbor);
98
99static int lldp_add_neighbor(sd_lldp *lldp, sd_lldp_neighbor *n) {
100 _cleanup_(sd_lldp_neighbor_unrefp)__attribute__((cleanup(sd_lldp_neighbor_unrefp))) sd_lldp_neighbor *old = NULL((void*)0);
101 bool_Bool keep;
102 int r;
103
104 assert(lldp)do { if ((__builtin_expect(!!(!(lldp)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("lldp"), "../src/libsystemd-network/sd-lldp.c"
, 104, __PRETTY_FUNCTION__); } while (0)
;
105 assert(n)do { if ((__builtin_expect(!!(!(n)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("n"), "../src/libsystemd-network/sd-lldp.c"
, 105, __PRETTY_FUNCTION__); } while (0)
;
106 assert(!n->lldp)do { if ((__builtin_expect(!!(!(!n->lldp)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("!n->lldp"), "../src/libsystemd-network/sd-lldp.c"
, 106, __PRETTY_FUNCTION__); } while (0)
;
107
108 keep = lldp_keep_neighbor(lldp, n);
109
110 /* First retrieve the old entry for this MSAP */
111 old = hashmap_get(lldp->neighbor_by_id, &n->id);
112 if (old) {
113 sd_lldp_neighbor_ref(old);
114
115 if (!keep) {
116 lldp_neighbor_unlink(old);
117 lldp_callback(lldp, SD_LLDP_EVENT_REMOVED, old);
118 return 0;
119 }
120
121 if (lldp_neighbor_equal(n, old)) {
122 /* Is this equal, then restart the TTL counter, but don't do anyting else. */
123 old->timestamp = n->timestamp;
124 lldp_start_timer(lldp, old);
125 lldp_callback(lldp, SD_LLDP_EVENT_REFRESHED, old);
126 return 0;
127 }
128
129 /* Data changed, remove the old entry, and add a new one */
130 lldp_neighbor_unlink(old);
131
132 } else if (!keep)
133 return 0;
134
135 /* Then, make room for at least one new neighbor */
136 lldp_make_space(lldp, 1);
137
138 r = hashmap_put(lldp->neighbor_by_id, &n->id, n);
139 if (r < 0)
140 goto finish;
141
142 r = prioq_put(lldp->neighbor_by_expiry, n, &n->prioq_idx);
143 if (r < 0) {
144 assert_se(hashmap_remove(lldp->neighbor_by_id, &n->id) == n)do { if ((__builtin_expect(!!(!(hashmap_remove(lldp->neighbor_by_id
, &n->id) == n)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD
, ("hashmap_remove(lldp->neighbor_by_id, &n->id) == n"
), "../src/libsystemd-network/sd-lldp.c", 144, __PRETTY_FUNCTION__
); } while (0)
;
145 goto finish;
146 }
147
148 n->lldp = lldp;
149
150 lldp_start_timer(lldp, n);
151 lldp_callback(lldp, old ? SD_LLDP_EVENT_UPDATED : SD_LLDP_EVENT_ADDED, n);
152
153 return 1;
154
155finish:
156 if (old)
157 lldp_callback(lldp, SD_LLDP_EVENT_REMOVED, old);
158
159 return r;
160}
161
162static int lldp_handle_datagram(sd_lldp *lldp, sd_lldp_neighbor *n) {
163 int r;
164
165 assert(lldp)do { if ((__builtin_expect(!!(!(lldp)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("lldp"), "../src/libsystemd-network/sd-lldp.c"
, 165, __PRETTY_FUNCTION__); } while (0)
;
166 assert(n)do { if ((__builtin_expect(!!(!(n)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("n"), "../src/libsystemd-network/sd-lldp.c"
, 166, __PRETTY_FUNCTION__); } while (0)
;
167
168 r = lldp_neighbor_parse(n);
169 if (r == -EBADMSG74) /* Ignore bad messages */
170 return 0;
171 if (r < 0)
172 return r;
173
174 r = lldp_add_neighbor(lldp, n);
175 if (r < 0) {
176 log_lldp_errno(r, "Failed to add datagram. Ignoring.")log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((7))),
r, "../src/libsystemd-network/sd-lldp.c", 176, __func__, "LLDP: "
"Failed to add datagram. Ignoring.")
;
177 return 0;
178 }
179
180 log_lldp("Successfully processed LLDP datagram.")log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((7))),
0, "../src/libsystemd-network/sd-lldp.c", 180, __func__, "LLDP: "
"Successfully processed LLDP datagram.")
;
181 return 0;
182}
183
184static int lldp_receive_datagram(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
185 _cleanup_(sd_lldp_neighbor_unrefp)__attribute__((cleanup(sd_lldp_neighbor_unrefp))) sd_lldp_neighbor *n = NULL((void*)0);
186 ssize_t space, length;
187 sd_lldp *lldp = userdata;
188 struct timespec ts;
189
190 assert(fd >= 0)do { if ((__builtin_expect(!!(!(fd >= 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("fd >= 0"), "../src/libsystemd-network/sd-lldp.c"
, 190, __PRETTY_FUNCTION__); } while (0)
;
191 assert(lldp)do { if ((__builtin_expect(!!(!(lldp)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("lldp"), "../src/libsystemd-network/sd-lldp.c"
, 191, __PRETTY_FUNCTION__); } while (0)
;
192
193 space = next_datagram_size_fd(fd);
194 if (space < 0)
195 return log_lldp_errno(space, "Failed to determine datagram size to read: %m")log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((7))),
space, "../src/libsystemd-network/sd-lldp.c", 195, __func__,
"LLDP: " "Failed to determine datagram size to read: %m")
;
196
197 n = lldp_neighbor_new(space);
198 if (!n)
199 return -ENOMEM12;
200
201 length = recv(fd, LLDP_NEIGHBOR_RAW(n), n->raw_size, MSG_DONTWAITMSG_DONTWAIT);
202 if (length < 0) {
203 if (IN_SET(errno, EAGAIN, EINTR)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){11, 4})/sizeof(int)]; switch((*__errno_location
())) { case 11: case 4: _found = 1; break; default: break; }
_found; })
)
204 return 0;
205
206 return log_lldp_errno(errno, "Failed to read LLDP datagram: %m")log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((7))),
(*__errno_location ()), "../src/libsystemd-network/sd-lldp.c"
, 206, __func__, "LLDP: " "Failed to read LLDP datagram: %m")
;
207 }
208
209 if ((size_t) length != n->raw_size) {
210 log_lldp("Packet size mismatch.")log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((7))),
0, "../src/libsystemd-network/sd-lldp.c", 210, __func__, "LLDP: "
"Packet size mismatch.")
;
211 return -EINVAL22;
212 }
213
214 /* Try to get the timestamp of this packet if it is known */
215 if (ioctl(fd, SIOCGSTAMPNS0x8907, &ts) >= 0)
216 triple_timestamp_from_realtime(&n->timestamp, timespec_load(&ts));
217 else
218 triple_timestamp_get(&n->timestamp);
219
220 return lldp_handle_datagram(lldp, n);
221}
222
223static void lldp_reset(sd_lldp *lldp) {
224 assert(lldp)do { if ((__builtin_expect(!!(!(lldp)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("lldp"), "../src/libsystemd-network/sd-lldp.c"
, 224, __PRETTY_FUNCTION__); } while (0)
;
225
226 lldp->timer_event_source = sd_event_source_unref(lldp->timer_event_source);
227 lldp->io_event_source = sd_event_source_unref(lldp->io_event_source);
228 lldp->fd = safe_close(lldp->fd);
229}
230
231_public___attribute__ ((visibility("default"))) int sd_lldp_start(sd_lldp *lldp) {
232 int r;
233
234 assert_return(lldp, -EINVAL)do { if (!(((__builtin_expect(!!(lldp),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("lldp"), "../src/libsystemd-network/sd-lldp.c"
, 234, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
235 assert_return(lldp->event, -EINVAL)do { if (!(((__builtin_expect(!!(lldp->event),1))) ? (1) :
(log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("lldp->event"
), "../src/libsystemd-network/sd-lldp.c", 235, __PRETTY_FUNCTION__
), 0))) return (-22); } while (0)
;
236 assert_return(lldp->ifindex > 0, -EINVAL)do { if (!(((__builtin_expect(!!(lldp->ifindex > 0),1))
) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, (
"lldp->ifindex > 0"), "../src/libsystemd-network/sd-lldp.c"
, 236, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
237
238 if (lldp->fd >= 0)
239 return 0;
240
241 assert(!lldp->io_event_source)do { if ((__builtin_expect(!!(!(!lldp->io_event_source)),0
))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("!lldp->io_event_source"
), "../src/libsystemd-network/sd-lldp.c", 241, __PRETTY_FUNCTION__
); } while (0)
;
242
243 lldp->fd = lldp_network_bind_raw_socket(lldp->ifindex);
244 if (lldp->fd < 0)
245 return lldp->fd;
246
247 r = sd_event_add_io(lldp->event, &lldp->io_event_source, lldp->fd, EPOLLINEPOLLIN, lldp_receive_datagram, lldp);
248 if (r < 0)
249 goto fail;
250
251 r = sd_event_source_set_priority(lldp->io_event_source, lldp->event_priority);
252 if (r < 0)
253 goto fail;
254
255 (void) sd_event_source_set_description(lldp->io_event_source, "lldp-io");
256
257 log_lldp("Started LLDP client")log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((7))),
0, "../src/libsystemd-network/sd-lldp.c", 257, __func__, "LLDP: "
"Started LLDP client")
;
258 return 1;
259
260fail:
261 lldp_reset(lldp);
262 return r;
263}
264
265_public___attribute__ ((visibility("default"))) int sd_lldp_stop(sd_lldp *lldp) {
266 assert_return(lldp, -EINVAL)do { if (!(((__builtin_expect(!!(lldp),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("lldp"), "../src/libsystemd-network/sd-lldp.c"
, 266, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
267
268 if (lldp->fd < 0)
269 return 0;
270
271 log_lldp("Stopping LLDP client")log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((7))),
0, "../src/libsystemd-network/sd-lldp.c", 271, __func__, "LLDP: "
"Stopping LLDP client")
;
272
273 lldp_reset(lldp);
274 lldp_flush_neighbors(lldp);
275
276 return 1;
277}
278
279_public___attribute__ ((visibility("default"))) int sd_lldp_attach_event(sd_lldp *lldp, sd_event *event, int64_t priority) {
280 int r;
281
282 assert_return(lldp, -EINVAL)do { if (!(((__builtin_expect(!!(lldp),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("lldp"), "../src/libsystemd-network/sd-lldp.c"
, 282, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
283 assert_return(lldp->fd < 0, -EBUSY)do { if (!(((__builtin_expect(!!(lldp->fd < 0),1))) ? (
1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("lldp->fd < 0"
), "../src/libsystemd-network/sd-lldp.c", 283, __PRETTY_FUNCTION__
), 0))) return (-16); } while (0)
;
284 assert_return(!lldp->event, -EBUSY)do { if (!(((__builtin_expect(!!(!lldp->event),1))) ? (1) :
(log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("!lldp->event"
), "../src/libsystemd-network/sd-lldp.c", 284, __PRETTY_FUNCTION__
), 0))) return (-16); } while (0)
;
285
286 if (event)
287 lldp->event = sd_event_ref(event);
288 else {
289 r = sd_event_default(&lldp->event);
290 if (r < 0)
291 return r;
292 }
293
294 lldp->event_priority = priority;
295
296 return 0;
297}
298
299_public___attribute__ ((visibility("default"))) int sd_lldp_detach_event(sd_lldp *lldp) {
300
301 assert_return(lldp, -EINVAL)do { if (!(((__builtin_expect(!!(lldp),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("lldp"), "../src/libsystemd-network/sd-lldp.c"
, 301, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
302 assert_return(lldp->fd < 0, -EBUSY)do { if (!(((__builtin_expect(!!(lldp->fd < 0),1))) ? (
1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("lldp->fd < 0"
), "../src/libsystemd-network/sd-lldp.c", 302, __PRETTY_FUNCTION__
), 0))) return (-16); } while (0)
;
303
304 lldp->event = sd_event_unref(lldp->event);
305 return 0;
306}
307
308_public___attribute__ ((visibility("default"))) sd_event* sd_lldp_get_event(sd_lldp *lldp) {
309 assert_return(lldp, NULL)do { if (!(((__builtin_expect(!!(lldp),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("lldp"), "../src/libsystemd-network/sd-lldp.c"
, 309, __PRETTY_FUNCTION__), 0))) return (((void*)0)); } while
(0)
;
310
311 return lldp->event;
312}
313
314_public___attribute__ ((visibility("default"))) int sd_lldp_set_callback(sd_lldp *lldp, sd_lldp_callback_t cb, void *userdata) {
315 assert_return(lldp, -EINVAL)do { if (!(((__builtin_expect(!!(lldp),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("lldp"), "../src/libsystemd-network/sd-lldp.c"
, 315, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
316
317 lldp->callback = cb;
318 lldp->userdata = userdata;
319
320 return 0;
321}
322
323_public___attribute__ ((visibility("default"))) int sd_lldp_set_ifindex(sd_lldp *lldp, int ifindex) {
324 assert_return(lldp, -EINVAL)do { if (!(((__builtin_expect(!!(lldp),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("lldp"), "../src/libsystemd-network/sd-lldp.c"
, 324, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
325 assert_return(ifindex > 0, -EINVAL)do { if (!(((__builtin_expect(!!(ifindex > 0),1))) ? (1) :
(log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("ifindex > 0"
), "../src/libsystemd-network/sd-lldp.c", 325, __PRETTY_FUNCTION__
), 0))) return (-22); } while (0)
;
326 assert_return(lldp->fd < 0, -EBUSY)do { if (!(((__builtin_expect(!!(lldp->fd < 0),1))) ? (
1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("lldp->fd < 0"
), "../src/libsystemd-network/sd-lldp.c", 326, __PRETTY_FUNCTION__
), 0))) return (-16); } while (0)
;
327
328 lldp->ifindex = ifindex;
329 return 0;
330}
331
332_public___attribute__ ((visibility("default"))) sd_lldp* sd_lldp_ref(sd_lldp *lldp) {
333
334 if (!lldp)
335 return NULL((void*)0);
336
337 assert(lldp->n_ref > 0)do { if ((__builtin_expect(!!(!(lldp->n_ref > 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("lldp->n_ref > 0"), "../src/libsystemd-network/sd-lldp.c"
, 337, __PRETTY_FUNCTION__); } while (0)
;
338 lldp->n_ref++;
339
340 return lldp;
341}
342
343_public___attribute__ ((visibility("default"))) sd_lldp* sd_lldp_unref(sd_lldp *lldp) {
344
345 if (!lldp)
346 return NULL((void*)0);
347
348 assert(lldp->n_ref > 0)do { if ((__builtin_expect(!!(!(lldp->n_ref > 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("lldp->n_ref > 0"), "../src/libsystemd-network/sd-lldp.c"
, 348, __PRETTY_FUNCTION__); } while (0)
;
349 lldp->n_ref --;
350
351 if (lldp->n_ref > 0)
352 return NULL((void*)0);
353
354 lldp_reset(lldp);
355 sd_lldp_detach_event(lldp);
356 lldp_flush_neighbors(lldp);
357
358 hashmap_free(lldp->neighbor_by_id);
359 prioq_free(lldp->neighbor_by_expiry);
360 return mfree(lldp);
361}
362
363_public___attribute__ ((visibility("default"))) int sd_lldp_new(sd_lldp **ret) {
364 _cleanup_(sd_lldp_unrefp)__attribute__((cleanup(sd_lldp_unrefp))) sd_lldp *lldp = NULL((void*)0);
365 int r;
366
367 assert_return(ret, -EINVAL)do { if (!(((__builtin_expect(!!(ret),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("ret"), "../src/libsystemd-network/sd-lldp.c"
, 367, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
1
Assuming 'ret' is non-null
2
'?' condition is true
3
Taking false branch
4
Loop condition is false. Exiting loop
368
369 lldp = new0(sd_lldp, 1)((sd_lldp*) calloc((1), sizeof(sd_lldp)));
5
Memory is allocated
370 if (!lldp)
6
Assuming 'lldp' is non-null
7
Taking false branch
371 return -ENOMEM12;
372
373 lldp->n_ref = 1;
374 lldp->fd = -1;
375 lldp->neighbors_max = LLDP_DEFAULT_NEIGHBORS_MAX128U;
376 lldp->capability_mask = (uint16_t) -1;
377
378 lldp->neighbor_by_id = hashmap_new(&lldp_neighbor_id_hash_ops)internal_hashmap_new(&lldp_neighbor_id_hash_ops );
379 if (!lldp->neighbor_by_id)
8
Assuming field 'neighbor_by_id' is null
9
Taking true branch
380 return -ENOMEM12;
10
Potential leak of memory pointed to by 'lldp'
381
382 r = prioq_ensure_allocated(&lldp->neighbor_by_expiry, lldp_neighbor_prioq_compare_func);
383 if (r < 0)
384 return r;
385
386 *ret = TAKE_PTR(lldp)({ typeof(lldp) _ptr_ = (lldp); (lldp) = ((void*)0); _ptr_; }
)
;
387
388 return 0;
389}
390
391static int neighbor_compare_func(const void *a, const void *b) {
392 const sd_lldp_neighbor * const*x = a, * const *y = b;
393
394 return lldp_neighbor_id_hash_ops.compare(&(*x)->id, &(*y)->id);
395}
396
397static int on_timer_event(sd_event_source *s, uint64_t usec, void *userdata) {
398 sd_lldp *lldp = userdata;
399 int r;
400
401 r = lldp_make_space(lldp, 0);
402 if (r < 0)
403 return log_lldp_errno(r, "Failed to make space: %m")log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((7))),
r, "../src/libsystemd-network/sd-lldp.c", 403, __func__, "LLDP: "
"Failed to make space: %m")
;
404
405 r = lldp_start_timer(lldp, NULL((void*)0));
406 if (r < 0)
407 return log_lldp_errno(r, "Failed to restart timer: %m")log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((7))),
r, "../src/libsystemd-network/sd-lldp.c", 407, __func__, "LLDP: "
"Failed to restart timer: %m")
;
408
409 return 0;
410}
411
412static int lldp_start_timer(sd_lldp *lldp, sd_lldp_neighbor *neighbor) {
413 sd_lldp_neighbor *n;
414 int r;
415
416 assert(lldp)do { if ((__builtin_expect(!!(!(lldp)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("lldp"), "../src/libsystemd-network/sd-lldp.c"
, 416, __PRETTY_FUNCTION__); } while (0)
;
417
418 if (neighbor)
419 lldp_neighbor_start_ttl(neighbor);
420
421 n = prioq_peek(lldp->neighbor_by_expiry);
422 if (!n) {
423
424 if (lldp->timer_event_source)
425 return sd_event_source_set_enabled(lldp->timer_event_source, SD_EVENT_OFF);
426
427 return 0;
428 }
429
430 if (lldp->timer_event_source) {
431 r = sd_event_source_set_time(lldp->timer_event_source, n->until);
432 if (r < 0)
433 return r;
434
435 return sd_event_source_set_enabled(lldp->timer_event_source, SD_EVENT_ONESHOT);
436 }
437
438 if (!lldp->event)
439 return 0;
440
441 r = sd_event_add_time(lldp->event, &lldp->timer_event_source, clock_boottime_or_monotonic(), n->until, 0, on_timer_event, lldp);
442 if (r < 0)
443 return r;
444
445 r = sd_event_source_set_priority(lldp->timer_event_source, lldp->event_priority);
446 if (r < 0)
447 return r;
448
449 (void) sd_event_source_set_description(lldp->timer_event_source, "lldp-timer");
450 return 0;
451}
452
453_public___attribute__ ((visibility("default"))) int sd_lldp_get_neighbors(sd_lldp *lldp, sd_lldp_neighbor ***ret) {
454 sd_lldp_neighbor **l = NULL((void*)0), *n;
455 Iterator i;
456 int k = 0, r;
457
458 assert_return(lldp, -EINVAL)do { if (!(((__builtin_expect(!!(lldp),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("lldp"), "../src/libsystemd-network/sd-lldp.c"
, 458, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
459 assert_return(ret, -EINVAL)do { if (!(((__builtin_expect(!!(ret),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("ret"), "../src/libsystemd-network/sd-lldp.c"
, 459, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
460
461 if (hashmap_isempty(lldp->neighbor_by_id)) { /* Special shortcut */
462 *ret = NULL((void*)0);
463 return 0;
464 }
465
466 l = new0(sd_lldp_neighbor*, hashmap_size(lldp->neighbor_by_id))((sd_lldp_neighbor**) calloc((hashmap_size(lldp->neighbor_by_id
)), sizeof(sd_lldp_neighbor*)))
;
467 if (!l)
468 return -ENOMEM12;
469
470 r = lldp_start_timer(lldp, NULL((void*)0));
471 if (r < 0) {
472 free(l);
473 return r;
474 }
475
476 HASHMAP_FOREACH(n, lldp->neighbor_by_id, i)for ((i) = ((Iterator) { .idx = ((2147483647 *2U +1U) - 1), .
next_key = ((void*)0) }); hashmap_iterate((lldp->neighbor_by_id
), &(i), (void**)&(n), ((void*)0)); )
477 l[k++] = sd_lldp_neighbor_ref(n);
478
479 assert((size_t) k == hashmap_size(lldp->neighbor_by_id))do { if ((__builtin_expect(!!(!((size_t) k == hashmap_size(lldp
->neighbor_by_id))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD
, ("(size_t) k == hashmap_size(lldp->neighbor_by_id)"), "../src/libsystemd-network/sd-lldp.c"
, 479, __PRETTY_FUNCTION__); } while (0)
;
480
481 /* Return things in a stable order */
482 qsort(l, k, sizeof(sd_lldp_neighbor*), neighbor_compare_func);
483 *ret = l;
484
485 return k;
486}
487
488_public___attribute__ ((visibility("default"))) int sd_lldp_set_neighbors_max(sd_lldp *lldp, uint64_t m) {
489 assert_return(lldp, -EINVAL)do { if (!(((__builtin_expect(!!(lldp),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("lldp"), "../src/libsystemd-network/sd-lldp.c"
, 489, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
490 assert_return(m <= 0, -EINVAL)do { if (!(((__builtin_expect(!!(m <= 0),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("m <= 0"), "../src/libsystemd-network/sd-lldp.c"
, 490, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
491
492 lldp->neighbors_max = m;
493 lldp_make_space(lldp, 0);
494
495 return 0;
496}
497
498_public___attribute__ ((visibility("default"))) int sd_lldp_match_capabilities(sd_lldp *lldp, uint16_t mask) {
499 assert_return(lldp, -EINVAL)do { if (!(((__builtin_expect(!!(lldp),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("lldp"), "../src/libsystemd-network/sd-lldp.c"
, 499, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
500 assert_return(mask != 0, -EINVAL)do { if (!(((__builtin_expect(!!(mask != 0),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("mask != 0"), "../src/libsystemd-network/sd-lldp.c"
, 500, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
501
502 lldp->capability_mask = mask;
503
504 return 0;
505}
506
507_public___attribute__ ((visibility("default"))) int sd_lldp_set_filter_address(sd_lldp *lldp, const struct ether_addr *addr) {
508 assert_return(lldp, -EINVAL)do { if (!(((__builtin_expect(!!(lldp),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("lldp"), "../src/libsystemd-network/sd-lldp.c"
, 508, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
509
510 /* In order to deal nicely with bridges that send back our own packets, allow one address to be filtered, so
511 * that our own can be filtered out here. */
512
513 if (addr)
514 lldp->filter_address = *addr;
515 else
516 zero(lldp->filter_address)(({ size_t _l_ = (sizeof(lldp->filter_address)); void *_x_
= (&(lldp->filter_address)); _l_ == 0 ? _x_ : memset(
_x_, 0, _l_); }))
;
517
518 return 0;
519}