Bug Summary

File:build-scan/../src/libsystemd/sd-netlink/sd-netlink.c
Warning:line 900, column 33
Potential leak of memory pointed to by 'c'

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-netlink.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/libsystemd_static.a.p -I src/libsystemd -I ../src/libsystemd -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 src/libsystemd-network -I ../src/libsystemd-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 default -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/sd-netlink/sd-netlink.c
1/* SPDX-License-Identifier: LGPL-2.1+ */
2
3#include <poll.h>
4#include <sys/socket.h>
5
6#include "sd-netlink.h"
7
8#include "alloc-util.h"
9#include "fd-util.h"
10#include "hashmap.h"
11#include "macro.h"
12#include "missing.h"
13#include "netlink-internal.h"
14#include "netlink-util.h"
15#include "process-util.h"
16#include "socket-util.h"
17#include "util.h"
18
19static int sd_netlink_new(sd_netlink **ret) {
20 _cleanup_(sd_netlink_unrefp)__attribute__((cleanup(sd_netlink_unrefp))) sd_netlink *rtnl = NULL((void*)0);
21
22 assert_return(ret, -EINVAL)do { if (!(((__builtin_expect(!!(ret),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("ret"), "../src/libsystemd/sd-netlink/sd-netlink.c"
, 22, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
23
24 rtnl = new0(sd_netlink, 1)((sd_netlink*) calloc((1), sizeof(sd_netlink)));
25 if (!rtnl)
26 return -ENOMEM12;
27
28 rtnl->n_ref = REFCNT_INIT((RefCount) { ._value = 1 });
29 rtnl->fd = -1;
30 rtnl->sockaddr.nl.nl_family = AF_NETLINK16;
31 rtnl->original_pid = getpid_cached();
32 rtnl->protocol = -1;
33
34 LIST_HEAD_INIT(rtnl->match_callbacks)do { (rtnl->match_callbacks) = ((void*)0); } while (0);
35
36 /* We guarantee that the read buffer has at least space for
37 * a message header */
38 if (!greedy_realloc((void**)&rtnl->rbuffer, &rtnl->rbuffer_allocated,
39 sizeof(struct nlmsghdr), sizeof(uint8_t)))
40 return -ENOMEM12;
41
42 /* Change notification responses have sequence 0, so we must
43 * start our request sequence numbers at 1, or we may confuse our
44 * responses with notifications from the kernel */
45 rtnl->serial = 1;
46
47 *ret = TAKE_PTR(rtnl)({ typeof(rtnl) _ptr_ = (rtnl); (rtnl) = ((void*)0); _ptr_; }
)
;
48
49 return 0;
50}
51
52int sd_netlink_new_from_netlink(sd_netlink **ret, int fd) {
53 _cleanup_(sd_netlink_unrefp)__attribute__((cleanup(sd_netlink_unrefp))) sd_netlink *rtnl = NULL((void*)0);
54 socklen_t addrlen;
55 int r;
56
57 assert_return(ret, -EINVAL)do { if (!(((__builtin_expect(!!(ret),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("ret"), "../src/libsystemd/sd-netlink/sd-netlink.c"
, 57, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
58
59 r = sd_netlink_new(&rtnl);
60 if (r < 0)
61 return r;
62
63 addrlen = sizeof(rtnl->sockaddr);
64
65 r = getsockname(fd, &rtnl->sockaddr.sa, &addrlen);
66 if (r < 0)
67 return -errno(*__errno_location ());
68
69 if (rtnl->sockaddr.nl.nl_family != AF_NETLINK16)
70 return -EINVAL22;
71
72 rtnl->fd = fd;
73
74 *ret = TAKE_PTR(rtnl)({ typeof(rtnl) _ptr_ = (rtnl); (rtnl) = ((void*)0); _ptr_; }
)
;
75
76 return 0;
77}
78
79static bool_Bool rtnl_pid_changed(sd_netlink *rtnl) {
80 assert(rtnl)do { if ((__builtin_expect(!!(!(rtnl)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("rtnl"), "../src/libsystemd/sd-netlink/sd-netlink.c"
, 80, __PRETTY_FUNCTION__); } while (0)
;
81
82 /* We don't support people creating an rtnl connection and
83 * keeping it around over a fork(). Let's complain. */
84
85 return rtnl->original_pid != getpid_cached();
86}
87
88int sd_netlink_open_fd(sd_netlink **ret, int fd) {
89 _cleanup_(sd_netlink_unrefp)__attribute__((cleanup(sd_netlink_unrefp))) sd_netlink *rtnl = NULL((void*)0);
90 int r;
91 int protocol;
92 socklen_t l;
93
94 assert_return(ret, -EINVAL)do { if (!(((__builtin_expect(!!(ret),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("ret"), "../src/libsystemd/sd-netlink/sd-netlink.c"
, 94, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
95 assert_return(fd >= 0, -EBADF)do { if (!(((__builtin_expect(!!(fd >= 0),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("fd >= 0"), "../src/libsystemd/sd-netlink/sd-netlink.c"
, 95, __PRETTY_FUNCTION__), 0))) return (-9); } while (0)
;
96
97 r = sd_netlink_new(&rtnl);
98 if (r < 0)
99 return r;
100
101 l = sizeof(protocol);
102 r = getsockopt(fd, SOL_SOCKET1, SO_PROTOCOL38, &protocol, &l);
103 if (r < 0)
104 return r;
105
106 rtnl->fd = fd;
107 rtnl->protocol = protocol;
108
109 r = socket_bind(rtnl);
110 if (r < 0) {
111 rtnl->fd = -1; /* on failure, the caller remains owner of the fd, hence don't close it here */
112 rtnl->protocol = -1;
113 return r;
114 }
115
116 *ret = TAKE_PTR(rtnl)({ typeof(rtnl) _ptr_ = (rtnl); (rtnl) = ((void*)0); _ptr_; }
)
;
117
118 return 0;
119}
120
121int netlink_open_family(sd_netlink **ret, int family) {
122 _cleanup_close___attribute__((cleanup(closep))) int fd = -1;
123 int r;
124
125 fd = socket_open(family);
126 if (fd < 0)
127 return fd;
128
129 r = sd_netlink_open_fd(ret, fd);
130 if (r < 0)
131 return r;
132
133 fd = -1;
134
135 return 0;
136}
137
138int sd_netlink_open(sd_netlink **ret) {
139 return netlink_open_family(ret, NETLINK_ROUTE0);
140}
141
142int sd_netlink_inc_rcvbuf(sd_netlink *rtnl, size_t size) {
143 assert_return(rtnl, -EINVAL)do { if (!(((__builtin_expect(!!(rtnl),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("rtnl"), "../src/libsystemd/sd-netlink/sd-netlink.c"
, 143, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
144 assert_return(!rtnl_pid_changed(rtnl), -ECHILD)do { if (!(((__builtin_expect(!!(!rtnl_pid_changed(rtnl)),1))
) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, (
"!rtnl_pid_changed(rtnl)"), "../src/libsystemd/sd-netlink/sd-netlink.c"
, 144, __PRETTY_FUNCTION__), 0))) return (-10); } while (0)
;
145
146 return fd_inc_rcvbuf(rtnl->fd, size);
147}
148
149sd_netlink *sd_netlink_ref(sd_netlink *rtnl) {
150 assert_return(rtnl, NULL)do { if (!(((__builtin_expect(!!(rtnl),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("rtnl"), "../src/libsystemd/sd-netlink/sd-netlink.c"
, 150, __PRETTY_FUNCTION__), 0))) return (((void*)0)); } while
(0)
;
151 assert_return(!rtnl_pid_changed(rtnl), NULL)do { if (!(((__builtin_expect(!!(!rtnl_pid_changed(rtnl)),1))
) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, (
"!rtnl_pid_changed(rtnl)"), "../src/libsystemd/sd-netlink/sd-netlink.c"
, 151, __PRETTY_FUNCTION__), 0))) return (((void*)0)); } while
(0)
;
152
153 if (rtnl)
154 assert_se(REFCNT_INC(rtnl->n_ref) >= 2)do { if ((__builtin_expect(!!(!((__sync_add_and_fetch(&(rtnl
->n_ref)._value, 1)) >= 2)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("REFCNT_INC(rtnl->n_ref) >= 2"), "../src/libsystemd/sd-netlink/sd-netlink.c"
, 154, __PRETTY_FUNCTION__); } while (0)
;
155
156 return rtnl;
157}
158
159sd_netlink *sd_netlink_unref(sd_netlink *rtnl) {
160 if (!rtnl)
161 return NULL((void*)0);
162
163 assert_return(!rtnl_pid_changed(rtnl), NULL)do { if (!(((__builtin_expect(!!(!rtnl_pid_changed(rtnl)),1))
) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, (
"!rtnl_pid_changed(rtnl)"), "../src/libsystemd/sd-netlink/sd-netlink.c"
, 163, __PRETTY_FUNCTION__), 0))) return (((void*)0)); } while
(0)
;
164
165 if (REFCNT_DEC(rtnl->n_ref)(__sync_sub_and_fetch(&(rtnl->n_ref)._value, 1)) == 0) {
166 struct match_callback *f;
167 unsigned i;
168
169 for (i = 0; i < rtnl->rqueue_size; i++)
170 sd_netlink_message_unref(rtnl->rqueue[i]);
171 free(rtnl->rqueue);
172
173 for (i = 0; i < rtnl->rqueue_partial_size; i++)
174 sd_netlink_message_unref(rtnl->rqueue_partial[i]);
175 free(rtnl->rqueue_partial);
176
177 free(rtnl->rbuffer);
178
179 hashmap_free_free(rtnl->reply_callbacks);
180 prioq_free(rtnl->reply_callbacks_prioq);
181
182 sd_event_source_unref(rtnl->io_event_source);
183 sd_event_source_unref(rtnl->time_event_source);
184 sd_event_unref(rtnl->event);
185
186 while ((f = rtnl->match_callbacks)) {
187 sd_netlink_remove_match(rtnl, f->type, f->callback, f->userdata);
188 }
189
190 hashmap_free(rtnl->broadcast_group_refs);
191
192 safe_close(rtnl->fd);
193 free(rtnl);
194 }
195
196 return NULL((void*)0);
197}
198
199static void rtnl_seal_message(sd_netlink *rtnl, sd_netlink_message *m) {
200 assert(rtnl)do { if ((__builtin_expect(!!(!(rtnl)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("rtnl"), "../src/libsystemd/sd-netlink/sd-netlink.c"
, 200, __PRETTY_FUNCTION__); } while (0)
;
201 assert(!rtnl_pid_changed(rtnl))do { if ((__builtin_expect(!!(!(!rtnl_pid_changed(rtnl))),0))
) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("!rtnl_pid_changed(rtnl)"
), "../src/libsystemd/sd-netlink/sd-netlink.c", 201, __PRETTY_FUNCTION__
); } while (0)
;
202 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-netlink/sd-netlink.c"
, 202, __PRETTY_FUNCTION__); } while (0)
;
203 assert(m->hdr)do { if ((__builtin_expect(!!(!(m->hdr)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m->hdr"), "../src/libsystemd/sd-netlink/sd-netlink.c"
, 203, __PRETTY_FUNCTION__); } while (0)
;
204
205 /* don't use seq == 0, as that is used for broadcasts, so we
206 would get confused by replies to such messages */
207 m->hdr->nlmsg_seq = rtnl->serial++ ? : rtnl->serial++;
208
209 rtnl_message_seal(m);
210
211 return;
212}
213
214int sd_netlink_send(sd_netlink *nl,
215 sd_netlink_message *message,
216 uint32_t *serial) {
217 int r;
218
219 assert_return(nl, -EINVAL)do { if (!(((__builtin_expect(!!(nl),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("nl"), "../src/libsystemd/sd-netlink/sd-netlink.c"
, 219, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
220 assert_return(!rtnl_pid_changed(nl), -ECHILD)do { if (!(((__builtin_expect(!!(!rtnl_pid_changed(nl)),1))) ?
(1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("!rtnl_pid_changed(nl)"
), "../src/libsystemd/sd-netlink/sd-netlink.c", 220, __PRETTY_FUNCTION__
), 0))) return (-10); } while (0)
;
221 assert_return(message, -EINVAL)do { if (!(((__builtin_expect(!!(message),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("message"), "../src/libsystemd/sd-netlink/sd-netlink.c"
, 221, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
222 assert_return(!message->sealed, -EPERM)do { if (!(((__builtin_expect(!!(!message->sealed),1))) ? (
1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("!message->sealed"
), "../src/libsystemd/sd-netlink/sd-netlink.c", 222, __PRETTY_FUNCTION__
), 0))) return (-1); } while (0)
;
223
224 rtnl_seal_message(nl, message);
225
226 r = socket_write_message(nl, message);
227 if (r < 0)
228 return r;
229
230 if (serial)
231 *serial = rtnl_message_get_serial(message);
232
233 return 1;
234}
235
236int rtnl_rqueue_make_room(sd_netlink *rtnl) {
237 assert(rtnl)do { if ((__builtin_expect(!!(!(rtnl)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("rtnl"), "../src/libsystemd/sd-netlink/sd-netlink.c"
, 237, __PRETTY_FUNCTION__); } while (0)
;
238
239 if (rtnl->rqueue_size >= RTNL_RQUEUE_MAX64*1024) {
240 log_debug("rtnl: exhausted the read queue size (%d)", RTNL_RQUEUE_MAX)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/libsystemd/sd-netlink/sd-netlink.c", 240, __func__,
"rtnl: exhausted the read queue size (%d)", 64*1024) : -abs(
_e); })
;
241 return -ENOBUFS105;
242 }
243
244 if (!GREEDY_REALLOC(rtnl->rqueue, rtnl->rqueue_allocated, rtnl->rqueue_size + 1)greedy_realloc((void**) &(rtnl->rqueue), &(rtnl->
rqueue_allocated), (rtnl->rqueue_size + 1), sizeof((rtnl->
rqueue)[0]))
)
245 return -ENOMEM12;
246
247 return 0;
248}
249
250int rtnl_rqueue_partial_make_room(sd_netlink *rtnl) {
251 assert(rtnl)do { if ((__builtin_expect(!!(!(rtnl)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("rtnl"), "../src/libsystemd/sd-netlink/sd-netlink.c"
, 251, __PRETTY_FUNCTION__); } while (0)
;
252
253 if (rtnl->rqueue_partial_size >= RTNL_RQUEUE_MAX64*1024) {
254 log_debug("rtnl: exhausted the partial read queue size (%d)", RTNL_RQUEUE_MAX)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/libsystemd/sd-netlink/sd-netlink.c", 254, __func__,
"rtnl: exhausted the partial read queue size (%d)", 64*1024)
: -abs(_e); })
;
255 return -ENOBUFS105;
256 }
257
258 if (!GREEDY_REALLOC(rtnl->rqueue_partial, rtnl->rqueue_partial_allocated,greedy_realloc((void**) &(rtnl->rqueue_partial), &
(rtnl->rqueue_partial_allocated), (rtnl->rqueue_partial_size
+ 1), sizeof((rtnl->rqueue_partial)[0]))
259 rtnl->rqueue_partial_size + 1)greedy_realloc((void**) &(rtnl->rqueue_partial), &
(rtnl->rqueue_partial_allocated), (rtnl->rqueue_partial_size
+ 1), sizeof((rtnl->rqueue_partial)[0]))
)
260 return -ENOMEM12;
261
262 return 0;
263}
264
265static int dispatch_rqueue(sd_netlink *rtnl, sd_netlink_message **message) {
266 int r;
267
268 assert(rtnl)do { if ((__builtin_expect(!!(!(rtnl)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("rtnl"), "../src/libsystemd/sd-netlink/sd-netlink.c"
, 268, __PRETTY_FUNCTION__); } while (0)
;
269 assert(message)do { if ((__builtin_expect(!!(!(message)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("message"), "../src/libsystemd/sd-netlink/sd-netlink.c"
, 269, __PRETTY_FUNCTION__); } while (0)
;
270
271 if (rtnl->rqueue_size <= 0) {
272 /* Try to read a new message */
273 r = socket_read_message(rtnl);
274 if (r == -ENOBUFS105) { /* FIXME: ignore buffer overruns for now */
275 log_debug_errno(r, "Got ENOBUFS from netlink socket, ignoring.")({ int _level = ((7)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/libsystemd/sd-netlink/sd-netlink.c", 275, __func__,
"Got ENOBUFS from netlink socket, ignoring.") : -abs(_e); })
;
276 return 1;
277 }
278 if (r <= 0)
279 return r;
280 }
281
282 /* Dispatch a queued message */
283 *message = rtnl->rqueue[0];
284 rtnl->rqueue_size--;
285 memmove(rtnl->rqueue, rtnl->rqueue + 1, sizeof(sd_netlink_message*) * rtnl->rqueue_size);
286
287 return 1;
288}
289
290static int process_timeout(sd_netlink *rtnl) {
291 _cleanup_(sd_netlink_message_unrefp)__attribute__((cleanup(sd_netlink_message_unrefp))) sd_netlink_message *m = NULL((void*)0);
292 struct reply_callback *c;
293 usec_t n;
294 int r;
295
296 assert(rtnl)do { if ((__builtin_expect(!!(!(rtnl)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("rtnl"), "../src/libsystemd/sd-netlink/sd-netlink.c"
, 296, __PRETTY_FUNCTION__); } while (0)
;
297
298 c = prioq_peek(rtnl->reply_callbacks_prioq);
299 if (!c)
300 return 0;
301
302 n = now(CLOCK_MONOTONIC1);
303 if (c->timeout > n)
304 return 0;
305
306 r = rtnl_message_new_synthetic_error(rtnl, -ETIMEDOUT110, c->serial, &m);
307 if (r < 0)
308 return r;
309
310 assert_se(prioq_pop(rtnl->reply_callbacks_prioq) == c)do { if ((__builtin_expect(!!(!(prioq_pop(rtnl->reply_callbacks_prioq
) == c)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("prioq_pop(rtnl->reply_callbacks_prioq) == c"
), "../src/libsystemd/sd-netlink/sd-netlink.c", 310, __PRETTY_FUNCTION__
); } while (0)
;
311 hashmap_remove(rtnl->reply_callbacks, &c->serial);
312
313 r = c->callback(rtnl, m, c->userdata);
314 if (r < 0)
315 log_debug_errno(r, "sd-netlink: timedout callback failed: %m")({ int _level = ((7)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/libsystemd/sd-netlink/sd-netlink.c", 315, __func__,
"sd-netlink: timedout callback failed: %m") : -abs(_e); })
;
316
317 free(c);
318
319 return 1;
320}
321
322static int process_reply(sd_netlink *rtnl, sd_netlink_message *m) {
323 _cleanup_free___attribute__((cleanup(freep))) struct reply_callback *c = NULL((void*)0);
324 uint64_t serial;
325 uint16_t type;
326 int r;
327
328 assert(rtnl)do { if ((__builtin_expect(!!(!(rtnl)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("rtnl"), "../src/libsystemd/sd-netlink/sd-netlink.c"
, 328, __PRETTY_FUNCTION__); } while (0)
;
329 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-netlink/sd-netlink.c"
, 329, __PRETTY_FUNCTION__); } while (0)
;
330
331 serial = rtnl_message_get_serial(m);
332 c = hashmap_remove(rtnl->reply_callbacks, &serial);
333 if (!c)
334 return 0;
335
336 if (c->timeout != 0)
337 prioq_remove(rtnl->reply_callbacks_prioq, c, &c->prioq_idx);
338
339 r = sd_netlink_message_get_type(m, &type);
340 if (r < 0)
341 return 0;
342
343 if (type == NLMSG_DONE0x3)
344 m = NULL((void*)0);
345
346 r = c->callback(rtnl, m, c->userdata);
347 if (r < 0)
348 log_debug_errno(r, "sd-netlink: callback failed: %m")({ int _level = ((7)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/libsystemd/sd-netlink/sd-netlink.c", 348, __func__,
"sd-netlink: callback failed: %m") : -abs(_e); })
;
349
350 return 1;
351}
352
353static int process_match(sd_netlink *rtnl, sd_netlink_message *m) {
354 struct match_callback *c;
355 uint16_t type;
356 int r;
357
358 assert(rtnl)do { if ((__builtin_expect(!!(!(rtnl)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("rtnl"), "../src/libsystemd/sd-netlink/sd-netlink.c"
, 358, __PRETTY_FUNCTION__); } while (0)
;
359 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-netlink/sd-netlink.c"
, 359, __PRETTY_FUNCTION__); } while (0)
;
360
361 r = sd_netlink_message_get_type(m, &type);
362 if (r < 0)
363 return r;
364
365 LIST_FOREACH(match_callbacks, c, rtnl->match_callbacks)for ((c) = (rtnl->match_callbacks); (c); (c) = (c)->match_callbacks_next
)
{
366 if (type == c->type) {
367 r = c->callback(rtnl, m, c->userdata);
368 if (r != 0) {
369 if (r < 0)
370 log_debug_errno(r, "sd-netlink: match callback failed: %m")({ int _level = ((7)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/libsystemd/sd-netlink/sd-netlink.c", 370, __func__,
"sd-netlink: match callback failed: %m") : -abs(_e); })
;
371
372 break;
373 }
374 }
375 }
376
377 return 1;
378}
379
380static int process_running(sd_netlink *rtnl, sd_netlink_message **ret) {
381 _cleanup_(sd_netlink_message_unrefp)__attribute__((cleanup(sd_netlink_message_unrefp))) sd_netlink_message *m = NULL((void*)0);
382 int r;
383
384 assert(rtnl)do { if ((__builtin_expect(!!(!(rtnl)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("rtnl"), "../src/libsystemd/sd-netlink/sd-netlink.c"
, 384, __PRETTY_FUNCTION__); } while (0)
;
385
386 r = process_timeout(rtnl);
387 if (r != 0)
388 goto null_message;
389
390 r = dispatch_rqueue(rtnl, &m);
391 if (r < 0)
392 return r;
393 if (!m)
394 goto null_message;
395
396 if (sd_netlink_message_is_broadcast(m)) {
397 r = process_match(rtnl, m);
398 if (r != 0)
399 goto null_message;
400 } else {
401 r = process_reply(rtnl, m);
402 if (r != 0)
403 goto null_message;
404 }
405
406 if (ret) {
407 *ret = TAKE_PTR(m)({ typeof(m) _ptr_ = (m); (m) = ((void*)0); _ptr_; });
408
409 return 1;
410 }
411
412 return 1;
413
414null_message:
415 if (r >= 0 && ret)
416 *ret = NULL((void*)0);
417
418 return r;
419}
420
421int sd_netlink_process(sd_netlink *rtnl, sd_netlink_message **ret) {
422 NETLINK_DONT_DESTROY(rtnl)__attribute__((cleanup(sd_netlink_unrefp))) __attribute__ ((unused
)) sd_netlink *_dont_destroy_rtnl = sd_netlink_ref(rtnl)
;
423 int r;
424
425 assert_return(rtnl, -EINVAL)do { if (!(((__builtin_expect(!!(rtnl),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("rtnl"), "../src/libsystemd/sd-netlink/sd-netlink.c"
, 425, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
426 assert_return(!rtnl_pid_changed(rtnl), -ECHILD)do { if (!(((__builtin_expect(!!(!rtnl_pid_changed(rtnl)),1))
) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, (
"!rtnl_pid_changed(rtnl)"), "../src/libsystemd/sd-netlink/sd-netlink.c"
, 426, __PRETTY_FUNCTION__), 0))) return (-10); } while (0)
;
427 assert_return(!rtnl->processing, -EBUSY)do { if (!(((__builtin_expect(!!(!rtnl->processing),1))) ?
(1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("!rtnl->processing"
), "../src/libsystemd/sd-netlink/sd-netlink.c", 427, __PRETTY_FUNCTION__
), 0))) return (-16); } while (0)
;
428
429 rtnl->processing = true1;
430 r = process_running(rtnl, ret);
431 rtnl->processing = false0;
432
433 return r;
434}
435
436static usec_t calc_elapse(uint64_t usec) {
437 if (usec == (uint64_t) -1)
438 return 0;
439
440 if (usec == 0)
441 usec = RTNL_DEFAULT_TIMEOUT((usec_t) (25 * ((usec_t) 1000000ULL)));
442
443 return now(CLOCK_MONOTONIC1) + usec;
444}
445
446static int rtnl_poll(sd_netlink *rtnl, bool_Bool need_more, uint64_t timeout_usec) {
447 struct pollfd p[1] = {};
448 struct timespec ts;
449 usec_t m = USEC_INFINITY((usec_t) -1);
450 int r, e;
451
452 assert(rtnl)do { if ((__builtin_expect(!!(!(rtnl)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("rtnl"), "../src/libsystemd/sd-netlink/sd-netlink.c"
, 452, __PRETTY_FUNCTION__); } while (0)
;
453
454 e = sd_netlink_get_events(rtnl);
455 if (e < 0)
456 return e;
457
458 if (need_more)
459 /* Caller wants more data, and doesn't care about
460 * what's been read or any other timeouts. */
461 e |= POLLIN0x001;
462 else {
463 usec_t until;
464 /* Caller wants to process if there is something to
465 * process, but doesn't care otherwise */
466
467 r = sd_netlink_get_timeout(rtnl, &until);
468 if (r < 0)
469 return r;
470 if (r > 0) {
471 usec_t nw;
472 nw = now(CLOCK_MONOTONIC1);
473 m = until > nw ? until - nw : 0;
474 }
475 }
476
477 if (timeout_usec != (uint64_t) -1 && (m == (uint64_t) -1 || timeout_usec < m))
478 m = timeout_usec;
479
480 p[0].fd = rtnl->fd;
481 p[0].events = e;
482
483 r = ppoll(p, 1, m == (uint64_t) -1 ? NULL((void*)0) : timespec_store(&ts, m), NULL((void*)0));
484 if (r < 0)
485 return -errno(*__errno_location ());
486
487 return r > 0 ? 1 : 0;
488}
489
490int sd_netlink_wait(sd_netlink *nl, uint64_t timeout_usec) {
491 assert_return(nl, -EINVAL)do { if (!(((__builtin_expect(!!(nl),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("nl"), "../src/libsystemd/sd-netlink/sd-netlink.c"
, 491, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
492 assert_return(!rtnl_pid_changed(nl), -ECHILD)do { if (!(((__builtin_expect(!!(!rtnl_pid_changed(nl)),1))) ?
(1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("!rtnl_pid_changed(nl)"
), "../src/libsystemd/sd-netlink/sd-netlink.c", 492, __PRETTY_FUNCTION__
), 0))) return (-10); } while (0)
;
493
494 if (nl->rqueue_size > 0)
495 return 0;
496
497 return rtnl_poll(nl, false0, timeout_usec);
498}
499
500static int timeout_compare(const void *a, const void *b) {
501 const struct reply_callback *x = a, *y = b;
502
503 if (x->timeout != 0 && y->timeout == 0)
504 return -1;
505
506 if (x->timeout == 0 && y->timeout != 0)
507 return 1;
508
509 if (x->timeout < y->timeout)
510 return -1;
511
512 if (x->timeout > y->timeout)
513 return 1;
514
515 return 0;
516}
517
518int sd_netlink_call_async(sd_netlink *nl,
519 sd_netlink_message *m,
520 sd_netlink_message_handler_t callback,
521 void *userdata,
522 uint64_t usec,
523 uint32_t *serial) {
524 struct reply_callback *c;
525 uint32_t s;
526 int r, k;
527
528 assert_return(nl, -EINVAL)do { if (!(((__builtin_expect(!!(nl),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("nl"), "../src/libsystemd/sd-netlink/sd-netlink.c"
, 528, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
529 assert_return(m, -EINVAL)do { if (!(((__builtin_expect(!!(m),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-netlink/sd-netlink.c"
, 529, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
530 assert_return(callback, -EINVAL)do { if (!(((__builtin_expect(!!(callback),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("callback"), "../src/libsystemd/sd-netlink/sd-netlink.c"
, 530, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
531 assert_return(!rtnl_pid_changed(nl), -ECHILD)do { if (!(((__builtin_expect(!!(!rtnl_pid_changed(nl)),1))) ?
(1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("!rtnl_pid_changed(nl)"
), "../src/libsystemd/sd-netlink/sd-netlink.c", 531, __PRETTY_FUNCTION__
), 0))) return (-10); } while (0)
;
532
533 r = hashmap_ensure_allocated(&nl->reply_callbacks, &uint64_hash_ops)internal_hashmap_ensure_allocated(&nl->reply_callbacks
, &uint64_hash_ops )
;
534 if (r < 0)
535 return r;
536
537 if (usec != (uint64_t) -1) {
538 r = prioq_ensure_allocated(&nl->reply_callbacks_prioq, timeout_compare);
539 if (r < 0)
540 return r;
541 }
542
543 c = new0(struct reply_callback, 1)((struct reply_callback*) calloc((1), sizeof(struct reply_callback
)))
;
544 if (!c)
545 return -ENOMEM12;
546
547 c->callback = callback;
548 c->userdata = userdata;
549 c->timeout = calc_elapse(usec);
550
551 k = sd_netlink_send(nl, m, &s);
552 if (k < 0) {
553 free(c);
554 return k;
555 }
556
557 c->serial = s;
558
559 r = hashmap_put(nl->reply_callbacks, &c->serial, c);
560 if (r < 0) {
561 free(c);
562 return r;
563 }
564
565 if (c->timeout != 0) {
566 r = prioq_put(nl->reply_callbacks_prioq, c, &c->prioq_idx);
567 if (r > 0) {
568 c->timeout = 0;
569 sd_netlink_call_async_cancel(nl, c->serial);
570 return r;
571 }
572 }
573
574 if (serial)
575 *serial = s;
576
577 return k;
578}
579
580int sd_netlink_call_async_cancel(sd_netlink *nl, uint32_t serial) {
581 struct reply_callback *c;
582 uint64_t s = serial;
583
584 assert_return(nl, -EINVAL)do { if (!(((__builtin_expect(!!(nl),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("nl"), "../src/libsystemd/sd-netlink/sd-netlink.c"
, 584, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
585 assert_return(serial != 0, -EINVAL)do { if (!(((__builtin_expect(!!(serial != 0),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("serial != 0"), "../src/libsystemd/sd-netlink/sd-netlink.c"
, 585, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
586 assert_return(!rtnl_pid_changed(nl), -ECHILD)do { if (!(((__builtin_expect(!!(!rtnl_pid_changed(nl)),1))) ?
(1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("!rtnl_pid_changed(nl)"
), "../src/libsystemd/sd-netlink/sd-netlink.c", 586, __PRETTY_FUNCTION__
), 0))) return (-10); } while (0)
;
587
588 c = hashmap_remove(nl->reply_callbacks, &s);
589 if (!c)
590 return 0;
591
592 if (c->timeout != 0)
593 prioq_remove(nl->reply_callbacks_prioq, c, &c->prioq_idx);
594
595 free(c);
596 return 1;
597}
598
599int sd_netlink_call(sd_netlink *rtnl,
600 sd_netlink_message *message,
601 uint64_t usec,
602 sd_netlink_message **ret) {
603 usec_t timeout;
604 uint32_t serial;
605 int r;
606
607 assert_return(rtnl, -EINVAL)do { if (!(((__builtin_expect(!!(rtnl),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("rtnl"), "../src/libsystemd/sd-netlink/sd-netlink.c"
, 607, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
608 assert_return(!rtnl_pid_changed(rtnl), -ECHILD)do { if (!(((__builtin_expect(!!(!rtnl_pid_changed(rtnl)),1))
) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, (
"!rtnl_pid_changed(rtnl)"), "../src/libsystemd/sd-netlink/sd-netlink.c"
, 608, __PRETTY_FUNCTION__), 0))) return (-10); } while (0)
;
609 assert_return(message, -EINVAL)do { if (!(((__builtin_expect(!!(message),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("message"), "../src/libsystemd/sd-netlink/sd-netlink.c"
, 609, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
610
611 r = sd_netlink_send(rtnl, message, &serial);
612 if (r < 0)
613 return r;
614
615 timeout = calc_elapse(usec);
616
617 for (;;) {
618 usec_t left;
619 unsigned i;
620
621 for (i = 0; i < rtnl->rqueue_size; i++) {
622 uint32_t received_serial;
623
624 received_serial = rtnl_message_get_serial(rtnl->rqueue[i]);
625
626 if (received_serial == serial) {
627 _cleanup_(sd_netlink_message_unrefp)__attribute__((cleanup(sd_netlink_message_unrefp))) sd_netlink_message *incoming = NULL((void*)0);
628 uint16_t type;
629
630 incoming = rtnl->rqueue[i];
631
632 /* found a match, remove from rqueue and return it */
633 memmove(rtnl->rqueue + i,rtnl->rqueue + i + 1,
634 sizeof(sd_netlink_message*) * (rtnl->rqueue_size - i - 1));
635 rtnl->rqueue_size--;
636
637 r = sd_netlink_message_get_errno(incoming);
638 if (r < 0)
639 return r;
640
641 r = sd_netlink_message_get_type(incoming, &type);
642 if (r < 0)
643 return r;
644
645 if (type == NLMSG_DONE0x3) {
646 *ret = NULL((void*)0);
647 return 0;
648 }
649
650 if (ret)
651 *ret = TAKE_PTR(incoming)({ typeof(incoming) _ptr_ = (incoming); (incoming) = ((void*)
0); _ptr_; })
;
652
653 return 1;
654 }
655 }
656
657 r = socket_read_message(rtnl);
658 if (r < 0)
659 return r;
660 if (r > 0)
661 /* received message, so try to process straight away */
662 continue;
663
664 if (timeout > 0) {
665 usec_t n;
666
667 n = now(CLOCK_MONOTONIC1);
668 if (n >= timeout)
669 return -ETIMEDOUT110;
670
671 left = timeout - n;
672 } else
673 left = (uint64_t) -1;
674
675 r = rtnl_poll(rtnl, true1, left);
676 if (r < 0)
677 return r;
678 else if (r == 0)
679 return -ETIMEDOUT110;
680 }
681}
682
683int sd_netlink_get_events(sd_netlink *rtnl) {
684 assert_return(rtnl, -EINVAL)do { if (!(((__builtin_expect(!!(rtnl),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("rtnl"), "../src/libsystemd/sd-netlink/sd-netlink.c"
, 684, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
685 assert_return(!rtnl_pid_changed(rtnl), -ECHILD)do { if (!(((__builtin_expect(!!(!rtnl_pid_changed(rtnl)),1))
) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, (
"!rtnl_pid_changed(rtnl)"), "../src/libsystemd/sd-netlink/sd-netlink.c"
, 685, __PRETTY_FUNCTION__), 0))) return (-10); } while (0)
;
686
687 if (rtnl->rqueue_size == 0)
688 return POLLIN0x001;
689 else
690 return 0;
691}
692
693int sd_netlink_get_timeout(sd_netlink *rtnl, uint64_t *timeout_usec) {
694 struct reply_callback *c;
695
696 assert_return(rtnl, -EINVAL)do { if (!(((__builtin_expect(!!(rtnl),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("rtnl"), "../src/libsystemd/sd-netlink/sd-netlink.c"
, 696, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
697 assert_return(timeout_usec, -EINVAL)do { if (!(((__builtin_expect(!!(timeout_usec),1))) ? (1) : (
log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("timeout_usec"
), "../src/libsystemd/sd-netlink/sd-netlink.c", 697, __PRETTY_FUNCTION__
), 0))) return (-22); } while (0)
;
698 assert_return(!rtnl_pid_changed(rtnl), -ECHILD)do { if (!(((__builtin_expect(!!(!rtnl_pid_changed(rtnl)),1))
) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, (
"!rtnl_pid_changed(rtnl)"), "../src/libsystemd/sd-netlink/sd-netlink.c"
, 698, __PRETTY_FUNCTION__), 0))) return (-10); } while (0)
;
699
700 if (rtnl->rqueue_size > 0) {
701 *timeout_usec = 0;
702 return 1;
703 }
704
705 c = prioq_peek(rtnl->reply_callbacks_prioq);
706 if (!c) {
707 *timeout_usec = (uint64_t) -1;
708 return 0;
709 }
710
711 *timeout_usec = c->timeout;
712
713 return 1;
714}
715
716static int io_callback(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
717 sd_netlink *rtnl = userdata;
718 int r;
719
720 assert(rtnl)do { if ((__builtin_expect(!!(!(rtnl)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("rtnl"), "../src/libsystemd/sd-netlink/sd-netlink.c"
, 720, __PRETTY_FUNCTION__); } while (0)
;
721
722 r = sd_netlink_process(rtnl, NULL((void*)0));
723 if (r < 0)
724 return r;
725
726 return 1;
727}
728
729static int time_callback(sd_event_source *s, uint64_t usec, void *userdata) {
730 sd_netlink *rtnl = userdata;
731 int r;
732
733 assert(rtnl)do { if ((__builtin_expect(!!(!(rtnl)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("rtnl"), "../src/libsystemd/sd-netlink/sd-netlink.c"
, 733, __PRETTY_FUNCTION__); } while (0)
;
734
735 r = sd_netlink_process(rtnl, NULL((void*)0));
736 if (r < 0)
737 return r;
738
739 return 1;
740}
741
742static int prepare_callback(sd_event_source *s, void *userdata) {
743 sd_netlink *rtnl = userdata;
744 int r, e;
745 usec_t until;
746
747 assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("s"), "../src/libsystemd/sd-netlink/sd-netlink.c"
, 747, __PRETTY_FUNCTION__); } while (0)
;
748 assert(rtnl)do { if ((__builtin_expect(!!(!(rtnl)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("rtnl"), "../src/libsystemd/sd-netlink/sd-netlink.c"
, 748, __PRETTY_FUNCTION__); } while (0)
;
749
750 e = sd_netlink_get_events(rtnl);
751 if (e < 0)
752 return e;
753
754 r = sd_event_source_set_io_events(rtnl->io_event_source, e);
755 if (r < 0)
756 return r;
757
758 r = sd_netlink_get_timeout(rtnl, &until);
759 if (r < 0)
760 return r;
761 if (r > 0) {
762 int j;
763
764 j = sd_event_source_set_time(rtnl->time_event_source, until);
765 if (j < 0)
766 return j;
767 }
768
769 r = sd_event_source_set_enabled(rtnl->time_event_source, r > 0);
770 if (r < 0)
771 return r;
772
773 return 1;
774}
775
776int sd_netlink_attach_event(sd_netlink *rtnl, sd_event *event, int64_t priority) {
777 int r;
778
779 assert_return(rtnl, -EINVAL)do { if (!(((__builtin_expect(!!(rtnl),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("rtnl"), "../src/libsystemd/sd-netlink/sd-netlink.c"
, 779, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
780 assert_return(!rtnl->event, -EBUSY)do { if (!(((__builtin_expect(!!(!rtnl->event),1))) ? (1) :
(log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("!rtnl->event"
), "../src/libsystemd/sd-netlink/sd-netlink.c", 780, __PRETTY_FUNCTION__
), 0))) return (-16); } while (0)
;
781
782 assert(!rtnl->io_event_source)do { if ((__builtin_expect(!!(!(!rtnl->io_event_source)),0
))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("!rtnl->io_event_source"
), "../src/libsystemd/sd-netlink/sd-netlink.c", 782, __PRETTY_FUNCTION__
); } while (0)
;
783 assert(!rtnl->time_event_source)do { if ((__builtin_expect(!!(!(!rtnl->time_event_source))
,0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("!rtnl->time_event_source"
), "../src/libsystemd/sd-netlink/sd-netlink.c", 783, __PRETTY_FUNCTION__
); } while (0)
;
784
785 if (event)
786 rtnl->event = sd_event_ref(event);
787 else {
788 r = sd_event_default(&rtnl->event);
789 if (r < 0)
790 return r;
791 }
792
793 r = sd_event_add_io(rtnl->event, &rtnl->io_event_source, rtnl->fd, 0, io_callback, rtnl);
794 if (r < 0)
795 goto fail;
796
797 r = sd_event_source_set_priority(rtnl->io_event_source, priority);
798 if (r < 0)
799 goto fail;
800
801 r = sd_event_source_set_description(rtnl->io_event_source, "rtnl-receive-message");
802 if (r < 0)
803 goto fail;
804
805 r = sd_event_source_set_prepare(rtnl->io_event_source, prepare_callback);
806 if (r < 0)
807 goto fail;
808
809 r = sd_event_add_time(rtnl->event, &rtnl->time_event_source, CLOCK_MONOTONIC1, 0, 0, time_callback, rtnl);
810 if (r < 0)
811 goto fail;
812
813 r = sd_event_source_set_priority(rtnl->time_event_source, priority);
814 if (r < 0)
815 goto fail;
816
817 r = sd_event_source_set_description(rtnl->time_event_source, "rtnl-timer");
818 if (r < 0)
819 goto fail;
820
821 return 0;
822
823fail:
824 sd_netlink_detach_event(rtnl);
825 return r;
826}
827
828int sd_netlink_detach_event(sd_netlink *rtnl) {
829 assert_return(rtnl, -EINVAL)do { if (!(((__builtin_expect(!!(rtnl),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("rtnl"), "../src/libsystemd/sd-netlink/sd-netlink.c"
, 829, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
830 assert_return(rtnl->event, -ENXIO)do { if (!(((__builtin_expect(!!(rtnl->event),1))) ? (1) :
(log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("rtnl->event"
), "../src/libsystemd/sd-netlink/sd-netlink.c", 830, __PRETTY_FUNCTION__
), 0))) return (-6); } while (0)
;
831
832 rtnl->io_event_source = sd_event_source_unref(rtnl->io_event_source);
833
834 rtnl->time_event_source = sd_event_source_unref(rtnl->time_event_source);
835
836 rtnl->event = sd_event_unref(rtnl->event);
837
838 return 0;
839}
840
841int sd_netlink_add_match(sd_netlink *rtnl,
842 uint16_t type,
843 sd_netlink_message_handler_t callback,
844 void *userdata) {
845 _cleanup_free___attribute__((cleanup(freep))) struct match_callback *c = NULL((void*)0);
846 int r;
847
848 assert_return(rtnl, -EINVAL)do { if (!(((__builtin_expect(!!(rtnl),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("rtnl"), "../src/libsystemd/sd-netlink/sd-netlink.c"
, 848, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
1
Assuming 'rtnl' is non-null
2
'?' condition is true
3
Taking false branch
4
Loop condition is false. Exiting loop
849 assert_return(callback, -EINVAL)do { if (!(((__builtin_expect(!!(callback),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("callback"), "../src/libsystemd/sd-netlink/sd-netlink.c"
, 849, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
5
Assuming 'callback' is non-null
6
'?' condition is true
7
Taking false branch
8
Loop condition is false. Exiting loop
850 assert_return(!rtnl_pid_changed(rtnl), -ECHILD)do { if (!(((__builtin_expect(!!(!rtnl_pid_changed(rtnl)),1))
) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, (
"!rtnl_pid_changed(rtnl)"), "../src/libsystemd/sd-netlink/sd-netlink.c"
, 850, __PRETTY_FUNCTION__), 0))) return (-10); } while (0)
;
9
'?' condition is true
10
Taking false branch
11
Loop condition is false. Exiting loop
851
852 c = new0(struct match_callback, 1)((struct match_callback*) calloc((1), sizeof(struct match_callback
)))
;
12
Memory is allocated
853 if (!c)
13
Assuming 'c' is non-null
14
Taking false branch
854 return -ENOMEM12;
855
856 c->callback = callback;
857 c->type = type;
858 c->userdata = userdata;
859
860 switch (type) {
15
Control jumps to the 'default' case at line 899
861 case RTM_NEWLINKRTM_NEWLINK:
862 case RTM_DELLINKRTM_DELLINK:
863 r = socket_broadcast_group_ref(rtnl, RTNLGRP_LINKRTNLGRP_LINK);
864 if (r < 0)
865 return r;
866
867 break;
868 case RTM_NEWADDRRTM_NEWADDR:
869 case RTM_DELADDRRTM_DELADDR:
870 r = socket_broadcast_group_ref(rtnl, RTNLGRP_IPV4_IFADDRRTNLGRP_IPV4_IFADDR);
871 if (r < 0)
872 return r;
873
874 r = socket_broadcast_group_ref(rtnl, RTNLGRP_IPV6_IFADDRRTNLGRP_IPV6_IFADDR);
875 if (r < 0)
876 return r;
877
878 break;
879 case RTM_NEWROUTERTM_NEWROUTE:
880 case RTM_DELROUTERTM_DELROUTE:
881 r = socket_broadcast_group_ref(rtnl, RTNLGRP_IPV4_ROUTERTNLGRP_IPV4_ROUTE);
882 if (r < 0)
883 return r;
884
885 r = socket_broadcast_group_ref(rtnl, RTNLGRP_IPV6_ROUTERTNLGRP_IPV6_ROUTE);
886 if (r < 0)
887 return r;
888 break;
889 case RTM_NEWRULERTM_NEWRULE:
890 case RTM_DELRULERTM_DELRULE:
891 r = socket_broadcast_group_ref(rtnl, RTNLGRP_IPV4_RULERTNLGRP_IPV4_RULE);
892 if (r < 0)
893 return r;
894
895 r = socket_broadcast_group_ref(rtnl, RTNLGRP_IPV6_RULERTNLGRP_IPV6_RULE);
896 if (r < 0)
897 return r;
898 break;
899 default:
900 return -EOPNOTSUPP95;
16
Potential leak of memory pointed to by 'c'
901 }
902
903 LIST_PREPEND(match_callbacks, rtnl->match_callbacks, c)do { typeof(*(rtnl->match_callbacks)) **_head = &(rtnl
->match_callbacks), *_item = (c); do { if ((__builtin_expect
(!!(!(_item)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD,
("_item"), "../src/libsystemd/sd-netlink/sd-netlink.c", 903,
__PRETTY_FUNCTION__); } while (0); if ((_item->match_callbacks_next
= *_head)) _item->match_callbacks_next->match_callbacks_prev
= _item; _item->match_callbacks_prev = ((void*)0); *_head
= _item; } while (0)
;
904
905 c = NULL((void*)0);
906
907 return 0;
908}
909
910int sd_netlink_remove_match(sd_netlink *rtnl,
911 uint16_t type,
912 sd_netlink_message_handler_t callback,
913 void *userdata) {
914 struct match_callback *c;
915 int r;
916
917 assert_return(rtnl, -EINVAL)do { if (!(((__builtin_expect(!!(rtnl),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("rtnl"), "../src/libsystemd/sd-netlink/sd-netlink.c"
, 917, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
918 assert_return(callback, -EINVAL)do { if (!(((__builtin_expect(!!(callback),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("callback"), "../src/libsystemd/sd-netlink/sd-netlink.c"
, 918, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
919 assert_return(!rtnl_pid_changed(rtnl), -ECHILD)do { if (!(((__builtin_expect(!!(!rtnl_pid_changed(rtnl)),1))
) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, (
"!rtnl_pid_changed(rtnl)"), "../src/libsystemd/sd-netlink/sd-netlink.c"
, 919, __PRETTY_FUNCTION__), 0))) return (-10); } while (0)
;
920
921 LIST_FOREACH(match_callbacks, c, rtnl->match_callbacks)for ((c) = (rtnl->match_callbacks); (c); (c) = (c)->match_callbacks_next
)
922 if (c->callback == callback && c->type == type && c->userdata == userdata) {
923 LIST_REMOVE(match_callbacks, rtnl->match_callbacks, c)do { typeof(*(rtnl->match_callbacks)) **_head = &(rtnl
->match_callbacks), *_item = (c); do { if ((__builtin_expect
(!!(!(_item)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD,
("_item"), "../src/libsystemd/sd-netlink/sd-netlink.c", 923,
__PRETTY_FUNCTION__); } while (0); if (_item->match_callbacks_next
) _item->match_callbacks_next->match_callbacks_prev = _item
->match_callbacks_prev; if (_item->match_callbacks_prev
) _item->match_callbacks_prev->match_callbacks_next = _item
->match_callbacks_next; else { do { if ((__builtin_expect(
!!(!(*_head == _item)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD
, ("*_head == _item"), "../src/libsystemd/sd-netlink/sd-netlink.c"
, 923, __PRETTY_FUNCTION__); } while (0); *_head = _item->
match_callbacks_next; } _item->match_callbacks_next = _item
->match_callbacks_prev = ((void*)0); } while (0)
;
924 free(c);
925
926 switch (type) {
927 case RTM_NEWLINKRTM_NEWLINK:
928 case RTM_DELLINKRTM_DELLINK:
929 r = socket_broadcast_group_unref(rtnl, RTNLGRP_LINKRTNLGRP_LINK);
930 if (r < 0)
931 return r;
932
933 break;
934 case RTM_NEWADDRRTM_NEWADDR:
935 case RTM_DELADDRRTM_DELADDR:
936 r = socket_broadcast_group_unref(rtnl, RTNLGRP_IPV4_IFADDRRTNLGRP_IPV4_IFADDR);
937 if (r < 0)
938 return r;
939
940 r = socket_broadcast_group_unref(rtnl, RTNLGRP_IPV6_IFADDRRTNLGRP_IPV6_IFADDR);
941 if (r < 0)
942 return r;
943
944 break;
945 case RTM_NEWROUTERTM_NEWROUTE:
946 case RTM_DELROUTERTM_DELROUTE:
947 r = socket_broadcast_group_unref(rtnl, RTNLGRP_IPV4_ROUTERTNLGRP_IPV4_ROUTE);
948 if (r < 0)
949 return r;
950
951 r = socket_broadcast_group_unref(rtnl, RTNLGRP_IPV6_ROUTERTNLGRP_IPV6_ROUTE);
952 if (r < 0)
953 return r;
954 break;
955 default:
956 return -EOPNOTSUPP95;
957 }
958
959 return 1;
960 }
961
962 return 0;
963}