1*4dc78e53SAndroid Build Coastguard Worker /* SPDX-License-Identifier: LGPL-2.1-only */
2*4dc78e53SAndroid Build Coastguard Worker /*
3*4dc78e53SAndroid Build Coastguard Worker * Copyright (c) 2003-2012 Thomas Graf <[email protected]>
4*4dc78e53SAndroid Build Coastguard Worker */
5*4dc78e53SAndroid Build Coastguard Worker
6*4dc78e53SAndroid Build Coastguard Worker /**
7*4dc78e53SAndroid Build Coastguard Worker * @defgroup core Core Library (libnl)
8*4dc78e53SAndroid Build Coastguard Worker *
9*4dc78e53SAndroid Build Coastguard Worker * Socket handling, connection management, sending and receiving of data,
10*4dc78e53SAndroid Build Coastguard Worker * message construction and parsing, object caching system, ...
11*4dc78e53SAndroid Build Coastguard Worker *
12*4dc78e53SAndroid Build Coastguard Worker * This is the API reference of the core library. It is not meant as a guide
13*4dc78e53SAndroid Build Coastguard Worker * but as a reference. Please refer to the core library guide for detailed
14*4dc78e53SAndroid Build Coastguard Worker * documentation on the library architecture and examples:
15*4dc78e53SAndroid Build Coastguard Worker *
16*4dc78e53SAndroid Build Coastguard Worker * * @ref_asciidoc{core,_,Netlink Core Library Development Guide}
17*4dc78e53SAndroid Build Coastguard Worker *
18*4dc78e53SAndroid Build Coastguard Worker *
19*4dc78e53SAndroid Build Coastguard Worker * @{
20*4dc78e53SAndroid Build Coastguard Worker */
21*4dc78e53SAndroid Build Coastguard Worker
22*4dc78e53SAndroid Build Coastguard Worker #include "nl-default.h"
23*4dc78e53SAndroid Build Coastguard Worker
24*4dc78e53SAndroid Build Coastguard Worker #include <linux/socket.h>
25*4dc78e53SAndroid Build Coastguard Worker
26*4dc78e53SAndroid Build Coastguard Worker #include <netlink/netlink.h>
27*4dc78e53SAndroid Build Coastguard Worker #include <netlink/utils.h>
28*4dc78e53SAndroid Build Coastguard Worker #include <netlink/handlers.h>
29*4dc78e53SAndroid Build Coastguard Worker #include <netlink/msg.h>
30*4dc78e53SAndroid Build Coastguard Worker #include <netlink/attr.h>
31*4dc78e53SAndroid Build Coastguard Worker
32*4dc78e53SAndroid Build Coastguard Worker #include "nl-core.h"
33*4dc78e53SAndroid Build Coastguard Worker #include "nl-priv-dynamic-core/nl-core.h"
34*4dc78e53SAndroid Build Coastguard Worker #include "nl-aux-core/nl-core.h"
35*4dc78e53SAndroid Build Coastguard Worker #include "nl-priv-dynamic-core/cache-api.h"
36*4dc78e53SAndroid Build Coastguard Worker
37*4dc78e53SAndroid Build Coastguard Worker /**
38*4dc78e53SAndroid Build Coastguard Worker * @defgroup core_types Data Types
39*4dc78e53SAndroid Build Coastguard Worker *
40*4dc78e53SAndroid Build Coastguard Worker * Core library data types
41*4dc78e53SAndroid Build Coastguard Worker * @{
42*4dc78e53SAndroid Build Coastguard Worker * @}
43*4dc78e53SAndroid Build Coastguard Worker *
44*4dc78e53SAndroid Build Coastguard Worker * @defgroup send_recv Send & Receive Data
45*4dc78e53SAndroid Build Coastguard Worker *
46*4dc78e53SAndroid Build Coastguard Worker * Connection management, sending & receiving of data
47*4dc78e53SAndroid Build Coastguard Worker *
48*4dc78e53SAndroid Build Coastguard Worker * Related sections in the development guide:
49*4dc78e53SAndroid Build Coastguard Worker * - @core_doc{core_send_recv, Sending & Receiving}
50*4dc78e53SAndroid Build Coastguard Worker * - @core_doc{core_sockets, Sockets}
51*4dc78e53SAndroid Build Coastguard Worker *
52*4dc78e53SAndroid Build Coastguard Worker * @{
53*4dc78e53SAndroid Build Coastguard Worker *
54*4dc78e53SAndroid Build Coastguard Worker * Header
55*4dc78e53SAndroid Build Coastguard Worker * ------
56*4dc78e53SAndroid Build Coastguard Worker * ~~~~{.c}
57*4dc78e53SAndroid Build Coastguard Worker * #include <netlink/netlink.h>
58*4dc78e53SAndroid Build Coastguard Worker * ~~~~
59*4dc78e53SAndroid Build Coastguard Worker */
60*4dc78e53SAndroid Build Coastguard Worker
61*4dc78e53SAndroid Build Coastguard Worker /**
62*4dc78e53SAndroid Build Coastguard Worker * @name Connection Management
63*4dc78e53SAndroid Build Coastguard Worker * @{
64*4dc78e53SAndroid Build Coastguard Worker */
65*4dc78e53SAndroid Build Coastguard Worker
66*4dc78e53SAndroid Build Coastguard Worker /**
67*4dc78e53SAndroid Build Coastguard Worker * Create file descriptor and bind socket.
68*4dc78e53SAndroid Build Coastguard Worker * @arg sk Netlink socket (required)
69*4dc78e53SAndroid Build Coastguard Worker * @arg protocol Netlink protocol to use (required)
70*4dc78e53SAndroid Build Coastguard Worker *
71*4dc78e53SAndroid Build Coastguard Worker * Creates a new Netlink socket using `socket()` and binds the socket to the
72*4dc78e53SAndroid Build Coastguard Worker * protocol and local port specified in the `sk` socket object. Fails if
73*4dc78e53SAndroid Build Coastguard Worker * the socket is already connected.
74*4dc78e53SAndroid Build Coastguard Worker *
75*4dc78e53SAndroid Build Coastguard Worker * @note If available, the `close-on-exec` (`SOCK_CLOEXEC`) feature is enabled
76*4dc78e53SAndroid Build Coastguard Worker * automatically on the new file descriptor. This causes the socket to
77*4dc78e53SAndroid Build Coastguard Worker * be closed automatically if any of the `exec` family functions succeed.
78*4dc78e53SAndroid Build Coastguard Worker * This is essential for multi threaded programs.
79*4dc78e53SAndroid Build Coastguard Worker *
80*4dc78e53SAndroid Build Coastguard Worker * @note The local port (`nl_socket_get_local_port()`) is unspecified after
81*4dc78e53SAndroid Build Coastguard Worker * creating a new socket. It only gets determined when accessing the
82*4dc78e53SAndroid Build Coastguard Worker * port the first time or during `nl_connect()`. When nl_connect()
83*4dc78e53SAndroid Build Coastguard Worker * fails during `bind()` due to `ADDRINUSE`, it will retry with
84*4dc78e53SAndroid Build Coastguard Worker * different ports if the port is unspecified. Unless you want to enforce
85*4dc78e53SAndroid Build Coastguard Worker * the use of a specific local port, don't access the local port (or
86*4dc78e53SAndroid Build Coastguard Worker * reset it to `unspecified` by calling `nl_socket_set_local_port(sk, 0)`).
87*4dc78e53SAndroid Build Coastguard Worker * This capability is indicated by
88*4dc78e53SAndroid Build Coastguard Worker * `%NL_CAPABILITY_NL_CONNECT_RETRY_GENERATE_PORT_ON_ADDRINUSE`.
89*4dc78e53SAndroid Build Coastguard Worker *
90*4dc78e53SAndroid Build Coastguard Worker * @note nl_connect() creates and sets the file descriptor. You can setup the file
91*4dc78e53SAndroid Build Coastguard Worker * descriptor yourself by creating and binding it, and then calling
92*4dc78e53SAndroid Build Coastguard Worker * nl_socket_set_fd(). The result will be the same.
93*4dc78e53SAndroid Build Coastguard Worker *
94*4dc78e53SAndroid Build Coastguard Worker * @see nl_socket_alloc()
95*4dc78e53SAndroid Build Coastguard Worker * @see nl_close()
96*4dc78e53SAndroid Build Coastguard Worker * @see nl_socket_set_fd()
97*4dc78e53SAndroid Build Coastguard Worker *
98*4dc78e53SAndroid Build Coastguard Worker * @return 0 on success or a negative error code.
99*4dc78e53SAndroid Build Coastguard Worker *
100*4dc78e53SAndroid Build Coastguard Worker * @retval -NLE_BAD_SOCK Socket is already connected
101*4dc78e53SAndroid Build Coastguard Worker */
nl_connect(struct nl_sock * sk,int protocol)102*4dc78e53SAndroid Build Coastguard Worker int nl_connect(struct nl_sock *sk, int protocol)
103*4dc78e53SAndroid Build Coastguard Worker {
104*4dc78e53SAndroid Build Coastguard Worker int err, flags = 0;
105*4dc78e53SAndroid Build Coastguard Worker int errsv;
106*4dc78e53SAndroid Build Coastguard Worker socklen_t addrlen;
107*4dc78e53SAndroid Build Coastguard Worker struct sockaddr_nl local = { 0 };
108*4dc78e53SAndroid Build Coastguard Worker int try_bind = 1;
109*4dc78e53SAndroid Build Coastguard Worker
110*4dc78e53SAndroid Build Coastguard Worker #ifdef SOCK_CLOEXEC
111*4dc78e53SAndroid Build Coastguard Worker flags |= SOCK_CLOEXEC;
112*4dc78e53SAndroid Build Coastguard Worker #endif
113*4dc78e53SAndroid Build Coastguard Worker
114*4dc78e53SAndroid Build Coastguard Worker if (sk->s_fd != -1)
115*4dc78e53SAndroid Build Coastguard Worker return -NLE_BAD_SOCK;
116*4dc78e53SAndroid Build Coastguard Worker
117*4dc78e53SAndroid Build Coastguard Worker sk->s_fd = socket(AF_NETLINK, SOCK_RAW | flags, protocol);
118*4dc78e53SAndroid Build Coastguard Worker if (sk->s_fd < 0) {
119*4dc78e53SAndroid Build Coastguard Worker errsv = errno;
120*4dc78e53SAndroid Build Coastguard Worker NL_DBG(4, "nl_connect(%p): socket() failed with %d (%s)\n", sk, errsv,
121*4dc78e53SAndroid Build Coastguard Worker nl_strerror_l(errsv));
122*4dc78e53SAndroid Build Coastguard Worker err = -nl_syserr2nlerr(errsv);
123*4dc78e53SAndroid Build Coastguard Worker goto errout;
124*4dc78e53SAndroid Build Coastguard Worker }
125*4dc78e53SAndroid Build Coastguard Worker
126*4dc78e53SAndroid Build Coastguard Worker err = nl_socket_set_buffer_size(sk, 0, 0);
127*4dc78e53SAndroid Build Coastguard Worker if (err < 0)
128*4dc78e53SAndroid Build Coastguard Worker goto errout;
129*4dc78e53SAndroid Build Coastguard Worker
130*4dc78e53SAndroid Build Coastguard Worker if (_nl_socket_is_local_port_unspecified (sk)) {
131*4dc78e53SAndroid Build Coastguard Worker uint32_t port;
132*4dc78e53SAndroid Build Coastguard Worker uint32_t used_ports[32] = { 0 };
133*4dc78e53SAndroid Build Coastguard Worker int ntries = 0;
134*4dc78e53SAndroid Build Coastguard Worker
135*4dc78e53SAndroid Build Coastguard Worker while (1) {
136*4dc78e53SAndroid Build Coastguard Worker if (ntries++ > 5) {
137*4dc78e53SAndroid Build Coastguard Worker /* try only a few times. We hit this only if many ports are already in
138*4dc78e53SAndroid Build Coastguard Worker * use but allocated *outside* libnl/generate_local_port(). */
139*4dc78e53SAndroid Build Coastguard Worker _nl_socket_set_local_port_no_release (sk, 0);
140*4dc78e53SAndroid Build Coastguard Worker break;
141*4dc78e53SAndroid Build Coastguard Worker }
142*4dc78e53SAndroid Build Coastguard Worker
143*4dc78e53SAndroid Build Coastguard Worker port = _nl_socket_set_local_port_no_release(sk, 1);
144*4dc78e53SAndroid Build Coastguard Worker if (port == 0)
145*4dc78e53SAndroid Build Coastguard Worker break;
146*4dc78e53SAndroid Build Coastguard Worker
147*4dc78e53SAndroid Build Coastguard Worker err = bind(sk->s_fd, (struct sockaddr*) &sk->s_local,
148*4dc78e53SAndroid Build Coastguard Worker sizeof(sk->s_local));
149*4dc78e53SAndroid Build Coastguard Worker if (err == 0) {
150*4dc78e53SAndroid Build Coastguard Worker try_bind = 0;
151*4dc78e53SAndroid Build Coastguard Worker break;
152*4dc78e53SAndroid Build Coastguard Worker }
153*4dc78e53SAndroid Build Coastguard Worker
154*4dc78e53SAndroid Build Coastguard Worker errsv = errno;
155*4dc78e53SAndroid Build Coastguard Worker if (errsv == EADDRINUSE) {
156*4dc78e53SAndroid Build Coastguard Worker NL_DBG(4, "nl_connect(%p): local port %u already in use. Retry.\n", sk, (unsigned) port);
157*4dc78e53SAndroid Build Coastguard Worker _nl_socket_used_ports_set(used_ports, port);
158*4dc78e53SAndroid Build Coastguard Worker } else {
159*4dc78e53SAndroid Build Coastguard Worker NL_DBG(4, "nl_connect(%p): bind() for port %u failed with %d (%s)\n",
160*4dc78e53SAndroid Build Coastguard Worker sk, (unsigned) port, errsv, nl_strerror_l(errsv));
161*4dc78e53SAndroid Build Coastguard Worker _nl_socket_used_ports_release_all(used_ports);
162*4dc78e53SAndroid Build Coastguard Worker err = -nl_syserr2nlerr(errsv);
163*4dc78e53SAndroid Build Coastguard Worker goto errout;
164*4dc78e53SAndroid Build Coastguard Worker }
165*4dc78e53SAndroid Build Coastguard Worker }
166*4dc78e53SAndroid Build Coastguard Worker _nl_socket_used_ports_release_all(used_ports);
167*4dc78e53SAndroid Build Coastguard Worker }
168*4dc78e53SAndroid Build Coastguard Worker if (try_bind) {
169*4dc78e53SAndroid Build Coastguard Worker err = bind(sk->s_fd, (struct sockaddr*) &sk->s_local,
170*4dc78e53SAndroid Build Coastguard Worker sizeof(sk->s_local));
171*4dc78e53SAndroid Build Coastguard Worker if (err != 0) {
172*4dc78e53SAndroid Build Coastguard Worker errsv = errno;
173*4dc78e53SAndroid Build Coastguard Worker NL_DBG(4, "nl_connect(%p): bind() failed with %d (%s)\n",
174*4dc78e53SAndroid Build Coastguard Worker sk, errsv, nl_strerror_l(errsv));
175*4dc78e53SAndroid Build Coastguard Worker err = -nl_syserr2nlerr(errsv);
176*4dc78e53SAndroid Build Coastguard Worker goto errout;
177*4dc78e53SAndroid Build Coastguard Worker }
178*4dc78e53SAndroid Build Coastguard Worker }
179*4dc78e53SAndroid Build Coastguard Worker
180*4dc78e53SAndroid Build Coastguard Worker addrlen = sizeof(local);
181*4dc78e53SAndroid Build Coastguard Worker err = getsockname(sk->s_fd, (struct sockaddr *) &local,
182*4dc78e53SAndroid Build Coastguard Worker &addrlen);
183*4dc78e53SAndroid Build Coastguard Worker if (err < 0) {
184*4dc78e53SAndroid Build Coastguard Worker NL_DBG(4, "nl_connect(%p): getsockname() failed with %d (%s)\n",
185*4dc78e53SAndroid Build Coastguard Worker sk, errno, nl_strerror_l(errno));
186*4dc78e53SAndroid Build Coastguard Worker err = -nl_syserr2nlerr(errno);
187*4dc78e53SAndroid Build Coastguard Worker goto errout;
188*4dc78e53SAndroid Build Coastguard Worker }
189*4dc78e53SAndroid Build Coastguard Worker
190*4dc78e53SAndroid Build Coastguard Worker if (addrlen != sizeof(local)) {
191*4dc78e53SAndroid Build Coastguard Worker err = -NLE_NOADDR;
192*4dc78e53SAndroid Build Coastguard Worker goto errout;
193*4dc78e53SAndroid Build Coastguard Worker }
194*4dc78e53SAndroid Build Coastguard Worker
195*4dc78e53SAndroid Build Coastguard Worker if (local.nl_family != AF_NETLINK) {
196*4dc78e53SAndroid Build Coastguard Worker err = -NLE_AF_NOSUPPORT;
197*4dc78e53SAndroid Build Coastguard Worker goto errout;
198*4dc78e53SAndroid Build Coastguard Worker }
199*4dc78e53SAndroid Build Coastguard Worker
200*4dc78e53SAndroid Build Coastguard Worker if (sk->s_local.nl_pid != local.nl_pid) {
201*4dc78e53SAndroid Build Coastguard Worker /* The port id is different. That can happen if the port id was zero
202*4dc78e53SAndroid Build Coastguard Worker * and kernel assigned a local port. */
203*4dc78e53SAndroid Build Coastguard Worker nl_socket_set_local_port (sk, local.nl_pid);
204*4dc78e53SAndroid Build Coastguard Worker }
205*4dc78e53SAndroid Build Coastguard Worker sk->s_local = local;
206*4dc78e53SAndroid Build Coastguard Worker sk->s_proto = protocol;
207*4dc78e53SAndroid Build Coastguard Worker
208*4dc78e53SAndroid Build Coastguard Worker return 0;
209*4dc78e53SAndroid Build Coastguard Worker errout:
210*4dc78e53SAndroid Build Coastguard Worker if (sk->s_fd != -1) {
211*4dc78e53SAndroid Build Coastguard Worker close(sk->s_fd);
212*4dc78e53SAndroid Build Coastguard Worker sk->s_fd = -1;
213*4dc78e53SAndroid Build Coastguard Worker }
214*4dc78e53SAndroid Build Coastguard Worker
215*4dc78e53SAndroid Build Coastguard Worker return err;
216*4dc78e53SAndroid Build Coastguard Worker }
217*4dc78e53SAndroid Build Coastguard Worker
218*4dc78e53SAndroid Build Coastguard Worker /**
219*4dc78e53SAndroid Build Coastguard Worker * Close Netlink socket
220*4dc78e53SAndroid Build Coastguard Worker * @arg sk Netlink socket (required)
221*4dc78e53SAndroid Build Coastguard Worker *
222*4dc78e53SAndroid Build Coastguard Worker * Closes the Netlink socket using `close()`.
223*4dc78e53SAndroid Build Coastguard Worker *
224*4dc78e53SAndroid Build Coastguard Worker * @note The socket is closed automatically if a `struct nl_sock` object is
225*4dc78e53SAndroid Build Coastguard Worker * freed using `nl_socket_free()`.
226*4dc78e53SAndroid Build Coastguard Worker *
227*4dc78e53SAndroid Build Coastguard Worker * @see nl_connect()
228*4dc78e53SAndroid Build Coastguard Worker */
nl_close(struct nl_sock * sk)229*4dc78e53SAndroid Build Coastguard Worker void nl_close(struct nl_sock *sk)
230*4dc78e53SAndroid Build Coastguard Worker {
231*4dc78e53SAndroid Build Coastguard Worker if (sk->s_fd >= 0) {
232*4dc78e53SAndroid Build Coastguard Worker close(sk->s_fd);
233*4dc78e53SAndroid Build Coastguard Worker sk->s_fd = -1;
234*4dc78e53SAndroid Build Coastguard Worker }
235*4dc78e53SAndroid Build Coastguard Worker
236*4dc78e53SAndroid Build Coastguard Worker sk->s_proto = 0;
237*4dc78e53SAndroid Build Coastguard Worker }
238*4dc78e53SAndroid Build Coastguard Worker
239*4dc78e53SAndroid Build Coastguard Worker /** @} */
240*4dc78e53SAndroid Build Coastguard Worker
241*4dc78e53SAndroid Build Coastguard Worker /**
242*4dc78e53SAndroid Build Coastguard Worker * @name Send
243*4dc78e53SAndroid Build Coastguard Worker * @{
244*4dc78e53SAndroid Build Coastguard Worker */
245*4dc78e53SAndroid Build Coastguard Worker
246*4dc78e53SAndroid Build Coastguard Worker /**
247*4dc78e53SAndroid Build Coastguard Worker * Transmit raw data over Netlink socket.
248*4dc78e53SAndroid Build Coastguard Worker * @arg sk Netlink socket (required)
249*4dc78e53SAndroid Build Coastguard Worker * @arg buf Buffer carrying data to send (required)
250*4dc78e53SAndroid Build Coastguard Worker * @arg size Size of buffer (required)
251*4dc78e53SAndroid Build Coastguard Worker *
252*4dc78e53SAndroid Build Coastguard Worker * Transmits "raw" data over the specified Netlink socket. Unlike the other
253*4dc78e53SAndroid Build Coastguard Worker * transmit functions it does not modify the data in any way. It directly
254*4dc78e53SAndroid Build Coastguard Worker * passes the buffer \c buf of \c size to sendto().
255*4dc78e53SAndroid Build Coastguard Worker *
256*4dc78e53SAndroid Build Coastguard Worker * The message is addressed to the peer as specified in the socket by either
257*4dc78e53SAndroid Build Coastguard Worker * the nl_socket_set_peer_port() or nl_socket_set_peer_groups() function.
258*4dc78e53SAndroid Build Coastguard Worker *
259*4dc78e53SAndroid Build Coastguard Worker * @note Because there is no indication on the message boundaries of the data
260*4dc78e53SAndroid Build Coastguard Worker * being sent, the \c NL_CB_MSG_OUT callback handler will not be invoked
261*4dc78e53SAndroid Build Coastguard Worker * for data that is being sent using this function.
262*4dc78e53SAndroid Build Coastguard Worker *
263*4dc78e53SAndroid Build Coastguard Worker * @see nl_socket_set_peer_port()
264*4dc78e53SAndroid Build Coastguard Worker * @see nl_socket_set_peer_groups()
265*4dc78e53SAndroid Build Coastguard Worker * @see nl_sendmsg()
266*4dc78e53SAndroid Build Coastguard Worker *
267*4dc78e53SAndroid Build Coastguard Worker * @return Number of bytes sent or a negative error code.
268*4dc78e53SAndroid Build Coastguard Worker */
nl_sendto(struct nl_sock * sk,void * buf,size_t size)269*4dc78e53SAndroid Build Coastguard Worker int nl_sendto(struct nl_sock *sk, void *buf, size_t size)
270*4dc78e53SAndroid Build Coastguard Worker {
271*4dc78e53SAndroid Build Coastguard Worker int ret;
272*4dc78e53SAndroid Build Coastguard Worker
273*4dc78e53SAndroid Build Coastguard Worker if (!buf)
274*4dc78e53SAndroid Build Coastguard Worker return -NLE_INVAL;
275*4dc78e53SAndroid Build Coastguard Worker
276*4dc78e53SAndroid Build Coastguard Worker if (sk->s_fd < 0)
277*4dc78e53SAndroid Build Coastguard Worker return -NLE_BAD_SOCK;
278*4dc78e53SAndroid Build Coastguard Worker
279*4dc78e53SAndroid Build Coastguard Worker ret = sendto(sk->s_fd, buf, size, 0, (struct sockaddr *)
280*4dc78e53SAndroid Build Coastguard Worker &sk->s_peer, sizeof(sk->s_peer));
281*4dc78e53SAndroid Build Coastguard Worker if (ret < 0) {
282*4dc78e53SAndroid Build Coastguard Worker NL_DBG(4, "nl_sendto(%p): sendto() failed with %d (%s)\n",
283*4dc78e53SAndroid Build Coastguard Worker sk, errno, nl_strerror_l(errno));
284*4dc78e53SAndroid Build Coastguard Worker return -nl_syserr2nlerr(errno);
285*4dc78e53SAndroid Build Coastguard Worker }
286*4dc78e53SAndroid Build Coastguard Worker
287*4dc78e53SAndroid Build Coastguard Worker return ret;
288*4dc78e53SAndroid Build Coastguard Worker }
289*4dc78e53SAndroid Build Coastguard Worker
290*4dc78e53SAndroid Build Coastguard Worker /**
291*4dc78e53SAndroid Build Coastguard Worker * Transmit Netlink message using sendmsg()
292*4dc78e53SAndroid Build Coastguard Worker * @arg sk Netlink socket (required)
293*4dc78e53SAndroid Build Coastguard Worker * @arg msg Netlink message to be sent (required)
294*4dc78e53SAndroid Build Coastguard Worker * @arg hdr sendmsg() message header (required)
295*4dc78e53SAndroid Build Coastguard Worker *
296*4dc78e53SAndroid Build Coastguard Worker * Transmits the message specified in \c hdr over the Netlink socket using the
297*4dc78e53SAndroid Build Coastguard Worker * sendmsg() system call.
298*4dc78e53SAndroid Build Coastguard Worker *
299*4dc78e53SAndroid Build Coastguard Worker * @attention
300*4dc78e53SAndroid Build Coastguard Worker * The `msg` argument will *not* be used to derive the message payload that
301*4dc78e53SAndroid Build Coastguard Worker * is being sent out. The `msg` argument is *only* passed on to the
302*4dc78e53SAndroid Build Coastguard Worker * `NL_CB_MSG_OUT` callback. The caller is responsible to initialize the
303*4dc78e53SAndroid Build Coastguard Worker * `hdr` struct properly and have it point to the message payload and
304*4dc78e53SAndroid Build Coastguard Worker * socket address.
305*4dc78e53SAndroid Build Coastguard Worker *
306*4dc78e53SAndroid Build Coastguard Worker * @note
307*4dc78e53SAndroid Build Coastguard Worker * This function uses `nlmsg_set_src()` to modify the `msg` argument prior to
308*4dc78e53SAndroid Build Coastguard Worker * invoking the `NL_CB_MSG_OUT` callback to provide the local port number.
309*4dc78e53SAndroid Build Coastguard Worker *
310*4dc78e53SAndroid Build Coastguard Worker * @callback This function triggers the `NL_CB_MSG_OUT` callback.
311*4dc78e53SAndroid Build Coastguard Worker *
312*4dc78e53SAndroid Build Coastguard Worker * @attention
313*4dc78e53SAndroid Build Coastguard Worker * Think twice before using this function. It provides a low level access to
314*4dc78e53SAndroid Build Coastguard Worker * the Netlink socket. Among other limitations, it does not add credentials
315*4dc78e53SAndroid Build Coastguard Worker * even if enabled or respect the destination address specified in the `msg`
316*4dc78e53SAndroid Build Coastguard Worker * object.
317*4dc78e53SAndroid Build Coastguard Worker *
318*4dc78e53SAndroid Build Coastguard Worker * @see nl_socket_set_local_port()
319*4dc78e53SAndroid Build Coastguard Worker * @see nl_send_auto()
320*4dc78e53SAndroid Build Coastguard Worker * @see nl_send_iovec()
321*4dc78e53SAndroid Build Coastguard Worker *
322*4dc78e53SAndroid Build Coastguard Worker * @return Number of bytes sent on success or a negative error code.
323*4dc78e53SAndroid Build Coastguard Worker *
324*4dc78e53SAndroid Build Coastguard Worker * @lowlevel
325*4dc78e53SAndroid Build Coastguard Worker */
nl_sendmsg(struct nl_sock * sk,struct nl_msg * msg,struct msghdr * hdr)326*4dc78e53SAndroid Build Coastguard Worker int nl_sendmsg(struct nl_sock *sk, struct nl_msg *msg, struct msghdr *hdr)
327*4dc78e53SAndroid Build Coastguard Worker {
328*4dc78e53SAndroid Build Coastguard Worker struct nl_cb *cb;
329*4dc78e53SAndroid Build Coastguard Worker int ret;
330*4dc78e53SAndroid Build Coastguard Worker
331*4dc78e53SAndroid Build Coastguard Worker if (sk->s_fd < 0)
332*4dc78e53SAndroid Build Coastguard Worker return -NLE_BAD_SOCK;
333*4dc78e53SAndroid Build Coastguard Worker
334*4dc78e53SAndroid Build Coastguard Worker nlmsg_set_src(msg, &sk->s_local);
335*4dc78e53SAndroid Build Coastguard Worker
336*4dc78e53SAndroid Build Coastguard Worker cb = sk->s_cb;
337*4dc78e53SAndroid Build Coastguard Worker if (cb->cb_set[NL_CB_MSG_OUT])
338*4dc78e53SAndroid Build Coastguard Worker if ((ret = nl_cb_call(cb, NL_CB_MSG_OUT, msg)) != NL_OK)
339*4dc78e53SAndroid Build Coastguard Worker return ret;
340*4dc78e53SAndroid Build Coastguard Worker
341*4dc78e53SAndroid Build Coastguard Worker ret = sendmsg(sk->s_fd, hdr, 0);
342*4dc78e53SAndroid Build Coastguard Worker if (ret < 0) {
343*4dc78e53SAndroid Build Coastguard Worker NL_DBG(4, "nl_sendmsg(%p): sendmsg() failed with %d (%s)\n",
344*4dc78e53SAndroid Build Coastguard Worker sk, errno, nl_strerror_l(errno));
345*4dc78e53SAndroid Build Coastguard Worker return -nl_syserr2nlerr(errno);
346*4dc78e53SAndroid Build Coastguard Worker }
347*4dc78e53SAndroid Build Coastguard Worker
348*4dc78e53SAndroid Build Coastguard Worker NL_DBG(4, "sent %d bytes\n", ret);
349*4dc78e53SAndroid Build Coastguard Worker return ret;
350*4dc78e53SAndroid Build Coastguard Worker }
351*4dc78e53SAndroid Build Coastguard Worker
352*4dc78e53SAndroid Build Coastguard Worker
353*4dc78e53SAndroid Build Coastguard Worker /**
354*4dc78e53SAndroid Build Coastguard Worker * Transmit Netlink message (taking IO vector)
355*4dc78e53SAndroid Build Coastguard Worker * @arg sk Netlink socket (required)
356*4dc78e53SAndroid Build Coastguard Worker * @arg msg Netlink message to be sent (required)
357*4dc78e53SAndroid Build Coastguard Worker * @arg iov IO vector to be sent (required)
358*4dc78e53SAndroid Build Coastguard Worker * @arg iovlen Number of struct iovec to be sent (required)
359*4dc78e53SAndroid Build Coastguard Worker *
360*4dc78e53SAndroid Build Coastguard Worker * This function is identical to nl_send() except that instead of taking a
361*4dc78e53SAndroid Build Coastguard Worker * `struct nl_msg` object it takes an IO vector. Please see the description
362*4dc78e53SAndroid Build Coastguard Worker * of `nl_send()`.
363*4dc78e53SAndroid Build Coastguard Worker *
364*4dc78e53SAndroid Build Coastguard Worker * @callback This function triggers the `NL_CB_MSG_OUT` callback.
365*4dc78e53SAndroid Build Coastguard Worker *
366*4dc78e53SAndroid Build Coastguard Worker * @see nl_send()
367*4dc78e53SAndroid Build Coastguard Worker *
368*4dc78e53SAndroid Build Coastguard Worker * @return Number of bytes sent on success or a negative error code.
369*4dc78e53SAndroid Build Coastguard Worker *
370*4dc78e53SAndroid Build Coastguard Worker * @lowlevel
371*4dc78e53SAndroid Build Coastguard Worker */
nl_send_iovec(struct nl_sock * sk,struct nl_msg * msg,struct iovec * iov,unsigned iovlen)372*4dc78e53SAndroid Build Coastguard Worker int nl_send_iovec(struct nl_sock *sk, struct nl_msg *msg, struct iovec *iov, unsigned iovlen)
373*4dc78e53SAndroid Build Coastguard Worker {
374*4dc78e53SAndroid Build Coastguard Worker struct sockaddr_nl *dst;
375*4dc78e53SAndroid Build Coastguard Worker struct ucred *creds;
376*4dc78e53SAndroid Build Coastguard Worker struct msghdr hdr = {
377*4dc78e53SAndroid Build Coastguard Worker .msg_name = (void *) &sk->s_peer,
378*4dc78e53SAndroid Build Coastguard Worker .msg_namelen = sizeof(struct sockaddr_nl),
379*4dc78e53SAndroid Build Coastguard Worker .msg_iov = iov,
380*4dc78e53SAndroid Build Coastguard Worker .msg_iovlen = iovlen,
381*4dc78e53SAndroid Build Coastguard Worker };
382*4dc78e53SAndroid Build Coastguard Worker char buf[CMSG_SPACE(sizeof(struct ucred))];
383*4dc78e53SAndroid Build Coastguard Worker
384*4dc78e53SAndroid Build Coastguard Worker /* Overwrite destination if specified in the message itself, defaults
385*4dc78e53SAndroid Build Coastguard Worker * to the peer address of the socket.
386*4dc78e53SAndroid Build Coastguard Worker */
387*4dc78e53SAndroid Build Coastguard Worker dst = nlmsg_get_dst(msg);
388*4dc78e53SAndroid Build Coastguard Worker if (dst->nl_family == AF_NETLINK)
389*4dc78e53SAndroid Build Coastguard Worker hdr.msg_name = dst;
390*4dc78e53SAndroid Build Coastguard Worker
391*4dc78e53SAndroid Build Coastguard Worker /* Add credentials if present. */
392*4dc78e53SAndroid Build Coastguard Worker creds = nlmsg_get_creds(msg);
393*4dc78e53SAndroid Build Coastguard Worker if (creds != NULL) {
394*4dc78e53SAndroid Build Coastguard Worker struct cmsghdr *cmsg;
395*4dc78e53SAndroid Build Coastguard Worker
396*4dc78e53SAndroid Build Coastguard Worker hdr.msg_control = buf;
397*4dc78e53SAndroid Build Coastguard Worker hdr.msg_controllen = sizeof(buf);
398*4dc78e53SAndroid Build Coastguard Worker
399*4dc78e53SAndroid Build Coastguard Worker cmsg = CMSG_FIRSTHDR(&hdr);
400*4dc78e53SAndroid Build Coastguard Worker cmsg->cmsg_level = SOL_SOCKET;
401*4dc78e53SAndroid Build Coastguard Worker cmsg->cmsg_type = SCM_CREDENTIALS;
402*4dc78e53SAndroid Build Coastguard Worker cmsg->cmsg_len = CMSG_LEN(sizeof(struct ucred));
403*4dc78e53SAndroid Build Coastguard Worker memcpy(CMSG_DATA(cmsg), creds, sizeof(struct ucred));
404*4dc78e53SAndroid Build Coastguard Worker }
405*4dc78e53SAndroid Build Coastguard Worker
406*4dc78e53SAndroid Build Coastguard Worker return nl_sendmsg(sk, msg, &hdr);
407*4dc78e53SAndroid Build Coastguard Worker }
408*4dc78e53SAndroid Build Coastguard Worker
409*4dc78e53SAndroid Build Coastguard Worker /**
410*4dc78e53SAndroid Build Coastguard Worker * Transmit Netlink message
411*4dc78e53SAndroid Build Coastguard Worker * @arg sk Netlink socket (required)
412*4dc78e53SAndroid Build Coastguard Worker * @arg msg Netlink message (required)
413*4dc78e53SAndroid Build Coastguard Worker *
414*4dc78e53SAndroid Build Coastguard Worker * Transmits the Netlink message `msg` over the Netlink socket using the
415*4dc78e53SAndroid Build Coastguard Worker * `sendmsg()` system call. This function is based on `nl_send_iovec()` but
416*4dc78e53SAndroid Build Coastguard Worker * takes care of initializing a `struct iovec` based on the `msg` object.
417*4dc78e53SAndroid Build Coastguard Worker *
418*4dc78e53SAndroid Build Coastguard Worker * The message is addressed to the peer as specified in the socket by either
419*4dc78e53SAndroid Build Coastguard Worker * the nl_socket_set_peer_port() or nl_socket_set_peer_groups() function.
420*4dc78e53SAndroid Build Coastguard Worker * The peer address can be overwritten by specifying an address in the `msg`
421*4dc78e53SAndroid Build Coastguard Worker * object using nlmsg_set_dst().
422*4dc78e53SAndroid Build Coastguard Worker *
423*4dc78e53SAndroid Build Coastguard Worker * If present in the `msg`, credentials set by the nlmsg_set_creds() function
424*4dc78e53SAndroid Build Coastguard Worker * are added to the control buffer of the message.
425*4dc78e53SAndroid Build Coastguard Worker *
426*4dc78e53SAndroid Build Coastguard Worker * @par Overwriting Capability:
427*4dc78e53SAndroid Build Coastguard Worker * Calls to this function can be overwritten by providing an alternative using
428*4dc78e53SAndroid Build Coastguard Worker * the nl_cb_overwrite_send() function.
429*4dc78e53SAndroid Build Coastguard Worker *
430*4dc78e53SAndroid Build Coastguard Worker * @callback This function triggers the `NL_CB_MSG_OUT` callback.
431*4dc78e53SAndroid Build Coastguard Worker *
432*4dc78e53SAndroid Build Coastguard Worker * @attention
433*4dc78e53SAndroid Build Coastguard Worker * Unlike `nl_send_auto()`, this function does *not* finalize the message in
434*4dc78e53SAndroid Build Coastguard Worker * terms of automatically adding needed flags or filling out port numbers.
435*4dc78e53SAndroid Build Coastguard Worker *
436*4dc78e53SAndroid Build Coastguard Worker * @see nl_send_auto()
437*4dc78e53SAndroid Build Coastguard Worker * @see nl_send_iovec()
438*4dc78e53SAndroid Build Coastguard Worker * @see nl_socket_set_peer_port()
439*4dc78e53SAndroid Build Coastguard Worker * @see nl_socket_set_peer_groups()
440*4dc78e53SAndroid Build Coastguard Worker * @see nlmsg_set_dst()
441*4dc78e53SAndroid Build Coastguard Worker * @see nlmsg_set_creds()
442*4dc78e53SAndroid Build Coastguard Worker * @see nl_cb_overwrite_send()
443*4dc78e53SAndroid Build Coastguard Worker *
444*4dc78e53SAndroid Build Coastguard Worker * @return Number of bytes sent on success or a negative error code.
445*4dc78e53SAndroid Build Coastguard Worker */
nl_send(struct nl_sock * sk,struct nl_msg * msg)446*4dc78e53SAndroid Build Coastguard Worker int nl_send(struct nl_sock *sk, struct nl_msg *msg)
447*4dc78e53SAndroid Build Coastguard Worker {
448*4dc78e53SAndroid Build Coastguard Worker struct nl_cb *cb = sk->s_cb;
449*4dc78e53SAndroid Build Coastguard Worker
450*4dc78e53SAndroid Build Coastguard Worker if (cb->cb_send_ow)
451*4dc78e53SAndroid Build Coastguard Worker return cb->cb_send_ow(sk, msg);
452*4dc78e53SAndroid Build Coastguard Worker else {
453*4dc78e53SAndroid Build Coastguard Worker struct iovec iov = {
454*4dc78e53SAndroid Build Coastguard Worker .iov_base = (void *) nlmsg_hdr(msg),
455*4dc78e53SAndroid Build Coastguard Worker .iov_len = nlmsg_hdr(msg)->nlmsg_len,
456*4dc78e53SAndroid Build Coastguard Worker };
457*4dc78e53SAndroid Build Coastguard Worker
458*4dc78e53SAndroid Build Coastguard Worker return nl_send_iovec(sk, msg, &iov, 1);
459*4dc78e53SAndroid Build Coastguard Worker }
460*4dc78e53SAndroid Build Coastguard Worker }
461*4dc78e53SAndroid Build Coastguard Worker
462*4dc78e53SAndroid Build Coastguard Worker /**
463*4dc78e53SAndroid Build Coastguard Worker * Finalize Netlink message
464*4dc78e53SAndroid Build Coastguard Worker * @arg sk Netlink socket (required)
465*4dc78e53SAndroid Build Coastguard Worker * @arg msg Netlink message (required)
466*4dc78e53SAndroid Build Coastguard Worker *
467*4dc78e53SAndroid Build Coastguard Worker * This function finalizes a Netlink message by completing the message with
468*4dc78e53SAndroid Build Coastguard Worker * desirable flags and values depending on the socket configuration.
469*4dc78e53SAndroid Build Coastguard Worker *
470*4dc78e53SAndroid Build Coastguard Worker * - If not yet filled out, the source address of the message (`nlmsg_pid`)
471*4dc78e53SAndroid Build Coastguard Worker * will be set to the local port number of the socket.
472*4dc78e53SAndroid Build Coastguard Worker * - If not yet specified, the next available sequence number is assigned
473*4dc78e53SAndroid Build Coastguard Worker * to the message (`nlmsg_seq`).
474*4dc78e53SAndroid Build Coastguard Worker * - If not yet specified, the protocol field of the message will be set to
475*4dc78e53SAndroid Build Coastguard Worker * the protocol field of the socket.
476*4dc78e53SAndroid Build Coastguard Worker * - The `NLM_F_REQUEST` Netlink message flag will be set.
477*4dc78e53SAndroid Build Coastguard Worker * - The `NLM_F_ACK` flag will be set if Auto-ACK mode is enabled on the
478*4dc78e53SAndroid Build Coastguard Worker * socket.
479*4dc78e53SAndroid Build Coastguard Worker */
nl_complete_msg(struct nl_sock * sk,struct nl_msg * msg)480*4dc78e53SAndroid Build Coastguard Worker void nl_complete_msg(struct nl_sock *sk, struct nl_msg *msg)
481*4dc78e53SAndroid Build Coastguard Worker {
482*4dc78e53SAndroid Build Coastguard Worker struct nlmsghdr *nlh;
483*4dc78e53SAndroid Build Coastguard Worker
484*4dc78e53SAndroid Build Coastguard Worker nlh = nlmsg_hdr(msg);
485*4dc78e53SAndroid Build Coastguard Worker if (nlh->nlmsg_pid == NL_AUTO_PORT)
486*4dc78e53SAndroid Build Coastguard Worker nlh->nlmsg_pid = nl_socket_get_local_port(sk);
487*4dc78e53SAndroid Build Coastguard Worker
488*4dc78e53SAndroid Build Coastguard Worker if (nlh->nlmsg_seq == NL_AUTO_SEQ)
489*4dc78e53SAndroid Build Coastguard Worker nlh->nlmsg_seq = nl_socket_use_seq(sk);
490*4dc78e53SAndroid Build Coastguard Worker
491*4dc78e53SAndroid Build Coastguard Worker if (msg->nm_protocol == -1)
492*4dc78e53SAndroid Build Coastguard Worker msg->nm_protocol = sk->s_proto;
493*4dc78e53SAndroid Build Coastguard Worker
494*4dc78e53SAndroid Build Coastguard Worker nlh->nlmsg_flags |= NLM_F_REQUEST;
495*4dc78e53SAndroid Build Coastguard Worker
496*4dc78e53SAndroid Build Coastguard Worker if (!(sk->s_flags & NL_NO_AUTO_ACK))
497*4dc78e53SAndroid Build Coastguard Worker nlh->nlmsg_flags |= NLM_F_ACK;
498*4dc78e53SAndroid Build Coastguard Worker }
499*4dc78e53SAndroid Build Coastguard Worker
500*4dc78e53SAndroid Build Coastguard Worker /**
501*4dc78e53SAndroid Build Coastguard Worker * Finalize and transmit Netlink message
502*4dc78e53SAndroid Build Coastguard Worker * @arg sk Netlink socket (required)
503*4dc78e53SAndroid Build Coastguard Worker * @arg msg Netlink message (required)
504*4dc78e53SAndroid Build Coastguard Worker *
505*4dc78e53SAndroid Build Coastguard Worker * Finalizes the message by passing it to `nl_complete_msg()` and transmits it
506*4dc78e53SAndroid Build Coastguard Worker * by passing it to `nl_send()`.
507*4dc78e53SAndroid Build Coastguard Worker *
508*4dc78e53SAndroid Build Coastguard Worker * @callback This function triggers the `NL_CB_MSG_OUT` callback.
509*4dc78e53SAndroid Build Coastguard Worker *
510*4dc78e53SAndroid Build Coastguard Worker * @see nl_complete_msg()
511*4dc78e53SAndroid Build Coastguard Worker * @see nl_send()
512*4dc78e53SAndroid Build Coastguard Worker *
513*4dc78e53SAndroid Build Coastguard Worker * @return Number of bytes sent or a negative error code.
514*4dc78e53SAndroid Build Coastguard Worker */
nl_send_auto(struct nl_sock * sk,struct nl_msg * msg)515*4dc78e53SAndroid Build Coastguard Worker int nl_send_auto(struct nl_sock *sk, struct nl_msg *msg)
516*4dc78e53SAndroid Build Coastguard Worker {
517*4dc78e53SAndroid Build Coastguard Worker nl_complete_msg(sk, msg);
518*4dc78e53SAndroid Build Coastguard Worker
519*4dc78e53SAndroid Build Coastguard Worker return nl_send(sk, msg);
520*4dc78e53SAndroid Build Coastguard Worker }
521*4dc78e53SAndroid Build Coastguard Worker
522*4dc78e53SAndroid Build Coastguard Worker /**
523*4dc78e53SAndroid Build Coastguard Worker * Finalize and transmit Netlink message and wait for ACK or error message
524*4dc78e53SAndroid Build Coastguard Worker * @arg sk Netlink socket (required)
525*4dc78e53SAndroid Build Coastguard Worker * @arg msg Netlink message (required)
526*4dc78e53SAndroid Build Coastguard Worker *
527*4dc78e53SAndroid Build Coastguard Worker * Passes the `msg` to `nl_send_auto()` to finalize and transmit it. Frees the
528*4dc78e53SAndroid Build Coastguard Worker * message and waits (sleeps) for the ACK or error message to be received.
529*4dc78e53SAndroid Build Coastguard Worker *
530*4dc78e53SAndroid Build Coastguard Worker * @attention
531*4dc78e53SAndroid Build Coastguard Worker * Disabling Auto-ACK (nl_socket_disable_auto_ack()) will cause this function
532*4dc78e53SAndroid Build Coastguard Worker * to return immediately after transmitting the message. However, the peer may
533*4dc78e53SAndroid Build Coastguard Worker * still be returning an error message in response to the request. It is the
534*4dc78e53SAndroid Build Coastguard Worker * responsibility of the caller to handle such messages.
535*4dc78e53SAndroid Build Coastguard Worker *
536*4dc78e53SAndroid Build Coastguard Worker * @callback This function triggers the `NL_CB_MSG_OUT` callback.
537*4dc78e53SAndroid Build Coastguard Worker *
538*4dc78e53SAndroid Build Coastguard Worker * @attention
539*4dc78e53SAndroid Build Coastguard Worker * This function frees the `msg` object after transmitting it by calling
540*4dc78e53SAndroid Build Coastguard Worker * `nlmsg_free()`.
541*4dc78e53SAndroid Build Coastguard Worker *
542*4dc78e53SAndroid Build Coastguard Worker * @see nl_send_auto().
543*4dc78e53SAndroid Build Coastguard Worker * @see nl_wait_for_ack()
544*4dc78e53SAndroid Build Coastguard Worker *
545*4dc78e53SAndroid Build Coastguard Worker * @return 0 on success or a negative error code.
546*4dc78e53SAndroid Build Coastguard Worker */
nl_send_sync(struct nl_sock * sk,struct nl_msg * msg)547*4dc78e53SAndroid Build Coastguard Worker int nl_send_sync(struct nl_sock *sk, struct nl_msg *msg)
548*4dc78e53SAndroid Build Coastguard Worker {
549*4dc78e53SAndroid Build Coastguard Worker int err;
550*4dc78e53SAndroid Build Coastguard Worker
551*4dc78e53SAndroid Build Coastguard Worker err = nl_send_auto(sk, msg);
552*4dc78e53SAndroid Build Coastguard Worker nlmsg_free(msg);
553*4dc78e53SAndroid Build Coastguard Worker if (err < 0)
554*4dc78e53SAndroid Build Coastguard Worker return err;
555*4dc78e53SAndroid Build Coastguard Worker
556*4dc78e53SAndroid Build Coastguard Worker return wait_for_ack(sk);
557*4dc78e53SAndroid Build Coastguard Worker }
558*4dc78e53SAndroid Build Coastguard Worker
559*4dc78e53SAndroid Build Coastguard Worker /**
560*4dc78e53SAndroid Build Coastguard Worker * Construct and transmit a Netlink message
561*4dc78e53SAndroid Build Coastguard Worker * @arg sk Netlink socket (required)
562*4dc78e53SAndroid Build Coastguard Worker * @arg type Netlink message type (required)
563*4dc78e53SAndroid Build Coastguard Worker * @arg flags Netlink message flags (optional)
564*4dc78e53SAndroid Build Coastguard Worker * @arg buf Data buffer (optional)
565*4dc78e53SAndroid Build Coastguard Worker * @arg size Size of data buffer (optional)
566*4dc78e53SAndroid Build Coastguard Worker *
567*4dc78e53SAndroid Build Coastguard Worker * Allocates a new Netlink message based on `type` and `flags`. If `buf`
568*4dc78e53SAndroid Build Coastguard Worker * points to payload of length `size` that payload will be appended to the
569*4dc78e53SAndroid Build Coastguard Worker * message.
570*4dc78e53SAndroid Build Coastguard Worker *
571*4dc78e53SAndroid Build Coastguard Worker * Sends out the message using `nl_send_auto()` and frees the message
572*4dc78e53SAndroid Build Coastguard Worker * afterwards.
573*4dc78e53SAndroid Build Coastguard Worker *
574*4dc78e53SAndroid Build Coastguard Worker * @see nl_send_auto()
575*4dc78e53SAndroid Build Coastguard Worker *
576*4dc78e53SAndroid Build Coastguard Worker * @return Number of characters sent on success or a negative error code.
577*4dc78e53SAndroid Build Coastguard Worker * @retval -NLE_NOMEM Unable to allocate Netlink message
578*4dc78e53SAndroid Build Coastguard Worker */
nl_send_simple(struct nl_sock * sk,int type,int flags,void * buf,size_t size)579*4dc78e53SAndroid Build Coastguard Worker int nl_send_simple(struct nl_sock *sk, int type, int flags, void *buf,
580*4dc78e53SAndroid Build Coastguard Worker size_t size)
581*4dc78e53SAndroid Build Coastguard Worker {
582*4dc78e53SAndroid Build Coastguard Worker int err;
583*4dc78e53SAndroid Build Coastguard Worker struct nl_msg *msg;
584*4dc78e53SAndroid Build Coastguard Worker
585*4dc78e53SAndroid Build Coastguard Worker msg = nlmsg_alloc_simple(type, flags);
586*4dc78e53SAndroid Build Coastguard Worker if (!msg)
587*4dc78e53SAndroid Build Coastguard Worker return -NLE_NOMEM;
588*4dc78e53SAndroid Build Coastguard Worker
589*4dc78e53SAndroid Build Coastguard Worker if (buf && size) {
590*4dc78e53SAndroid Build Coastguard Worker err = nlmsg_append(msg, buf, size, NLMSG_ALIGNTO);
591*4dc78e53SAndroid Build Coastguard Worker if (err < 0)
592*4dc78e53SAndroid Build Coastguard Worker goto errout;
593*4dc78e53SAndroid Build Coastguard Worker }
594*4dc78e53SAndroid Build Coastguard Worker
595*4dc78e53SAndroid Build Coastguard Worker err = nl_send_auto(sk, msg);
596*4dc78e53SAndroid Build Coastguard Worker errout:
597*4dc78e53SAndroid Build Coastguard Worker nlmsg_free(msg);
598*4dc78e53SAndroid Build Coastguard Worker
599*4dc78e53SAndroid Build Coastguard Worker return err;
600*4dc78e53SAndroid Build Coastguard Worker }
601*4dc78e53SAndroid Build Coastguard Worker
602*4dc78e53SAndroid Build Coastguard Worker /** @} */
603*4dc78e53SAndroid Build Coastguard Worker
604*4dc78e53SAndroid Build Coastguard Worker /**
605*4dc78e53SAndroid Build Coastguard Worker * @name Receive
606*4dc78e53SAndroid Build Coastguard Worker * @{
607*4dc78e53SAndroid Build Coastguard Worker */
608*4dc78e53SAndroid Build Coastguard Worker
609*4dc78e53SAndroid Build Coastguard Worker /**
610*4dc78e53SAndroid Build Coastguard Worker * Receive data from netlink socket
611*4dc78e53SAndroid Build Coastguard Worker * @arg sk Netlink socket (required)
612*4dc78e53SAndroid Build Coastguard Worker * @arg nla Netlink socket structure to hold address of peer (required)
613*4dc78e53SAndroid Build Coastguard Worker * @arg buf Destination pointer for message content (required)
614*4dc78e53SAndroid Build Coastguard Worker * @arg creds Destination pointer for credentials (optional)
615*4dc78e53SAndroid Build Coastguard Worker *
616*4dc78e53SAndroid Build Coastguard Worker * Receives data from a connected netlink socket using recvmsg() and returns
617*4dc78e53SAndroid Build Coastguard Worker * the number of bytes read. The read data is stored in a newly allocated
618*4dc78e53SAndroid Build Coastguard Worker * buffer that is assigned to \c *buf. The peer's netlink address will be
619*4dc78e53SAndroid Build Coastguard Worker * stored in \c *nla.
620*4dc78e53SAndroid Build Coastguard Worker *
621*4dc78e53SAndroid Build Coastguard Worker * This function blocks until data is available to be read unless the socket
622*4dc78e53SAndroid Build Coastguard Worker * has been put into non-blocking mode using nl_socket_set_nonblocking() in
623*4dc78e53SAndroid Build Coastguard Worker * which case this function will return immediately with a return value of
624*4dc78e53SAndroid Build Coastguard Worker * -NLA_AGAIN (versions before 3.2.22 returned instead 0, in which case you
625*4dc78e53SAndroid Build Coastguard Worker * should check first clear errno and then check for errno EAGAIN).
626*4dc78e53SAndroid Build Coastguard Worker *
627*4dc78e53SAndroid Build Coastguard Worker * The buffer size used when reading from the netlink socket and thus limiting
628*4dc78e53SAndroid Build Coastguard Worker * the maximum size of a netlink message that can be read defaults to the size
629*4dc78e53SAndroid Build Coastguard Worker * of a memory page (getpagesize()). The buffer size can be modified on a per
630*4dc78e53SAndroid Build Coastguard Worker * socket level using the function nl_socket_set_msg_buf_size().
631*4dc78e53SAndroid Build Coastguard Worker *
632*4dc78e53SAndroid Build Coastguard Worker * If message peeking is enabled using nl_socket_enable_msg_peek() the size of
633*4dc78e53SAndroid Build Coastguard Worker * the message to be read will be determined using the MSG_PEEK flag prior to
634*4dc78e53SAndroid Build Coastguard Worker * performing the actual read. This leads to an additional recvmsg() call for
635*4dc78e53SAndroid Build Coastguard Worker * every read operation which has performance implications and is not
636*4dc78e53SAndroid Build Coastguard Worker * recommended for high throughput protocols.
637*4dc78e53SAndroid Build Coastguard Worker *
638*4dc78e53SAndroid Build Coastguard Worker * An eventual interruption of the recvmsg() system call is automatically
639*4dc78e53SAndroid Build Coastguard Worker * handled by retrying the operation.
640*4dc78e53SAndroid Build Coastguard Worker *
641*4dc78e53SAndroid Build Coastguard Worker * If receiving of credentials has been enabled using the function
642*4dc78e53SAndroid Build Coastguard Worker * nl_socket_set_passcred(), this function will allocate a new struct ucred
643*4dc78e53SAndroid Build Coastguard Worker * filled with the received credentials and assign it to \c *creds. The caller
644*4dc78e53SAndroid Build Coastguard Worker * is responsible for freeing the buffer.
645*4dc78e53SAndroid Build Coastguard Worker *
646*4dc78e53SAndroid Build Coastguard Worker * @note The caller is responsible to free the returned data buffer and if
647*4dc78e53SAndroid Build Coastguard Worker * enabled, the credentials buffer.
648*4dc78e53SAndroid Build Coastguard Worker *
649*4dc78e53SAndroid Build Coastguard Worker * @see nl_socket_set_nonblocking()
650*4dc78e53SAndroid Build Coastguard Worker * @see nl_socket_set_msg_buf_size()
651*4dc78e53SAndroid Build Coastguard Worker * @see nl_socket_enable_msg_peek()
652*4dc78e53SAndroid Build Coastguard Worker * @see nl_socket_set_passcred()
653*4dc78e53SAndroid Build Coastguard Worker *
654*4dc78e53SAndroid Build Coastguard Worker * @return Number of bytes read, 0 on EOF, 0 on no data event (non-blocking
655*4dc78e53SAndroid Build Coastguard Worker * mode), or a negative error code.
656*4dc78e53SAndroid Build Coastguard Worker */
nl_recv(struct nl_sock * sk,struct sockaddr_nl * nla,unsigned char ** buf,struct ucred ** creds)657*4dc78e53SAndroid Build Coastguard Worker int nl_recv(struct nl_sock *sk, struct sockaddr_nl *nla,
658*4dc78e53SAndroid Build Coastguard Worker unsigned char **buf, struct ucred **creds)
659*4dc78e53SAndroid Build Coastguard Worker {
660*4dc78e53SAndroid Build Coastguard Worker ssize_t n;
661*4dc78e53SAndroid Build Coastguard Worker int flags = 0;
662*4dc78e53SAndroid Build Coastguard Worker static int page_size = 0; /* GLOBAL! */
663*4dc78e53SAndroid Build Coastguard Worker struct iovec iov;
664*4dc78e53SAndroid Build Coastguard Worker struct msghdr msg = {
665*4dc78e53SAndroid Build Coastguard Worker .msg_name = (void *) nla,
666*4dc78e53SAndroid Build Coastguard Worker .msg_namelen = sizeof(struct sockaddr_nl),
667*4dc78e53SAndroid Build Coastguard Worker .msg_iov = &iov,
668*4dc78e53SAndroid Build Coastguard Worker .msg_iovlen = 1,
669*4dc78e53SAndroid Build Coastguard Worker };
670*4dc78e53SAndroid Build Coastguard Worker struct ucred* tmpcreds = NULL;
671*4dc78e53SAndroid Build Coastguard Worker int retval = 0;
672*4dc78e53SAndroid Build Coastguard Worker
673*4dc78e53SAndroid Build Coastguard Worker if (!buf || !nla)
674*4dc78e53SAndroid Build Coastguard Worker return -NLE_INVAL;
675*4dc78e53SAndroid Build Coastguard Worker
676*4dc78e53SAndroid Build Coastguard Worker if ( (sk->s_flags & NL_MSG_PEEK)
677*4dc78e53SAndroid Build Coastguard Worker || (!(sk->s_flags & NL_MSG_PEEK_EXPLICIT) && sk->s_bufsize == 0))
678*4dc78e53SAndroid Build Coastguard Worker flags |= MSG_PEEK | MSG_TRUNC;
679*4dc78e53SAndroid Build Coastguard Worker
680*4dc78e53SAndroid Build Coastguard Worker if (page_size == 0)
681*4dc78e53SAndroid Build Coastguard Worker page_size = getpagesize() * 4;
682*4dc78e53SAndroid Build Coastguard Worker
683*4dc78e53SAndroid Build Coastguard Worker iov.iov_len = sk->s_bufsize ? sk->s_bufsize : ((size_t)page_size);
684*4dc78e53SAndroid Build Coastguard Worker iov.iov_base = malloc(iov.iov_len);
685*4dc78e53SAndroid Build Coastguard Worker
686*4dc78e53SAndroid Build Coastguard Worker if (!iov.iov_base) {
687*4dc78e53SAndroid Build Coastguard Worker retval = -NLE_NOMEM;
688*4dc78e53SAndroid Build Coastguard Worker goto abort;
689*4dc78e53SAndroid Build Coastguard Worker }
690*4dc78e53SAndroid Build Coastguard Worker
691*4dc78e53SAndroid Build Coastguard Worker if (creds && (sk->s_flags & NL_SOCK_PASSCRED)) {
692*4dc78e53SAndroid Build Coastguard Worker msg.msg_controllen = CMSG_SPACE(sizeof(struct ucred));
693*4dc78e53SAndroid Build Coastguard Worker msg.msg_control = malloc(msg.msg_controllen);
694*4dc78e53SAndroid Build Coastguard Worker if (!msg.msg_control) {
695*4dc78e53SAndroid Build Coastguard Worker retval = -NLE_NOMEM;
696*4dc78e53SAndroid Build Coastguard Worker goto abort;
697*4dc78e53SAndroid Build Coastguard Worker }
698*4dc78e53SAndroid Build Coastguard Worker }
699*4dc78e53SAndroid Build Coastguard Worker retry:
700*4dc78e53SAndroid Build Coastguard Worker
701*4dc78e53SAndroid Build Coastguard Worker n = recvmsg(sk->s_fd, &msg, flags);
702*4dc78e53SAndroid Build Coastguard Worker if (!n) {
703*4dc78e53SAndroid Build Coastguard Worker retval = 0;
704*4dc78e53SAndroid Build Coastguard Worker goto abort;
705*4dc78e53SAndroid Build Coastguard Worker }
706*4dc78e53SAndroid Build Coastguard Worker if (n < 0) {
707*4dc78e53SAndroid Build Coastguard Worker if (errno == EINTR) {
708*4dc78e53SAndroid Build Coastguard Worker NL_DBG(3, "recvmsg() returned EINTR, retrying\n");
709*4dc78e53SAndroid Build Coastguard Worker goto retry;
710*4dc78e53SAndroid Build Coastguard Worker }
711*4dc78e53SAndroid Build Coastguard Worker
712*4dc78e53SAndroid Build Coastguard Worker NL_DBG(4, "recvmsg(%p): nl_recv() failed with %d (%s)\n",
713*4dc78e53SAndroid Build Coastguard Worker sk, errno, nl_strerror_l(errno));
714*4dc78e53SAndroid Build Coastguard Worker retval = -nl_syserr2nlerr(errno);
715*4dc78e53SAndroid Build Coastguard Worker goto abort;
716*4dc78e53SAndroid Build Coastguard Worker }
717*4dc78e53SAndroid Build Coastguard Worker
718*4dc78e53SAndroid Build Coastguard Worker if (msg.msg_flags & MSG_CTRUNC) {
719*4dc78e53SAndroid Build Coastguard Worker void *tmp;
720*4dc78e53SAndroid Build Coastguard Worker
721*4dc78e53SAndroid Build Coastguard Worker if (msg.msg_controllen == 0) {
722*4dc78e53SAndroid Build Coastguard Worker retval = -NLE_MSG_TRUNC;
723*4dc78e53SAndroid Build Coastguard Worker NL_DBG(4, "recvmsg(%p): Received unexpected control data", sk);
724*4dc78e53SAndroid Build Coastguard Worker goto abort;
725*4dc78e53SAndroid Build Coastguard Worker }
726*4dc78e53SAndroid Build Coastguard Worker
727*4dc78e53SAndroid Build Coastguard Worker msg.msg_controllen *= 2;
728*4dc78e53SAndroid Build Coastguard Worker tmp = realloc(msg.msg_control, msg.msg_controllen);
729*4dc78e53SAndroid Build Coastguard Worker if (!tmp) {
730*4dc78e53SAndroid Build Coastguard Worker retval = -NLE_NOMEM;
731*4dc78e53SAndroid Build Coastguard Worker goto abort;
732*4dc78e53SAndroid Build Coastguard Worker }
733*4dc78e53SAndroid Build Coastguard Worker msg.msg_control = tmp;
734*4dc78e53SAndroid Build Coastguard Worker goto retry;
735*4dc78e53SAndroid Build Coastguard Worker }
736*4dc78e53SAndroid Build Coastguard Worker
737*4dc78e53SAndroid Build Coastguard Worker if (iov.iov_len < ((size_t)n) || (msg.msg_flags & MSG_TRUNC)) {
738*4dc78e53SAndroid Build Coastguard Worker void *tmp;
739*4dc78e53SAndroid Build Coastguard Worker
740*4dc78e53SAndroid Build Coastguard Worker /* respond with error to an incomplete message */
741*4dc78e53SAndroid Build Coastguard Worker if (flags == 0) {
742*4dc78e53SAndroid Build Coastguard Worker retval = -NLE_MSG_TRUNC;
743*4dc78e53SAndroid Build Coastguard Worker goto abort;
744*4dc78e53SAndroid Build Coastguard Worker }
745*4dc78e53SAndroid Build Coastguard Worker
746*4dc78e53SAndroid Build Coastguard Worker /* Provided buffer is not long enough, enlarge it
747*4dc78e53SAndroid Build Coastguard Worker * to size of n (which should be total length of the message)
748*4dc78e53SAndroid Build Coastguard Worker * and try again. */
749*4dc78e53SAndroid Build Coastguard Worker iov.iov_len = n;
750*4dc78e53SAndroid Build Coastguard Worker tmp = realloc(iov.iov_base, iov.iov_len);
751*4dc78e53SAndroid Build Coastguard Worker if (!tmp) {
752*4dc78e53SAndroid Build Coastguard Worker retval = -NLE_NOMEM;
753*4dc78e53SAndroid Build Coastguard Worker goto abort;
754*4dc78e53SAndroid Build Coastguard Worker }
755*4dc78e53SAndroid Build Coastguard Worker iov.iov_base = tmp;
756*4dc78e53SAndroid Build Coastguard Worker flags = 0;
757*4dc78e53SAndroid Build Coastguard Worker goto retry;
758*4dc78e53SAndroid Build Coastguard Worker }
759*4dc78e53SAndroid Build Coastguard Worker
760*4dc78e53SAndroid Build Coastguard Worker if (flags != 0) {
761*4dc78e53SAndroid Build Coastguard Worker /* Buffer is big enough, do the actual reading */
762*4dc78e53SAndroid Build Coastguard Worker flags = 0;
763*4dc78e53SAndroid Build Coastguard Worker goto retry;
764*4dc78e53SAndroid Build Coastguard Worker }
765*4dc78e53SAndroid Build Coastguard Worker
766*4dc78e53SAndroid Build Coastguard Worker if (msg.msg_namelen != sizeof(struct sockaddr_nl)) {
767*4dc78e53SAndroid Build Coastguard Worker retval = -NLE_NOADDR;
768*4dc78e53SAndroid Build Coastguard Worker goto abort;
769*4dc78e53SAndroid Build Coastguard Worker }
770*4dc78e53SAndroid Build Coastguard Worker
771*4dc78e53SAndroid Build Coastguard Worker if (creds && (sk->s_flags & NL_SOCK_PASSCRED)) {
772*4dc78e53SAndroid Build Coastguard Worker struct cmsghdr *cmsg;
773*4dc78e53SAndroid Build Coastguard Worker
774*4dc78e53SAndroid Build Coastguard Worker for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
775*4dc78e53SAndroid Build Coastguard Worker if (cmsg->cmsg_level != SOL_SOCKET)
776*4dc78e53SAndroid Build Coastguard Worker continue;
777*4dc78e53SAndroid Build Coastguard Worker if (cmsg->cmsg_type != SCM_CREDENTIALS)
778*4dc78e53SAndroid Build Coastguard Worker continue;
779*4dc78e53SAndroid Build Coastguard Worker tmpcreds = malloc(sizeof(*tmpcreds));
780*4dc78e53SAndroid Build Coastguard Worker if (!tmpcreds) {
781*4dc78e53SAndroid Build Coastguard Worker retval = -NLE_NOMEM;
782*4dc78e53SAndroid Build Coastguard Worker goto abort;
783*4dc78e53SAndroid Build Coastguard Worker }
784*4dc78e53SAndroid Build Coastguard Worker memcpy(tmpcreds, CMSG_DATA(cmsg), sizeof(*tmpcreds));
785*4dc78e53SAndroid Build Coastguard Worker break;
786*4dc78e53SAndroid Build Coastguard Worker }
787*4dc78e53SAndroid Build Coastguard Worker }
788*4dc78e53SAndroid Build Coastguard Worker
789*4dc78e53SAndroid Build Coastguard Worker retval = n;
790*4dc78e53SAndroid Build Coastguard Worker abort:
791*4dc78e53SAndroid Build Coastguard Worker free(msg.msg_control);
792*4dc78e53SAndroid Build Coastguard Worker
793*4dc78e53SAndroid Build Coastguard Worker if (retval <= 0) {
794*4dc78e53SAndroid Build Coastguard Worker free(iov.iov_base);
795*4dc78e53SAndroid Build Coastguard Worker iov.iov_base = NULL;
796*4dc78e53SAndroid Build Coastguard Worker free(tmpcreds);
797*4dc78e53SAndroid Build Coastguard Worker tmpcreds = NULL;
798*4dc78e53SAndroid Build Coastguard Worker } else
799*4dc78e53SAndroid Build Coastguard Worker *buf = iov.iov_base;
800*4dc78e53SAndroid Build Coastguard Worker
801*4dc78e53SAndroid Build Coastguard Worker if (creds)
802*4dc78e53SAndroid Build Coastguard Worker *creds = tmpcreds;
803*4dc78e53SAndroid Build Coastguard Worker
804*4dc78e53SAndroid Build Coastguard Worker return retval;
805*4dc78e53SAndroid Build Coastguard Worker }
806*4dc78e53SAndroid Build Coastguard Worker
807*4dc78e53SAndroid Build Coastguard Worker /** @cond SKIP */
808*4dc78e53SAndroid Build Coastguard Worker #define NL_CB_CALL(cb, type, msg) \
809*4dc78e53SAndroid Build Coastguard Worker do { \
810*4dc78e53SAndroid Build Coastguard Worker err = nl_cb_call(cb, type, msg); \
811*4dc78e53SAndroid Build Coastguard Worker switch (err) { \
812*4dc78e53SAndroid Build Coastguard Worker case NL_OK: \
813*4dc78e53SAndroid Build Coastguard Worker err = 0; \
814*4dc78e53SAndroid Build Coastguard Worker break; \
815*4dc78e53SAndroid Build Coastguard Worker case NL_SKIP: \
816*4dc78e53SAndroid Build Coastguard Worker goto skip; \
817*4dc78e53SAndroid Build Coastguard Worker case NL_STOP: \
818*4dc78e53SAndroid Build Coastguard Worker goto stop; \
819*4dc78e53SAndroid Build Coastguard Worker default: \
820*4dc78e53SAndroid Build Coastguard Worker goto out; \
821*4dc78e53SAndroid Build Coastguard Worker } \
822*4dc78e53SAndroid Build Coastguard Worker } while (0)
823*4dc78e53SAndroid Build Coastguard Worker /** @endcond */
824*4dc78e53SAndroid Build Coastguard Worker
recvmsgs(struct nl_sock * sk,struct nl_cb * cb)825*4dc78e53SAndroid Build Coastguard Worker static int recvmsgs(struct nl_sock *sk, struct nl_cb *cb)
826*4dc78e53SAndroid Build Coastguard Worker {
827*4dc78e53SAndroid Build Coastguard Worker int n, err = 0, multipart = 0, interrupted = 0, nrecv = 0;
828*4dc78e53SAndroid Build Coastguard Worker unsigned char *buf = NULL;
829*4dc78e53SAndroid Build Coastguard Worker struct nlmsghdr *hdr;
830*4dc78e53SAndroid Build Coastguard Worker
831*4dc78e53SAndroid Build Coastguard Worker /*
832*4dc78e53SAndroid Build Coastguard Worker nla is passed on to not only to nl_recv() but may also be passed
833*4dc78e53SAndroid Build Coastguard Worker to a function pointer provided by the caller which may or may not
834*4dc78e53SAndroid Build Coastguard Worker initialize the variable. Thomas Graf.
835*4dc78e53SAndroid Build Coastguard Worker */
836*4dc78e53SAndroid Build Coastguard Worker struct sockaddr_nl nla = {0};
837*4dc78e53SAndroid Build Coastguard Worker struct nl_msg *msg = NULL;
838*4dc78e53SAndroid Build Coastguard Worker struct ucred *creds = NULL;
839*4dc78e53SAndroid Build Coastguard Worker
840*4dc78e53SAndroid Build Coastguard Worker continue_reading:
841*4dc78e53SAndroid Build Coastguard Worker NL_DBG(3, "Attempting to read from %p\n", sk);
842*4dc78e53SAndroid Build Coastguard Worker if (cb->cb_recv_ow)
843*4dc78e53SAndroid Build Coastguard Worker n = cb->cb_recv_ow(sk, &nla, &buf, &creds);
844*4dc78e53SAndroid Build Coastguard Worker else
845*4dc78e53SAndroid Build Coastguard Worker n = nl_recv(sk, &nla, &buf, &creds);
846*4dc78e53SAndroid Build Coastguard Worker
847*4dc78e53SAndroid Build Coastguard Worker if (n <= 0)
848*4dc78e53SAndroid Build Coastguard Worker return n;
849*4dc78e53SAndroid Build Coastguard Worker
850*4dc78e53SAndroid Build Coastguard Worker NL_DBG(3, "recvmsgs(%p): Read %d bytes\n", sk, n);
851*4dc78e53SAndroid Build Coastguard Worker
852*4dc78e53SAndroid Build Coastguard Worker hdr = (struct nlmsghdr *) buf;
853*4dc78e53SAndroid Build Coastguard Worker while (nlmsg_ok(hdr, n)) {
854*4dc78e53SAndroid Build Coastguard Worker NL_DBG(3, "recvmsgs(%p): Processing valid message...\n", sk);
855*4dc78e53SAndroid Build Coastguard Worker
856*4dc78e53SAndroid Build Coastguard Worker nlmsg_free(msg);
857*4dc78e53SAndroid Build Coastguard Worker msg = nlmsg_convert(hdr);
858*4dc78e53SAndroid Build Coastguard Worker if (!msg) {
859*4dc78e53SAndroid Build Coastguard Worker err = -NLE_NOMEM;
860*4dc78e53SAndroid Build Coastguard Worker goto out;
861*4dc78e53SAndroid Build Coastguard Worker }
862*4dc78e53SAndroid Build Coastguard Worker
863*4dc78e53SAndroid Build Coastguard Worker nlmsg_set_proto(msg, sk->s_proto);
864*4dc78e53SAndroid Build Coastguard Worker nlmsg_set_src(msg, &nla);
865*4dc78e53SAndroid Build Coastguard Worker if (creds)
866*4dc78e53SAndroid Build Coastguard Worker nlmsg_set_creds(msg, creds);
867*4dc78e53SAndroid Build Coastguard Worker
868*4dc78e53SAndroid Build Coastguard Worker nrecv++;
869*4dc78e53SAndroid Build Coastguard Worker
870*4dc78e53SAndroid Build Coastguard Worker /* Raw callback is the first, it gives the most control
871*4dc78e53SAndroid Build Coastguard Worker * to the user and he can do his very own parsing. */
872*4dc78e53SAndroid Build Coastguard Worker if (cb->cb_set[NL_CB_MSG_IN])
873*4dc78e53SAndroid Build Coastguard Worker NL_CB_CALL(cb, NL_CB_MSG_IN, msg);
874*4dc78e53SAndroid Build Coastguard Worker
875*4dc78e53SAndroid Build Coastguard Worker /* Sequence number checking. The check may be done by
876*4dc78e53SAndroid Build Coastguard Worker * the user, otherwise a very simple check is applied
877*4dc78e53SAndroid Build Coastguard Worker * enforcing strict ordering */
878*4dc78e53SAndroid Build Coastguard Worker if (cb->cb_set[NL_CB_SEQ_CHECK]) {
879*4dc78e53SAndroid Build Coastguard Worker NL_CB_CALL(cb, NL_CB_SEQ_CHECK, msg);
880*4dc78e53SAndroid Build Coastguard Worker
881*4dc78e53SAndroid Build Coastguard Worker /* Only do sequence checking if auto-ack mode is enabled */
882*4dc78e53SAndroid Build Coastguard Worker } else if (!(sk->s_flags & NL_NO_AUTO_ACK)) {
883*4dc78e53SAndroid Build Coastguard Worker if (hdr->nlmsg_seq != sk->s_seq_expect) {
884*4dc78e53SAndroid Build Coastguard Worker if (cb->cb_set[NL_CB_INVALID])
885*4dc78e53SAndroid Build Coastguard Worker NL_CB_CALL(cb, NL_CB_INVALID, msg);
886*4dc78e53SAndroid Build Coastguard Worker else {
887*4dc78e53SAndroid Build Coastguard Worker err = -NLE_SEQ_MISMATCH;
888*4dc78e53SAndroid Build Coastguard Worker goto out;
889*4dc78e53SAndroid Build Coastguard Worker }
890*4dc78e53SAndroid Build Coastguard Worker }
891*4dc78e53SAndroid Build Coastguard Worker }
892*4dc78e53SAndroid Build Coastguard Worker
893*4dc78e53SAndroid Build Coastguard Worker if (hdr->nlmsg_type == NLMSG_DONE ||
894*4dc78e53SAndroid Build Coastguard Worker hdr->nlmsg_type == NLMSG_ERROR ||
895*4dc78e53SAndroid Build Coastguard Worker hdr->nlmsg_type == NLMSG_NOOP ||
896*4dc78e53SAndroid Build Coastguard Worker hdr->nlmsg_type == NLMSG_OVERRUN) {
897*4dc78e53SAndroid Build Coastguard Worker /* We can't check for !NLM_F_MULTI since some netlink
898*4dc78e53SAndroid Build Coastguard Worker * users in the kernel are broken. */
899*4dc78e53SAndroid Build Coastguard Worker sk->s_seq_expect++;
900*4dc78e53SAndroid Build Coastguard Worker NL_DBG(3, "recvmsgs(%p): Increased expected " \
901*4dc78e53SAndroid Build Coastguard Worker "sequence number to %d\n",
902*4dc78e53SAndroid Build Coastguard Worker sk, sk->s_seq_expect);
903*4dc78e53SAndroid Build Coastguard Worker }
904*4dc78e53SAndroid Build Coastguard Worker
905*4dc78e53SAndroid Build Coastguard Worker if (hdr->nlmsg_flags & NLM_F_MULTI)
906*4dc78e53SAndroid Build Coastguard Worker multipart = 1;
907*4dc78e53SAndroid Build Coastguard Worker
908*4dc78e53SAndroid Build Coastguard Worker if (hdr->nlmsg_flags & NLM_F_DUMP_INTR) {
909*4dc78e53SAndroid Build Coastguard Worker if (cb->cb_set[NL_CB_DUMP_INTR])
910*4dc78e53SAndroid Build Coastguard Worker NL_CB_CALL(cb, NL_CB_DUMP_INTR, msg);
911*4dc78e53SAndroid Build Coastguard Worker else {
912*4dc78e53SAndroid Build Coastguard Worker /*
913*4dc78e53SAndroid Build Coastguard Worker * We have to continue reading to clear
914*4dc78e53SAndroid Build Coastguard Worker * all messages until a NLMSG_DONE is
915*4dc78e53SAndroid Build Coastguard Worker * received and report the inconsistency.
916*4dc78e53SAndroid Build Coastguard Worker */
917*4dc78e53SAndroid Build Coastguard Worker interrupted = 1;
918*4dc78e53SAndroid Build Coastguard Worker }
919*4dc78e53SAndroid Build Coastguard Worker }
920*4dc78e53SAndroid Build Coastguard Worker
921*4dc78e53SAndroid Build Coastguard Worker /* Other side wishes to see an ack for this message */
922*4dc78e53SAndroid Build Coastguard Worker if (hdr->nlmsg_flags & NLM_F_ACK) {
923*4dc78e53SAndroid Build Coastguard Worker if (cb->cb_set[NL_CB_SEND_ACK])
924*4dc78e53SAndroid Build Coastguard Worker NL_CB_CALL(cb, NL_CB_SEND_ACK, msg);
925*4dc78e53SAndroid Build Coastguard Worker else {
926*4dc78e53SAndroid Build Coastguard Worker /* FIXME: implement */
927*4dc78e53SAndroid Build Coastguard Worker }
928*4dc78e53SAndroid Build Coastguard Worker }
929*4dc78e53SAndroid Build Coastguard Worker
930*4dc78e53SAndroid Build Coastguard Worker /* messages terminates a multipart message, this is
931*4dc78e53SAndroid Build Coastguard Worker * usually the end of a message and therefore we slip
932*4dc78e53SAndroid Build Coastguard Worker * out of the loop by default. the user may overrule
933*4dc78e53SAndroid Build Coastguard Worker * this action by skipping this packet. */
934*4dc78e53SAndroid Build Coastguard Worker if (hdr->nlmsg_type == NLMSG_DONE) {
935*4dc78e53SAndroid Build Coastguard Worker multipart = 0;
936*4dc78e53SAndroid Build Coastguard Worker if (cb->cb_set[NL_CB_FINISH])
937*4dc78e53SAndroid Build Coastguard Worker NL_CB_CALL(cb, NL_CB_FINISH, msg);
938*4dc78e53SAndroid Build Coastguard Worker }
939*4dc78e53SAndroid Build Coastguard Worker
940*4dc78e53SAndroid Build Coastguard Worker /* Message to be ignored, the default action is to
941*4dc78e53SAndroid Build Coastguard Worker * skip this message if no callback is specified. The
942*4dc78e53SAndroid Build Coastguard Worker * user may overrule this action by returning
943*4dc78e53SAndroid Build Coastguard Worker * NL_PROCEED. */
944*4dc78e53SAndroid Build Coastguard Worker else if (hdr->nlmsg_type == NLMSG_NOOP) {
945*4dc78e53SAndroid Build Coastguard Worker if (cb->cb_set[NL_CB_SKIPPED])
946*4dc78e53SAndroid Build Coastguard Worker NL_CB_CALL(cb, NL_CB_SKIPPED, msg);
947*4dc78e53SAndroid Build Coastguard Worker else
948*4dc78e53SAndroid Build Coastguard Worker goto skip;
949*4dc78e53SAndroid Build Coastguard Worker }
950*4dc78e53SAndroid Build Coastguard Worker
951*4dc78e53SAndroid Build Coastguard Worker /* Data got lost, report back to user. The default action is to
952*4dc78e53SAndroid Build Coastguard Worker * quit parsing. The user may overrule this action by retuning
953*4dc78e53SAndroid Build Coastguard Worker * NL_SKIP or NL_PROCEED (dangerous) */
954*4dc78e53SAndroid Build Coastguard Worker else if (hdr->nlmsg_type == NLMSG_OVERRUN) {
955*4dc78e53SAndroid Build Coastguard Worker if (cb->cb_set[NL_CB_OVERRUN])
956*4dc78e53SAndroid Build Coastguard Worker NL_CB_CALL(cb, NL_CB_OVERRUN, msg);
957*4dc78e53SAndroid Build Coastguard Worker else {
958*4dc78e53SAndroid Build Coastguard Worker err = -NLE_MSG_OVERFLOW;
959*4dc78e53SAndroid Build Coastguard Worker goto out;
960*4dc78e53SAndroid Build Coastguard Worker }
961*4dc78e53SAndroid Build Coastguard Worker }
962*4dc78e53SAndroid Build Coastguard Worker
963*4dc78e53SAndroid Build Coastguard Worker /* Message carries a nlmsgerr */
964*4dc78e53SAndroid Build Coastguard Worker else if (hdr->nlmsg_type == NLMSG_ERROR) {
965*4dc78e53SAndroid Build Coastguard Worker struct nlmsgerr *e = nlmsg_data(hdr);
966*4dc78e53SAndroid Build Coastguard Worker
967*4dc78e53SAndroid Build Coastguard Worker if (hdr->nlmsg_len <
968*4dc78e53SAndroid Build Coastguard Worker ((unsigned)nlmsg_size(sizeof(*e)))) {
969*4dc78e53SAndroid Build Coastguard Worker /* Truncated error message, the default action
970*4dc78e53SAndroid Build Coastguard Worker * is to stop parsing. The user may overrule
971*4dc78e53SAndroid Build Coastguard Worker * this action by returning NL_SKIP or
972*4dc78e53SAndroid Build Coastguard Worker * NL_PROCEED (dangerous) */
973*4dc78e53SAndroid Build Coastguard Worker if (cb->cb_set[NL_CB_INVALID])
974*4dc78e53SAndroid Build Coastguard Worker NL_CB_CALL(cb, NL_CB_INVALID, msg);
975*4dc78e53SAndroid Build Coastguard Worker else {
976*4dc78e53SAndroid Build Coastguard Worker err = -NLE_MSG_TRUNC;
977*4dc78e53SAndroid Build Coastguard Worker goto out;
978*4dc78e53SAndroid Build Coastguard Worker }
979*4dc78e53SAndroid Build Coastguard Worker } else if (e->error) {
980*4dc78e53SAndroid Build Coastguard Worker NL_DBG(4, "recvmsgs(%p): RTNETLINK responded with %d (%s)\n",
981*4dc78e53SAndroid Build Coastguard Worker sk, -e->error, nl_strerror_l(-e->error));
982*4dc78e53SAndroid Build Coastguard Worker
983*4dc78e53SAndroid Build Coastguard Worker /* Error message reported back from kernel. */
984*4dc78e53SAndroid Build Coastguard Worker if (cb->cb_err) {
985*4dc78e53SAndroid Build Coastguard Worker err = cb->cb_err(&nla, e,
986*4dc78e53SAndroid Build Coastguard Worker cb->cb_err_arg);
987*4dc78e53SAndroid Build Coastguard Worker if (err < 0)
988*4dc78e53SAndroid Build Coastguard Worker goto out;
989*4dc78e53SAndroid Build Coastguard Worker else if (err == NL_SKIP)
990*4dc78e53SAndroid Build Coastguard Worker goto skip;
991*4dc78e53SAndroid Build Coastguard Worker else if (err == NL_STOP) {
992*4dc78e53SAndroid Build Coastguard Worker err = -nl_syserr2nlerr(e->error);
993*4dc78e53SAndroid Build Coastguard Worker goto out;
994*4dc78e53SAndroid Build Coastguard Worker }
995*4dc78e53SAndroid Build Coastguard Worker } else {
996*4dc78e53SAndroid Build Coastguard Worker err = -nl_syserr2nlerr(e->error);
997*4dc78e53SAndroid Build Coastguard Worker goto out;
998*4dc78e53SAndroid Build Coastguard Worker }
999*4dc78e53SAndroid Build Coastguard Worker } else if (cb->cb_set[NL_CB_ACK])
1000*4dc78e53SAndroid Build Coastguard Worker NL_CB_CALL(cb, NL_CB_ACK, msg);
1001*4dc78e53SAndroid Build Coastguard Worker } else {
1002*4dc78e53SAndroid Build Coastguard Worker /* Valid message (not checking for MULTIPART bit to
1003*4dc78e53SAndroid Build Coastguard Worker * get along with broken kernels. NL_SKIP has no
1004*4dc78e53SAndroid Build Coastguard Worker * effect on this. */
1005*4dc78e53SAndroid Build Coastguard Worker if (cb->cb_set[NL_CB_VALID])
1006*4dc78e53SAndroid Build Coastguard Worker NL_CB_CALL(cb, NL_CB_VALID, msg);
1007*4dc78e53SAndroid Build Coastguard Worker }
1008*4dc78e53SAndroid Build Coastguard Worker skip:
1009*4dc78e53SAndroid Build Coastguard Worker err = 0;
1010*4dc78e53SAndroid Build Coastguard Worker hdr = nlmsg_next(hdr, &n);
1011*4dc78e53SAndroid Build Coastguard Worker }
1012*4dc78e53SAndroid Build Coastguard Worker
1013*4dc78e53SAndroid Build Coastguard Worker nlmsg_free(msg);
1014*4dc78e53SAndroid Build Coastguard Worker free(buf);
1015*4dc78e53SAndroid Build Coastguard Worker free(creds);
1016*4dc78e53SAndroid Build Coastguard Worker buf = NULL;
1017*4dc78e53SAndroid Build Coastguard Worker msg = NULL;
1018*4dc78e53SAndroid Build Coastguard Worker creds = NULL;
1019*4dc78e53SAndroid Build Coastguard Worker
1020*4dc78e53SAndroid Build Coastguard Worker if (multipart) {
1021*4dc78e53SAndroid Build Coastguard Worker /* Multipart message not yet complete, continue reading */
1022*4dc78e53SAndroid Build Coastguard Worker goto continue_reading;
1023*4dc78e53SAndroid Build Coastguard Worker }
1024*4dc78e53SAndroid Build Coastguard Worker stop:
1025*4dc78e53SAndroid Build Coastguard Worker err = 0;
1026*4dc78e53SAndroid Build Coastguard Worker out:
1027*4dc78e53SAndroid Build Coastguard Worker nlmsg_free(msg);
1028*4dc78e53SAndroid Build Coastguard Worker free(buf);
1029*4dc78e53SAndroid Build Coastguard Worker free(creds);
1030*4dc78e53SAndroid Build Coastguard Worker
1031*4dc78e53SAndroid Build Coastguard Worker if (interrupted)
1032*4dc78e53SAndroid Build Coastguard Worker err = -NLE_DUMP_INTR;
1033*4dc78e53SAndroid Build Coastguard Worker
1034*4dc78e53SAndroid Build Coastguard Worker if (!err)
1035*4dc78e53SAndroid Build Coastguard Worker err = nrecv;
1036*4dc78e53SAndroid Build Coastguard Worker
1037*4dc78e53SAndroid Build Coastguard Worker return err;
1038*4dc78e53SAndroid Build Coastguard Worker }
1039*4dc78e53SAndroid Build Coastguard Worker
1040*4dc78e53SAndroid Build Coastguard Worker /**
1041*4dc78e53SAndroid Build Coastguard Worker * Receive a set of messages from a netlink socket and report parsed messages
1042*4dc78e53SAndroid Build Coastguard Worker * @arg sk Netlink socket.
1043*4dc78e53SAndroid Build Coastguard Worker * @arg cb set of callbacks to control behaviour.
1044*4dc78e53SAndroid Build Coastguard Worker *
1045*4dc78e53SAndroid Build Coastguard Worker * This function is identical to nl_recvmsgs() to the point that it will
1046*4dc78e53SAndroid Build Coastguard Worker * return the number of parsed messages instead of 0 on success.
1047*4dc78e53SAndroid Build Coastguard Worker *
1048*4dc78e53SAndroid Build Coastguard Worker * @see nl_recvmsgs()
1049*4dc78e53SAndroid Build Coastguard Worker *
1050*4dc78e53SAndroid Build Coastguard Worker * @return Number of received messages or a negative error code from nl_recv().
1051*4dc78e53SAndroid Build Coastguard Worker */
nl_recvmsgs_report(struct nl_sock * sk,struct nl_cb * cb)1052*4dc78e53SAndroid Build Coastguard Worker int nl_recvmsgs_report(struct nl_sock *sk, struct nl_cb *cb)
1053*4dc78e53SAndroid Build Coastguard Worker {
1054*4dc78e53SAndroid Build Coastguard Worker if (cb->cb_recvmsgs_ow)
1055*4dc78e53SAndroid Build Coastguard Worker return cb->cb_recvmsgs_ow(sk, cb);
1056*4dc78e53SAndroid Build Coastguard Worker else
1057*4dc78e53SAndroid Build Coastguard Worker return recvmsgs(sk, cb);
1058*4dc78e53SAndroid Build Coastguard Worker }
1059*4dc78e53SAndroid Build Coastguard Worker
1060*4dc78e53SAndroid Build Coastguard Worker /**
1061*4dc78e53SAndroid Build Coastguard Worker * Receive a set of messages from a netlink socket.
1062*4dc78e53SAndroid Build Coastguard Worker * @arg sk Netlink socket.
1063*4dc78e53SAndroid Build Coastguard Worker * @arg cb set of callbacks to control behaviour.
1064*4dc78e53SAndroid Build Coastguard Worker *
1065*4dc78e53SAndroid Build Coastguard Worker * Repeatedly calls nl_recv() or the respective replacement if provided
1066*4dc78e53SAndroid Build Coastguard Worker * by the application (see nl_cb_overwrite_recv()) and parses the
1067*4dc78e53SAndroid Build Coastguard Worker * received data as netlink messages. Stops reading if one of the
1068*4dc78e53SAndroid Build Coastguard Worker * callbacks returns NL_STOP or nl_recv returns either 0 or a negative error code.
1069*4dc78e53SAndroid Build Coastguard Worker *
1070*4dc78e53SAndroid Build Coastguard Worker * A non-blocking sockets causes the function to return immediately if
1071*4dc78e53SAndroid Build Coastguard Worker * no data is available.
1072*4dc78e53SAndroid Build Coastguard Worker *
1073*4dc78e53SAndroid Build Coastguard Worker * @see nl_recvmsgs_report()
1074*4dc78e53SAndroid Build Coastguard Worker *
1075*4dc78e53SAndroid Build Coastguard Worker * @return 0 on success or a negative error code from nl_recv().
1076*4dc78e53SAndroid Build Coastguard Worker */
nl_recvmsgs(struct nl_sock * sk,struct nl_cb * cb)1077*4dc78e53SAndroid Build Coastguard Worker int nl_recvmsgs(struct nl_sock *sk, struct nl_cb *cb)
1078*4dc78e53SAndroid Build Coastguard Worker {
1079*4dc78e53SAndroid Build Coastguard Worker int err;
1080*4dc78e53SAndroid Build Coastguard Worker
1081*4dc78e53SAndroid Build Coastguard Worker if ((err = nl_recvmsgs_report(sk, cb)) > 0)
1082*4dc78e53SAndroid Build Coastguard Worker err = 0;
1083*4dc78e53SAndroid Build Coastguard Worker
1084*4dc78e53SAndroid Build Coastguard Worker return err;
1085*4dc78e53SAndroid Build Coastguard Worker }
1086*4dc78e53SAndroid Build Coastguard Worker
1087*4dc78e53SAndroid Build Coastguard Worker /**
1088*4dc78e53SAndroid Build Coastguard Worker * Receive a set of message from a netlink socket using handlers in nl_sock.
1089*4dc78e53SAndroid Build Coastguard Worker * @arg sk Netlink socket.
1090*4dc78e53SAndroid Build Coastguard Worker *
1091*4dc78e53SAndroid Build Coastguard Worker * Calls nl_recvmsgs() with the handlers configured in the netlink socket.
1092*4dc78e53SAndroid Build Coastguard Worker */
nl_recvmsgs_default(struct nl_sock * sk)1093*4dc78e53SAndroid Build Coastguard Worker int nl_recvmsgs_default(struct nl_sock *sk)
1094*4dc78e53SAndroid Build Coastguard Worker {
1095*4dc78e53SAndroid Build Coastguard Worker return nl_recvmsgs(sk, sk->s_cb);
1096*4dc78e53SAndroid Build Coastguard Worker
1097*4dc78e53SAndroid Build Coastguard Worker }
1098*4dc78e53SAndroid Build Coastguard Worker
ack_wait_handler(struct nl_msg * msg,void * arg)1099*4dc78e53SAndroid Build Coastguard Worker static int ack_wait_handler(struct nl_msg *msg, void *arg)
1100*4dc78e53SAndroid Build Coastguard Worker {
1101*4dc78e53SAndroid Build Coastguard Worker return NL_STOP;
1102*4dc78e53SAndroid Build Coastguard Worker }
1103*4dc78e53SAndroid Build Coastguard Worker
1104*4dc78e53SAndroid Build Coastguard Worker /**
1105*4dc78e53SAndroid Build Coastguard Worker * Wait for ACK.
1106*4dc78e53SAndroid Build Coastguard Worker * @arg sk Netlink socket.
1107*4dc78e53SAndroid Build Coastguard Worker * @pre The netlink socket must be in blocking state.
1108*4dc78e53SAndroid Build Coastguard Worker *
1109*4dc78e53SAndroid Build Coastguard Worker * Waits until an ACK is received for the latest not yet acknowledged
1110*4dc78e53SAndroid Build Coastguard Worker * netlink message.
1111*4dc78e53SAndroid Build Coastguard Worker */
nl_wait_for_ack(struct nl_sock * sk)1112*4dc78e53SAndroid Build Coastguard Worker int nl_wait_for_ack(struct nl_sock *sk)
1113*4dc78e53SAndroid Build Coastguard Worker {
1114*4dc78e53SAndroid Build Coastguard Worker int err;
1115*4dc78e53SAndroid Build Coastguard Worker struct nl_cb *cb;
1116*4dc78e53SAndroid Build Coastguard Worker
1117*4dc78e53SAndroid Build Coastguard Worker cb = nl_cb_clone(sk->s_cb);
1118*4dc78e53SAndroid Build Coastguard Worker if (cb == NULL)
1119*4dc78e53SAndroid Build Coastguard Worker return -NLE_NOMEM;
1120*4dc78e53SAndroid Build Coastguard Worker
1121*4dc78e53SAndroid Build Coastguard Worker nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_wait_handler, NULL);
1122*4dc78e53SAndroid Build Coastguard Worker err = nl_recvmsgs(sk, cb);
1123*4dc78e53SAndroid Build Coastguard Worker nl_cb_put(cb);
1124*4dc78e53SAndroid Build Coastguard Worker
1125*4dc78e53SAndroid Build Coastguard Worker return err;
1126*4dc78e53SAndroid Build Coastguard Worker }
1127*4dc78e53SAndroid Build Coastguard Worker
1128*4dc78e53SAndroid Build Coastguard Worker /** @cond SKIP */
1129*4dc78e53SAndroid Build Coastguard Worker struct pickup_param
1130*4dc78e53SAndroid Build Coastguard Worker {
1131*4dc78e53SAndroid Build Coastguard Worker int (*parser)(struct nl_cache_ops *, struct sockaddr_nl *,
1132*4dc78e53SAndroid Build Coastguard Worker struct nlmsghdr *, struct nl_parser_param *);
1133*4dc78e53SAndroid Build Coastguard Worker struct nl_object *result;
1134*4dc78e53SAndroid Build Coastguard Worker int *syserror;
1135*4dc78e53SAndroid Build Coastguard Worker };
1136*4dc78e53SAndroid Build Coastguard Worker
__store_answer(struct nl_object * obj,struct nl_parser_param * p)1137*4dc78e53SAndroid Build Coastguard Worker static int __store_answer(struct nl_object *obj, struct nl_parser_param *p)
1138*4dc78e53SAndroid Build Coastguard Worker {
1139*4dc78e53SAndroid Build Coastguard Worker struct pickup_param *pp = p->pp_arg;
1140*4dc78e53SAndroid Build Coastguard Worker /*
1141*4dc78e53SAndroid Build Coastguard Worker * the parser will put() the object at the end, expecting the cache
1142*4dc78e53SAndroid Build Coastguard Worker * to take the reference.
1143*4dc78e53SAndroid Build Coastguard Worker */
1144*4dc78e53SAndroid Build Coastguard Worker nl_object_get(obj);
1145*4dc78e53SAndroid Build Coastguard Worker pp->result = obj;
1146*4dc78e53SAndroid Build Coastguard Worker
1147*4dc78e53SAndroid Build Coastguard Worker return 0;
1148*4dc78e53SAndroid Build Coastguard Worker }
1149*4dc78e53SAndroid Build Coastguard Worker
__pickup_answer(struct nl_msg * msg,void * arg)1150*4dc78e53SAndroid Build Coastguard Worker static int __pickup_answer(struct nl_msg *msg, void *arg)
1151*4dc78e53SAndroid Build Coastguard Worker {
1152*4dc78e53SAndroid Build Coastguard Worker struct pickup_param *pp = arg;
1153*4dc78e53SAndroid Build Coastguard Worker struct nl_parser_param parse_arg = {
1154*4dc78e53SAndroid Build Coastguard Worker .pp_cb = __store_answer,
1155*4dc78e53SAndroid Build Coastguard Worker .pp_arg = pp,
1156*4dc78e53SAndroid Build Coastguard Worker };
1157*4dc78e53SAndroid Build Coastguard Worker
1158*4dc78e53SAndroid Build Coastguard Worker return pp->parser(NULL, &msg->nm_src, msg->nm_nlh, &parse_arg);
1159*4dc78e53SAndroid Build Coastguard Worker }
1160*4dc78e53SAndroid Build Coastguard Worker
__pickup_answer_syserr(struct sockaddr_nl * nla,struct nlmsgerr * nlerr,void * arg)1161*4dc78e53SAndroid Build Coastguard Worker static int __pickup_answer_syserr(struct sockaddr_nl *nla, struct nlmsgerr *nlerr, void *arg)
1162*4dc78e53SAndroid Build Coastguard Worker {
1163*4dc78e53SAndroid Build Coastguard Worker *(((struct pickup_param *) arg)->syserror) = nlerr->error;
1164*4dc78e53SAndroid Build Coastguard Worker
1165*4dc78e53SAndroid Build Coastguard Worker return -nl_syserr2nlerr(nlerr->error);
1166*4dc78e53SAndroid Build Coastguard Worker }
1167*4dc78e53SAndroid Build Coastguard Worker
1168*4dc78e53SAndroid Build Coastguard Worker /** @endcond */
1169*4dc78e53SAndroid Build Coastguard Worker
1170*4dc78e53SAndroid Build Coastguard Worker /**
1171*4dc78e53SAndroid Build Coastguard Worker * Pickup netlink answer, parse is and return object
1172*4dc78e53SAndroid Build Coastguard Worker * @arg sk Netlink socket
1173*4dc78e53SAndroid Build Coastguard Worker * @arg parser Parser function to parse answer
1174*4dc78e53SAndroid Build Coastguard Worker * @arg result Result pointer to return parsed object
1175*4dc78e53SAndroid Build Coastguard Worker *
1176*4dc78e53SAndroid Build Coastguard Worker * @return 0 on success or a negative error code.
1177*4dc78e53SAndroid Build Coastguard Worker */
nl_pickup(struct nl_sock * sk,int (* parser)(struct nl_cache_ops *,struct sockaddr_nl *,struct nlmsghdr *,struct nl_parser_param *),struct nl_object ** result)1178*4dc78e53SAndroid Build Coastguard Worker int nl_pickup(struct nl_sock *sk,
1179*4dc78e53SAndroid Build Coastguard Worker int (*parser)(struct nl_cache_ops *, struct sockaddr_nl *,
1180*4dc78e53SAndroid Build Coastguard Worker struct nlmsghdr *, struct nl_parser_param *),
1181*4dc78e53SAndroid Build Coastguard Worker struct nl_object **result)
1182*4dc78e53SAndroid Build Coastguard Worker {
1183*4dc78e53SAndroid Build Coastguard Worker return nl_pickup_keep_syserr(sk, parser, result, NULL);
1184*4dc78e53SAndroid Build Coastguard Worker }
1185*4dc78e53SAndroid Build Coastguard Worker
1186*4dc78e53SAndroid Build Coastguard Worker /**
1187*4dc78e53SAndroid Build Coastguard Worker * Pickup netlink answer, parse is and return object with preserving system error
1188*4dc78e53SAndroid Build Coastguard Worker * @arg sk Netlink socket
1189*4dc78e53SAndroid Build Coastguard Worker * @arg parser Parser function to parse answer
1190*4dc78e53SAndroid Build Coastguard Worker * @arg result Result pointer to return parsed object
1191*4dc78e53SAndroid Build Coastguard Worker * @arg syserr Result pointer for the system error in case of failure
1192*4dc78e53SAndroid Build Coastguard Worker *
1193*4dc78e53SAndroid Build Coastguard Worker * @return 0 on success or a negative error code.
1194*4dc78e53SAndroid Build Coastguard Worker */
nl_pickup_keep_syserr(struct nl_sock * sk,int (* parser)(struct nl_cache_ops *,struct sockaddr_nl *,struct nlmsghdr *,struct nl_parser_param *),struct nl_object ** result,int * syserror)1195*4dc78e53SAndroid Build Coastguard Worker int nl_pickup_keep_syserr(struct nl_sock *sk,
1196*4dc78e53SAndroid Build Coastguard Worker int (*parser)(struct nl_cache_ops *, struct sockaddr_nl *,
1197*4dc78e53SAndroid Build Coastguard Worker struct nlmsghdr *, struct nl_parser_param *),
1198*4dc78e53SAndroid Build Coastguard Worker struct nl_object **result,
1199*4dc78e53SAndroid Build Coastguard Worker int *syserror)
1200*4dc78e53SAndroid Build Coastguard Worker {
1201*4dc78e53SAndroid Build Coastguard Worker struct nl_cb *cb;
1202*4dc78e53SAndroid Build Coastguard Worker int err;
1203*4dc78e53SAndroid Build Coastguard Worker struct pickup_param pp = {
1204*4dc78e53SAndroid Build Coastguard Worker .parser = parser,
1205*4dc78e53SAndroid Build Coastguard Worker };
1206*4dc78e53SAndroid Build Coastguard Worker
1207*4dc78e53SAndroid Build Coastguard Worker cb = nl_cb_clone(sk->s_cb);
1208*4dc78e53SAndroid Build Coastguard Worker if (cb == NULL)
1209*4dc78e53SAndroid Build Coastguard Worker return -NLE_NOMEM;
1210*4dc78e53SAndroid Build Coastguard Worker
1211*4dc78e53SAndroid Build Coastguard Worker nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, __pickup_answer, &pp);
1212*4dc78e53SAndroid Build Coastguard Worker if (syserror) {
1213*4dc78e53SAndroid Build Coastguard Worker *syserror = 0;
1214*4dc78e53SAndroid Build Coastguard Worker pp.syserror = syserror;
1215*4dc78e53SAndroid Build Coastguard Worker nl_cb_err(cb, NL_CB_CUSTOM, __pickup_answer_syserr, &pp);
1216*4dc78e53SAndroid Build Coastguard Worker }
1217*4dc78e53SAndroid Build Coastguard Worker
1218*4dc78e53SAndroid Build Coastguard Worker err = nl_recvmsgs(sk, cb);
1219*4dc78e53SAndroid Build Coastguard Worker if (err < 0)
1220*4dc78e53SAndroid Build Coastguard Worker goto errout;
1221*4dc78e53SAndroid Build Coastguard Worker
1222*4dc78e53SAndroid Build Coastguard Worker *result = pp.result;
1223*4dc78e53SAndroid Build Coastguard Worker errout:
1224*4dc78e53SAndroid Build Coastguard Worker nl_cb_put(cb);
1225*4dc78e53SAndroid Build Coastguard Worker
1226*4dc78e53SAndroid Build Coastguard Worker return err;
1227*4dc78e53SAndroid Build Coastguard Worker }
1228*4dc78e53SAndroid Build Coastguard Worker
1229*4dc78e53SAndroid Build Coastguard Worker /** @} */
1230*4dc78e53SAndroid Build Coastguard Worker
1231*4dc78e53SAndroid Build Coastguard Worker /**
1232*4dc78e53SAndroid Build Coastguard Worker * @name Deprecated
1233*4dc78e53SAndroid Build Coastguard Worker * @{
1234*4dc78e53SAndroid Build Coastguard Worker */
1235*4dc78e53SAndroid Build Coastguard Worker
1236*4dc78e53SAndroid Build Coastguard Worker /**
1237*4dc78e53SAndroid Build Coastguard Worker * @deprecated Please use nl_complete_msg()
1238*4dc78e53SAndroid Build Coastguard Worker */
nl_auto_complete(struct nl_sock * sk,struct nl_msg * msg)1239*4dc78e53SAndroid Build Coastguard Worker void nl_auto_complete(struct nl_sock *sk, struct nl_msg *msg)
1240*4dc78e53SAndroid Build Coastguard Worker {
1241*4dc78e53SAndroid Build Coastguard Worker nl_complete_msg(sk, msg);
1242*4dc78e53SAndroid Build Coastguard Worker }
1243*4dc78e53SAndroid Build Coastguard Worker
1244*4dc78e53SAndroid Build Coastguard Worker /**
1245*4dc78e53SAndroid Build Coastguard Worker * @deprecated Please use nl_send_auto()
1246*4dc78e53SAndroid Build Coastguard Worker */
nl_send_auto_complete(struct nl_sock * sk,struct nl_msg * msg)1247*4dc78e53SAndroid Build Coastguard Worker int nl_send_auto_complete(struct nl_sock *sk, struct nl_msg *msg)
1248*4dc78e53SAndroid Build Coastguard Worker {
1249*4dc78e53SAndroid Build Coastguard Worker return nl_send_auto(sk, msg);
1250*4dc78e53SAndroid Build Coastguard Worker }
1251*4dc78e53SAndroid Build Coastguard Worker
1252*4dc78e53SAndroid Build Coastguard Worker
1253*4dc78e53SAndroid Build Coastguard Worker /** @} */
1254*4dc78e53SAndroid Build Coastguard Worker
1255*4dc78e53SAndroid Build Coastguard Worker /** @} */
1256*4dc78e53SAndroid Build Coastguard Worker
1257*4dc78e53SAndroid Build Coastguard Worker /** @} */
1258