]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd/sd-netlink/netlink-slot.c
sd-netlink: introduce sd_netlink_slot
[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"
10
11sd_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
42void 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
98static 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
109DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_netlink_slot, sd_netlink_slot, netlink_slot_free);