Branch data Line data Source code
1 : : /* SPDX-License-Identifier: LGPL-2.1+ */
2 : :
3 : : #include <errno.h>
4 : :
5 : : #include "sd-netlink.h"
6 : :
7 : : #include "alloc-util.h"
8 : : #include "netlink-internal.h"
9 : : #include "netlink-slot.h"
10 : : #include "string-util.h"
11 : :
12 : 124 : int netlink_slot_allocate(
13 : : sd_netlink *nl,
14 : : bool floating,
15 : : NetlinkSlotType type,
16 : : size_t extra,
17 : : void *userdata,
18 : : const char *description,
19 : : sd_netlink_slot **ret) {
20 : :
21 : 124 : _cleanup_free_ sd_netlink_slot *slot = NULL;
22 : :
23 [ - + ]: 124 : assert(nl);
24 [ - + ]: 124 : assert(ret);
25 : :
26 : 124 : slot = malloc0(offsetof(sd_netlink_slot, reply_callback) + extra);
27 [ - + ]: 124 : if (!slot)
28 : 0 : return -ENOMEM;
29 : :
30 : 124 : slot->n_ref = 1;
31 : 124 : slot->netlink = nl;
32 : 124 : slot->userdata = userdata;
33 : 124 : slot->type = type;
34 : 124 : slot->floating = floating;
35 : :
36 [ + + ]: 124 : if (description) {
37 : 84 : slot->description = strdup(description);
38 [ - + ]: 84 : if (!slot->description)
39 : 0 : return -ENOMEM;
40 : : }
41 : :
42 [ + + ]: 124 : if (!floating)
43 : 20 : sd_netlink_ref(nl);
44 : :
45 [ - + + + ]: 124 : LIST_PREPEND(slots, nl->slots, slot);
46 : :
47 : 124 : *ret = TAKE_PTR(slot);
48 : :
49 : 124 : return 0;
50 : : }
51 : :
52 : 232 : void netlink_slot_disconnect(sd_netlink_slot *slot, bool unref) {
53 : : sd_netlink *nl;
54 : :
55 [ - + ]: 232 : assert(slot);
56 : :
57 : 232 : nl = slot->netlink;
58 [ + + ]: 232 : if (!nl)
59 : 108 : return;
60 : :
61 [ + + - ]: 124 : switch (slot->type) {
62 : :
63 : 72 : case NETLINK_REPLY_CALLBACK:
64 : 72 : (void) hashmap_remove(nl->reply_callbacks, &slot->reply_callback.serial);
65 : :
66 [ + + ]: 72 : if (slot->reply_callback.timeout != 0)
67 : 36 : prioq_remove(nl->reply_callbacks_prioq, &slot->reply_callback, &slot->reply_callback.prioq_idx);
68 : :
69 : 72 : break;
70 : 52 : case NETLINK_MATCH_CALLBACK:
71 [ - + + + : 52 : LIST_REMOVE(match_callbacks, nl->match_callbacks, &slot->match_callback);
+ + - + ]
72 : :
73 [ + + + + ]: 52 : switch (slot->match_callback.type) {
74 : 20 : case RTM_NEWLINK:
75 : : case RTM_DELLINK:
76 : 20 : (void) socket_broadcast_group_unref(nl, RTNLGRP_LINK);
77 : :
78 : 20 : break;
79 : 8 : case RTM_NEWADDR:
80 : : case RTM_DELADDR:
81 : 8 : (void) socket_broadcast_group_unref(nl, RTNLGRP_IPV4_IFADDR);
82 : 8 : (void) socket_broadcast_group_unref(nl, RTNLGRP_IPV6_IFADDR);
83 : :
84 : 8 : break;
85 : 8 : case RTM_NEWROUTE:
86 : : case RTM_DELROUTE:
87 : 8 : (void) socket_broadcast_group_unref(nl, RTNLGRP_IPV4_ROUTE);
88 : 8 : (void) socket_broadcast_group_unref(nl, RTNLGRP_IPV6_ROUTE);
89 : :
90 : 8 : break;
91 : : }
92 : :
93 : 52 : break;
94 : 0 : default:
95 : 0 : assert_not_reached("Wut? Unknown slot type?");
96 : : }
97 : :
98 : 124 : slot->type = _NETLINK_SLOT_INVALID;
99 : 124 : slot->netlink = NULL;
100 [ - + + + : 124 : LIST_REMOVE(slots, nl->slots, slot);
+ + - + ]
101 : :
102 [ + + ]: 124 : if (!slot->floating)
103 : 16 : sd_netlink_unref(nl);
104 [ + - ]: 108 : else if (unref)
105 : 108 : sd_netlink_slot_unref(slot);
106 : : }
107 : :
108 : 124 : static sd_netlink_slot* netlink_slot_free(sd_netlink_slot *slot) {
109 [ - + ]: 124 : assert(slot);
110 : :
111 : 124 : netlink_slot_disconnect(slot, false);
112 : :
113 [ + + ]: 124 : if (slot->destroy_callback)
114 : 48 : slot->destroy_callback(slot->userdata);
115 : :
116 : 124 : free(slot->description);
117 : 124 : return mfree(slot);
118 : : }
119 : :
120 [ - + - + : 132 : DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_netlink_slot, sd_netlink_slot, netlink_slot_free);
+ + ]
121 : :
122 : 8 : sd_netlink *sd_netlink_slot_get_netlink(sd_netlink_slot *slot) {
123 [ - + - + ]: 8 : assert_return(slot, NULL);
124 : :
125 : 8 : return slot->netlink;
126 : : }
127 : :
128 : 12 : void *sd_netlink_slot_get_userdata(sd_netlink_slot *slot) {
129 [ - + - + ]: 12 : assert_return(slot, NULL);
130 : :
131 : 12 : return slot->userdata;
132 : : }
133 : :
134 : 4 : void *sd_netlink_slot_set_userdata(sd_netlink_slot *slot, void *userdata) {
135 : : void *ret;
136 : :
137 [ - + - + ]: 4 : assert_return(slot, NULL);
138 : :
139 : 4 : ret = slot->userdata;
140 : 4 : slot->userdata = userdata;
141 : :
142 : 4 : return ret;
143 : : }
144 : :
145 : 12 : int sd_netlink_slot_get_destroy_callback(sd_netlink_slot *slot, sd_netlink_destroy_t *callback) {
146 [ - + - + ]: 12 : assert_return(slot, -EINVAL);
147 : :
148 [ + + ]: 12 : if (callback)
149 : 8 : *callback = slot->destroy_callback;
150 : :
151 : 12 : return !!slot->destroy_callback;
152 : : }
153 : :
154 : 4 : int sd_netlink_slot_set_destroy_callback(sd_netlink_slot *slot, sd_netlink_destroy_t callback) {
155 [ - + - + ]: 4 : assert_return(slot, -EINVAL);
156 : :
157 : 4 : slot->destroy_callback = callback;
158 : 4 : return 0;
159 : : }
160 : :
161 : 12 : int sd_netlink_slot_get_floating(sd_netlink_slot *slot) {
162 [ - + - + ]: 12 : assert_return(slot, -EINVAL);
163 : :
164 : 12 : return slot->floating;
165 : : }
166 : :
167 : 4 : int sd_netlink_slot_set_floating(sd_netlink_slot *slot, int b) {
168 [ - + - + ]: 4 : assert_return(slot, -EINVAL);
169 : :
170 [ - + ]: 4 : if (slot->floating == !!b)
171 : 0 : return 0;
172 : :
173 [ - + ]: 4 : if (!slot->netlink) /* Already disconnected */
174 : 0 : return -ESTALE;
175 : :
176 : 4 : slot->floating = b;
177 : :
178 [ + - ]: 4 : if (b) {
179 : 4 : sd_netlink_slot_ref(slot);
180 : 4 : sd_netlink_unref(slot->netlink);
181 : : } else {
182 : 0 : sd_netlink_ref(slot->netlink);
183 : 0 : sd_netlink_slot_unref(slot);
184 : : }
185 : :
186 : 4 : return 1;
187 : : }
188 : :
189 : 12 : int sd_netlink_slot_get_description(sd_netlink_slot *slot, const char **description) {
190 [ - + - + ]: 12 : assert_return(slot, -EINVAL);
191 : :
192 [ + + ]: 12 : if (description)
193 : 8 : *description = slot->description;
194 : :
195 : 12 : return !!slot->description;
196 : : }
197 : :
198 : 4 : int sd_netlink_slot_set_description(sd_netlink_slot *slot, const char *description) {
199 [ - + - + ]: 4 : assert_return(slot, -EINVAL);
200 : :
201 : 4 : return free_and_strdup(&slot->description, description);
202 : : }
|