]>
Commit | Line | Data |
---|---|---|
52ad194e | 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ |
60f067b4 JS |
2 | #pragma once |
3 | ||
60f067b4 JS |
4 | #include <linux/netlink.h> |
5 | ||
86f210e9 | 6 | #include "sd-netlink.h" |
60f067b4 | 7 | |
db2df898 | 8 | #include "list.h" |
86f210e9 | 9 | #include "netlink-types.h" |
db2df898 | 10 | #include "prioq.h" |
bb4f798a | 11 | #include "time-util.h" |
60f067b4 JS |
12 | |
13 | #define RTNL_DEFAULT_TIMEOUT ((usec_t) (25 * USEC_PER_SEC)) | |
14 | ||
15 | #define RTNL_WQUEUE_MAX 1024 | |
16 | #define RTNL_RQUEUE_MAX 64*1024 | |
17 | ||
18 | #define RTNL_CONTAINER_DEPTH 32 | |
19 | ||
20 | struct reply_callback { | |
86f210e9 | 21 | sd_netlink_message_handler_t callback; |
60f067b4 JS |
22 | usec_t timeout; |
23 | uint64_t serial; | |
24 | unsigned prioq_idx; | |
25 | }; | |
26 | ||
27 | struct match_callback { | |
86f210e9 | 28 | sd_netlink_message_handler_t callback; |
60f067b4 | 29 | uint16_t type; |
60f067b4 JS |
30 | |
31 | LIST_FIELDS(struct match_callback, match_callbacks); | |
32 | }; | |
33 | ||
6e866b33 MB |
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; | |
48 | char *description; | |
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 | ||
86f210e9 | 58 | struct sd_netlink { |
bb4f798a | 59 | unsigned n_ref; |
60f067b4 JS |
60 | |
61 | int fd; | |
62 | ||
63 | union { | |
64 | struct sockaddr sa; | |
65 | struct sockaddr_nl nl; | |
66 | } sockaddr; | |
67 | ||
1d42b86d MB |
68 | int protocol; |
69 | ||
db2df898 MP |
70 | Hashmap *broadcast_group_refs; |
71 | bool broadcast_group_dont_leave:1; /* until we can rely on 4.2 */ | |
72 | ||
86f210e9 | 73 | sd_netlink_message **rqueue; |
60f067b4 JS |
74 | unsigned rqueue_size; |
75 | size_t rqueue_allocated; | |
76 | ||
86f210e9 | 77 | sd_netlink_message **rqueue_partial; |
60f067b4 JS |
78 | unsigned rqueue_partial_size; |
79 | size_t rqueue_partial_allocated; | |
80 | ||
60f067b4 JS |
81 | struct nlmsghdr *rbuffer; |
82 | size_t rbuffer_allocated; | |
83 | ||
84 | bool processing:1; | |
85 | ||
86 | uint32_t serial; | |
87 | ||
88 | struct Prioq *reply_callbacks_prioq; | |
89 | Hashmap *reply_callbacks; | |
90 | ||
91 | LIST_HEAD(struct match_callback, match_callbacks); | |
92 | ||
6e866b33 MB |
93 | LIST_HEAD(sd_netlink_slot, slots); |
94 | ||
60f067b4 JS |
95 | pid_t original_pid; |
96 | ||
97 | sd_event_source *io_event_source; | |
98 | sd_event_source *time_event_source; | |
99 | sd_event_source *exit_event_source; | |
100 | sd_event *event; | |
101 | }; | |
102 | ||
fb183854 MP |
103 | struct netlink_attribute { |
104 | size_t offset; /* offset from hdr to attribute */ | |
7035cd9e MP |
105 | bool nested:1; |
106 | bool net_byteorder:1; | |
fb183854 MP |
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 | ||
86f210e9 | 116 | struct sd_netlink_message { |
bb4f798a | 117 | unsigned n_ref; |
60f067b4 | 118 | |
86f210e9 | 119 | sd_netlink *rtnl; |
60f067b4 | 120 | |
1d42b86d MB |
121 | int protocol; |
122 | ||
60f067b4 | 123 | struct nlmsghdr *hdr; |
fb183854 | 124 | struct netlink_container containers[RTNL_CONTAINER_DEPTH]; |
60f067b4 | 125 | unsigned n_containers; /* number of containers */ |
60f067b4 | 126 | bool sealed:1; |
e3bff60a | 127 | bool broadcast:1; |
60f067b4 | 128 | |
86f210e9 | 129 | sd_netlink_message *next; /* next in a chain of multi-part messages */ |
60f067b4 JS |
130 | }; |
131 | ||
86f210e9 MP |
132 | int message_new(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t type); |
133 | int message_new_empty(sd_netlink *rtnl, sd_netlink_message **ret); | |
60f067b4 | 134 | |
1d42b86d MB |
135 | int netlink_open_family(sd_netlink **ret, int family); |
136 | ||
86f210e9 MP |
137 | int socket_open(int family); |
138 | int socket_bind(sd_netlink *nl); | |
db2df898 MP |
139 | int socket_broadcast_group_ref(sd_netlink *nl, unsigned group); |
140 | int socket_broadcast_group_unref(sd_netlink *nl, unsigned group); | |
86f210e9 MP |
141 | int socket_write_message(sd_netlink *nl, sd_netlink_message *m); |
142 | int socket_read_message(sd_netlink *nl); | |
60f067b4 | 143 | |
86f210e9 MP |
144 | int rtnl_rqueue_make_room(sd_netlink *rtnl); |
145 | int rtnl_rqueue_partial_make_room(sd_netlink *rtnl); | |
60f067b4 | 146 | |
60f067b4 | 147 | /* Make sure callbacks don't destroy the rtnl connection */ |
4c89c718 MP |
148 | #define NETLINK_DONT_DESTROY(rtnl) \ |
149 | _cleanup_(sd_netlink_unrefp) _unused_ sd_netlink *_dont_destroy_##rtnl = sd_netlink_ref(rtnl) |