File: | build-scan/../src/libsystemd/sd-netlink/sd-netlink.c |
Warning: | line 133, column 9 Value stored to 'fd' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | |
19 | static 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 | |
52 | int 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 | |
79 | static 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 | |
88 | int 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 | |
121 | int 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; |
Value stored to 'fd' is never read | |
134 | |
135 | return 0; |
136 | } |
137 | |
138 | int sd_netlink_open(sd_netlink **ret) { |
139 | return netlink_open_family(ret, NETLINK_ROUTE0); |
140 | } |
141 | |
142 | int 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 | |
149 | sd_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 | |
159 | sd_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 | |
199 | static 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 | |
214 | int 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 | |
236 | int 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 | |
250 | int 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 | |
265 | static 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 | |
290 | static 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 | |
322 | static 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 | |
353 | static 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 | |
380 | static 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 | |
414 | null_message: |
415 | if (r >= 0 && ret) |
416 | *ret = NULL((void*)0); |
417 | |
418 | return r; |
419 | } |
420 | |
421 | int 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 | |
436 | static 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 | |
446 | static 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 | |
490 | int 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 | |
500 | static 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 | |
518 | int 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 | |
580 | int 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 | |
599 | int 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 | |
683 | int 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 | |
693 | int 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 | |
716 | static 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 | |
729 | static 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 | |
742 | static 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 | |
776 | int 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 | |
823 | fail: |
824 | sd_netlink_detach_event(rtnl); |
825 | return r; |
826 | } |
827 | |
828 | int 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 | |
841 | int 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); |
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); |
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); |
851 | |
852 | c = new0(struct match_callback, 1)((struct match_callback*) calloc((1), sizeof(struct match_callback ))); |
853 | if (!c) |
854 | return -ENOMEM12; |
855 | |
856 | c->callback = callback; |
857 | c->type = type; |
858 | c->userdata = userdata; |
859 | |
860 | switch (type) { |
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; |
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 | |
910 | int 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 | } |