]>
Commit | Line | Data |
---|---|---|
db9ecf05 | 1 | /* SPDX-License-Identifier: LGPL-2.1-or-later */ |
a2cdd907 LP |
2 | #pragma once |
3 | ||
a33dece5 | 4 | #include <linux/netlink.h> |
5cdf13c7 | 5 | #include <sys/socket.h> |
a33dece5 | 6 | |
5cdf13c7 | 7 | #include "forward.h" |
07630cea | 8 | #include "list.h" |
1c4baffc | 9 | #include "netlink-types.h" |
d8e538ec | 10 | |
409856d3 | 11 | #define NETLINK_DEFAULT_TIMEOUT_USEC ((usec_t) (25 * USEC_PER_SEC)) |
3815f36f | 12 | |
409856d3 | 13 | #define NETLINK_RQUEUE_MAX 64*1024 |
3815f36f | 14 | |
409856d3 | 15 | #define NETLINK_CONTAINER_DEPTH 32 |
3815f36f | 16 | |
e16bcf98 | 17 | struct reply_callback { |
1c4baffc | 18 | sd_netlink_message_handler_t callback; |
e16bcf98 | 19 | usec_t timeout; |
b522c4b9 | 20 | uint32_t serial; |
e16bcf98 TG |
21 | unsigned prioq_idx; |
22 | }; | |
65f568bb | 23 | |
8cec01b9 | 24 | struct match_callback { |
1c4baffc | 25 | sd_netlink_message_handler_t callback; |
3f60e448 YW |
26 | uint32_t *groups; |
27 | size_t n_groups; | |
23a7f0f7 | 28 | uint16_t type; |
e1578f60 | 29 | uint8_t cmd; /* used by genl */ |
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, | |
2d93c20e | 37 | _NETLINK_SLOT_INVALID = -EINVAL, |
ee38400b YW |
38 | } NetlinkSlotType; |
39 | ||
5cdf13c7 | 40 | typedef struct sd_netlink_slot { |
ee38400b | 41 | unsigned n_ref; |
399f74c7 ZJS |
42 | NetlinkSlotType type:8; |
43 | bool floating; | |
ee38400b YW |
44 | sd_netlink *netlink; |
45 | void *userdata; | |
46 | sd_netlink_destroy_t destroy_callback; | |
ee38400b | 47 | |
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 | }; | |
5cdf13c7 | 56 | } sd_netlink_slot; |
ee38400b | 57 | |
5cdf13c7 | 58 | typedef struct sd_netlink { |
f23ab4dc | 59 | unsigned n_ref; |
65f568bb TG |
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 | 70 | Hashmap *broadcast_group_refs; |
9c5a882b | 71 | |
e417c4ac | 72 | OrderedSet *rqueue; |
7b34bae3 | 73 | Hashmap *rqueue_by_serial; |
e417c4ac | 74 | Hashmap *rqueue_partial_by_serial; |
4e996881 | 75 | |
a88f77c4 | 76 | struct nlmsghdr *rbuffer; |
a88f77c4 | 77 | |
4555ec72 TG |
78 | bool processing:1; |
79 | ||
d4bbdb77 TG |
80 | uint32_t serial; |
81 | ||
e16bcf98 TG |
82 | struct Prioq *reply_callbacks_prioq; |
83 | Hashmap *reply_callbacks; | |
84 | ||
8cec01b9 TG |
85 | LIST_HEAD(struct match_callback, match_callbacks); |
86 | ||
ee38400b YW |
87 | LIST_HEAD(sd_netlink_slot, slots); |
88 | ||
adf412b9 | 89 | pid_t original_pid; |
b4f2a5b1 TG |
90 | |
91 | sd_event_source *io_event_source; | |
92 | sd_event_source *time_event_source; | |
6203e07a | 93 | sd_event_source *exit_event_source; |
b4f2a5b1 | 94 | sd_event *event; |
4e8f0ef9 | 95 | |
56fdc16d YW |
96 | Hashmap *genl_family_by_name; |
97 | Hashmap *genl_family_by_id; | |
5cdf13c7 | 98 | } sd_netlink; |
98dd77e8 | 99 | |
f663aeb8 | 100 | struct netlink_attribute { |
aa6b0ac4 | 101 | size_t offset; /* offset from hdr to attribute */ |
4c641e99 TG |
102 | bool nested:1; |
103 | bool net_byteorder:1; | |
f663aeb8 TG |
104 | }; |
105 | ||
106 | struct netlink_container { | |
ebf404a4 | 107 | const struct NLAPolicySet *policy_set; /* the policy set of the container */ |
f663aeb8 TG |
108 | size_t offset; /* offset from hdr to the start of the container */ |
109 | struct netlink_attribute *attributes; | |
416e8419 | 110 | uint16_t max_attribute; /* the maximum attribute in container */ |
f663aeb8 TG |
111 | }; |
112 | ||
5cdf13c7 | 113 | typedef struct sd_netlink_message { |
f23ab4dc | 114 | unsigned n_ref; |
4555ec72 | 115 | |
05d0c2e3 JT |
116 | int protocol; |
117 | ||
3815f36f | 118 | struct nlmsghdr *hdr; |
409856d3 | 119 | struct netlink_container containers[NETLINK_CONTAINER_DEPTH]; |
3815f36f | 120 | unsigned n_containers; /* number of containers */ |
4d4d898a | 121 | uint32_t multicast_group; |
3815f36f | 122 | bool sealed:1; |
1403f45a | 123 | |
1c4baffc | 124 | sd_netlink_message *next; /* next in a chain of multi-part messages */ |
5cdf13c7 | 125 | } sd_netlink_message; |
9d0db178 | 126 | |
409856d3 | 127 | int message_new_empty(sd_netlink *nl, sd_netlink_message **ret); |
1cedca05 YW |
128 | int message_new_full( |
129 | sd_netlink *nl, | |
130 | uint16_t nlmsg_type, | |
6e196011 | 131 | uint16_t nlmsg_flags, |
ebf404a4 | 132 | const NLAPolicySet *policy_set, |
1cedca05 YW |
133 | size_t header_size, |
134 | sd_netlink_message **ret); | |
6e196011 | 135 | int message_new(sd_netlink *nl, sd_netlink_message **ret, uint16_t type, uint16_t flags); |
409856d3 | 136 | int message_new_synthetic_error(sd_netlink *nl, int error, uint32_t serial, sd_netlink_message **ret); |
84e10015 | 137 | |
a6f4a9c0 DDM |
138 | static inline uint32_t message_get_serial(sd_netlink_message *m) { |
139 | assert(m); | |
140 | return ASSERT_PTR(m->hdr)->nlmsg_seq; | |
141 | } | |
84e10015 | 142 | |
409856d3 | 143 | void message_seal(sd_netlink_message *m); |
9d0db178 | 144 | |
05d0c2e3 | 145 | int netlink_open_family(sd_netlink **ret, int family); |
409856d3 | 146 | bool netlink_pid_changed(sd_netlink *nl); |
05d0c2e3 | 147 | |
b95cc756 | 148 | int socket_bind(sd_netlink *nl); |
9c5a882b TG |
149 | int socket_broadcast_group_ref(sd_netlink *nl, unsigned group); |
150 | int socket_broadcast_group_unref(sd_netlink *nl, unsigned group); | |
1c4baffc TG |
151 | int socket_write_message(sd_netlink *nl, sd_netlink_message *m); |
152 | int socket_read_message(sd_netlink *nl); | |
1b89cf56 | 153 | |
3f60e448 YW |
154 | int netlink_add_match_internal( |
155 | sd_netlink *nl, | |
156 | sd_netlink_slot **ret_slot, | |
157 | const uint32_t *groups, | |
158 | size_t n_groups, | |
159 | uint16_t type, | |
e1578f60 | 160 | uint8_t cmd, |
3f60e448 YW |
161 | sd_netlink_message_handler_t callback, |
162 | sd_netlink_destroy_t destroy_callback, | |
163 | void *userdata, | |
164 | const char *description); | |
165 | ||
409856d3 YW |
166 | /* Make sure callbacks don't destroy the netlink connection */ |
167 | #define NETLINK_DONT_DESTROY(nl) \ | |
168 | _cleanup_(sd_netlink_unrefp) _unused_ sd_netlink *_dont_destroy_##nl = sd_netlink_ref(nl) | |
84e10015 | 169 | |
94096580 TM |
170 | bool nfproto_is_valid(int nfproto); |
171 | ||
84e10015 ZJS |
172 | /* nfnl */ |
173 | /* TODO: to be exported later */ | |
174 | int sd_nfnl_socket_open(sd_netlink **ret); | |
573bb24d YW |
175 | int sd_nfnl_send_batch( |
176 | sd_netlink *nfnl, | |
177 | sd_netlink_message **messages, | |
178 | size_t msgcount, | |
179 | uint32_t **ret_serials); | |
180 | int sd_nfnl_call_batch( | |
181 | sd_netlink *nfnl, | |
182 | sd_netlink_message **messages, | |
183 | size_t n_messages, | |
184 | uint64_t usec, | |
185 | sd_netlink_message ***ret_messages); | |
186 | int sd_nfnl_message_new( | |
187 | sd_netlink *nfnl, | |
188 | sd_netlink_message **ret, | |
189 | int nfproto, | |
190 | uint16_t subsys, | |
191 | uint16_t msg_type, | |
192 | uint16_t flags); | |
84e10015 | 193 | int sd_nfnl_nft_message_new_table(sd_netlink *nfnl, sd_netlink_message **ret, |
64f090a6 | 194 | int nfproto, const char *table); |
84e10015 | 195 | int sd_nfnl_nft_message_new_basechain(sd_netlink *nfnl, sd_netlink_message **ret, |
64f090a6 | 196 | int nfproto, const char *table, const char *chain, |
84e10015 ZJS |
197 | const char *type, uint8_t hook, int prio); |
198 | int sd_nfnl_nft_message_new_rule(sd_netlink *nfnl, sd_netlink_message **ret, | |
64f090a6 | 199 | int nfproto, const char *table, const char *chain); |
84e10015 | 200 | int sd_nfnl_nft_message_new_set(sd_netlink *nfnl, sd_netlink_message **ret, |
64f090a6 | 201 | int nfproto, const char *table, const char *set_name, |
84e10015 | 202 | uint32_t setid, uint32_t klen); |
df737170 YW |
203 | int sd_nfnl_nft_message_new_setelems(sd_netlink *nfnl, sd_netlink_message **ret, |
204 | int add, int nfproto, const char *table, const char *set_name); | |
205 | int sd_nfnl_nft_message_append_setelem(sd_netlink_message *m, | |
206 | uint32_t index, | |
207 | const void *key, size_t key_len, | |
208 | const void *data, size_t data_len, | |
209 | uint32_t flags); |