]>
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; |
23a7f0f7 | 28 | uint16_t type; |
8cec01b9 TG |
29 | |
30 | LIST_FIELDS(struct match_callback, match_callbacks); | |
31 | }; | |
32 | ||
ee38400b YW |
33 | typedef enum NetlinkSlotType { |
34 | NETLINK_REPLY_CALLBACK, | |
35 | NETLINK_MATCH_CALLBACK, | |
2d93c20e | 36 | _NETLINK_SLOT_INVALID = -EINVAL, |
ee38400b YW |
37 | } NetlinkSlotType; |
38 | ||
39 | struct sd_netlink_slot { | |
40 | unsigned n_ref; | |
399f74c7 ZJS |
41 | NetlinkSlotType type:8; |
42 | bool floating; | |
ee38400b YW |
43 | sd_netlink *netlink; |
44 | void *userdata; | |
45 | sd_netlink_destroy_t destroy_callback; | |
ee38400b | 46 | |
8190a388 | 47 | char *description; |
ee38400b YW |
48 | |
49 | LIST_FIELDS(sd_netlink_slot, slots); | |
50 | ||
51 | union { | |
52 | struct reply_callback reply_callback; | |
53 | struct match_callback match_callback; | |
54 | }; | |
55 | }; | |
56 | ||
1c4baffc | 57 | struct sd_netlink { |
f23ab4dc | 58 | unsigned n_ref; |
65f568bb TG |
59 | |
60 | int fd; | |
61 | ||
62 | union { | |
63 | struct sockaddr sa; | |
64 | struct sockaddr_nl nl; | |
65 | } sockaddr; | |
66 | ||
05d0c2e3 JT |
67 | int protocol; |
68 | ||
9c5a882b TG |
69 | Hashmap *broadcast_group_refs; |
70 | bool broadcast_group_dont_leave:1; /* until we can rely on 4.2 */ | |
71 | ||
1c4baffc | 72 | sd_netlink_message **rqueue; |
4555ec72 TG |
73 | unsigned rqueue_size; |
74 | ||
1c4baffc | 75 | sd_netlink_message **rqueue_partial; |
4e996881 | 76 | unsigned rqueue_partial_size; |
4e996881 | 77 | |
a88f77c4 | 78 | struct nlmsghdr *rbuffer; |
a88f77c4 | 79 | |
4555ec72 TG |
80 | bool processing:1; |
81 | ||
d4bbdb77 TG |
82 | uint32_t serial; |
83 | ||
e16bcf98 TG |
84 | struct Prioq *reply_callbacks_prioq; |
85 | Hashmap *reply_callbacks; | |
86 | ||
8cec01b9 TG |
87 | LIST_HEAD(struct match_callback, match_callbacks); |
88 | ||
ee38400b YW |
89 | LIST_HEAD(sd_netlink_slot, slots); |
90 | ||
adf412b9 | 91 | pid_t original_pid; |
b4f2a5b1 TG |
92 | |
93 | sd_event_source *io_event_source; | |
94 | sd_event_source *time_event_source; | |
6203e07a | 95 | sd_event_source *exit_event_source; |
b4f2a5b1 | 96 | sd_event *event; |
4e8f0ef9 | 97 | |
56fdc16d YW |
98 | Hashmap *genl_family_by_name; |
99 | Hashmap *genl_family_by_id; | |
65f568bb | 100 | }; |
98dd77e8 | 101 | |
f663aeb8 | 102 | struct netlink_attribute { |
aa6b0ac4 | 103 | size_t offset; /* offset from hdr to attribute */ |
4c641e99 TG |
104 | bool nested:1; |
105 | bool net_byteorder:1; | |
f663aeb8 TG |
106 | }; |
107 | ||
108 | struct netlink_container { | |
109 | const struct NLTypeSystem *type_system; /* the type system of the container */ | |
110 | size_t offset; /* offset from hdr to the start of the container */ | |
111 | struct netlink_attribute *attributes; | |
112 | unsigned short n_attributes; /* number of attributes in container */ | |
113 | }; | |
114 | ||
1c4baffc | 115 | struct sd_netlink_message { |
f23ab4dc | 116 | unsigned n_ref; |
4555ec72 | 117 | |
05d0c2e3 JT |
118 | int protocol; |
119 | ||
3815f36f | 120 | struct nlmsghdr *hdr; |
409856d3 | 121 | struct netlink_container containers[NETLINK_CONTAINER_DEPTH]; |
3815f36f | 122 | unsigned n_containers; /* number of containers */ |
3815f36f | 123 | bool sealed:1; |
3f42446d | 124 | bool broadcast:1; |
1403f45a | 125 | |
1c4baffc | 126 | sd_netlink_message *next; /* next in a chain of multi-part messages */ |
3815f36f | 127 | }; |
9d0db178 | 128 | |
409856d3 | 129 | int message_new_empty(sd_netlink *nl, sd_netlink_message **ret); |
1cedca05 YW |
130 | int message_new_full( |
131 | sd_netlink *nl, | |
132 | uint16_t nlmsg_type, | |
133 | const NLTypeSystem *type_system, | |
134 | size_t header_size, | |
135 | sd_netlink_message **ret); | |
136 | int message_new(sd_netlink *nl, sd_netlink_message **ret, uint16_t type); | |
409856d3 YW |
137 | int message_new_synthetic_error(sd_netlink *nl, int error, uint32_t serial, sd_netlink_message **ret); |
138 | uint32_t message_get_serial(sd_netlink_message *m); | |
139 | void message_seal(sd_netlink_message *m); | |
9d0db178 | 140 | |
05d0c2e3 | 141 | int netlink_open_family(sd_netlink **ret, int family); |
409856d3 YW |
142 | bool netlink_pid_changed(sd_netlink *nl); |
143 | int netlink_rqueue_make_room(sd_netlink *nl); | |
144 | int netlink_rqueue_partial_make_room(sd_netlink *nl); | |
05d0c2e3 | 145 | |
b95cc756 TG |
146 | int socket_open(int family); |
147 | int socket_bind(sd_netlink *nl); | |
9c5a882b TG |
148 | int socket_broadcast_group_ref(sd_netlink *nl, unsigned group); |
149 | int socket_broadcast_group_unref(sd_netlink *nl, unsigned group); | |
1c4baffc | 150 | int socket_write_message(sd_netlink *nl, sd_netlink_message *m); |
2d1ad724 | 151 | int socket_writev_message(sd_netlink *nl, sd_netlink_message **m, size_t msgcount); |
1c4baffc | 152 | int socket_read_message(sd_netlink *nl); |
1b89cf56 | 153 | |
409856d3 YW |
154 | /* Make sure callbacks don't destroy the netlink connection */ |
155 | #define NETLINK_DONT_DESTROY(nl) \ | |
156 | _cleanup_(sd_netlink_unrefp) _unused_ sd_netlink *_dont_destroy_##nl = sd_netlink_ref(nl) |