xref: /aosp_15_r20/external/libnl/lib/nl.c (revision 4dc78e53d49367fa8e61b07018507c90983a077d)
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