]>
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" | |
10 | ||
11 | sd_netlink_slot *netlink_slot_allocate( | |
12 | sd_netlink *nl, | |
13 | bool floating, | |
14 | NetlinkSlotType type, | |
15 | size_t extra, | |
16 | sd_netlink_destroy_t destroy_callback, | |
17 | void *userdata) { | |
18 | ||
19 | sd_netlink_slot *slot; | |
20 | ||
21 | assert(nl); | |
22 | ||
23 | slot = malloc0(offsetof(sd_netlink_slot, reply_callback) + extra); | |
24 | if (!slot) | |
25 | return NULL; | |
26 | ||
27 | slot->n_ref = 1; | |
28 | slot->netlink = nl; | |
29 | slot->userdata = userdata; | |
30 | slot->destroy_callback = destroy_callback; | |
31 | slot->type = type; | |
32 | slot->floating = floating; | |
33 | ||
34 | if (!floating) | |
35 | sd_netlink_ref(nl); | |
36 | ||
37 | LIST_PREPEND(slots, nl->slots, slot); | |
38 | ||
39 | return slot; | |
40 | } | |
41 | ||
42 | void netlink_slot_disconnect(sd_netlink_slot *slot, bool unref) { | |
43 | sd_netlink *nl; | |
44 | ||
45 | assert(slot); | |
46 | ||
47 | nl = slot->netlink; | |
48 | if (!nl) | |
49 | return; | |
50 | ||
51 | switch (slot->type) { | |
52 | ||
53 | case NETLINK_REPLY_CALLBACK: | |
54 | (void) hashmap_remove(nl->reply_callbacks, &slot->reply_callback.serial); | |
55 | ||
56 | if (slot->reply_callback.timeout != 0) | |
57 | prioq_remove(nl->reply_callbacks_prioq, &slot->reply_callback, &slot->reply_callback.prioq_idx); | |
58 | ||
59 | break; | |
60 | case NETLINK_MATCH_CALLBACK: | |
61 | LIST_REMOVE(match_callbacks, nl->match_callbacks, &slot->match_callback); | |
62 | ||
63 | switch (slot->match_callback.type) { | |
64 | case RTM_NEWLINK: | |
65 | case RTM_DELLINK: | |
66 | (void) socket_broadcast_group_unref(nl, RTNLGRP_LINK); | |
67 | ||
68 | break; | |
69 | case RTM_NEWADDR: | |
70 | case RTM_DELADDR: | |
71 | (void) socket_broadcast_group_unref(nl, RTNLGRP_IPV4_IFADDR); | |
72 | (void) socket_broadcast_group_unref(nl, RTNLGRP_IPV6_IFADDR); | |
73 | ||
74 | break; | |
75 | case RTM_NEWROUTE: | |
76 | case RTM_DELROUTE: | |
77 | (void) socket_broadcast_group_unref(nl, RTNLGRP_IPV4_ROUTE); | |
78 | (void) socket_broadcast_group_unref(nl, RTNLGRP_IPV6_ROUTE); | |
79 | ||
80 | break; | |
81 | } | |
82 | ||
83 | break; | |
84 | default: | |
85 | assert_not_reached("Wut? Unknown slot type?"); | |
86 | } | |
87 | ||
88 | slot->type = _NETLINK_SLOT_INVALID; | |
89 | slot->netlink = NULL; | |
90 | LIST_REMOVE(slots, nl->slots, slot); | |
91 | ||
92 | if (!slot->floating) | |
93 | sd_netlink_unref(nl); | |
94 | else if (unref) | |
95 | sd_netlink_slot_unref(slot); | |
96 | } | |
97 | ||
98 | static sd_netlink_slot* netlink_slot_free(sd_netlink_slot *slot) { | |
99 | assert(slot); | |
100 | ||
101 | netlink_slot_disconnect(slot, false); | |
102 | ||
103 | if (slot->destroy_callback) | |
104 | slot->destroy_callback(slot->userdata); | |
105 | ||
106 | return mfree(slot); | |
107 | } | |
108 | ||
109 | DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_netlink_slot, sd_netlink_slot, netlink_slot_free); |