Branch data Line data Source code
1 : : /* SPDX-License-Identifier: GPL-2.0-only */
2 : :
3 : : #ifndef _NET_ETHTOOL_NETLINK_H
4 : : #define _NET_ETHTOOL_NETLINK_H
5 : :
6 : : #include <linux/ethtool_netlink.h>
7 : : #include <linux/netdevice.h>
8 : : #include <net/genetlink.h>
9 : : #include <net/sock.h>
10 : :
11 : : struct ethnl_req_info;
12 : :
13 : : int ethnl_parse_header(struct ethnl_req_info *req_info,
14 : : const struct nlattr *nest, struct net *net,
15 : : struct netlink_ext_ack *extack, bool require_dev);
16 : : int ethnl_fill_reply_header(struct sk_buff *skb, struct net_device *dev,
17 : : u16 attrtype);
18 : : struct sk_buff *ethnl_reply_init(size_t payload, struct net_device *dev, u8 cmd,
19 : : u16 hdr_attrtype, struct genl_info *info,
20 : : void **ehdrp);
21 : :
22 : : /**
23 : : * ethnl_strz_size() - calculate attribute length for fixed size string
24 : : * @s: ETH_GSTRING_LEN sized string (may not be null terminated)
25 : : *
26 : : * Return: total length of an attribute with null terminated string from @s
27 : : */
28 : 0 : static inline int ethnl_strz_size(const char *s)
29 : : {
30 : 0 : return nla_total_size(strnlen(s, ETH_GSTRING_LEN) + 1);
31 : : }
32 : :
33 : : /**
34 : : * ethnl_put_strz() - put string attribute with fixed size string
35 : : * @skb: skb with the message
36 : : * @attrype: attribute type
37 : : * @s: ETH_GSTRING_LEN sized string (may not be null terminated)
38 : : *
39 : : * Puts an attribute with null terminated string from @s into the message.
40 : : *
41 : : * Return: 0 on success, negative error code on failure
42 : : */
43 : 0 : static inline int ethnl_put_strz(struct sk_buff *skb, u16 attrtype,
44 : : const char *s)
45 : : {
46 : 0 : unsigned int len = strnlen(s, ETH_GSTRING_LEN);
47 : 0 : struct nlattr *attr;
48 : :
49 : 0 : attr = nla_reserve(skb, attrtype, len + 1);
50 [ # # ]: 0 : if (!attr)
51 : : return -EMSGSIZE;
52 : :
53 : 0 : memcpy(nla_data(attr), s, len);
54 : 0 : ((char *)nla_data(attr))[len] = '\0';
55 : 0 : return 0;
56 : : }
57 : :
58 : : /**
59 : : * ethnl_update_u32() - update u32 value from NLA_U32 attribute
60 : : * @dst: value to update
61 : : * @attr: netlink attribute with new value or null
62 : : * @mod: pointer to bool for modification tracking
63 : : *
64 : : * Copy the u32 value from NLA_U32 netlink attribute @attr into variable
65 : : * pointed to by @dst; do nothing if @attr is null. Bool pointed to by @mod
66 : : * is set to true if this function changed the value of *dst, otherwise it
67 : : * is left as is.
68 : : */
69 : : static inline void ethnl_update_u32(u32 *dst, const struct nlattr *attr,
70 : : bool *mod)
71 : : {
72 : : u32 val;
73 : :
74 : : if (!attr)
75 : : return;
76 : : val = nla_get_u32(attr);
77 : : if (*dst == val)
78 : : return;
79 : :
80 : : *dst = val;
81 : : *mod = true;
82 : : }
83 : :
84 : : /**
85 : : * ethnl_update_u8() - update u8 value from NLA_U8 attribute
86 : : * @dst: value to update
87 : : * @attr: netlink attribute with new value or null
88 : : * @mod: pointer to bool for modification tracking
89 : : *
90 : : * Copy the u8 value from NLA_U8 netlink attribute @attr into variable
91 : : * pointed to by @dst; do nothing if @attr is null. Bool pointed to by @mod
92 : : * is set to true if this function changed the value of *dst, otherwise it
93 : : * is left as is.
94 : : */
95 : 0 : static inline void ethnl_update_u8(u8 *dst, const struct nlattr *attr,
96 : : bool *mod)
97 : : {
98 : 0 : u8 val;
99 : :
100 [ # # # # : 0 : if (!attr)
# # ]
101 : : return;
102 [ # # # # : 0 : val = nla_get_u8(attr);
# # ]
103 [ # # # # : 0 : if (*dst == val)
# # ]
104 : : return;
105 : :
106 : 0 : *dst = val;
107 : 0 : *mod = true;
108 : : }
109 : :
110 : : /**
111 : : * ethnl_update_bool32() - update u32 used as bool from NLA_U8 attribute
112 : : * @dst: value to update
113 : : * @attr: netlink attribute with new value or null
114 : : * @mod: pointer to bool for modification tracking
115 : : *
116 : : * Use the u8 value from NLA_U8 netlink attribute @attr to set u32 variable
117 : : * pointed to by @dst to 0 (if zero) or 1 (if not); do nothing if @attr is
118 : : * null. Bool pointed to by @mod is set to true if this function changed the
119 : : * logical value of *dst, otherwise it is left as is.
120 : : */
121 : : static inline void ethnl_update_bool32(u32 *dst, const struct nlattr *attr,
122 : : bool *mod)
123 : : {
124 : : u8 val;
125 : :
126 : : if (!attr)
127 : : return;
128 : : val = !!nla_get_u8(attr);
129 : : if (!!*dst == val)
130 : : return;
131 : :
132 : : *dst = val;
133 : : *mod = true;
134 : : }
135 : :
136 : : /**
137 : : * ethnl_update_binary() - update binary data from NLA_BINARY atribute
138 : : * @dst: value to update
139 : : * @len: destination buffer length
140 : : * @attr: netlink attribute with new value or null
141 : : * @mod: pointer to bool for modification tracking
142 : : *
143 : : * Use the u8 value from NLA_U8 netlink attribute @attr to rewrite data block
144 : : * of length @len at @dst by attribute payload; do nothing if @attr is null.
145 : : * Bool pointed to by @mod is set to true if this function changed the logical
146 : : * value of *dst, otherwise it is left as is.
147 : : */
148 : 0 : static inline void ethnl_update_binary(void *dst, unsigned int len,
149 : : const struct nlattr *attr, bool *mod)
150 : : {
151 [ # # ]: 0 : if (!attr)
152 : : return;
153 [ # # ]: 0 : if (nla_len(attr) < len)
154 : : len = nla_len(attr);
155 [ # # ]: 0 : if (!memcmp(dst, nla_data(attr), len))
156 : : return;
157 : :
158 : 0 : memcpy(dst, nla_data(attr), len);
159 : 0 : *mod = true;
160 : : }
161 : :
162 : : /**
163 : : * ethnl_update_bitfield32() - update u32 value from NLA_BITFIELD32 attribute
164 : : * @dst: value to update
165 : : * @attr: netlink attribute with new value or null
166 : : * @mod: pointer to bool for modification tracking
167 : : *
168 : : * Update bits in u32 value which are set in attribute's mask to values from
169 : : * attribute's value. Do nothing if @attr is null or the value wouldn't change;
170 : : * otherwise, set bool pointed to by @mod to true.
171 : : */
172 : : static inline void ethnl_update_bitfield32(u32 *dst, const struct nlattr *attr,
173 : : bool *mod)
174 : : {
175 : : struct nla_bitfield32 change;
176 : : u32 newval;
177 : :
178 : : if (!attr)
179 : : return;
180 : : change = nla_get_bitfield32(attr);
181 : : newval = (*dst & ~change.selector) | (change.value & change.selector);
182 : : if (*dst == newval)
183 : : return;
184 : :
185 : : *dst = newval;
186 : : *mod = true;
187 : : }
188 : :
189 : : /**
190 : : * ethnl_reply_header_size() - total size of reply header
191 : : *
192 : : * This is an upper estimate so that we do not need to hold RTNL lock longer
193 : : * than necessary (to prevent rename between size estimate and composing the
194 : : * message). Accounts only for device ifindex and name as those are the only
195 : : * attributes ethnl_fill_reply_header() puts into the reply header.
196 : : */
197 : 0 : static inline unsigned int ethnl_reply_header_size(void)
198 : : {
199 : 0 : return nla_total_size(nla_total_size(sizeof(u32)) +
200 : : nla_total_size(IFNAMSIZ));
201 : : }
202 : :
203 : : /* GET request handling */
204 : :
205 : : /* Unified processing of GET requests uses two data structures: request info
206 : : * and reply data. Request info holds information parsed from client request
207 : : * and its stays constant through all request processing. Reply data holds data
208 : : * retrieved from ethtool_ops callbacks or other internal sources which is used
209 : : * to compose the reply. When processing a dump request, request info is filled
210 : : * only once (when the request message is parsed) but reply data is filled for
211 : : * each reply message.
212 : : *
213 : : * Both structures consist of part common for all request types (struct
214 : : * ethnl_req_info and struct ethnl_reply_data defined below) and optional
215 : : * parts specific for each request type. Common part always starts at offset 0.
216 : : */
217 : :
218 : : /**
219 : : * struct ethnl_req_info - base type of request information for GET requests
220 : : * @dev: network device the request is for (may be null)
221 : : * @flags: request flags common for all request types
222 : : *
223 : : * This is a common base for request specific structures holding data from
224 : : * parsed userspace request. These always embed struct ethnl_req_info at
225 : : * zero offset.
226 : : */
227 : : struct ethnl_req_info {
228 : : struct net_device *dev;
229 : : u32 flags;
230 : : };
231 : :
232 : : /**
233 : : * struct ethnl_reply_data - base type of reply data for GET requests
234 : : * @dev: device for current reply message; in single shot requests it is
235 : : * equal to ðnl_req_info.dev; in dumps it's different for each
236 : : * reply message
237 : : *
238 : : * This is a common base for request specific structures holding data for
239 : : * kernel reply message. These always embed struct ethnl_reply_data at zero
240 : : * offset.
241 : : */
242 : : struct ethnl_reply_data {
243 : : struct net_device *dev;
244 : : };
245 : :
246 : 0 : static inline int ethnl_ops_begin(struct net_device *dev)
247 : : {
248 [ # # # # : 0 : if (dev && dev->ethtool_ops->begin)
# # # # ]
249 : 0 : return dev->ethtool_ops->begin(dev);
250 : : else
251 : : return 0;
252 : : }
253 : :
254 : 0 : static inline void ethnl_ops_complete(struct net_device *dev)
255 : : {
256 [ # # # # : 0 : if (dev && dev->ethtool_ops->complete)
# # # # ]
257 : 0 : dev->ethtool_ops->complete(dev);
258 : : }
259 : :
260 : : /**
261 : : * struct ethnl_request_ops - unified handling of GET requests
262 : : * @request_cmd: command id for request (GET)
263 : : * @reply_cmd: command id for reply (GET_REPLY)
264 : : * @hdr_attr: attribute type for request header
265 : : * @max_attr: maximum (top level) attribute type
266 : : * @req_info_size: size of request info
267 : : * @reply_data_size: size of reply data
268 : : * @request_policy: netlink policy for message contents
269 : : * @allow_nodev_do: allow non-dump request with no device identification
270 : : * @parse_request:
271 : : * Parse request except common header (struct ethnl_req_info). Common
272 : : * header is already filled on entry, the rest up to @repdata_offset
273 : : * is zero initialized. This callback should only modify type specific
274 : : * request info by parsed attributes from request message.
275 : : * @prepare_data:
276 : : * Retrieve and prepare data needed to compose a reply message. Calls to
277 : : * ethtool_ops handlers are limited to this callback. Common reply data
278 : : * (struct ethnl_reply_data) is filled on entry, type specific part after
279 : : * it is zero initialized. This callback should only modify the type
280 : : * specific part of reply data. Device identification from struct
281 : : * ethnl_reply_data is to be used as for dump requests, it iterates
282 : : * through network devices while dev member of struct ethnl_req_info
283 : : * points to the device from client request.
284 : : * @reply_size:
285 : : * Estimate reply message size. Returned value must be sufficient for
286 : : * message payload without common reply header. The callback may returned
287 : : * estimate higher than actual message size if exact calculation would
288 : : * not be worth the saved memory space.
289 : : * @fill_reply:
290 : : * Fill reply message payload (except for common header) from reply data.
291 : : * The callback must not generate more payload than previously called
292 : : * ->reply_size() estimated.
293 : : * @cleanup_data:
294 : : * Optional cleanup called when reply data is no longer needed. Can be
295 : : * used e.g. to free any additional data structures outside the main
296 : : * structure which were allocated by ->prepare_data(). When processing
297 : : * dump requests, ->cleanup() is called for each message.
298 : : *
299 : : * Description of variable parts of GET request handling when using the
300 : : * unified infrastructure. When used, a pointer to an instance of this
301 : : * structure is to be added to ðnl_default_requests array and generic
302 : : * handlers ethnl_default_doit(), ethnl_default_dumpit(),
303 : : * ethnl_default_start() and ethnl_default_done() used in @ethtool_genl_ops;
304 : : * ethnl_default_notify() can be used in @ethnl_notify_handlers to send
305 : : * notifications of the corresponding type.
306 : : */
307 : : struct ethnl_request_ops {
308 : : u8 request_cmd;
309 : : u8 reply_cmd;
310 : : u16 hdr_attr;
311 : : unsigned int max_attr;
312 : : unsigned int req_info_size;
313 : : unsigned int reply_data_size;
314 : : const struct nla_policy *request_policy;
315 : : bool allow_nodev_do;
316 : :
317 : : int (*parse_request)(struct ethnl_req_info *req_info,
318 : : struct nlattr **tb,
319 : : struct netlink_ext_ack *extack);
320 : : int (*prepare_data)(const struct ethnl_req_info *req_info,
321 : : struct ethnl_reply_data *reply_data,
322 : : struct genl_info *info);
323 : : int (*reply_size)(const struct ethnl_req_info *req_info,
324 : : const struct ethnl_reply_data *reply_data);
325 : : int (*fill_reply)(struct sk_buff *skb,
326 : : const struct ethnl_req_info *req_info,
327 : : const struct ethnl_reply_data *reply_data);
328 : : void (*cleanup_data)(struct ethnl_reply_data *reply_data);
329 : : };
330 : :
331 : : /* request handlers */
332 : :
333 : : extern const struct ethnl_request_ops ethnl_strset_request_ops;
334 : : extern const struct ethnl_request_ops ethnl_linkinfo_request_ops;
335 : : extern const struct ethnl_request_ops ethnl_linkmodes_request_ops;
336 : : extern const struct ethnl_request_ops ethnl_linkstate_request_ops;
337 : : extern const struct ethnl_request_ops ethnl_debug_request_ops;
338 : : extern const struct ethnl_request_ops ethnl_wol_request_ops;
339 : :
340 : : int ethnl_set_linkinfo(struct sk_buff *skb, struct genl_info *info);
341 : : int ethnl_set_linkmodes(struct sk_buff *skb, struct genl_info *info);
342 : : int ethnl_set_debug(struct sk_buff *skb, struct genl_info *info);
343 : : int ethnl_set_wol(struct sk_buff *skb, struct genl_info *info);
344 : :
345 : : #endif /* _NET_ETHTOOL_NETLINK_H */
|