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