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