]>
Commit | Line | Data |
---|---|---|
db9ecf05 | 1 | /* SPDX-License-Identifier: LGPL-2.1-or-later */ |
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 | 10 | #include "prioq.h" |
ca78ad1d | 11 | #include "time-util.h" |
d8e538ec | 12 | |
409856d3 | 13 | #define NETLINK_DEFAULT_TIMEOUT_USEC ((usec_t) (25 * USEC_PER_SEC)) |
3815f36f | 14 | |
409856d3 | 15 | #define NETLINK_RQUEUE_MAX 64*1024 |
3815f36f | 16 | |
409856d3 | 17 | #define NETLINK_CONTAINER_DEPTH 32 |
3815f36f | 18 | |
e16bcf98 | 19 | struct reply_callback { |
1c4baffc | 20 | sd_netlink_message_handler_t callback; |
e16bcf98 | 21 | usec_t timeout; |
b522c4b9 | 22 | uint32_t serial; |
e16bcf98 TG |
23 | unsigned prioq_idx; |
24 | }; | |
65f568bb | 25 | |
8cec01b9 | 26 | struct match_callback { |
1c4baffc | 27 | sd_netlink_message_handler_t callback; |
3f60e448 YW |
28 | uint32_t *groups; |
29 | size_t n_groups; | |
23a7f0f7 | 30 | uint16_t type; |
e1578f60 | 31 | uint8_t cmd; /* used by genl */ |
8cec01b9 TG |
32 | |
33 | LIST_FIELDS(struct match_callback, match_callbacks); | |
34 | }; | |
35 | ||
ee38400b YW |
36 | typedef enum NetlinkSlotType { |
37 | NETLINK_REPLY_CALLBACK, | |
38 | NETLINK_MATCH_CALLBACK, | |
2d93c20e | 39 | _NETLINK_SLOT_INVALID = -EINVAL, |
ee38400b YW |
40 | } NetlinkSlotType; |
41 | ||
42 | struct sd_netlink_slot { | |
43 | unsigned n_ref; | |
399f74c7 ZJS |
44 | NetlinkSlotType type:8; |
45 | bool floating; | |
ee38400b YW |
46 | sd_netlink *netlink; |
47 | void *userdata; | |
48 | sd_netlink_destroy_t destroy_callback; | |
ee38400b | 49 | |
8190a388 | 50 | char *description; |
ee38400b YW |
51 | |
52 | LIST_FIELDS(sd_netlink_slot, slots); | |
53 | ||
54 | union { | |
55 | struct reply_callback reply_callback; | |
56 | struct match_callback match_callback; | |
57 | }; | |
58 | }; | |
59 | ||
1c4baffc | 60 | struct sd_netlink { |
f23ab4dc | 61 | unsigned n_ref; |
65f568bb TG |
62 | |
63 | int fd; | |
64 | ||
65 | union { | |
66 | struct sockaddr sa; | |
67 | struct sockaddr_nl nl; | |
68 | } sockaddr; | |
69 | ||
05d0c2e3 JT |
70 | int protocol; |
71 | ||
9c5a882b TG |
72 | Hashmap *broadcast_group_refs; |
73 | bool broadcast_group_dont_leave:1; /* until we can rely on 4.2 */ | |
74 | ||
1c4baffc | 75 | sd_netlink_message **rqueue; |
4555ec72 TG |
76 | unsigned rqueue_size; |
77 | ||
1c4baffc | 78 | sd_netlink_message **rqueue_partial; |
4e996881 | 79 | unsigned rqueue_partial_size; |
4e996881 | 80 | |
a88f77c4 | 81 | struct nlmsghdr *rbuffer; |
a88f77c4 | 82 | |
4555ec72 TG |
83 | bool processing:1; |
84 | ||
d4bbdb77 TG |
85 | uint32_t serial; |
86 | ||
e16bcf98 TG |
87 | struct Prioq *reply_callbacks_prioq; |
88 | Hashmap *reply_callbacks; | |
89 | ||
8cec01b9 TG |
90 | LIST_HEAD(struct match_callback, match_callbacks); |
91 | ||
ee38400b YW |
92 | LIST_HEAD(sd_netlink_slot, slots); |
93 | ||
adf412b9 | 94 | pid_t original_pid; |
b4f2a5b1 TG |
95 | |
96 | sd_event_source *io_event_source; | |
97 | sd_event_source *time_event_source; | |
6203e07a | 98 | sd_event_source *exit_event_source; |
b4f2a5b1 | 99 | sd_event *event; |
4e8f0ef9 | 100 | |
56fdc16d YW |
101 | Hashmap *genl_family_by_name; |
102 | Hashmap *genl_family_by_id; | |
65f568bb | 103 | }; |
98dd77e8 | 104 | |
f663aeb8 | 105 | struct netlink_attribute { |
aa6b0ac4 | 106 | size_t offset; /* offset from hdr to attribute */ |
4c641e99 TG |
107 | bool nested:1; |
108 | bool net_byteorder:1; | |
f663aeb8 TG |
109 | }; |
110 | ||
111 | struct netlink_container { | |
112 | const struct NLTypeSystem *type_system; /* the type system of the container */ | |
113 | size_t offset; /* offset from hdr to the start of the container */ | |
114 | struct netlink_attribute *attributes; | |
416e8419 | 115 | uint16_t max_attribute; /* the maximum attribute in container */ |
f663aeb8 TG |
116 | }; |
117 | ||
1c4baffc | 118 | struct sd_netlink_message { |
f23ab4dc | 119 | unsigned n_ref; |
4555ec72 | 120 | |
05d0c2e3 JT |
121 | int protocol; |
122 | ||
3815f36f | 123 | struct nlmsghdr *hdr; |
409856d3 | 124 | struct netlink_container containers[NETLINK_CONTAINER_DEPTH]; |
3815f36f | 125 | unsigned n_containers; /* number of containers */ |
4d4d898a | 126 | uint32_t multicast_group; |
3815f36f | 127 | bool sealed:1; |
1403f45a | 128 | |
1c4baffc | 129 | sd_netlink_message *next; /* next in a chain of multi-part messages */ |
3815f36f | 130 | }; |
9d0db178 | 131 | |
409856d3 | 132 | int message_new_empty(sd_netlink *nl, sd_netlink_message **ret); |
1cedca05 YW |
133 | int message_new_full( |
134 | sd_netlink *nl, | |
135 | uint16_t nlmsg_type, | |
136 | const NLTypeSystem *type_system, | |
137 | size_t header_size, | |
138 | sd_netlink_message **ret); | |
139 | int message_new(sd_netlink *nl, sd_netlink_message **ret, uint16_t type); | |
409856d3 | 140 | int message_new_synthetic_error(sd_netlink *nl, int error, uint32_t serial, sd_netlink_message **ret); |
84e10015 ZJS |
141 | |
142 | static inline uint32_t message_get_serial(sd_netlink_message *m) { | |
143 | assert(m); | |
144 | return ASSERT_PTR(m->hdr)->nlmsg_seq; | |
145 | } | |
146 | ||
409856d3 | 147 | void message_seal(sd_netlink_message *m); |
9d0db178 | 148 | |
05d0c2e3 | 149 | int netlink_open_family(sd_netlink **ret, int family); |
409856d3 YW |
150 | bool netlink_pid_changed(sd_netlink *nl); |
151 | int netlink_rqueue_make_room(sd_netlink *nl); | |
152 | int netlink_rqueue_partial_make_room(sd_netlink *nl); | |
05d0c2e3 | 153 | |
b95cc756 | 154 | int socket_bind(sd_netlink *nl); |
9c5a882b TG |
155 | int socket_broadcast_group_ref(sd_netlink *nl, unsigned group); |
156 | int socket_broadcast_group_unref(sd_netlink *nl, unsigned group); | |
1c4baffc TG |
157 | int socket_write_message(sd_netlink *nl, sd_netlink_message *m); |
158 | int socket_read_message(sd_netlink *nl); | |
1b89cf56 | 159 | |
3f60e448 YW |
160 | int netlink_add_match_internal( |
161 | sd_netlink *nl, | |
162 | sd_netlink_slot **ret_slot, | |
163 | const uint32_t *groups, | |
164 | size_t n_groups, | |
165 | uint16_t type, | |
e1578f60 | 166 | uint8_t cmd, |
3f60e448 YW |
167 | sd_netlink_message_handler_t callback, |
168 | sd_netlink_destroy_t destroy_callback, | |
169 | void *userdata, | |
170 | const char *description); | |
171 | ||
409856d3 YW |
172 | /* Make sure callbacks don't destroy the netlink connection */ |
173 | #define NETLINK_DONT_DESTROY(nl) \ | |
174 | _cleanup_(sd_netlink_unrefp) _unused_ sd_netlink *_dont_destroy_##nl = sd_netlink_ref(nl) | |
84e10015 ZJS |
175 | |
176 | /* nfnl */ | |
177 | /* TODO: to be exported later */ | |
178 | int sd_nfnl_socket_open(sd_netlink **ret); | |
179 | int sd_nfnl_message_batch_begin(sd_netlink *nfnl, sd_netlink_message **ret); | |
180 | int sd_nfnl_message_batch_end(sd_netlink *nfnl, sd_netlink_message **ret); | |
181 | int sd_nfnl_nft_message_del_table(sd_netlink *nfnl, sd_netlink_message **ret, | |
64f090a6 | 182 | int nfproto, const char *table); |
84e10015 | 183 | int sd_nfnl_nft_message_new_table(sd_netlink *nfnl, sd_netlink_message **ret, |
64f090a6 | 184 | int nfproto, const char *table); |
84e10015 | 185 | int sd_nfnl_nft_message_new_basechain(sd_netlink *nfnl, sd_netlink_message **ret, |
64f090a6 | 186 | int nfproto, const char *table, const char *chain, |
84e10015 ZJS |
187 | const char *type, uint8_t hook, int prio); |
188 | int sd_nfnl_nft_message_new_rule(sd_netlink *nfnl, sd_netlink_message **ret, | |
64f090a6 | 189 | int nfproto, const char *table, const char *chain); |
84e10015 | 190 | int sd_nfnl_nft_message_new_set(sd_netlink *nfnl, sd_netlink_message **ret, |
64f090a6 | 191 | int nfproto, const char *table, const char *set_name, |
84e10015 ZJS |
192 | uint32_t setid, uint32_t klen); |
193 | int sd_nfnl_nft_message_new_setelems_begin(sd_netlink *nfnl, sd_netlink_message **ret, | |
64f090a6 | 194 | int nfproto, const char *table, const char *set_name); |
84e10015 | 195 | int sd_nfnl_nft_message_del_setelems_begin(sd_netlink *nfnl, sd_netlink_message **ret, |
64f090a6 | 196 | int nfproto, const char *table, const char *set_name); |
84e10015 | 197 | int sd_nfnl_nft_message_add_setelem(sd_netlink_message *m, |
64f090a6 YW |
198 | uint32_t index, |
199 | const void *key, size_t key_len, | |
200 | const void *data, size_t data_len); | |
84e10015 | 201 | int sd_nfnl_nft_message_add_setelem_end(sd_netlink_message *m); |