1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 #pragma once
3 
4 #include "sd-event.h"
5 #include "sd-netlink.h"
6 
7 #include "alloc-util.h"
8 #include "hash-funcs.h"
9 
10 typedef struct Link Link;
11 typedef struct NetDev NetDev;
12 typedef struct Manager Manager;
13 typedef struct Request Request;
14 
15 typedef int (*request_process_func_t)(Request *req, Link *link, void *userdata);
16 typedef int (*request_netlink_handler_t)(sd_netlink *nl, sd_netlink_message *m, Request *req, Link *link, void *userdata);
17 
18 typedef enum RequestType {
19         REQUEST_TYPE_ACTIVATE_LINK,
20         REQUEST_TYPE_ADDRESS,
21         REQUEST_TYPE_ADDRESS_LABEL,
22         REQUEST_TYPE_BRIDGE_FDB,
23         REQUEST_TYPE_BRIDGE_MDB,
24         REQUEST_TYPE_DHCP_SERVER,
25         REQUEST_TYPE_DHCP4_CLIENT,
26         REQUEST_TYPE_DHCP6_CLIENT,
27         REQUEST_TYPE_IPV6_PROXY_NDP,
28         REQUEST_TYPE_NDISC,
29         REQUEST_TYPE_NEIGHBOR,
30         REQUEST_TYPE_NETDEV_INDEPENDENT,
31         REQUEST_TYPE_NETDEV_STACKED,
32         REQUEST_TYPE_NEXTHOP,
33         REQUEST_TYPE_RADV,
34         REQUEST_TYPE_ROUTE,
35         REQUEST_TYPE_ROUTING_POLICY_RULE,
36         REQUEST_TYPE_SET_LINK_ADDRESS_GENERATION_MODE, /* Setting IPv6LL address generation mode. */
37         REQUEST_TYPE_SET_LINK_BOND,                    /* Setting bond configs. */
38         REQUEST_TYPE_SET_LINK_BRIDGE,                  /* Setting bridge configs. */
39         REQUEST_TYPE_SET_LINK_BRIDGE_VLAN,             /* Setting bridge VLAN configs. */
40         REQUEST_TYPE_SET_LINK_CAN,                     /* Setting CAN interface configs. */
41         REQUEST_TYPE_SET_LINK_FLAGS,                   /* Setting IFF_NOARP or friends. */
42         REQUEST_TYPE_SET_LINK_GROUP,                   /* Setting interface group. */
43         REQUEST_TYPE_SET_LINK_IPOIB,                   /* Setting IPoIB configs. */
44         REQUEST_TYPE_SET_LINK_MAC,                     /* Setting MAC address. */
45         REQUEST_TYPE_SET_LINK_MASTER,                  /* Setting IFLA_MASTER. */
46         REQUEST_TYPE_SET_LINK_MTU,                     /* Setting MTU. */
47         REQUEST_TYPE_SRIOV,
48         REQUEST_TYPE_TC_CLASS,
49         REQUEST_TYPE_TC_QDISC,
50         REQUEST_TYPE_UP_DOWN,
51         _REQUEST_TYPE_MAX,
52         _REQUEST_TYPE_INVALID = -EINVAL,
53 } RequestType;
54 
55 struct Request {
56         unsigned n_ref;
57 
58         Manager *manager; /* must be non-NULL */
59         Link *link; /* can be NULL */
60 
61         RequestType type;
62 
63         /* Target object, e.g. Address, Route, NetDev, and so on. */
64         void *userdata;
65         /* freeing userdata when the request is completed or failed. */
66         mfree_func_t free_func;
67 
68         /* hash and compare functions for userdata, used for dedup requests. */
69         hash_func_t hash_func;
70         compare_func_t compare_func;
71 
72         /* Checks the request dependencies, and then processes this request, e.g. call address_configure().
73          * Return 1 when processed, 0 when its dependencies not resolved, and negative errno on failure. */
74         request_process_func_t process;
75 
76         /* incremented when requested, decremented when request is completed or failed. */
77         unsigned *counter;
78         /* called in netlink handler, the 'counter' is decremented before this is called.
79          * If this is specified, then the 'process' function must increment the reference of this
80          * request, and pass this request to the netlink_call_async(), and set the destroy function
81          * to the slot. */
82         request_netlink_handler_t netlink_handler;
83 };
84 
85 Request *request_ref(Request *req);
86 Request *request_unref(Request *req);
87 DEFINE_TRIVIAL_CLEANUP_FUNC(Request*, request_unref);
88 
89 void request_detach(Manager *manager, Request *req);
90 
91 int netdev_queue_request(
92                 NetDev *netdev,
93                 request_process_func_t process,
94                 Request **ret);
95 
96 int link_queue_request_full(
97                 Link *link,
98                 RequestType type,
99                 void *userdata,
100                 mfree_func_t free_func,
101                 hash_func_t hash_func,
102                 compare_func_t compare_func,
103                 request_process_func_t process,
104                 unsigned *counter,
105                 request_netlink_handler_t netlink_handler,
106                 Request **ret);
107 
link_queue_request(Link * link,RequestType type,request_process_func_t process,Request ** ret)108 static inline int link_queue_request(
109                 Link *link,
110                 RequestType type,
111                 request_process_func_t process,
112                 Request **ret) {
113 
114         return link_queue_request_full(link, type, NULL, NULL, NULL, NULL,
115                                        process, NULL, NULL, ret);
116 }
117 
118 #define link_queue_request_safe(link, type, userdata, free_func, hash_func, compare_func, process, counter, netlink_handler, ret) \
119         ({                                                              \
120                 typeof(userdata) (*_f)(typeof(userdata)) = (free_func); \
121                 void (*_h)(const typeof(*userdata)*, struct siphash*) = (hash_func); \
122                 int (*_c)(const typeof(*userdata)*, const typeof(*userdata)*) = (compare_func); \
123                 int (*_p)(Request*, Link*, typeof(userdata)) = (process); \
124                 int (*_n)(sd_netlink*, sd_netlink_message*, Request*, Link*, typeof(userdata)) = (netlink_handler); \
125                                                                         \
126                 link_queue_request_full(link, type, userdata,           \
127                                         (mfree_func_t) _f,              \
128                                         (hash_func_t) _h,               \
129                                         (compare_func_t) _c,            \
130                                         (request_process_func_t) _p,    \
131                                         counter,                        \
132                                         (request_netlink_handler_t) _n, \
133                                         ret);                           \
134         })
135 
136 int manager_process_requests(sd_event_source *s, void *userdata);
137 int request_call_netlink_async(sd_netlink *nl, sd_netlink_message *m, Request *req);
138 
139 const char* request_type_to_string(RequestType t) _const_;
140