xref: /aosp_15_r20/external/libnl/lib/socket.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  * @ingroup core_types
8*4dc78e53SAndroid Build Coastguard Worker  * @defgroup socket Socket
9*4dc78e53SAndroid Build Coastguard Worker  *
10*4dc78e53SAndroid Build Coastguard Worker  * Representation of a netlink socket
11*4dc78e53SAndroid Build Coastguard Worker  *
12*4dc78e53SAndroid Build Coastguard Worker  * Related sections in the development guide:
13*4dc78e53SAndroid Build Coastguard Worker  * - @core_doc{core_sockets, Netlink Sockets}
14*4dc78e53SAndroid Build Coastguard Worker  *
15*4dc78e53SAndroid Build Coastguard Worker  * @{
16*4dc78e53SAndroid Build Coastguard Worker  *
17*4dc78e53SAndroid Build Coastguard Worker  * Header
18*4dc78e53SAndroid Build Coastguard Worker  * ------
19*4dc78e53SAndroid Build Coastguard Worker  * ~~~~{.c}
20*4dc78e53SAndroid Build Coastguard Worker  * #include <netlink/socket.h>
21*4dc78e53SAndroid Build Coastguard Worker  * ~~~~
22*4dc78e53SAndroid Build Coastguard Worker  */
23*4dc78e53SAndroid Build Coastguard Worker 
24*4dc78e53SAndroid Build Coastguard Worker #include "nl-default.h"
25*4dc78e53SAndroid Build Coastguard Worker 
26*4dc78e53SAndroid Build Coastguard Worker #include <fcntl.h>
27*4dc78e53SAndroid Build Coastguard Worker #include <limits.h>
28*4dc78e53SAndroid Build Coastguard Worker #include <sys/socket.h>
29*4dc78e53SAndroid Build Coastguard Worker 
30*4dc78e53SAndroid Build Coastguard Worker #include <netlink/netlink.h>
31*4dc78e53SAndroid Build Coastguard Worker #include <netlink/utils.h>
32*4dc78e53SAndroid Build Coastguard Worker #include <netlink/handlers.h>
33*4dc78e53SAndroid Build Coastguard Worker #include <netlink/msg.h>
34*4dc78e53SAndroid Build Coastguard Worker #include <netlink/attr.h>
35*4dc78e53SAndroid Build Coastguard Worker 
36*4dc78e53SAndroid Build Coastguard Worker #include "nl-core.h"
37*4dc78e53SAndroid Build Coastguard Worker #include "nl-priv-dynamic-core/nl-core.h"
38*4dc78e53SAndroid Build Coastguard Worker #include "nl-aux-core/nl-core.h"
39*4dc78e53SAndroid Build Coastguard Worker 
40*4dc78e53SAndroid Build Coastguard Worker #ifndef SOL_NETLINK
41*4dc78e53SAndroid Build Coastguard Worker #define SOL_NETLINK 270
42*4dc78e53SAndroid Build Coastguard Worker #endif
43*4dc78e53SAndroid Build Coastguard Worker 
44*4dc78e53SAndroid Build Coastguard Worker static int default_cb = NL_CB_DEFAULT;
45*4dc78e53SAndroid Build Coastguard Worker 
init_default_cb(void)46*4dc78e53SAndroid Build Coastguard Worker static void _nl_init init_default_cb(void)
47*4dc78e53SAndroid Build Coastguard Worker {
48*4dc78e53SAndroid Build Coastguard Worker 	char *nlcb;
49*4dc78e53SAndroid Build Coastguard Worker 
50*4dc78e53SAndroid Build Coastguard Worker 	if ((nlcb = getenv("NLCB"))) {
51*4dc78e53SAndroid Build Coastguard Worker 		if (!strcasecmp(nlcb, "default"))
52*4dc78e53SAndroid Build Coastguard Worker 			default_cb = NL_CB_DEFAULT;
53*4dc78e53SAndroid Build Coastguard Worker 		else if (!strcasecmp(nlcb, "verbose"))
54*4dc78e53SAndroid Build Coastguard Worker 			default_cb = NL_CB_VERBOSE;
55*4dc78e53SAndroid Build Coastguard Worker 		else if (!strcasecmp(nlcb, "debug"))
56*4dc78e53SAndroid Build Coastguard Worker 			default_cb = NL_CB_DEBUG;
57*4dc78e53SAndroid Build Coastguard Worker 		else {
58*4dc78e53SAndroid Build Coastguard Worker 			fprintf(stderr, "Unknown value for NLCB, valid values: "
59*4dc78e53SAndroid Build Coastguard Worker 				"{default | verbose | debug}\n");
60*4dc78e53SAndroid Build Coastguard Worker 		}
61*4dc78e53SAndroid Build Coastguard Worker 	}
62*4dc78e53SAndroid Build Coastguard Worker }
63*4dc78e53SAndroid Build Coastguard Worker 
_badrandom_from_time(void)64*4dc78e53SAndroid Build Coastguard Worker static uint32_t _badrandom_from_time(void)
65*4dc78e53SAndroid Build Coastguard Worker {
66*4dc78e53SAndroid Build Coastguard Worker 	uint32_t result;
67*4dc78e53SAndroid Build Coastguard Worker 	uint64_t v64;
68*4dc78e53SAndroid Build Coastguard Worker 	time_t t;
69*4dc78e53SAndroid Build Coastguard Worker 
70*4dc78e53SAndroid Build Coastguard Worker 	t = time(NULL);
71*4dc78e53SAndroid Build Coastguard Worker 	v64 = (uint64_t)t;
72*4dc78e53SAndroid Build Coastguard Worker 	result = (uint32_t)v64;
73*4dc78e53SAndroid Build Coastguard Worker 
74*4dc78e53SAndroid Build Coastguard Worker 	/* XOR with the upper bits. Otherwise, coverity warns about only
75*4dc78e53SAndroid Build Coastguard Worker 	 * considering 32 bit from time_t.  Use the inverse, so that for the
76*4dc78e53SAndroid Build Coastguard Worker 	 * most part the bits don't change.  */
77*4dc78e53SAndroid Build Coastguard Worker 	result ^= (~(v64 >> 32));
78*4dc78e53SAndroid Build Coastguard Worker 
79*4dc78e53SAndroid Build Coastguard Worker 	return result;
80*4dc78e53SAndroid Build Coastguard Worker }
81*4dc78e53SAndroid Build Coastguard Worker 
82*4dc78e53SAndroid Build Coastguard Worker static uint32_t used_ports_map[32];
83*4dc78e53SAndroid Build Coastguard Worker static NL_RW_LOCK(port_map_lock);
84*4dc78e53SAndroid Build Coastguard Worker 
generate_local_port(void)85*4dc78e53SAndroid Build Coastguard Worker static uint32_t generate_local_port(void)
86*4dc78e53SAndroid Build Coastguard Worker {
87*4dc78e53SAndroid Build Coastguard Worker 	int i, j, m;
88*4dc78e53SAndroid Build Coastguard Worker 	uint32_t n;
89*4dc78e53SAndroid Build Coastguard Worker 	static uint16_t idx_state = 0;
90*4dc78e53SAndroid Build Coastguard Worker 	uint32_t pid = getpid() & 0x3FFFFF;
91*4dc78e53SAndroid Build Coastguard Worker 
92*4dc78e53SAndroid Build Coastguard Worker 	nl_write_lock(&port_map_lock);
93*4dc78e53SAndroid Build Coastguard Worker 
94*4dc78e53SAndroid Build Coastguard Worker 	if (idx_state == 0) {
95*4dc78e53SAndroid Build Coastguard Worker 		uint32_t t = _badrandom_from_time();
96*4dc78e53SAndroid Build Coastguard Worker 
97*4dc78e53SAndroid Build Coastguard Worker 		/* from time to time (on average each 2^15 calls), the idx_state will
98*4dc78e53SAndroid Build Coastguard Worker 		 * be zero again. No problem, just "seed" anew with time(). */
99*4dc78e53SAndroid Build Coastguard Worker 		idx_state = t ^ (t >> 16) ^ 0x3047;
100*4dc78e53SAndroid Build Coastguard Worker 	} else
101*4dc78e53SAndroid Build Coastguard Worker 		idx_state = idx_state + 20011; /* add prime number */
102*4dc78e53SAndroid Build Coastguard Worker 
103*4dc78e53SAndroid Build Coastguard Worker 	i = idx_state >> 5;
104*4dc78e53SAndroid Build Coastguard Worker 	n = idx_state;
105*4dc78e53SAndroid Build Coastguard Worker 	for (j = 0; j < 32; j++) {
106*4dc78e53SAndroid Build Coastguard Worker 		/* walk the index somewhat randomized, with always leaving the block
107*4dc78e53SAndroid Build Coastguard Worker 		 * #0 as last. The reason is that libnl-1 will start at block #0,
108*4dc78e53SAndroid Build Coastguard Worker 		 * so just leave the first 32 ports preferably for libnl-1 owned sockets
109*4dc78e53SAndroid Build Coastguard Worker 		 * (this is relevant only if the applications ends up using both versions
110*4dc78e53SAndroid Build Coastguard Worker 		 * of the library and doesn't hurt otherwise). */
111*4dc78e53SAndroid Build Coastguard Worker 		if (j == 31)
112*4dc78e53SAndroid Build Coastguard Worker 			i = 0;
113*4dc78e53SAndroid Build Coastguard Worker 		else
114*4dc78e53SAndroid Build Coastguard Worker 			i = (((i-1) + 7) % 31) + 1;
115*4dc78e53SAndroid Build Coastguard Worker 
116*4dc78e53SAndroid Build Coastguard Worker 		if (used_ports_map[i] == 0xFFFFFFFF)
117*4dc78e53SAndroid Build Coastguard Worker 			continue;
118*4dc78e53SAndroid Build Coastguard Worker 
119*4dc78e53SAndroid Build Coastguard Worker 		for (m = 0; m < 32; m++) {
120*4dc78e53SAndroid Build Coastguard Worker 			n = (n + 13u) % 32u;
121*4dc78e53SAndroid Build Coastguard Worker 			if (1UL & (used_ports_map[i] >> n))
122*4dc78e53SAndroid Build Coastguard Worker 				continue;
123*4dc78e53SAndroid Build Coastguard Worker 
124*4dc78e53SAndroid Build Coastguard Worker 			used_ports_map[i] |= (1UL << n);
125*4dc78e53SAndroid Build Coastguard Worker 			n += (i * 32);
126*4dc78e53SAndroid Build Coastguard Worker 
127*4dc78e53SAndroid Build Coastguard Worker 			/* PID_MAX_LIMIT is currently at 2^22, leaving 10 bit
128*4dc78e53SAndroid Build Coastguard Worker 			 * to, i.e. 1024 unique ports per application. */
129*4dc78e53SAndroid Build Coastguard Worker 
130*4dc78e53SAndroid Build Coastguard Worker 			nl_write_unlock(&port_map_lock);
131*4dc78e53SAndroid Build Coastguard Worker 
132*4dc78e53SAndroid Build Coastguard Worker 			/* ensure we don't return zero. */
133*4dc78e53SAndroid Build Coastguard Worker 			pid = pid + (n << 22);
134*4dc78e53SAndroid Build Coastguard Worker 			return pid ? pid : 1024;
135*4dc78e53SAndroid Build Coastguard Worker 		}
136*4dc78e53SAndroid Build Coastguard Worker 	}
137*4dc78e53SAndroid Build Coastguard Worker 
138*4dc78e53SAndroid Build Coastguard Worker 	nl_write_unlock(&port_map_lock);
139*4dc78e53SAndroid Build Coastguard Worker 	return 0;
140*4dc78e53SAndroid Build Coastguard Worker }
141*4dc78e53SAndroid Build Coastguard Worker 
release_local_port(uint32_t port)142*4dc78e53SAndroid Build Coastguard Worker static void release_local_port(uint32_t port)
143*4dc78e53SAndroid Build Coastguard Worker {
144*4dc78e53SAndroid Build Coastguard Worker 	int nr;
145*4dc78e53SAndroid Build Coastguard Worker 	uint32_t mask;
146*4dc78e53SAndroid Build Coastguard Worker 
147*4dc78e53SAndroid Build Coastguard Worker 	BUG_ON(port == 0);
148*4dc78e53SAndroid Build Coastguard Worker 
149*4dc78e53SAndroid Build Coastguard Worker 	nr = port >> 22;
150*4dc78e53SAndroid Build Coastguard Worker 	mask = 1UL << (nr % 32);
151*4dc78e53SAndroid Build Coastguard Worker 	nr /= 32;
152*4dc78e53SAndroid Build Coastguard Worker 
153*4dc78e53SAndroid Build Coastguard Worker 	nl_write_lock(&port_map_lock);
154*4dc78e53SAndroid Build Coastguard Worker 	BUG_ON((used_ports_map[nr] & mask) != mask);
155*4dc78e53SAndroid Build Coastguard Worker 	used_ports_map[nr] &= ~mask;
156*4dc78e53SAndroid Build Coastguard Worker 	nl_write_unlock(&port_map_lock);
157*4dc78e53SAndroid Build Coastguard Worker }
158*4dc78e53SAndroid Build Coastguard Worker 
159*4dc78e53SAndroid Build Coastguard Worker /** \cond skip */
_nl_socket_used_ports_release_all(const uint32_t * used_ports)160*4dc78e53SAndroid Build Coastguard Worker void _nl_socket_used_ports_release_all(const uint32_t *used_ports)
161*4dc78e53SAndroid Build Coastguard Worker {
162*4dc78e53SAndroid Build Coastguard Worker 	int i;
163*4dc78e53SAndroid Build Coastguard Worker 
164*4dc78e53SAndroid Build Coastguard Worker 	for (i = 0; i < 32; i++) {
165*4dc78e53SAndroid Build Coastguard Worker 		if (used_ports[i] != 0) {
166*4dc78e53SAndroid Build Coastguard Worker 			nl_write_lock(&port_map_lock);
167*4dc78e53SAndroid Build Coastguard Worker 			for (; i < 32; i++) {
168*4dc78e53SAndroid Build Coastguard Worker 				BUG_ON((used_ports_map[i] & used_ports[i]) != used_ports[i]);
169*4dc78e53SAndroid Build Coastguard Worker 				used_ports_map[i] &= ~(used_ports[i]);
170*4dc78e53SAndroid Build Coastguard Worker 			}
171*4dc78e53SAndroid Build Coastguard Worker 			nl_write_unlock(&port_map_lock);
172*4dc78e53SAndroid Build Coastguard Worker 			return;
173*4dc78e53SAndroid Build Coastguard Worker 		}
174*4dc78e53SAndroid Build Coastguard Worker 	}
175*4dc78e53SAndroid Build Coastguard Worker }
176*4dc78e53SAndroid Build Coastguard Worker 
_nl_socket_used_ports_set(uint32_t * used_ports,uint32_t port)177*4dc78e53SAndroid Build Coastguard Worker void _nl_socket_used_ports_set(uint32_t *used_ports, uint32_t port)
178*4dc78e53SAndroid Build Coastguard Worker {
179*4dc78e53SAndroid Build Coastguard Worker 	int nr;
180*4dc78e53SAndroid Build Coastguard Worker 	int32_t mask;
181*4dc78e53SAndroid Build Coastguard Worker 
182*4dc78e53SAndroid Build Coastguard Worker 	nr = port >> 22;
183*4dc78e53SAndroid Build Coastguard Worker 	mask = 1UL << (nr % 32);
184*4dc78e53SAndroid Build Coastguard Worker 	nr /= 32;
185*4dc78e53SAndroid Build Coastguard Worker 
186*4dc78e53SAndroid Build Coastguard Worker 	/*
187*4dc78e53SAndroid Build Coastguard Worker 	BUG_ON(port == 0 || (getpid() & 0x3FFFFF) != (port & 0x3FFFFF));
188*4dc78e53SAndroid Build Coastguard Worker 	BUG_ON(used_ports[nr] & mask);
189*4dc78e53SAndroid Build Coastguard Worker 	*/
190*4dc78e53SAndroid Build Coastguard Worker 
191*4dc78e53SAndroid Build Coastguard Worker 	used_ports[nr] |= mask;
192*4dc78e53SAndroid Build Coastguard Worker }
193*4dc78e53SAndroid Build Coastguard Worker /** \endcond */
194*4dc78e53SAndroid Build Coastguard Worker 
195*4dc78e53SAndroid Build Coastguard Worker /**
196*4dc78e53SAndroid Build Coastguard Worker  * @name Allocation
197*4dc78e53SAndroid Build Coastguard Worker  * @{
198*4dc78e53SAndroid Build Coastguard Worker  */
199*4dc78e53SAndroid Build Coastguard Worker 
__alloc_socket(struct nl_cb * cb)200*4dc78e53SAndroid Build Coastguard Worker static struct nl_sock *__alloc_socket(struct nl_cb *cb)
201*4dc78e53SAndroid Build Coastguard Worker {
202*4dc78e53SAndroid Build Coastguard Worker 	struct nl_sock *sk;
203*4dc78e53SAndroid Build Coastguard Worker 
204*4dc78e53SAndroid Build Coastguard Worker 	sk = calloc(1, sizeof(*sk));
205*4dc78e53SAndroid Build Coastguard Worker 	if (!sk)
206*4dc78e53SAndroid Build Coastguard Worker 		return NULL;
207*4dc78e53SAndroid Build Coastguard Worker 
208*4dc78e53SAndroid Build Coastguard Worker 	sk->s_fd = -1;
209*4dc78e53SAndroid Build Coastguard Worker 	sk->s_cb = nl_cb_get(cb);
210*4dc78e53SAndroid Build Coastguard Worker 	sk->s_local.nl_family = AF_NETLINK;
211*4dc78e53SAndroid Build Coastguard Worker 	sk->s_peer.nl_family = AF_NETLINK;
212*4dc78e53SAndroid Build Coastguard Worker 	sk->s_seq_next = _badrandom_from_time();
213*4dc78e53SAndroid Build Coastguard Worker 	sk->s_seq_expect = sk->s_seq_next;
214*4dc78e53SAndroid Build Coastguard Worker 
215*4dc78e53SAndroid Build Coastguard Worker 	/* the port is 0 (unspecified), meaning NL_OWN_PORT */
216*4dc78e53SAndroid Build Coastguard Worker 	sk->s_flags = NL_OWN_PORT;
217*4dc78e53SAndroid Build Coastguard Worker 
218*4dc78e53SAndroid Build Coastguard Worker 	return sk;
219*4dc78e53SAndroid Build Coastguard Worker }
220*4dc78e53SAndroid Build Coastguard Worker 
221*4dc78e53SAndroid Build Coastguard Worker /**
222*4dc78e53SAndroid Build Coastguard Worker  * Allocate new netlink socket
223*4dc78e53SAndroid Build Coastguard Worker  *
224*4dc78e53SAndroid Build Coastguard Worker  * @return Newly allocated netlink socket or NULL.
225*4dc78e53SAndroid Build Coastguard Worker  */
nl_socket_alloc(void)226*4dc78e53SAndroid Build Coastguard Worker struct nl_sock *nl_socket_alloc(void)
227*4dc78e53SAndroid Build Coastguard Worker {
228*4dc78e53SAndroid Build Coastguard Worker 	struct nl_cb *cb;
229*4dc78e53SAndroid Build Coastguard Worker 	struct nl_sock *sk;
230*4dc78e53SAndroid Build Coastguard Worker 
231*4dc78e53SAndroid Build Coastguard Worker 	cb = nl_cb_alloc(default_cb);
232*4dc78e53SAndroid Build Coastguard Worker 	if (!cb)
233*4dc78e53SAndroid Build Coastguard Worker 		return NULL;
234*4dc78e53SAndroid Build Coastguard Worker 
235*4dc78e53SAndroid Build Coastguard Worker 	/* will increment cb reference count on success */
236*4dc78e53SAndroid Build Coastguard Worker 	sk = __alloc_socket(cb);
237*4dc78e53SAndroid Build Coastguard Worker 
238*4dc78e53SAndroid Build Coastguard Worker 	nl_cb_put(cb);
239*4dc78e53SAndroid Build Coastguard Worker 
240*4dc78e53SAndroid Build Coastguard Worker 	return sk;
241*4dc78e53SAndroid Build Coastguard Worker }
242*4dc78e53SAndroid Build Coastguard Worker 
243*4dc78e53SAndroid Build Coastguard Worker /**
244*4dc78e53SAndroid Build Coastguard Worker  * Allocate new socket with custom callbacks
245*4dc78e53SAndroid Build Coastguard Worker  * @arg cb		Callback handler
246*4dc78e53SAndroid Build Coastguard Worker  *
247*4dc78e53SAndroid Build Coastguard Worker  * The reference to the callback handler is taken into account
248*4dc78e53SAndroid Build Coastguard Worker  * automatically, it is released again upon calling nl_socket_free().
249*4dc78e53SAndroid Build Coastguard Worker  *
250*4dc78e53SAndroid Build Coastguard Worker  *@return Newly allocted socket handle or NULL.
251*4dc78e53SAndroid Build Coastguard Worker  */
nl_socket_alloc_cb(struct nl_cb * cb)252*4dc78e53SAndroid Build Coastguard Worker struct nl_sock *nl_socket_alloc_cb(struct nl_cb *cb)
253*4dc78e53SAndroid Build Coastguard Worker {
254*4dc78e53SAndroid Build Coastguard Worker 	if (cb == NULL)
255*4dc78e53SAndroid Build Coastguard Worker 		BUG();
256*4dc78e53SAndroid Build Coastguard Worker 
257*4dc78e53SAndroid Build Coastguard Worker 	return __alloc_socket(cb);
258*4dc78e53SAndroid Build Coastguard Worker }
259*4dc78e53SAndroid Build Coastguard Worker 
260*4dc78e53SAndroid Build Coastguard Worker /**
261*4dc78e53SAndroid Build Coastguard Worker  * Free a netlink socket.
262*4dc78e53SAndroid Build Coastguard Worker  * @arg sk		Netlink socket.
263*4dc78e53SAndroid Build Coastguard Worker  */
nl_socket_free(struct nl_sock * sk)264*4dc78e53SAndroid Build Coastguard Worker void nl_socket_free(struct nl_sock *sk)
265*4dc78e53SAndroid Build Coastguard Worker {
266*4dc78e53SAndroid Build Coastguard Worker 	if (!sk)
267*4dc78e53SAndroid Build Coastguard Worker 		return;
268*4dc78e53SAndroid Build Coastguard Worker 
269*4dc78e53SAndroid Build Coastguard Worker 	if (sk->s_fd >= 0)
270*4dc78e53SAndroid Build Coastguard Worker 		close(sk->s_fd);
271*4dc78e53SAndroid Build Coastguard Worker 
272*4dc78e53SAndroid Build Coastguard Worker 	if (!(sk->s_flags & NL_OWN_PORT))
273*4dc78e53SAndroid Build Coastguard Worker 		release_local_port(sk->s_local.nl_pid);
274*4dc78e53SAndroid Build Coastguard Worker 
275*4dc78e53SAndroid Build Coastguard Worker 	nl_cb_put(sk->s_cb);
276*4dc78e53SAndroid Build Coastguard Worker 	free(sk);
277*4dc78e53SAndroid Build Coastguard Worker }
278*4dc78e53SAndroid Build Coastguard Worker 
279*4dc78e53SAndroid Build Coastguard Worker /** @} */
280*4dc78e53SAndroid Build Coastguard Worker 
281*4dc78e53SAndroid Build Coastguard Worker /**
282*4dc78e53SAndroid Build Coastguard Worker  * @name Sequence Numbers
283*4dc78e53SAndroid Build Coastguard Worker  * @{
284*4dc78e53SAndroid Build Coastguard Worker  */
285*4dc78e53SAndroid Build Coastguard Worker 
noop_seq_check(struct nl_msg * msg,void * arg)286*4dc78e53SAndroid Build Coastguard Worker static int noop_seq_check(struct nl_msg *msg, void *arg)
287*4dc78e53SAndroid Build Coastguard Worker {
288*4dc78e53SAndroid Build Coastguard Worker 	return NL_OK;
289*4dc78e53SAndroid Build Coastguard Worker }
290*4dc78e53SAndroid Build Coastguard Worker 
291*4dc78e53SAndroid Build Coastguard Worker 
292*4dc78e53SAndroid Build Coastguard Worker /**
293*4dc78e53SAndroid Build Coastguard Worker  * Disable sequence number checking.
294*4dc78e53SAndroid Build Coastguard Worker  * @arg sk		Netlink socket.
295*4dc78e53SAndroid Build Coastguard Worker  *
296*4dc78e53SAndroid Build Coastguard Worker  * Disables checking of sequence numbers on the netlink socket This is
297*4dc78e53SAndroid Build Coastguard Worker  * required to allow messages to be processed which were not requested by
298*4dc78e53SAndroid Build Coastguard Worker  * a preceding request message, e.g. netlink events.
299*4dc78e53SAndroid Build Coastguard Worker  *
300*4dc78e53SAndroid Build Coastguard Worker  * @note This function modifies the NL_CB_SEQ_CHECK configuration in
301*4dc78e53SAndroid Build Coastguard Worker  * the callback handle associated with the socket.
302*4dc78e53SAndroid Build Coastguard Worker  */
nl_socket_disable_seq_check(struct nl_sock * sk)303*4dc78e53SAndroid Build Coastguard Worker void nl_socket_disable_seq_check(struct nl_sock *sk)
304*4dc78e53SAndroid Build Coastguard Worker {
305*4dc78e53SAndroid Build Coastguard Worker 	nl_cb_set(sk->s_cb, NL_CB_SEQ_CHECK,
306*4dc78e53SAndroid Build Coastguard Worker 		  NL_CB_CUSTOM, noop_seq_check, NULL);
307*4dc78e53SAndroid Build Coastguard Worker }
308*4dc78e53SAndroid Build Coastguard Worker 
309*4dc78e53SAndroid Build Coastguard Worker /**
310*4dc78e53SAndroid Build Coastguard Worker  * Use next sequence number
311*4dc78e53SAndroid Build Coastguard Worker  * @arg sk		Netlink socket.
312*4dc78e53SAndroid Build Coastguard Worker  *
313*4dc78e53SAndroid Build Coastguard Worker  * Uses the next available sequence number and increases the counter
314*4dc78e53SAndroid Build Coastguard Worker  * by one for subsequent calls.
315*4dc78e53SAndroid Build Coastguard Worker  *
316*4dc78e53SAndroid Build Coastguard Worker  * @return Unique serial sequence number
317*4dc78e53SAndroid Build Coastguard Worker  */
nl_socket_use_seq(struct nl_sock * sk)318*4dc78e53SAndroid Build Coastguard Worker unsigned int nl_socket_use_seq(struct nl_sock *sk)
319*4dc78e53SAndroid Build Coastguard Worker {
320*4dc78e53SAndroid Build Coastguard Worker 	if (sk->s_seq_next == UINT_MAX) {
321*4dc78e53SAndroid Build Coastguard Worker 		sk->s_seq_next = 0;
322*4dc78e53SAndroid Build Coastguard Worker 		return UINT_MAX;
323*4dc78e53SAndroid Build Coastguard Worker 	}
324*4dc78e53SAndroid Build Coastguard Worker 	return sk->s_seq_next++;
325*4dc78e53SAndroid Build Coastguard Worker }
326*4dc78e53SAndroid Build Coastguard Worker 
327*4dc78e53SAndroid Build Coastguard Worker /**
328*4dc78e53SAndroid Build Coastguard Worker  * Disable automatic request for ACK
329*4dc78e53SAndroid Build Coastguard Worker  * @arg sk		Netlink socket.
330*4dc78e53SAndroid Build Coastguard Worker  *
331*4dc78e53SAndroid Build Coastguard Worker  * The default behaviour of a socket is to request an ACK for
332*4dc78e53SAndroid Build Coastguard Worker  * each message sent to allow for the caller to synchronize to
333*4dc78e53SAndroid Build Coastguard Worker  * the completion of the netlink operation. This function
334*4dc78e53SAndroid Build Coastguard Worker  * disables this behaviour and will result in requests being
335*4dc78e53SAndroid Build Coastguard Worker  * sent which will not have the NLM_F_ACK flag set automatically.
336*4dc78e53SAndroid Build Coastguard Worker  * However, it is still possible for the caller to set the
337*4dc78e53SAndroid Build Coastguard Worker  * NLM_F_ACK flag explicitely.
338*4dc78e53SAndroid Build Coastguard Worker  */
nl_socket_disable_auto_ack(struct nl_sock * sk)339*4dc78e53SAndroid Build Coastguard Worker void nl_socket_disable_auto_ack(struct nl_sock *sk)
340*4dc78e53SAndroid Build Coastguard Worker {
341*4dc78e53SAndroid Build Coastguard Worker 	sk->s_flags |= NL_NO_AUTO_ACK;
342*4dc78e53SAndroid Build Coastguard Worker }
343*4dc78e53SAndroid Build Coastguard Worker 
344*4dc78e53SAndroid Build Coastguard Worker /**
345*4dc78e53SAndroid Build Coastguard Worker  * Enable automatic request for ACK (default)
346*4dc78e53SAndroid Build Coastguard Worker  * @arg sk		Netlink socket.
347*4dc78e53SAndroid Build Coastguard Worker  * @see nl_socket_disable_auto_ack
348*4dc78e53SAndroid Build Coastguard Worker  */
nl_socket_enable_auto_ack(struct nl_sock * sk)349*4dc78e53SAndroid Build Coastguard Worker void nl_socket_enable_auto_ack(struct nl_sock *sk)
350*4dc78e53SAndroid Build Coastguard Worker {
351*4dc78e53SAndroid Build Coastguard Worker 	sk->s_flags &= ~NL_NO_AUTO_ACK;
352*4dc78e53SAndroid Build Coastguard Worker }
353*4dc78e53SAndroid Build Coastguard Worker 
354*4dc78e53SAndroid Build Coastguard Worker /** @} */
355*4dc78e53SAndroid Build Coastguard Worker 
356*4dc78e53SAndroid Build Coastguard Worker /** \cond skip */
_nl_socket_is_local_port_unspecified(struct nl_sock * sk)357*4dc78e53SAndroid Build Coastguard Worker int _nl_socket_is_local_port_unspecified(struct nl_sock *sk)
358*4dc78e53SAndroid Build Coastguard Worker {
359*4dc78e53SAndroid Build Coastguard Worker 	return (sk->s_local.nl_pid == 0);
360*4dc78e53SAndroid Build Coastguard Worker }
361*4dc78e53SAndroid Build Coastguard Worker 
_nl_socket_set_local_port_no_release(struct nl_sock * sk,int generate_other)362*4dc78e53SAndroid Build Coastguard Worker uint32_t _nl_socket_set_local_port_no_release(struct nl_sock *sk, int generate_other)
363*4dc78e53SAndroid Build Coastguard Worker {
364*4dc78e53SAndroid Build Coastguard Worker 	uint32_t port;
365*4dc78e53SAndroid Build Coastguard Worker 
366*4dc78e53SAndroid Build Coastguard Worker 	/* reset the port to generate_local_port(), but do not release
367*4dc78e53SAndroid Build Coastguard Worker 	 * the previously generated port. */
368*4dc78e53SAndroid Build Coastguard Worker 
369*4dc78e53SAndroid Build Coastguard Worker 	if (generate_other)
370*4dc78e53SAndroid Build Coastguard Worker 		port = generate_local_port();
371*4dc78e53SAndroid Build Coastguard Worker 	else
372*4dc78e53SAndroid Build Coastguard Worker 		port = 0;
373*4dc78e53SAndroid Build Coastguard Worker 	sk->s_local.nl_pid = port;
374*4dc78e53SAndroid Build Coastguard Worker 	if (port == 0) {
375*4dc78e53SAndroid Build Coastguard Worker 		/* failed to find an unsed port. Restore the socket to have an
376*4dc78e53SAndroid Build Coastguard Worker 		 * unspecified port. */
377*4dc78e53SAndroid Build Coastguard Worker 		sk->s_flags |= NL_OWN_PORT;
378*4dc78e53SAndroid Build Coastguard Worker 	} else
379*4dc78e53SAndroid Build Coastguard Worker 		sk->s_flags &= ~NL_OWN_PORT;
380*4dc78e53SAndroid Build Coastguard Worker 	return port;
381*4dc78e53SAndroid Build Coastguard Worker }
382*4dc78e53SAndroid Build Coastguard Worker /** \endcond */
383*4dc78e53SAndroid Build Coastguard Worker 
384*4dc78e53SAndroid Build Coastguard Worker /**
385*4dc78e53SAndroid Build Coastguard Worker  * @name Source Idenficiation
386*4dc78e53SAndroid Build Coastguard Worker  * @{
387*4dc78e53SAndroid Build Coastguard Worker  */
388*4dc78e53SAndroid Build Coastguard Worker 
nl_socket_get_local_port(const struct nl_sock * sk)389*4dc78e53SAndroid Build Coastguard Worker uint32_t nl_socket_get_local_port(const struct nl_sock *sk)
390*4dc78e53SAndroid Build Coastguard Worker {
391*4dc78e53SAndroid Build Coastguard Worker 	if (sk->s_local.nl_pid == 0) {
392*4dc78e53SAndroid Build Coastguard Worker 		struct nl_sock *sk_mutable = (struct nl_sock *) sk;
393*4dc78e53SAndroid Build Coastguard Worker 
394*4dc78e53SAndroid Build Coastguard Worker 		/* modify the const argument sk. This is justified, because
395*4dc78e53SAndroid Build Coastguard Worker 		 * nobody ever saw the local_port from externally. So, we
396*4dc78e53SAndroid Build Coastguard Worker 		 * initilize it on first use.
397*4dc78e53SAndroid Build Coastguard Worker 		 *
398*4dc78e53SAndroid Build Coastguard Worker 		 * Note that this also means that you cannot call this function
399*4dc78e53SAndroid Build Coastguard Worker 		 * from multiple threads without synchronization. But nl_sock
400*4dc78e53SAndroid Build Coastguard Worker 		 * is not automatically threadsafe anyway, so the user is not
401*4dc78e53SAndroid Build Coastguard Worker 		 * allowed to do that.
402*4dc78e53SAndroid Build Coastguard Worker 		 */
403*4dc78e53SAndroid Build Coastguard Worker 		sk_mutable->s_local.nl_pid = generate_local_port();
404*4dc78e53SAndroid Build Coastguard Worker 		if (sk_mutable->s_local.nl_pid == 0) {
405*4dc78e53SAndroid Build Coastguard Worker 			/* could not generate a local port. Assign UINT32_MAX to preserve
406*4dc78e53SAndroid Build Coastguard Worker 			 * backward compatibility. A user who cares can clear that anyway
407*4dc78e53SAndroid Build Coastguard Worker 			 * with nl_socket_set_local_port(). */
408*4dc78e53SAndroid Build Coastguard Worker 			sk_mutable->s_local.nl_pid = UINT32_MAX;
409*4dc78e53SAndroid Build Coastguard Worker 			sk_mutable->s_flags |= NL_OWN_PORT;
410*4dc78e53SAndroid Build Coastguard Worker 		} else
411*4dc78e53SAndroid Build Coastguard Worker 			sk_mutable->s_flags &= ~NL_OWN_PORT;
412*4dc78e53SAndroid Build Coastguard Worker 	}
413*4dc78e53SAndroid Build Coastguard Worker 	return sk->s_local.nl_pid;
414*4dc78e53SAndroid Build Coastguard Worker }
415*4dc78e53SAndroid Build Coastguard Worker 
416*4dc78e53SAndroid Build Coastguard Worker /**
417*4dc78e53SAndroid Build Coastguard Worker  * Set local port of socket
418*4dc78e53SAndroid Build Coastguard Worker  * @arg sk		Netlink socket.
419*4dc78e53SAndroid Build Coastguard Worker  * @arg port		Local port identifier
420*4dc78e53SAndroid Build Coastguard Worker  *
421*4dc78e53SAndroid Build Coastguard Worker  * Assigns a local port identifier to the socket.
422*4dc78e53SAndroid Build Coastguard Worker  *
423*4dc78e53SAndroid Build Coastguard Worker  * If port is 0, the port is reset to 'unspecified' as it is after newly
424*4dc78e53SAndroid Build Coastguard Worker  * calling nl_socket_alloc().
425*4dc78e53SAndroid Build Coastguard Worker  * Unspecified means, that the port will be generated automatically later
426*4dc78e53SAndroid Build Coastguard Worker  * on first use (either on nl_socket_get_local_port() or nl_connect()).
427*4dc78e53SAndroid Build Coastguard Worker  */
nl_socket_set_local_port(struct nl_sock * sk,uint32_t port)428*4dc78e53SAndroid Build Coastguard Worker void nl_socket_set_local_port(struct nl_sock *sk, uint32_t port)
429*4dc78e53SAndroid Build Coastguard Worker {
430*4dc78e53SAndroid Build Coastguard Worker 	if (!(sk->s_flags & NL_OWN_PORT))
431*4dc78e53SAndroid Build Coastguard Worker 		release_local_port(sk->s_local.nl_pid);
432*4dc78e53SAndroid Build Coastguard Worker 	sk->s_flags |= NL_OWN_PORT;
433*4dc78e53SAndroid Build Coastguard Worker 	sk->s_local.nl_pid = port;
434*4dc78e53SAndroid Build Coastguard Worker }
435*4dc78e53SAndroid Build Coastguard Worker 
436*4dc78e53SAndroid Build Coastguard Worker /** @} */
437*4dc78e53SAndroid Build Coastguard Worker 
438*4dc78e53SAndroid Build Coastguard Worker /**
439*4dc78e53SAndroid Build Coastguard Worker  * @name Group Subscriptions
440*4dc78e53SAndroid Build Coastguard Worker  * @{
441*4dc78e53SAndroid Build Coastguard Worker  */
442*4dc78e53SAndroid Build Coastguard Worker 
443*4dc78e53SAndroid Build Coastguard Worker /**
444*4dc78e53SAndroid Build Coastguard Worker  * Join groups
445*4dc78e53SAndroid Build Coastguard Worker  * @arg sk		Netlink socket
446*4dc78e53SAndroid Build Coastguard Worker  * @arg group		Group identifier
447*4dc78e53SAndroid Build Coastguard Worker  *
448*4dc78e53SAndroid Build Coastguard Worker  * Joins the specified groups using the modern socket option which
449*4dc78e53SAndroid Build Coastguard Worker  * is available since kernel version 2.6.14. It allows joining an
450*4dc78e53SAndroid Build Coastguard Worker  * almost arbitary number of groups without limitation.  The list
451*4dc78e53SAndroid Build Coastguard Worker  * of groups has to be terminated by 0 (%NFNLGRP_NONE).
452*4dc78e53SAndroid Build Coastguard Worker  *
453*4dc78e53SAndroid Build Coastguard Worker  * Make sure to use the correct group definitions as the older
454*4dc78e53SAndroid Build Coastguard Worker  * bitmask definitions for nl_join_groups() are likely to still
455*4dc78e53SAndroid Build Coastguard Worker  * be present for backward compatibility reasons.
456*4dc78e53SAndroid Build Coastguard Worker  *
457*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success or a negative error code.
458*4dc78e53SAndroid Build Coastguard Worker  */
nl_socket_add_memberships(struct nl_sock * sk,int group,...)459*4dc78e53SAndroid Build Coastguard Worker int nl_socket_add_memberships(struct nl_sock *sk, int group, ...)
460*4dc78e53SAndroid Build Coastguard Worker {
461*4dc78e53SAndroid Build Coastguard Worker 	int err;
462*4dc78e53SAndroid Build Coastguard Worker 	va_list ap;
463*4dc78e53SAndroid Build Coastguard Worker 
464*4dc78e53SAndroid Build Coastguard Worker 	if (sk->s_fd == -1)
465*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_BAD_SOCK;
466*4dc78e53SAndroid Build Coastguard Worker 
467*4dc78e53SAndroid Build Coastguard Worker 	va_start(ap, group);
468*4dc78e53SAndroid Build Coastguard Worker 
469*4dc78e53SAndroid Build Coastguard Worker 	while (group != 0) {
470*4dc78e53SAndroid Build Coastguard Worker 		if (group < 0) {
471*4dc78e53SAndroid Build Coastguard Worker 			va_end(ap);
472*4dc78e53SAndroid Build Coastguard Worker 			return -NLE_INVAL;
473*4dc78e53SAndroid Build Coastguard Worker 		}
474*4dc78e53SAndroid Build Coastguard Worker 
475*4dc78e53SAndroid Build Coastguard Worker 		err = setsockopt(sk->s_fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP,
476*4dc78e53SAndroid Build Coastguard Worker 						 &group, sizeof(group));
477*4dc78e53SAndroid Build Coastguard Worker 		if (err < 0) {
478*4dc78e53SAndroid Build Coastguard Worker 			va_end(ap);
479*4dc78e53SAndroid Build Coastguard Worker 			NL_DBG(4, "nl_socket_add_memberships(%p): setsockopt() failed with %d (%s)\n",
480*4dc78e53SAndroid Build Coastguard Worker 				sk, errno, nl_strerror_l(errno));
481*4dc78e53SAndroid Build Coastguard Worker 			return -nl_syserr2nlerr(errno);
482*4dc78e53SAndroid Build Coastguard Worker 		}
483*4dc78e53SAndroid Build Coastguard Worker 
484*4dc78e53SAndroid Build Coastguard Worker 		group = va_arg(ap, int);
485*4dc78e53SAndroid Build Coastguard Worker 	}
486*4dc78e53SAndroid Build Coastguard Worker 
487*4dc78e53SAndroid Build Coastguard Worker 	va_end(ap);
488*4dc78e53SAndroid Build Coastguard Worker 
489*4dc78e53SAndroid Build Coastguard Worker 	return 0;
490*4dc78e53SAndroid Build Coastguard Worker }
491*4dc78e53SAndroid Build Coastguard Worker 
nl_socket_add_membership(struct nl_sock * sk,int group)492*4dc78e53SAndroid Build Coastguard Worker int nl_socket_add_membership(struct nl_sock *sk, int group)
493*4dc78e53SAndroid Build Coastguard Worker {
494*4dc78e53SAndroid Build Coastguard Worker 	return nl_socket_add_memberships(sk, group, 0);
495*4dc78e53SAndroid Build Coastguard Worker }
496*4dc78e53SAndroid Build Coastguard Worker 
497*4dc78e53SAndroid Build Coastguard Worker /**
498*4dc78e53SAndroid Build Coastguard Worker  * Leave groups
499*4dc78e53SAndroid Build Coastguard Worker  * @arg sk		Netlink socket
500*4dc78e53SAndroid Build Coastguard Worker  * @arg group		Group identifier
501*4dc78e53SAndroid Build Coastguard Worker  *
502*4dc78e53SAndroid Build Coastguard Worker  * Leaves the specified groups using the modern socket option
503*4dc78e53SAndroid Build Coastguard Worker  * which is available since kernel version 2.6.14. The list of groups
504*4dc78e53SAndroid Build Coastguard Worker  * has to terminated by 0 (%NFNLGRP_NONE).
505*4dc78e53SAndroid Build Coastguard Worker  *
506*4dc78e53SAndroid Build Coastguard Worker  * @see nl_socket_add_membership
507*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success or a negative error code.
508*4dc78e53SAndroid Build Coastguard Worker  */
nl_socket_drop_memberships(struct nl_sock * sk,int group,...)509*4dc78e53SAndroid Build Coastguard Worker int nl_socket_drop_memberships(struct nl_sock *sk, int group, ...)
510*4dc78e53SAndroid Build Coastguard Worker {
511*4dc78e53SAndroid Build Coastguard Worker 	int err;
512*4dc78e53SAndroid Build Coastguard Worker 	va_list ap;
513*4dc78e53SAndroid Build Coastguard Worker 
514*4dc78e53SAndroid Build Coastguard Worker 	if (sk->s_fd == -1)
515*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_BAD_SOCK;
516*4dc78e53SAndroid Build Coastguard Worker 
517*4dc78e53SAndroid Build Coastguard Worker 	va_start(ap, group);
518*4dc78e53SAndroid Build Coastguard Worker 
519*4dc78e53SAndroid Build Coastguard Worker 	while (group != 0) {
520*4dc78e53SAndroid Build Coastguard Worker 		if (group < 0) {
521*4dc78e53SAndroid Build Coastguard Worker 			va_end(ap);
522*4dc78e53SAndroid Build Coastguard Worker 			return -NLE_INVAL;
523*4dc78e53SAndroid Build Coastguard Worker 		}
524*4dc78e53SAndroid Build Coastguard Worker 
525*4dc78e53SAndroid Build Coastguard Worker 		err = setsockopt(sk->s_fd, SOL_NETLINK, NETLINK_DROP_MEMBERSHIP,
526*4dc78e53SAndroid Build Coastguard Worker 						 &group, sizeof(group));
527*4dc78e53SAndroid Build Coastguard Worker 		if (err < 0) {
528*4dc78e53SAndroid Build Coastguard Worker 			va_end(ap);
529*4dc78e53SAndroid Build Coastguard Worker 			NL_DBG(4, "nl_socket_drop_memberships(%p): setsockopt() failed with %d (%s)\n",
530*4dc78e53SAndroid Build Coastguard Worker 				sk, errno, nl_strerror_l(errno));
531*4dc78e53SAndroid Build Coastguard Worker 			return -nl_syserr2nlerr(errno);
532*4dc78e53SAndroid Build Coastguard Worker 		}
533*4dc78e53SAndroid Build Coastguard Worker 
534*4dc78e53SAndroid Build Coastguard Worker 		group = va_arg(ap, int);
535*4dc78e53SAndroid Build Coastguard Worker 	}
536*4dc78e53SAndroid Build Coastguard Worker 
537*4dc78e53SAndroid Build Coastguard Worker 	va_end(ap);
538*4dc78e53SAndroid Build Coastguard Worker 
539*4dc78e53SAndroid Build Coastguard Worker 	return 0;
540*4dc78e53SAndroid Build Coastguard Worker }
541*4dc78e53SAndroid Build Coastguard Worker 
nl_socket_drop_membership(struct nl_sock * sk,int group)542*4dc78e53SAndroid Build Coastguard Worker int nl_socket_drop_membership(struct nl_sock *sk, int group)
543*4dc78e53SAndroid Build Coastguard Worker {
544*4dc78e53SAndroid Build Coastguard Worker 	return nl_socket_drop_memberships(sk, group, 0);
545*4dc78e53SAndroid Build Coastguard Worker }
546*4dc78e53SAndroid Build Coastguard Worker 
547*4dc78e53SAndroid Build Coastguard Worker 
548*4dc78e53SAndroid Build Coastguard Worker /**
549*4dc78e53SAndroid Build Coastguard Worker  * Join multicast groups (deprecated)
550*4dc78e53SAndroid Build Coastguard Worker  * @arg sk		Netlink socket.
551*4dc78e53SAndroid Build Coastguard Worker  * @arg groups		Bitmask of groups to join.
552*4dc78e53SAndroid Build Coastguard Worker  *
553*4dc78e53SAndroid Build Coastguard Worker  * This function defines the old way of joining multicast group which
554*4dc78e53SAndroid Build Coastguard Worker  * has to be done prior to calling nl_connect(). It works on any kernel
555*4dc78e53SAndroid Build Coastguard Worker  * version but is very limited as only 32 groups can be joined.
556*4dc78e53SAndroid Build Coastguard Worker  */
nl_join_groups(struct nl_sock * sk,int groups)557*4dc78e53SAndroid Build Coastguard Worker void nl_join_groups(struct nl_sock *sk, int groups)
558*4dc78e53SAndroid Build Coastguard Worker {
559*4dc78e53SAndroid Build Coastguard Worker 	sk->s_local.nl_groups |= groups;
560*4dc78e53SAndroid Build Coastguard Worker }
561*4dc78e53SAndroid Build Coastguard Worker 
562*4dc78e53SAndroid Build Coastguard Worker 
563*4dc78e53SAndroid Build Coastguard Worker /** @} */
564*4dc78e53SAndroid Build Coastguard Worker 
565*4dc78e53SAndroid Build Coastguard Worker /**
566*4dc78e53SAndroid Build Coastguard Worker  * @name Peer Identfication
567*4dc78e53SAndroid Build Coastguard Worker  * @{
568*4dc78e53SAndroid Build Coastguard Worker  */
569*4dc78e53SAndroid Build Coastguard Worker 
nl_socket_get_peer_port(const struct nl_sock * sk)570*4dc78e53SAndroid Build Coastguard Worker uint32_t nl_socket_get_peer_port(const struct nl_sock *sk)
571*4dc78e53SAndroid Build Coastguard Worker {
572*4dc78e53SAndroid Build Coastguard Worker 	return sk->s_peer.nl_pid;
573*4dc78e53SAndroid Build Coastguard Worker }
574*4dc78e53SAndroid Build Coastguard Worker 
nl_socket_set_peer_port(struct nl_sock * sk,uint32_t port)575*4dc78e53SAndroid Build Coastguard Worker void nl_socket_set_peer_port(struct nl_sock *sk, uint32_t port)
576*4dc78e53SAndroid Build Coastguard Worker {
577*4dc78e53SAndroid Build Coastguard Worker 	sk->s_peer.nl_pid = port;
578*4dc78e53SAndroid Build Coastguard Worker }
579*4dc78e53SAndroid Build Coastguard Worker 
nl_socket_get_peer_groups(const struct nl_sock * sk)580*4dc78e53SAndroid Build Coastguard Worker uint32_t nl_socket_get_peer_groups(const struct nl_sock *sk)
581*4dc78e53SAndroid Build Coastguard Worker {
582*4dc78e53SAndroid Build Coastguard Worker 	return sk->s_peer.nl_groups;
583*4dc78e53SAndroid Build Coastguard Worker }
584*4dc78e53SAndroid Build Coastguard Worker 
nl_socket_set_peer_groups(struct nl_sock * sk,uint32_t groups)585*4dc78e53SAndroid Build Coastguard Worker void nl_socket_set_peer_groups(struct nl_sock *sk, uint32_t groups)
586*4dc78e53SAndroid Build Coastguard Worker {
587*4dc78e53SAndroid Build Coastguard Worker 	sk->s_peer.nl_groups = groups;
588*4dc78e53SAndroid Build Coastguard Worker }
589*4dc78e53SAndroid Build Coastguard Worker 
590*4dc78e53SAndroid Build Coastguard Worker 
591*4dc78e53SAndroid Build Coastguard Worker 
592*4dc78e53SAndroid Build Coastguard Worker /** @} */
593*4dc78e53SAndroid Build Coastguard Worker 
594*4dc78e53SAndroid Build Coastguard Worker /**
595*4dc78e53SAndroid Build Coastguard Worker  * @name File Descriptor
596*4dc78e53SAndroid Build Coastguard Worker  * @{
597*4dc78e53SAndroid Build Coastguard Worker  */
598*4dc78e53SAndroid Build Coastguard Worker 
599*4dc78e53SAndroid Build Coastguard Worker /**
600*4dc78e53SAndroid Build Coastguard Worker  * Return the file descriptor of the backing socket
601*4dc78e53SAndroid Build Coastguard Worker  * @arg sk		Netlink socket
602*4dc78e53SAndroid Build Coastguard Worker  *
603*4dc78e53SAndroid Build Coastguard Worker  * Only valid after calling nl_connect() to create and bind the respective
604*4dc78e53SAndroid Build Coastguard Worker  * socket.
605*4dc78e53SAndroid Build Coastguard Worker  *
606*4dc78e53SAndroid Build Coastguard Worker  * @return File descriptor or -1 if not available.
607*4dc78e53SAndroid Build Coastguard Worker  */
nl_socket_get_fd(const struct nl_sock * sk)608*4dc78e53SAndroid Build Coastguard Worker int nl_socket_get_fd(const struct nl_sock *sk)
609*4dc78e53SAndroid Build Coastguard Worker {
610*4dc78e53SAndroid Build Coastguard Worker 	return sk->s_fd;
611*4dc78e53SAndroid Build Coastguard Worker }
612*4dc78e53SAndroid Build Coastguard Worker 
613*4dc78e53SAndroid Build Coastguard Worker /**
614*4dc78e53SAndroid Build Coastguard Worker  * Set the socket file descriptor externally which initializes the
615*4dc78e53SAndroid Build Coastguard Worker  * socket similar to nl_connect().
616*4dc78e53SAndroid Build Coastguard Worker  *
617*4dc78e53SAndroid Build Coastguard Worker  * @arg sk         Netlink socket (required)
618*4dc78e53SAndroid Build Coastguard Worker  * @arg protocol   The socket protocol (optional). Linux 2.6.32 supports
619*4dc78e53SAndroid Build Coastguard Worker  *                 the socket option SO_PROTOCOL. In this case, you can set
620*4dc78e53SAndroid Build Coastguard Worker  *                 protocol to a negative value and let it autodetect.
621*4dc78e53SAndroid Build Coastguard Worker  *                 If you set it to a non-negative value, the detected protocol
622*4dc78e53SAndroid Build Coastguard Worker  *                 must match the one provided.
623*4dc78e53SAndroid Build Coastguard Worker  *                 To support older kernels, you must specify the protocol.
624*4dc78e53SAndroid Build Coastguard Worker  * @arg fd         Socket file descriptor to use (required)
625*4dc78e53SAndroid Build Coastguard Worker  *
626*4dc78e53SAndroid Build Coastguard Worker  * Set the socket file descriptor. @fd must be valid and bind'ed.
627*4dc78e53SAndroid Build Coastguard Worker  *
628*4dc78e53SAndroid Build Coastguard Worker  * This is an alternative to nl_connect(). nl_connect() creates, binds and
629*4dc78e53SAndroid Build Coastguard Worker  * sets the socket. With this function you can set the socket to an externally
630*4dc78e53SAndroid Build Coastguard Worker  * created file descriptor.
631*4dc78e53SAndroid Build Coastguard Worker  *
632*4dc78e53SAndroid Build Coastguard Worker  * @see nl_connect()
633*4dc78e53SAndroid Build Coastguard Worker  *
634*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success or a negative error code. On error, @fd is not closed but
635*4dc78e53SAndroid Build Coastguard Worker  * possibly unusable.
636*4dc78e53SAndroid Build Coastguard Worker  *
637*4dc78e53SAndroid Build Coastguard Worker  * @retval -NLE_BAD_SOCK Netlink socket is already connected
638*4dc78e53SAndroid Build Coastguard Worker  * @retval -NLE_INVAL Socket is of unexpected type
639*4dc78e53SAndroid Build Coastguard Worker  */
nl_socket_set_fd(struct nl_sock * sk,int protocol,int fd)640*4dc78e53SAndroid Build Coastguard Worker int nl_socket_set_fd(struct nl_sock *sk, int protocol, int fd)
641*4dc78e53SAndroid Build Coastguard Worker {
642*4dc78e53SAndroid Build Coastguard Worker 	int err = 0;
643*4dc78e53SAndroid Build Coastguard Worker 	socklen_t addrlen;
644*4dc78e53SAndroid Build Coastguard Worker 	struct sockaddr_nl local = { 0 };
645*4dc78e53SAndroid Build Coastguard Worker 	int so_type = -1, so_protocol = -1;
646*4dc78e53SAndroid Build Coastguard Worker 
647*4dc78e53SAndroid Build Coastguard Worker 	if (sk->s_fd != -1)
648*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_BAD_SOCK;
649*4dc78e53SAndroid Build Coastguard Worker 	if (fd < 0)
650*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_INVAL;
651*4dc78e53SAndroid Build Coastguard Worker 
652*4dc78e53SAndroid Build Coastguard Worker 	addrlen = sizeof(local);
653*4dc78e53SAndroid Build Coastguard Worker 	err = getsockname(fd, (struct sockaddr *) &local,
654*4dc78e53SAndroid Build Coastguard Worker 	                  &addrlen);
655*4dc78e53SAndroid Build Coastguard Worker 	if (err < 0) {
656*4dc78e53SAndroid Build Coastguard Worker 		NL_DBG(4, "nl_socket_set_fd(%p,%d): getsockname() failed with %d (%s)\n",
657*4dc78e53SAndroid Build Coastguard Worker 		       sk, fd, errno, nl_strerror_l(errno));
658*4dc78e53SAndroid Build Coastguard Worker 		return -nl_syserr2nlerr(errno);
659*4dc78e53SAndroid Build Coastguard Worker 	}
660*4dc78e53SAndroid Build Coastguard Worker 	if (addrlen != sizeof(local))
661*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_INVAL;
662*4dc78e53SAndroid Build Coastguard Worker 	if (local.nl_family != AF_NETLINK) {
663*4dc78e53SAndroid Build Coastguard Worker 		NL_DBG(4, "nl_socket_set_fd(%p,%d): getsockname() returned family %d instead of %d (AF_NETLINK)\n",
664*4dc78e53SAndroid Build Coastguard Worker 		       sk, fd, local.nl_family, AF_NETLINK);
665*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_INVAL;
666*4dc78e53SAndroid Build Coastguard Worker 	}
667*4dc78e53SAndroid Build Coastguard Worker 
668*4dc78e53SAndroid Build Coastguard Worker 	addrlen = sizeof(so_type);
669*4dc78e53SAndroid Build Coastguard Worker 	err = getsockopt(fd, SOL_SOCKET, SO_TYPE, &so_type, &addrlen);
670*4dc78e53SAndroid Build Coastguard Worker 	if (err < 0) {
671*4dc78e53SAndroid Build Coastguard Worker 		NL_DBG(4, "nl_socket_set_fd(%p,%d): getsockopt() for SO_TYPE failed with %d (%s)\n",
672*4dc78e53SAndroid Build Coastguard Worker 		       sk, fd, errno, nl_strerror_l(errno));
673*4dc78e53SAndroid Build Coastguard Worker 		return -nl_syserr2nlerr(errno);
674*4dc78e53SAndroid Build Coastguard Worker 	}
675*4dc78e53SAndroid Build Coastguard Worker 	if (addrlen != sizeof(so_type))
676*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_INVAL;
677*4dc78e53SAndroid Build Coastguard Worker 	if (so_type != SOCK_RAW) {
678*4dc78e53SAndroid Build Coastguard Worker 		NL_DBG(4, "nl_socket_set_fd(%p,%d): getsockopt() returned SO_TYPE %d instead of %d (SOCK_RAW)\n",
679*4dc78e53SAndroid Build Coastguard Worker 		       sk, fd, so_type, SOCK_RAW);
680*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_INVAL;
681*4dc78e53SAndroid Build Coastguard Worker 	}
682*4dc78e53SAndroid Build Coastguard Worker 
683*4dc78e53SAndroid Build Coastguard Worker #if SO_PROTOCOL
684*4dc78e53SAndroid Build Coastguard Worker 	addrlen = sizeof(so_protocol);
685*4dc78e53SAndroid Build Coastguard Worker 	err = getsockopt(fd, SOL_SOCKET, SO_PROTOCOL, &so_protocol, &addrlen);
686*4dc78e53SAndroid Build Coastguard Worker 	if (err < 0) {
687*4dc78e53SAndroid Build Coastguard Worker 		if (errno == ENOPROTOOPT)
688*4dc78e53SAndroid Build Coastguard Worker 			goto no_so_protocol;
689*4dc78e53SAndroid Build Coastguard Worker 		NL_DBG(4, "nl_socket_set_fd(%p,%d): getsockopt() for SO_PROTOCOL failed with %d (%s)\n",
690*4dc78e53SAndroid Build Coastguard Worker 		       sk, fd, errno, nl_strerror_l(errno));
691*4dc78e53SAndroid Build Coastguard Worker 		return -nl_syserr2nlerr(errno);
692*4dc78e53SAndroid Build Coastguard Worker 	}
693*4dc78e53SAndroid Build Coastguard Worker 	if (addrlen != sizeof(so_protocol))
694*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_INVAL;
695*4dc78e53SAndroid Build Coastguard Worker 	if (protocol >= 0 && protocol != so_protocol) {
696*4dc78e53SAndroid Build Coastguard Worker 		NL_DBG(4, "nl_socket_set_fd(%p,%d): getsockopt() for SO_PROTOCOL returned %d instead of %d\n",
697*4dc78e53SAndroid Build Coastguard Worker 		       sk, fd, so_protocol, protocol);
698*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_INVAL;
699*4dc78e53SAndroid Build Coastguard Worker 	}
700*4dc78e53SAndroid Build Coastguard Worker 
701*4dc78e53SAndroid Build Coastguard Worker 	if (0)
702*4dc78e53SAndroid Build Coastguard Worker #endif
703*4dc78e53SAndroid Build Coastguard Worker 	{
704*4dc78e53SAndroid Build Coastguard Worker no_so_protocol:
705*4dc78e53SAndroid Build Coastguard Worker 		if (protocol < 0) {
706*4dc78e53SAndroid Build Coastguard Worker 			NL_DBG(4, "nl_socket_set_fd(%p,%d): unknown protocol and unable to detect it via SO_PROTOCOL socket option\n",
707*4dc78e53SAndroid Build Coastguard Worker 			       sk, fd);
708*4dc78e53SAndroid Build Coastguard Worker 			return -NLE_INVAL;
709*4dc78e53SAndroid Build Coastguard Worker 		}
710*4dc78e53SAndroid Build Coastguard Worker 		so_protocol = protocol;
711*4dc78e53SAndroid Build Coastguard Worker 	}
712*4dc78e53SAndroid Build Coastguard Worker 
713*4dc78e53SAndroid Build Coastguard Worker 	nl_socket_set_local_port (sk, local.nl_pid);
714*4dc78e53SAndroid Build Coastguard Worker 	sk->s_local = local;
715*4dc78e53SAndroid Build Coastguard Worker 	sk->s_fd = fd;
716*4dc78e53SAndroid Build Coastguard Worker 	sk->s_proto = so_protocol;
717*4dc78e53SAndroid Build Coastguard Worker 
718*4dc78e53SAndroid Build Coastguard Worker 	return 0;
719*4dc78e53SAndroid Build Coastguard Worker }
720*4dc78e53SAndroid Build Coastguard Worker 
721*4dc78e53SAndroid Build Coastguard Worker /**
722*4dc78e53SAndroid Build Coastguard Worker  * Set file descriptor of socket to non-blocking state
723*4dc78e53SAndroid Build Coastguard Worker  * @arg sk		Netlink socket.
724*4dc78e53SAndroid Build Coastguard Worker  *
725*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success or a negative error code.
726*4dc78e53SAndroid Build Coastguard Worker  */
nl_socket_set_nonblocking(const struct nl_sock * sk)727*4dc78e53SAndroid Build Coastguard Worker int nl_socket_set_nonblocking(const struct nl_sock *sk)
728*4dc78e53SAndroid Build Coastguard Worker {
729*4dc78e53SAndroid Build Coastguard Worker 	if (sk->s_fd == -1)
730*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_BAD_SOCK;
731*4dc78e53SAndroid Build Coastguard Worker 
732*4dc78e53SAndroid Build Coastguard Worker 	if (fcntl(sk->s_fd, F_SETFL, O_NONBLOCK) < 0) {
733*4dc78e53SAndroid Build Coastguard Worker 		NL_DBG(4, "nl_socket_set_nonblocking(%p): fcntl() failed with %d (%s)\n",
734*4dc78e53SAndroid Build Coastguard Worker 			sk, errno, nl_strerror_l(errno));
735*4dc78e53SAndroid Build Coastguard Worker 		return -nl_syserr2nlerr(errno);
736*4dc78e53SAndroid Build Coastguard Worker 	}
737*4dc78e53SAndroid Build Coastguard Worker 
738*4dc78e53SAndroid Build Coastguard Worker 	return 0;
739*4dc78e53SAndroid Build Coastguard Worker }
740*4dc78e53SAndroid Build Coastguard Worker 
741*4dc78e53SAndroid Build Coastguard Worker /**
742*4dc78e53SAndroid Build Coastguard Worker  * Enable use of MSG_PEEK when reading from socket
743*4dc78e53SAndroid Build Coastguard Worker  * @arg sk		Netlink socket.
744*4dc78e53SAndroid Build Coastguard Worker  *
745*4dc78e53SAndroid Build Coastguard Worker  * See also NL_CAPABILITY_NL_RECVMSGS_PEEK_BY_DEFAULT capability
746*4dc78e53SAndroid Build Coastguard Worker  */
nl_socket_enable_msg_peek(struct nl_sock * sk)747*4dc78e53SAndroid Build Coastguard Worker void nl_socket_enable_msg_peek(struct nl_sock *sk)
748*4dc78e53SAndroid Build Coastguard Worker {
749*4dc78e53SAndroid Build Coastguard Worker 	sk->s_flags |= (NL_MSG_PEEK | NL_MSG_PEEK_EXPLICIT);
750*4dc78e53SAndroid Build Coastguard Worker }
751*4dc78e53SAndroid Build Coastguard Worker 
752*4dc78e53SAndroid Build Coastguard Worker /**
753*4dc78e53SAndroid Build Coastguard Worker  * Disable use of MSG_PEEK when reading from socket
754*4dc78e53SAndroid Build Coastguard Worker  * @arg sk		Netlink socket.
755*4dc78e53SAndroid Build Coastguard Worker  *
756*4dc78e53SAndroid Build Coastguard Worker  * See also NL_CAPABILITY_NL_RECVMSGS_PEEK_BY_DEFAULT capability
757*4dc78e53SAndroid Build Coastguard Worker  */
nl_socket_disable_msg_peek(struct nl_sock * sk)758*4dc78e53SAndroid Build Coastguard Worker void nl_socket_disable_msg_peek(struct nl_sock *sk)
759*4dc78e53SAndroid Build Coastguard Worker {
760*4dc78e53SAndroid Build Coastguard Worker 	sk->s_flags |= NL_MSG_PEEK_EXPLICIT;
761*4dc78e53SAndroid Build Coastguard Worker 	sk->s_flags &= ~NL_MSG_PEEK;
762*4dc78e53SAndroid Build Coastguard Worker }
763*4dc78e53SAndroid Build Coastguard Worker 
764*4dc78e53SAndroid Build Coastguard Worker /** @} */
765*4dc78e53SAndroid Build Coastguard Worker 
766*4dc78e53SAndroid Build Coastguard Worker /**
767*4dc78e53SAndroid Build Coastguard Worker  * @name Callback Handler
768*4dc78e53SAndroid Build Coastguard Worker  * @{
769*4dc78e53SAndroid Build Coastguard Worker  */
770*4dc78e53SAndroid Build Coastguard Worker 
nl_socket_get_cb(const struct nl_sock * sk)771*4dc78e53SAndroid Build Coastguard Worker struct nl_cb *nl_socket_get_cb(const struct nl_sock *sk)
772*4dc78e53SAndroid Build Coastguard Worker {
773*4dc78e53SAndroid Build Coastguard Worker 	return nl_cb_get(sk->s_cb);
774*4dc78e53SAndroid Build Coastguard Worker }
775*4dc78e53SAndroid Build Coastguard Worker 
nl_socket_set_cb(struct nl_sock * sk,struct nl_cb * cb)776*4dc78e53SAndroid Build Coastguard Worker void nl_socket_set_cb(struct nl_sock *sk, struct nl_cb *cb)
777*4dc78e53SAndroid Build Coastguard Worker {
778*4dc78e53SAndroid Build Coastguard Worker 	if (cb == NULL)
779*4dc78e53SAndroid Build Coastguard Worker 		BUG();
780*4dc78e53SAndroid Build Coastguard Worker 
781*4dc78e53SAndroid Build Coastguard Worker 	nl_cb_put(sk->s_cb);
782*4dc78e53SAndroid Build Coastguard Worker 	sk->s_cb = nl_cb_get(cb);
783*4dc78e53SAndroid Build Coastguard Worker }
784*4dc78e53SAndroid Build Coastguard Worker 
785*4dc78e53SAndroid Build Coastguard Worker /**
786*4dc78e53SAndroid Build Coastguard Worker  * Modify the callback handler associated with the socket
787*4dc78e53SAndroid Build Coastguard Worker  * @arg sk		Netlink socket.
788*4dc78e53SAndroid Build Coastguard Worker  * @arg type		which type callback to set
789*4dc78e53SAndroid Build Coastguard Worker  * @arg kind		kind of callback
790*4dc78e53SAndroid Build Coastguard Worker  * @arg func		callback function
791*4dc78e53SAndroid Build Coastguard Worker  * @arg arg		argument to be passed to callback function
792*4dc78e53SAndroid Build Coastguard Worker  *
793*4dc78e53SAndroid Build Coastguard Worker  * @see nl_cb_set
794*4dc78e53SAndroid Build Coastguard Worker  */
nl_socket_modify_cb(struct nl_sock * sk,enum nl_cb_type type,enum nl_cb_kind kind,nl_recvmsg_msg_cb_t func,void * arg)795*4dc78e53SAndroid Build Coastguard Worker int nl_socket_modify_cb(struct nl_sock *sk, enum nl_cb_type type,
796*4dc78e53SAndroid Build Coastguard Worker 			enum nl_cb_kind kind, nl_recvmsg_msg_cb_t func,
797*4dc78e53SAndroid Build Coastguard Worker 			void *arg)
798*4dc78e53SAndroid Build Coastguard Worker {
799*4dc78e53SAndroid Build Coastguard Worker 	return nl_cb_set(sk->s_cb, type, kind, func, arg);
800*4dc78e53SAndroid Build Coastguard Worker }
801*4dc78e53SAndroid Build Coastguard Worker 
802*4dc78e53SAndroid Build Coastguard Worker /**
803*4dc78e53SAndroid Build Coastguard Worker  * Modify the error callback handler associated with the socket
804*4dc78e53SAndroid Build Coastguard Worker  * @arg sk		Netlink socket.
805*4dc78e53SAndroid Build Coastguard Worker  * @arg kind		kind of callback
806*4dc78e53SAndroid Build Coastguard Worker  * @arg func		callback function
807*4dc78e53SAndroid Build Coastguard Worker  * @arg arg		argument to be passed to callback function
808*4dc78e53SAndroid Build Coastguard Worker  *
809*4dc78e53SAndroid Build Coastguard Worker  * @see nl_cb_err
810*4dc78e53SAndroid Build Coastguard Worker  */
nl_socket_modify_err_cb(struct nl_sock * sk,enum nl_cb_kind kind,nl_recvmsg_err_cb_t func,void * arg)811*4dc78e53SAndroid Build Coastguard Worker int nl_socket_modify_err_cb(struct nl_sock *sk, enum nl_cb_kind kind,
812*4dc78e53SAndroid Build Coastguard Worker 			    nl_recvmsg_err_cb_t func, void *arg)
813*4dc78e53SAndroid Build Coastguard Worker {
814*4dc78e53SAndroid Build Coastguard Worker 	return nl_cb_err(sk->s_cb, kind, func, arg);
815*4dc78e53SAndroid Build Coastguard Worker }
816*4dc78e53SAndroid Build Coastguard Worker 
817*4dc78e53SAndroid Build Coastguard Worker /** @} */
818*4dc78e53SAndroid Build Coastguard Worker 
819*4dc78e53SAndroid Build Coastguard Worker /**
820*4dc78e53SAndroid Build Coastguard Worker  * @name Utilities
821*4dc78e53SAndroid Build Coastguard Worker  * @{
822*4dc78e53SAndroid Build Coastguard Worker  */
823*4dc78e53SAndroid Build Coastguard Worker 
824*4dc78e53SAndroid Build Coastguard Worker /**
825*4dc78e53SAndroid Build Coastguard Worker  * Set socket buffer size of netlink socket.
826*4dc78e53SAndroid Build Coastguard Worker  * @arg sk		Netlink socket.
827*4dc78e53SAndroid Build Coastguard Worker  * @arg rxbuf		New receive socket buffer size in bytes.
828*4dc78e53SAndroid Build Coastguard Worker  * @arg txbuf		New transmit socket buffer size in bytes.
829*4dc78e53SAndroid Build Coastguard Worker  *
830*4dc78e53SAndroid Build Coastguard Worker  * Sets the socket buffer size of a netlink socket to the specified
831*4dc78e53SAndroid Build Coastguard Worker  * values \c rxbuf and \c txbuf. Providing a value of \c 0 assumes a
832*4dc78e53SAndroid Build Coastguard Worker  * good default value.
833*4dc78e53SAndroid Build Coastguard Worker  *
834*4dc78e53SAndroid Build Coastguard Worker  * @note It is not required to call this function prior to nl_connect().
835*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success or a negative error code.
836*4dc78e53SAndroid Build Coastguard Worker  */
nl_socket_set_buffer_size(struct nl_sock * sk,int rxbuf,int txbuf)837*4dc78e53SAndroid Build Coastguard Worker int nl_socket_set_buffer_size(struct nl_sock *sk, int rxbuf, int txbuf)
838*4dc78e53SAndroid Build Coastguard Worker {
839*4dc78e53SAndroid Build Coastguard Worker 	int err;
840*4dc78e53SAndroid Build Coastguard Worker 
841*4dc78e53SAndroid Build Coastguard Worker 	if (rxbuf <= 0)
842*4dc78e53SAndroid Build Coastguard Worker 		rxbuf = 32768;
843*4dc78e53SAndroid Build Coastguard Worker 
844*4dc78e53SAndroid Build Coastguard Worker 	if (txbuf <= 0)
845*4dc78e53SAndroid Build Coastguard Worker 		txbuf = 32768;
846*4dc78e53SAndroid Build Coastguard Worker 
847*4dc78e53SAndroid Build Coastguard Worker 	if (sk->s_fd == -1)
848*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_BAD_SOCK;
849*4dc78e53SAndroid Build Coastguard Worker 
850*4dc78e53SAndroid Build Coastguard Worker 	err = setsockopt(sk->s_fd, SOL_SOCKET, SO_SNDBUF,
851*4dc78e53SAndroid Build Coastguard Worker 			 &txbuf, sizeof(txbuf));
852*4dc78e53SAndroid Build Coastguard Worker 	if (err < 0) {
853*4dc78e53SAndroid Build Coastguard Worker 		NL_DBG(4, "nl_socket_set_buffer_size(%p): setsockopt() failed with %d (%s)\n",
854*4dc78e53SAndroid Build Coastguard Worker 			sk, errno, nl_strerror_l(errno));
855*4dc78e53SAndroid Build Coastguard Worker 		return -nl_syserr2nlerr(errno);
856*4dc78e53SAndroid Build Coastguard Worker 	}
857*4dc78e53SAndroid Build Coastguard Worker 
858*4dc78e53SAndroid Build Coastguard Worker 	err = setsockopt(sk->s_fd, SOL_SOCKET, SO_RCVBUF,
859*4dc78e53SAndroid Build Coastguard Worker 			 &rxbuf, sizeof(rxbuf));
860*4dc78e53SAndroid Build Coastguard Worker 	if (err < 0) {
861*4dc78e53SAndroid Build Coastguard Worker 		NL_DBG(4, "nl_socket_set_buffer_size(%p): setsockopt() failed with %d (%s)\n",
862*4dc78e53SAndroid Build Coastguard Worker 			sk, errno, nl_strerror_l(errno));
863*4dc78e53SAndroid Build Coastguard Worker 		return -nl_syserr2nlerr(errno);
864*4dc78e53SAndroid Build Coastguard Worker 	}
865*4dc78e53SAndroid Build Coastguard Worker 
866*4dc78e53SAndroid Build Coastguard Worker 	return 0;
867*4dc78e53SAndroid Build Coastguard Worker }
868*4dc78e53SAndroid Build Coastguard Worker 
869*4dc78e53SAndroid Build Coastguard Worker /**
870*4dc78e53SAndroid Build Coastguard Worker  * Set default message buffer size of netlink socket.
871*4dc78e53SAndroid Build Coastguard Worker  * @arg sk		Netlink socket.
872*4dc78e53SAndroid Build Coastguard Worker  * @arg bufsize		Default message buffer size in bytes.
873*4dc78e53SAndroid Build Coastguard Worker  *
874*4dc78e53SAndroid Build Coastguard Worker  * Sets the default message buffer size to the specified length in bytes.
875*4dc78e53SAndroid Build Coastguard Worker  * The default message buffer size limits the maximum message size the
876*4dc78e53SAndroid Build Coastguard Worker  * socket will be able to receive. It is generally recommneded to specify
877*4dc78e53SAndroid Build Coastguard Worker  * a buffer size no less than the size of a memory page.
878*4dc78e53SAndroid Build Coastguard Worker  *
879*4dc78e53SAndroid Build Coastguard Worker  * Setting the @bufsize to zero means to use a default of 4 times getpagesize().
880*4dc78e53SAndroid Build Coastguard Worker  *
881*4dc78e53SAndroid Build Coastguard Worker  * When MSG_PEEK is enabled, the buffer size is used for the initial choice
882*4dc78e53SAndroid Build Coastguard Worker  * of the buffer while peeking. It still makes sense to choose an optimal value
883*4dc78e53SAndroid Build Coastguard Worker  * to avoid realloc().
884*4dc78e53SAndroid Build Coastguard Worker  *
885*4dc78e53SAndroid Build Coastguard Worker  * When MSG_PEEK is disabled, the buffer size is important because a too small
886*4dc78e53SAndroid Build Coastguard Worker  * size will lead to failure of receiving the message via nl_recvmsgs().
887*4dc78e53SAndroid Build Coastguard Worker  *
888*4dc78e53SAndroid Build Coastguard Worker  * By default, MSG_PEEK is enabled unless the user calls either nl_socket_disable_msg_peek()/
889*4dc78e53SAndroid Build Coastguard Worker  * nl_socket_enable_msg_peek() or sets the message buffer size to a positive value.
890*4dc78e53SAndroid Build Coastguard Worker  * See capability NL_CAPABILITY_NL_RECVMSGS_PEEK_BY_DEFAULT for that.
891*4dc78e53SAndroid Build Coastguard Worker  *
892*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success or a negative error code.
893*4dc78e53SAndroid Build Coastguard Worker  */
nl_socket_set_msg_buf_size(struct nl_sock * sk,size_t bufsize)894*4dc78e53SAndroid Build Coastguard Worker int nl_socket_set_msg_buf_size(struct nl_sock *sk, size_t bufsize)
895*4dc78e53SAndroid Build Coastguard Worker {
896*4dc78e53SAndroid Build Coastguard Worker 	sk->s_bufsize = bufsize;
897*4dc78e53SAndroid Build Coastguard Worker 
898*4dc78e53SAndroid Build Coastguard Worker 	return 0;
899*4dc78e53SAndroid Build Coastguard Worker }
900*4dc78e53SAndroid Build Coastguard Worker 
901*4dc78e53SAndroid Build Coastguard Worker /**
902*4dc78e53SAndroid Build Coastguard Worker  * Get default message buffer size of netlink socket.
903*4dc78e53SAndroid Build Coastguard Worker  * @arg sk		Netlink socket.
904*4dc78e53SAndroid Build Coastguard Worker  *
905*4dc78e53SAndroid Build Coastguard Worker  * @return Size of default message buffer.
906*4dc78e53SAndroid Build Coastguard Worker  */
nl_socket_get_msg_buf_size(struct nl_sock * sk)907*4dc78e53SAndroid Build Coastguard Worker size_t nl_socket_get_msg_buf_size(struct nl_sock *sk)
908*4dc78e53SAndroid Build Coastguard Worker {
909*4dc78e53SAndroid Build Coastguard Worker 	return sk->s_bufsize;
910*4dc78e53SAndroid Build Coastguard Worker }
911*4dc78e53SAndroid Build Coastguard Worker 
912*4dc78e53SAndroid Build Coastguard Worker /**
913*4dc78e53SAndroid Build Coastguard Worker  * Enable/disable credential passing on netlink socket.
914*4dc78e53SAndroid Build Coastguard Worker  * @arg sk		Netlink socket.
915*4dc78e53SAndroid Build Coastguard Worker  * @arg state		New state (0 - disabled, 1 - enabled)
916*4dc78e53SAndroid Build Coastguard Worker  *
917*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success or a negative error code
918*4dc78e53SAndroid Build Coastguard Worker  */
nl_socket_set_passcred(struct nl_sock * sk,int state)919*4dc78e53SAndroid Build Coastguard Worker int nl_socket_set_passcred(struct nl_sock *sk, int state)
920*4dc78e53SAndroid Build Coastguard Worker {
921*4dc78e53SAndroid Build Coastguard Worker 	int err;
922*4dc78e53SAndroid Build Coastguard Worker 
923*4dc78e53SAndroid Build Coastguard Worker 	if (sk->s_fd == -1)
924*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_BAD_SOCK;
925*4dc78e53SAndroid Build Coastguard Worker 
926*4dc78e53SAndroid Build Coastguard Worker 	err = setsockopt(sk->s_fd, SOL_SOCKET, SO_PASSCRED,
927*4dc78e53SAndroid Build Coastguard Worker 			 &state, sizeof(state));
928*4dc78e53SAndroid Build Coastguard Worker 	if (err < 0) {
929*4dc78e53SAndroid Build Coastguard Worker 		NL_DBG(4, "nl_socket_set_passcred(%p): setsockopt() failed with %d (%s)\n",
930*4dc78e53SAndroid Build Coastguard Worker 			sk, errno, nl_strerror_l(errno));
931*4dc78e53SAndroid Build Coastguard Worker 		return -nl_syserr2nlerr(errno);
932*4dc78e53SAndroid Build Coastguard Worker 	}
933*4dc78e53SAndroid Build Coastguard Worker 
934*4dc78e53SAndroid Build Coastguard Worker 	if (state)
935*4dc78e53SAndroid Build Coastguard Worker 		sk->s_flags |= NL_SOCK_PASSCRED;
936*4dc78e53SAndroid Build Coastguard Worker 	else
937*4dc78e53SAndroid Build Coastguard Worker 		sk->s_flags &= ~NL_SOCK_PASSCRED;
938*4dc78e53SAndroid Build Coastguard Worker 
939*4dc78e53SAndroid Build Coastguard Worker 	return 0;
940*4dc78e53SAndroid Build Coastguard Worker }
941*4dc78e53SAndroid Build Coastguard Worker 
942*4dc78e53SAndroid Build Coastguard Worker /**
943*4dc78e53SAndroid Build Coastguard Worker  * Enable/disable receival of additional packet information
944*4dc78e53SAndroid Build Coastguard Worker  * @arg sk		Netlink socket.
945*4dc78e53SAndroid Build Coastguard Worker  * @arg state		New state (0 - disabled, 1 - enabled)
946*4dc78e53SAndroid Build Coastguard Worker  *
947*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success or a negative error code
948*4dc78e53SAndroid Build Coastguard Worker  */
nl_socket_recv_pktinfo(struct nl_sock * sk,int state)949*4dc78e53SAndroid Build Coastguard Worker int nl_socket_recv_pktinfo(struct nl_sock *sk, int state)
950*4dc78e53SAndroid Build Coastguard Worker {
951*4dc78e53SAndroid Build Coastguard Worker 	int err;
952*4dc78e53SAndroid Build Coastguard Worker 
953*4dc78e53SAndroid Build Coastguard Worker 	if (sk->s_fd == -1)
954*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_BAD_SOCK;
955*4dc78e53SAndroid Build Coastguard Worker 
956*4dc78e53SAndroid Build Coastguard Worker 	err = setsockopt(sk->s_fd, SOL_NETLINK, NETLINK_PKTINFO,
957*4dc78e53SAndroid Build Coastguard Worker 			 &state, sizeof(state));
958*4dc78e53SAndroid Build Coastguard Worker 	if (err < 0) {
959*4dc78e53SAndroid Build Coastguard Worker 		NL_DBG(4, "nl_socket_recv_pktinfo(%p): setsockopt() failed with %d (%s)\n",
960*4dc78e53SAndroid Build Coastguard Worker 			sk, errno, nl_strerror_l(errno));
961*4dc78e53SAndroid Build Coastguard Worker 		return -nl_syserr2nlerr(errno);
962*4dc78e53SAndroid Build Coastguard Worker 	}
963*4dc78e53SAndroid Build Coastguard Worker 
964*4dc78e53SAndroid Build Coastguard Worker 	return 0;
965*4dc78e53SAndroid Build Coastguard Worker }
966*4dc78e53SAndroid Build Coastguard Worker 
967*4dc78e53SAndroid Build Coastguard Worker /** @} */
968*4dc78e53SAndroid Build Coastguard Worker 
969*4dc78e53SAndroid Build Coastguard Worker /** @} */
970