]>
Commit | Line | Data |
---|---|---|
53e1b683 | 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ |
a2cdd907 LP |
2 | #pragma once |
3 | ||
a33dece5 LP |
4 | #include <linux/netlink.h> |
5 | ||
1c4baffc | 6 | #include "sd-netlink.h" |
e16bcf98 | 7 | |
07630cea | 8 | #include "list.h" |
1c4baffc | 9 | #include "netlink-types.h" |
07630cea LP |
10 | #include "prioq.h" |
11 | #include "refcnt.h" | |
d8e538ec | 12 | |
59a7a684 | 13 | #define RTNL_DEFAULT_TIMEOUT ((usec_t) (25 * USEC_PER_SEC)) |
3815f36f TG |
14 | |
15 | #define RTNL_WQUEUE_MAX 1024 | |
16 | #define RTNL_RQUEUE_MAX 64*1024 | |
17 | ||
18 | #define RTNL_CONTAINER_DEPTH 32 | |
19 | ||
e16bcf98 | 20 | struct reply_callback { |
1c4baffc | 21 | sd_netlink_message_handler_t callback; |
e16bcf98 TG |
22 | usec_t timeout; |
23 | uint64_t serial; | |
24 | unsigned prioq_idx; | |
25 | }; | |
65f568bb | 26 | |
8cec01b9 | 27 | struct match_callback { |
1c4baffc | 28 | sd_netlink_message_handler_t callback; |
23a7f0f7 | 29 | uint16_t type; |
8cec01b9 TG |
30 | |
31 | LIST_FIELDS(struct match_callback, match_callbacks); | |
32 | }; | |
33 | ||
ee38400b YW |
34 | typedef enum NetlinkSlotType { |
35 | NETLINK_REPLY_CALLBACK, | |
36 | NETLINK_MATCH_CALLBACK, | |
37 | _NETLINK_SLOT_INVALID = -1, | |
38 | } NetlinkSlotType; | |
39 | ||
40 | struct sd_netlink_slot { | |
41 | unsigned n_ref; | |
42 | sd_netlink *netlink; | |
43 | void *userdata; | |
44 | sd_netlink_destroy_t destroy_callback; | |
45 | NetlinkSlotType type:2; | |
46 | ||
47 | bool floating:1; | |
8190a388 | 48 | char *description; |
ee38400b YW |
49 | |
50 | LIST_FIELDS(sd_netlink_slot, slots); | |
51 | ||
52 | union { | |
53 | struct reply_callback reply_callback; | |
54 | struct match_callback match_callback; | |
55 | }; | |
56 | }; | |
57 | ||
1c4baffc | 58 | struct sd_netlink { |
65f568bb TG |
59 | RefCount n_ref; |
60 | ||
61 | int fd; | |
62 | ||
63 | union { | |
64 | struct sockaddr sa; | |
65 | struct sockaddr_nl nl; | |
66 | } sockaddr; | |
67 | ||
05d0c2e3 JT |
68 | int protocol; |
69 | ||
9c5a882b TG |
70 | Hashmap *broadcast_group_refs; |
71 | bool broadcast_group_dont_leave:1; /* until we can rely on 4.2 */ | |
72 | ||
1c4baffc | 73 | sd_netlink_message **rqueue; |
4555ec72 | 74 | unsigned rqueue_size; |
77768cba | 75 | size_t rqueue_allocated; |
4555ec72 | 76 | |
1c4baffc | 77 | sd_netlink_message **rqueue_partial; |
4e996881 TG |
78 | unsigned rqueue_partial_size; |
79 | size_t rqueue_partial_allocated; | |
80 | ||
a88f77c4 TG |
81 | struct nlmsghdr *rbuffer; |
82 | size_t rbuffer_allocated; | |
83 | ||
4555ec72 TG |
84 | bool processing:1; |
85 | ||
d4bbdb77 TG |
86 | uint32_t serial; |
87 | ||
e16bcf98 TG |
88 | struct Prioq *reply_callbacks_prioq; |
89 | Hashmap *reply_callbacks; | |
90 | ||
8cec01b9 TG |
91 | LIST_HEAD(struct match_callback, match_callbacks); |
92 | ||
ee38400b YW |
93 | LIST_HEAD(sd_netlink_slot, slots); |
94 | ||
adf412b9 | 95 | pid_t original_pid; |
b4f2a5b1 TG |
96 | |
97 | sd_event_source *io_event_source; | |
98 | sd_event_source *time_event_source; | |
6203e07a | 99 | sd_event_source *exit_event_source; |
b4f2a5b1 | 100 | sd_event *event; |
65f568bb | 101 | }; |
98dd77e8 | 102 | |
f663aeb8 | 103 | struct netlink_attribute { |
aa6b0ac4 | 104 | size_t offset; /* offset from hdr to attribute */ |
4c641e99 TG |
105 | bool nested:1; |
106 | bool net_byteorder:1; | |
f663aeb8 TG |
107 | }; |
108 | ||
109 | struct netlink_container { | |
110 | const struct NLTypeSystem *type_system; /* the type system of the container */ | |
111 | size_t offset; /* offset from hdr to the start of the container */ | |
112 | struct netlink_attribute *attributes; | |
113 | unsigned short n_attributes; /* number of attributes in container */ | |
114 | }; | |
115 | ||
1c4baffc | 116 | struct sd_netlink_message { |
3815f36f | 117 | RefCount n_ref; |
4555ec72 | 118 | |
1c4baffc | 119 | sd_netlink *rtnl; |
4fb7242c | 120 | |
05d0c2e3 JT |
121 | int protocol; |
122 | ||
3815f36f | 123 | struct nlmsghdr *hdr; |
f663aeb8 | 124 | struct netlink_container containers[RTNL_CONTAINER_DEPTH]; |
3815f36f | 125 | unsigned n_containers; /* number of containers */ |
3815f36f | 126 | bool sealed:1; |
3f42446d | 127 | bool broadcast:1; |
1403f45a | 128 | |
1c4baffc | 129 | sd_netlink_message *next; /* next in a chain of multi-part messages */ |
3815f36f | 130 | }; |
9d0db178 | 131 | |
1c4baffc | 132 | int message_new(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t type); |
89489ef7 | 133 | int message_new_empty(sd_netlink *rtnl, sd_netlink_message **ret); |
9d0db178 | 134 | |
05d0c2e3 JT |
135 | int netlink_open_family(sd_netlink **ret, int family); |
136 | ||
b95cc756 TG |
137 | int socket_open(int family); |
138 | int socket_bind(sd_netlink *nl); | |
9c5a882b TG |
139 | int socket_broadcast_group_ref(sd_netlink *nl, unsigned group); |
140 | int socket_broadcast_group_unref(sd_netlink *nl, unsigned group); | |
1c4baffc TG |
141 | int socket_write_message(sd_netlink *nl, sd_netlink_message *m); |
142 | int socket_read_message(sd_netlink *nl); | |
1b89cf56 | 143 | |
1c4baffc TG |
144 | int rtnl_rqueue_make_room(sd_netlink *rtnl); |
145 | int rtnl_rqueue_partial_make_room(sd_netlink *rtnl); | |
e16bcf98 TG |
146 | |
147 | /* Make sure callbacks don't destroy the rtnl connection */ | |
4afd3348 LP |
148 | #define NETLINK_DONT_DESTROY(rtnl) \ |
149 | _cleanup_(sd_netlink_unrefp) _unused_ sd_netlink *_dont_destroy_##rtnl = sd_netlink_ref(rtnl) |