1 /* SPDX-License-Identifier: LGPL-2.1+ */
5 #include "sd-netlink.h"
7 #include "alloc-util.h"
8 #include "netlink-internal.h"
9 #include "netlink-slot.h"
10 #include "string-util.h"
12 int netlink_slot_allocate(
18 const char *description
,
19 sd_netlink_slot
**ret
) {
21 _cleanup_free_ sd_netlink_slot
*slot
= NULL
;
26 slot
= malloc0(offsetof(sd_netlink_slot
, reply_callback
) + extra
);
32 slot
->userdata
= userdata
;
34 slot
->floating
= floating
;
37 slot
->description
= strdup(description
);
38 if (!slot
->description
)
45 LIST_PREPEND(slots
, nl
->slots
, slot
);
47 *ret
= TAKE_PTR(slot
);
52 void netlink_slot_disconnect(sd_netlink_slot
*slot
, bool unref
) {
63 case NETLINK_REPLY_CALLBACK
:
64 (void) hashmap_remove(nl
->reply_callbacks
, &slot
->reply_callback
.serial
);
66 if (slot
->reply_callback
.timeout
!= 0)
67 prioq_remove(nl
->reply_callbacks_prioq
, &slot
->reply_callback
, &slot
->reply_callback
.prioq_idx
);
70 case NETLINK_MATCH_CALLBACK
:
71 LIST_REMOVE(match_callbacks
, nl
->match_callbacks
, &slot
->match_callback
);
73 switch (slot
->match_callback
.type
) {
76 (void) socket_broadcast_group_unref(nl
, RTNLGRP_LINK
);
81 (void) socket_broadcast_group_unref(nl
, RTNLGRP_IPV4_IFADDR
);
82 (void) socket_broadcast_group_unref(nl
, RTNLGRP_IPV6_IFADDR
);
87 (void) socket_broadcast_group_unref(nl
, RTNLGRP_IPV4_ROUTE
);
88 (void) socket_broadcast_group_unref(nl
, RTNLGRP_IPV6_ROUTE
);
95 assert_not_reached("Wut? Unknown slot type?");
98 slot
->type
= _NETLINK_SLOT_INVALID
;
100 LIST_REMOVE(slots
, nl
->slots
, slot
);
103 sd_netlink_unref(nl
);
105 sd_netlink_slot_unref(slot
);
108 static sd_netlink_slot
* netlink_slot_free(sd_netlink_slot
*slot
) {
111 netlink_slot_disconnect(slot
, false);
113 if (slot
->destroy_callback
)
114 slot
->destroy_callback(slot
->userdata
);
116 free(slot
->description
);
120 DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_netlink_slot
, sd_netlink_slot
, netlink_slot_free
);
122 sd_netlink
*sd_netlink_slot_get_netlink(sd_netlink_slot
*slot
) {
123 assert_return(slot
, NULL
);
125 return slot
->netlink
;
128 void *sd_netlink_slot_get_userdata(sd_netlink_slot
*slot
) {
129 assert_return(slot
, NULL
);
131 return slot
->userdata
;
134 void *sd_netlink_slot_set_userdata(sd_netlink_slot
*slot
, void *userdata
) {
137 assert_return(slot
, NULL
);
139 ret
= slot
->userdata
;
140 slot
->userdata
= userdata
;
145 int sd_netlink_slot_get_destroy_callback(sd_netlink_slot
*slot
, sd_netlink_destroy_t
*callback
) {
146 assert_return(slot
, -EINVAL
);
149 *callback
= slot
->destroy_callback
;
151 return !!slot
->destroy_callback
;
154 int sd_netlink_slot_set_destroy_callback(sd_netlink_slot
*slot
, sd_netlink_destroy_t callback
) {
155 assert_return(slot
, -EINVAL
);
157 slot
->destroy_callback
= callback
;
161 int sd_netlink_slot_get_floating(sd_netlink_slot
*slot
) {
162 assert_return(slot
, -EINVAL
);
164 return slot
->floating
;
167 int sd_netlink_slot_set_floating(sd_netlink_slot
*slot
, int b
) {
168 assert_return(slot
, -EINVAL
);
170 if (slot
->floating
== !!b
)
173 if (!slot
->netlink
) /* Already disconnected */
179 sd_netlink_slot_ref(slot
);
180 sd_netlink_unref(slot
->netlink
);
182 sd_netlink_ref(slot
->netlink
);
183 sd_netlink_slot_unref(slot
);
189 int sd_netlink_slot_get_description(sd_netlink_slot
*slot
, const char **description
) {
190 assert_return(slot
, -EINVAL
);
193 *description
= slot
->description
;
195 return !!slot
->description
;
198 int sd_netlink_slot_set_description(sd_netlink_slot
*slot
, const char *description
) {
199 assert_return(slot
, -EINVAL
);
201 return free_and_strdup(&slot
->description
, description
);