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(
17 sd_netlink_destroy_t destroy_callback
,
19 const char *description
,
20 sd_netlink_slot
**ret
) {
22 _cleanup_free_ sd_netlink_slot
*slot
= NULL
;
27 slot
= malloc0(offsetof(sd_netlink_slot
, reply_callback
) + extra
);
33 slot
->userdata
= userdata
;
34 slot
->destroy_callback
= destroy_callback
;
36 slot
->floating
= floating
;
39 slot
->description
= strdup(description
);
40 if (!slot
->description
)
47 LIST_PREPEND(slots
, nl
->slots
, slot
);
49 *ret
= TAKE_PTR(slot
);
54 void netlink_slot_disconnect(sd_netlink_slot
*slot
, bool unref
) {
65 case NETLINK_REPLY_CALLBACK
:
66 (void) hashmap_remove(nl
->reply_callbacks
, &slot
->reply_callback
.serial
);
68 if (slot
->reply_callback
.timeout
!= 0)
69 prioq_remove(nl
->reply_callbacks_prioq
, &slot
->reply_callback
, &slot
->reply_callback
.prioq_idx
);
72 case NETLINK_MATCH_CALLBACK
:
73 LIST_REMOVE(match_callbacks
, nl
->match_callbacks
, &slot
->match_callback
);
75 switch (slot
->match_callback
.type
) {
78 (void) socket_broadcast_group_unref(nl
, RTNLGRP_LINK
);
83 (void) socket_broadcast_group_unref(nl
, RTNLGRP_IPV4_IFADDR
);
84 (void) socket_broadcast_group_unref(nl
, RTNLGRP_IPV6_IFADDR
);
89 (void) socket_broadcast_group_unref(nl
, RTNLGRP_IPV4_ROUTE
);
90 (void) socket_broadcast_group_unref(nl
, RTNLGRP_IPV6_ROUTE
);
97 assert_not_reached("Wut? Unknown slot type?");
100 slot
->type
= _NETLINK_SLOT_INVALID
;
101 slot
->netlink
= NULL
;
102 LIST_REMOVE(slots
, nl
->slots
, slot
);
105 sd_netlink_unref(nl
);
107 sd_netlink_slot_unref(slot
);
110 static sd_netlink_slot
* netlink_slot_free(sd_netlink_slot
*slot
) {
113 netlink_slot_disconnect(slot
, false);
115 if (slot
->destroy_callback
)
116 slot
->destroy_callback(slot
->userdata
);
118 free(slot
->description
);
122 DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_netlink_slot
, sd_netlink_slot
, netlink_slot_free
);
124 sd_netlink
*sd_netlink_slot_get_netlink(sd_netlink_slot
*slot
) {
125 assert_return(slot
, NULL
);
127 return slot
->netlink
;
130 void *sd_netlink_slot_get_userdata(sd_netlink_slot
*slot
) {
131 assert_return(slot
, NULL
);
133 return slot
->userdata
;
136 void *sd_netlink_slot_set_userdata(sd_netlink_slot
*slot
, void *userdata
) {
139 assert_return(slot
, NULL
);
141 ret
= slot
->userdata
;
142 slot
->userdata
= userdata
;
147 int sd_netlink_slot_get_destroy_callback(sd_netlink_slot
*slot
, sd_netlink_destroy_t
*callback
) {
148 assert_return(slot
, -EINVAL
);
151 *callback
= slot
->destroy_callback
;
153 return !!slot
->destroy_callback
;
156 int sd_netlink_slot_set_destroy_callback(sd_netlink_slot
*slot
, sd_netlink_destroy_t callback
) {
157 assert_return(slot
, -EINVAL
);
159 slot
->destroy_callback
= callback
;
163 int sd_netlink_slot_get_floating(sd_netlink_slot
*slot
) {
164 assert_return(slot
, -EINVAL
);
166 return slot
->floating
;
169 int sd_netlink_slot_set_floating(sd_netlink_slot
*slot
, int b
) {
170 assert_return(slot
, -EINVAL
);
172 if (slot
->floating
== !!b
)
175 if (!slot
->netlink
) /* Already disconnected */
181 sd_netlink_slot_ref(slot
);
182 sd_netlink_unref(slot
->netlink
);
184 sd_netlink_ref(slot
->netlink
);
185 sd_netlink_slot_unref(slot
);
191 int sd_netlink_slot_get_description(sd_netlink_slot
*slot
, const char **description
) {
192 assert_return(slot
, -EINVAL
);
195 *description
= slot
->description
;
197 return !!slot
->description
;
200 int sd_netlink_slot_set_description(sd_netlink_slot
*slot
, const char *description
) {
201 assert_return(slot
, -EINVAL
);
203 return free_and_strdup(&slot
->description
, description
);