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