libnl 3.9.0
genl.c
1/* SPDX-License-Identifier: LGPL-2.1-only */
2/*
3 * Copyright (c) 2003-2012 Thomas Graf <tgraf@suug.ch>
4 */
5
6/**
7 * @defgroup genl Generic Netlink Library (libnl-genl)
8 *
9 * @{
10 */
11
12#include "nl-default.h"
13
14#include <netlink/netlink.h>
15#include <netlink/genl/genl.h>
16#include <netlink/utils.h>
17
18#include "nl-genl.h"
19#include "nl-aux-core/nl-core.h"
20
21/**
22 * @name Generic Netlink Socket
23 * @{
24 */
25
26/**
27 * Connect a Generic Netlink socket
28 * @arg sk Unconnected Netlink socket
29 *
30 * This function expects a struct nl_socket object previously allocated via
31 * nl_socket_alloc(). It calls nl_connect() to create the local socket file
32 * descriptor and binds the socket to the \c NETLINK_GENERIC Netlink protocol.
33 *
34 * Using this function is equivalent to:
35 * @code
36 * nl_connect(sk, NETLINK_GENERIC);
37 * @endcode
38 *
39 * @see nl_connect()
40 *
41 * @return 0 on success or a negative error code.
42 */
43int genl_connect(struct nl_sock *sk)
44{
45 return nl_connect(sk, NETLINK_GENERIC);
46}
47
48/** @} */
49
50/**
51 * @name Sending Data
52 * @{
53 */
54
55/**
56 * Send a Generic Netlink message consisting only of a header
57 * @arg sk Generic Netlink socket
58 * @arg family Numeric family identifier
59 * @arg cmd Numeric command identifier
60 * @arg version Interface version
61 * @arg flags Additional Netlink message flags (optional)
62 *
63 * This function is a shortcut for sending a Generic Netlink message without
64 * any message payload. The message will only consist of the Netlink and
65 * Generic Netlink headers. The header is constructed based on the specified
66 * parameters and passed on to nl_send_simple() to send it on the specified
67 * socket.
68 *
69 * @par Example:
70 * @code
71 * #include <netlink/genl/genl.h>
72 * #include <linux/genetlink.h>
73 *
74 * err = genl_send_simple(sk, GENL_ID_CTRL, CTRL_CMD_GETFAMILY, CTRL_VERSION,
75 * NLM_F_DUMP);
76 * @endcode
77 *
78 * @see nl_send_simple()
79 *
80 * @return 0 on success or a negative error code. Due to a bug, this function
81 * returns the number of bytes sent. Treat any non-negative number as success.
82 */
83int genl_send_simple(struct nl_sock *sk, int family, int cmd,
84 int version, int flags)
85{
86 struct genlmsghdr hdr = {
87 .cmd = cmd,
88 .version = version,
89 };
90
91 return nl_send_simple(sk, family, flags, &hdr, sizeof(hdr));
92}
93
94/** @} */
95
96/**
97 * @name Message Parsing
98 * @{
99 */
100
101/**
102 * Validate Generic Netlink message headers
103 * @arg nlh Pointer to Netlink message header
104 * @arg hdrlen Length of user header
105 *
106 * Verifies the integrity of the Netlink and Generic Netlink headers by
107 * enforcing the following requirements:
108 * - Valid Netlink message header (nlmsg_valid_hdr())
109 * - Presence of a complete Generic Netlink header
110 * - At least \c hdrlen bytes of payload included after the generic
111 * netlink header.
112 *
113 * @return A positive integer (true) if the headers are valid or
114 * 0 (false) if not.
115 */
116int genlmsg_valid_hdr(struct nlmsghdr *nlh, int hdrlen)
117{
118 struct genlmsghdr *ghdr;
119
120 if (!nlmsg_valid_hdr(nlh, GENL_HDRLEN))
121 return 0;
122
123 ghdr = nlmsg_data(nlh);
124 if (genlmsg_len(ghdr) < NLMSG_ALIGN(hdrlen))
125 return 0;
126
127 return 1;
128}
129
130/**
131 * Validate Generic Netlink message including attributes
132 * @arg nlh Pointer to Netlink message header
133 * @arg hdrlen Length of user header
134 * @arg maxtype Maximum attribtue id expected
135 * @arg policy Attribute validation policy
136 *
137 * Verifies the validity of the Netlink and Generic Netlink headers using
138 * genlmsg_valid_hdr() and calls nla_validate() on the message payload to
139 * verify the integrity of eventual attributes.
140 *
141 * @note You may call genlmsg_parse() directly to perform validation and
142 * parsing in a single step.
143 *
144 * @see genlmsg_valid_hdr()
145 * @see nla_validate()
146 * @see genlmsg_parse()
147 *
148 * @return 0 on success or a negative error code.
149 */
150int genlmsg_validate(struct nlmsghdr *nlh, int hdrlen, int maxtype,
151 const struct nla_policy *policy)
152{
153 struct genlmsghdr *ghdr;
154
155 if (!genlmsg_valid_hdr(nlh, hdrlen))
156 return -NLE_MSG_TOOSHORT;
157
158 ghdr = nlmsg_data(nlh);
159 return nla_validate(genlmsg_attrdata(ghdr, hdrlen),
160 genlmsg_attrlen(ghdr, hdrlen), maxtype, policy);
161}
162
163/**
164 * Parse Generic Netlink message including attributes
165 * @arg nlh Pointer to Netlink message header
166 * @arg hdrlen Length of user header
167 * @arg tb Array to store parsed attributes
168 * @arg maxtype Maximum attribute id expected
169 * @arg policy Attribute validation policy
170 *
171 * Verifies the validity of the Netlink and Generic Netlink headers using
172 * genlmsg_valid_hdr() and calls nla_parse() on the message payload to
173 * parse eventual attributes.
174 *
175 * @par Example:
176 * @code
177 * struct nlattr *attrs[MY_TYPE_MAX+1];
178 *
179 * if ((err = genlmsg_parse(nlmsg_hdr(msg), sizeof(struct my_hdr), attrs,
180 * MY_TYPE_MAX, attr_policy)) < 0)
181 * // ERROR
182 * @endcode
183 *
184 * @see genlmsg_valid_hdr()
185 * @see genlmsg_validate()
186 * @see nla_parse()
187 *
188 * @return 0 on success or a negative error code.
189 */
190int genlmsg_parse(struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[],
191 int maxtype, const struct nla_policy *policy)
192{
193 struct genlmsghdr *ghdr;
194
195 if (!genlmsg_valid_hdr(nlh, hdrlen))
196 return -NLE_MSG_TOOSHORT;
197
198 ghdr = nlmsg_data(nlh);
199 return nla_parse(tb, maxtype, genlmsg_attrdata(ghdr, hdrlen),
200 genlmsg_attrlen(ghdr, hdrlen), policy);
201}
202
203/**
204 * Return pointer to Generic Netlink header
205 * @arg nlh Netlink message header
206 *
207 * @return Pointer to Generic Netlink message header
208 */
209struct genlmsghdr *genlmsg_hdr(struct nlmsghdr *nlh)
210{
211 return nlmsg_data(nlh);
212}
213
214/**
215 * Return length of message payload including user header
216 * @arg gnlh Generic Netlink message header
217 *
218 * @see genlmsg_data()
219 *
220 * @return Length of user payload including an eventual user header in
221 * number of bytes.
222 */
223int genlmsg_len(const struct genlmsghdr *gnlh)
224{
225 const struct nlmsghdr *nlh;
226
227 nlh = (const struct nlmsghdr *)((const unsigned char *) gnlh - NLMSG_HDRLEN);
228 return (nlh->nlmsg_len - GENL_HDRLEN - NLMSG_HDRLEN);
229}
230
231
232/**
233 * Return pointer to user header
234 * @arg gnlh Generic Netlink message header
235 *
236 * Calculates the pointer to the user header based on the pointer to
237 * the Generic Netlink message header.
238 *
239 * @return Pointer to the user header
240 */
241void *genlmsg_user_hdr(const struct genlmsghdr *gnlh)
242{
243 return genlmsg_data(gnlh);
244}
245
246/**
247 * Return pointer to user data
248 * @arg gnlh Generic netlink message header
249 * @arg hdrlen Length of user header
250 *
251 * Calculates the pointer to the user data based on the pointer to
252 * the Generic Netlink message header.
253 *
254 * @see genlmsg_user_datalen()
255 *
256 * @return Pointer to the user data
257 */
258void *genlmsg_user_data(const struct genlmsghdr *gnlh, const int hdrlen)
259{
260 return (char *) genlmsg_user_hdr(gnlh) + NLMSG_ALIGN(hdrlen);
261}
262
263/**
264 * Return length of user data
265 * @arg gnlh Generic Netlink message header
266 * @arg hdrlen Length of user header
267 *
268 * @see genlmsg_user_data()
269 *
270 * @return Length of user data in bytes
271 */
272int genlmsg_user_datalen(const struct genlmsghdr *gnlh, const int hdrlen)
273{
274 return genlmsg_len(gnlh) - NLMSG_ALIGN(hdrlen);
275}
276
277/**
278 * Return pointer to message attributes
279 * @arg gnlh Generic Netlink message header
280 * @arg hdrlen Length of user header
281 *
282 * @see genlmsg_attrlen()
283 *
284 * @return Pointer to the start of the message's attributes section.
285 */
286struct nlattr *genlmsg_attrdata(const struct genlmsghdr *gnlh, int hdrlen)
287{
288 return genlmsg_user_data(gnlh, hdrlen);
289}
290
291/**
292 * Return length of message attributes
293 * @arg gnlh Generic Netlink message header
294 * @arg hdrlen Length of user header
295 *
296 * @see genlmsg_attrdata()
297 *
298 * @return Length of the message section containing attributes in number
299 * of bytes.
300 */
301int genlmsg_attrlen(const struct genlmsghdr *gnlh, int hdrlen)
302{
303 return genlmsg_len(gnlh) - NLMSG_ALIGN(hdrlen);
304}
305
306/** @} */
307
308/**
309 * @name Message Construction
310 * @{
311 */
312
313/**
314 * Add Generic Netlink headers to Netlink message
315 * @arg msg Netlink message object
316 * @arg port Netlink port or NL_AUTO_PORT
317 * @arg seq Sequence number of message or NL_AUTO_SEQ
318 * @arg family Numeric family identifier
319 * @arg hdrlen Length of user header
320 * @arg flags Additional Netlink message flags (optional)
321 * @arg cmd Numeric command identifier
322 * @arg version Interface version
323 *
324 * Calls nlmsg_put() on the specified message object to reserve space for
325 * the Netlink header, the Generic Netlink header, and a user header of
326 * specified length. Fills out the header fields with the specified
327 * parameters.
328 *
329 * @par Example:
330 * @code
331 * struct nl_msg *msg;
332 * struct my_hdr *user_hdr;
333 *
334 * if (!(msg = nlmsg_alloc()))
335 * // ERROR
336 *
337 * user_hdr = genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, family_id,
338 * sizeof(struct my_hdr), 0, MY_CMD_FOO, 0);
339 * if (!user_hdr)
340 * // ERROR
341 * @endcode
342 *
343 * @see nlmsg_put()
344 *
345 * Returns Pointer to user header or NULL if an error occurred.
346 */
347void *genlmsg_put(struct nl_msg *msg, uint32_t port, uint32_t seq, int family,
348 int hdrlen, int flags, uint8_t cmd, uint8_t version)
349{
350 struct nlmsghdr *nlh;
351 struct genlmsghdr hdr = {
352 .cmd = cmd,
353 .version = version,
354 };
355
356 nlh = nlmsg_put(msg, port, seq, family, GENL_HDRLEN + hdrlen, flags);
357 if (nlh == NULL)
358 return NULL;
359
360 memcpy(nlmsg_data(nlh), &hdr, sizeof(hdr));
361 NL_DBG(2, "msg %p: Added generic netlink header cmd=%d version=%d\n",
362 msg, cmd, version);
363
364 return (char *) nlmsg_data(nlh) + GENL_HDRLEN;
365}
366
367/** @} */
368
369/**
370 * @name Deprecated
371 * @{
372 */
373
374/**
375 * Return pointer to message payload
376 * @arg gnlh Generic Netlink message header
377 *
378 * @deprecated This function has been deprecated due to inability to specify
379 * the length of the user header. Use genlmsg_user_hdr()
380 * respectively genlmsg_user_data().
381 *
382 * @return Pointer to payload section
383 */
384void *genlmsg_data(const struct genlmsghdr *gnlh)
385{
386 return ((unsigned char *) gnlh + GENL_HDRLEN);
387}
388
389/** @} */
390/** @} */
int nla_validate(const struct nlattr *head, int len, int maxtype, const struct nla_policy *policy)
Validate a stream of attributes.
Definition attr.c:292
int nla_parse(struct nlattr *tb[], int maxtype, struct nlattr *head, int len, const struct nla_policy *policy)
Create attribute index based on a stream of attributes.
Definition attr.c:241
struct genlmsghdr * genlmsg_hdr(struct nlmsghdr *nlh)
Return pointer to Generic Netlink header.
Definition genl.c:209
int genlmsg_validate(struct nlmsghdr *nlh, int hdrlen, int maxtype, const struct nla_policy *policy)
Validate Generic Netlink message including attributes.
Definition genl.c:150
void * genlmsg_put(struct nl_msg *msg, uint32_t port, uint32_t seq, int family, int hdrlen, int flags, uint8_t cmd, uint8_t version)
Add Generic Netlink headers to Netlink message.
Definition genl.c:347
struct nlattr * genlmsg_attrdata(const struct genlmsghdr *gnlh, int hdrlen)
Return pointer to message attributes.
Definition genl.c:286
int genlmsg_len(const struct genlmsghdr *gnlh)
Return length of message payload including user header.
Definition genl.c:223
int genlmsg_user_datalen(const struct genlmsghdr *gnlh, const int hdrlen)
Return length of user data.
Definition genl.c:272
void * genlmsg_user_hdr(const struct genlmsghdr *gnlh)
Return pointer to user header.
Definition genl.c:241
int genl_send_simple(struct nl_sock *sk, int family, int cmd, int version, int flags)
Send a Generic Netlink message consisting only of a header.
Definition genl.c:83
int genlmsg_parse(struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[], int maxtype, const struct nla_policy *policy)
Parse Generic Netlink message including attributes.
Definition genl.c:190
void * genlmsg_user_data(const struct genlmsghdr *gnlh, const int hdrlen)
Return pointer to user data.
Definition genl.c:258
void * genlmsg_data(const struct genlmsghdr *gnlh)
Return pointer to message payload.
Definition genl.c:384
int genl_connect(struct nl_sock *sk)
Connect a Generic Netlink socket.
Definition genl.c:43
int genlmsg_attrlen(const struct genlmsghdr *gnlh, int hdrlen)
Return length of message attributes.
Definition genl.c:301
int genlmsg_valid_hdr(struct nlmsghdr *nlh, int hdrlen)
Validate Generic Netlink message headers.
Definition genl.c:116
void * nlmsg_data(const struct nlmsghdr *nlh)
Return pointer to message payload.
Definition msg.c:108
struct nlmsghdr * nlmsg_put(struct nl_msg *n, uint32_t pid, uint32_t seq, int type, int payload, int flags)
Add a netlink message header to a netlink message.
Definition msg.c:511
int nl_connect(struct nl_sock *sk, int protocol)
Create file descriptor and bind socket.
Definition nl.c:102
int nl_send_simple(struct nl_sock *sk, int type, int flags, void *buf, size_t size)
Construct and transmit a Netlink message.
Definition nl.c:579
Attribute validation policy.
Definition attr.h:63