]>
Commit | Line | Data |
---|---|---|
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 | 12 | int 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 | ||
52 | void 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 | ||
108 | static 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 | ||
120 | DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_netlink_slot, sd_netlink_slot, netlink_slot_free); | |
1a7baaa9 YW |
121 | |
122 | sd_netlink *sd_netlink_slot_get_netlink(sd_netlink_slot *slot) { | |
123 | assert_return(slot, NULL); | |
124 | ||
125 | return slot->netlink; | |
126 | } | |
127 | ||
128 | void *sd_netlink_slot_get_userdata(sd_netlink_slot *slot) { | |
129 | assert_return(slot, NULL); | |
130 | ||
131 | return slot->userdata; | |
132 | } | |
133 | ||
134 | void *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 | ||
145 | int 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 | ||
154 | int 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 | ||
161 | int sd_netlink_slot_get_floating(sd_netlink_slot *slot) { | |
162 | assert_return(slot, -EINVAL); | |
163 | ||
164 | return slot->floating; | |
165 | } | |
166 | ||
167 | int 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 | |
189 | int 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 | ||
198 | int 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 | } |