Fixed compile time warning by adding upstream patches
[platform/upstream/libnl2.git] / lib / socket.c
1 /*
2  * lib/socket.c         Netlink Socket
3  *
4  *      This library is free software; you can redistribute it and/or
5  *      modify it under the terms of the GNU Lesser General Public
6  *      License as published by the Free Software Foundation version 2.1
7  *      of the License.
8  *
9  * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
10  */
11
12 /**
13  * @ingroup core
14  * @defgroup socket Socket
15  * @{
16  */
17
18 #include <netlink-local.h>
19 #include <netlink/netlink.h>
20 #include <netlink/utils.h>
21 #include <netlink/handlers.h>
22 #include <netlink/msg.h>
23 #include <netlink/attr.h>
24
25 static int default_cb = NL_CB_DEFAULT;
26
27 static void __init init_default_cb(void)
28 {
29         char *nlcb;
30
31         if ((nlcb = getenv("NLCB"))) {
32                 if (!strcasecmp(nlcb, "default"))
33                         default_cb = NL_CB_DEFAULT;
34                 else if (!strcasecmp(nlcb, "verbose"))
35                         default_cb = NL_CB_VERBOSE;
36                 else if (!strcasecmp(nlcb, "debug"))
37                         default_cb = NL_CB_DEBUG;
38                 else {
39                         fprintf(stderr, "Unknown value for NLCB, valid values: "
40                                 "{default | verbose | debug}\n");
41                 }
42         }
43 }
44
45 static uint32_t used_ports_map[32];
46
47 static uint32_t generate_local_port(void)
48 {
49         int i, n;
50         uint32_t pid = getpid() & 0x3FFFFF;
51
52         for (i = 0; i < 32; i++) {
53                 if (used_ports_map[i] == 0xFFFFFFFF)
54                         continue;
55
56                 for (n = 0; n < 32; n++) {
57                         if (1UL & (used_ports_map[i] >> n))
58                                 continue;
59
60                         used_ports_map[i] |= (1UL << n);
61                         n += (i * 32);
62
63                         /* PID_MAX_LIMIT is currently at 2^22, leaving 10 bit
64                          * to, i.e. 1024 unique ports per application. */
65                         return pid + (n << 22);
66
67                 }
68         }
69
70         /* Out of sockets in our own PID namespace, what to do? FIXME */
71         return UINT_MAX;
72 }
73
74 static void release_local_port(uint32_t port)
75 {
76         int nr;
77
78         if (port == UINT_MAX)
79                 return;
80         
81         nr = port >> 22;
82         used_ports_map[nr / 32] &= ~(1 << nr % 32);
83 }
84
85 /**
86  * @name Allocation
87  * @{
88  */
89
90 static struct nl_sock *__alloc_socket(struct nl_cb *cb)
91 {
92         struct nl_sock *sk;
93
94         sk = calloc(1, sizeof(*sk));
95         if (!sk)
96                 return NULL;
97
98         sk->s_fd = -1;
99         sk->s_cb = cb;
100         sk->s_local.nl_family = AF_NETLINK;
101         sk->s_peer.nl_family = AF_NETLINK;
102         sk->s_seq_expect = sk->s_seq_next = time(0);
103         sk->s_local.nl_pid = generate_local_port();
104         if (sk->s_local.nl_pid == UINT_MAX) {
105                 nl_socket_free(sk);
106                 return NULL;
107         }
108
109         return sk;
110 }
111
112 /**
113  * Allocate new netlink socket
114  *
115  * @return Newly allocated netlink socket or NULL.
116  */
117 struct nl_sock *nl_socket_alloc(void)
118 {
119         struct nl_cb *cb;
120         
121         cb = nl_cb_alloc(default_cb);
122         if (!cb)
123                 return NULL;
124
125         return __alloc_socket(cb);
126 }
127
128 /**
129  * Allocate new socket with custom callbacks
130  * @arg cb              Callback handler
131  *
132  * The reference to the callback handler is taken into account
133  * automatically, it is released again upon calling nl_socket_free().
134  *
135  *@return Newly allocted socket handle or NULL.
136  */
137 struct nl_sock *nl_socket_alloc_cb(struct nl_cb *cb)
138 {
139         if (cb == NULL)
140                 BUG();
141
142         return __alloc_socket(nl_cb_get(cb));
143 }
144
145 /**
146  * Free a netlink socket.
147  * @arg sk              Netlink socket.
148  */
149 void nl_socket_free(struct nl_sock *sk)
150 {
151         if (!sk)
152                 return;
153
154         if (sk->s_fd >= 0)
155                 close(sk->s_fd);
156
157         if (!(sk->s_flags & NL_OWN_PORT))
158                 release_local_port(sk->s_local.nl_pid);
159
160         nl_cb_put(sk->s_cb);
161         free(sk);
162 }
163
164 /** @} */
165
166 /**
167  * @name Sequence Numbers
168  * @{
169  */
170
171 static int noop_seq_check(struct nl_msg *msg, void *arg)
172 {
173         return NL_OK;
174 }
175
176
177 /**
178  * Disable sequence number checking.
179  * @arg sk              Netlink socket.
180  *
181  * Disables checking of sequence numbers on the netlink socket This is
182  * required to allow messages to be processed which were not requested by
183  * a preceding request message, e.g. netlink events.
184  *
185  * @note This function modifies the NL_CB_SEQ_CHECK configuration in
186  * the callback handle associated with the socket.
187  */
188 void nl_socket_disable_seq_check(struct nl_sock *sk)
189 {
190         nl_cb_set(sk->s_cb, NL_CB_SEQ_CHECK,
191                   NL_CB_CUSTOM, noop_seq_check, NULL);
192 }
193
194 /**
195  * Use next sequence number
196  * @arg sk              Netlink socket.
197  *
198  * Uses the next available sequence number and increases the counter
199  * by one for subsequent calls.
200  *
201  * @return Unique serial sequence number
202  */
203 unsigned int nl_socket_use_seq(struct nl_sock *sk)
204 {
205         return sk->s_seq_next++;
206 }
207
208 /**
209  * Disable automatic request for ACK
210  * @arg sk              Netlink socket.
211  *
212  * The default behaviour of a socket is to request an ACK for
213  * each message sent to allow for the caller to synchronize to
214  * the completion of the netlink operation. This function
215  * disables this behaviour and will result in requests being
216  * sent which will not have the NLM_F_ACK flag set automatically.
217  * However, it is still possible for the caller to set the
218  * NLM_F_ACK flag explicitely.
219  */
220 void nl_socket_disable_auto_ack(struct nl_sock *sk)
221 {
222         sk->s_flags |= NL_NO_AUTO_ACK;
223 }
224
225 /**
226  * Enable automatic request for ACK (default)
227  * @arg sk              Netlink socket.
228  * @see nl_socket_disable_auto_ack
229  */
230 void nl_socket_enable_auto_ack(struct nl_sock *sk)
231 {
232         sk->s_flags &= ~NL_NO_AUTO_ACK;
233 }
234
235 /** @} */
236
237 /**
238  * @name Source Idenficiation
239  * @{
240  */
241
242 uint32_t nl_socket_get_local_port(struct nl_sock *sk)
243 {
244         return sk->s_local.nl_pid;
245 }
246
247 /**
248  * Set local port of socket
249  * @arg sk              Netlink socket.
250  * @arg port            Local port identifier
251  *
252  * Assigns a local port identifier to the socket. If port is 0
253  * a unique port identifier will be generated automatically.
254  */
255 void nl_socket_set_local_port(struct nl_sock *sk, uint32_t port)
256 {
257         if (port == 0) {
258                 port = generate_local_port(); 
259                 sk->s_flags &= ~NL_OWN_PORT;
260         } else  {
261                 if (!(sk->s_flags & NL_OWN_PORT))
262                         release_local_port(sk->s_local.nl_pid);
263                 sk->s_flags |= NL_OWN_PORT;
264         }
265
266         sk->s_local.nl_pid = port;
267 }
268
269 /** @} */
270
271 /**
272  * @name Group Subscriptions
273  * @{
274  */
275
276 /**
277  * Join groups
278  * @arg sk              Netlink socket
279  * @arg group           Group identifier
280  *
281  * Joins the specified groups using the modern socket option which
282  * is available since kernel version 2.6.14. It allows joining an
283  * almost arbitary number of groups without limitation.  The list
284  * of groups has to be terminated by 0 (%NFNLGRP_NONE).
285  *
286  * Make sure to use the correct group definitions as the older
287  * bitmask definitions for nl_join_groups() are likely to still
288  * be present for backward compatibility reasons.
289  *
290  * @return 0 on sucess or a negative error code.
291  */
292 int nl_socket_add_memberships(struct nl_sock *sk, int group, ...)
293 {
294         int err;
295         va_list ap;
296
297         if (sk->s_fd == -1)
298                 return -NLE_BAD_SOCK;
299
300         va_start(ap, group);
301
302         while (group != 0) {
303                 if (group < 0)
304                         return -NLE_INVAL;
305
306                 err = setsockopt(sk->s_fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP,
307                                                  &group, sizeof(group));
308                 if (err < 0)
309                         return -nl_syserr2nlerr(errno);
310
311                 group = va_arg(ap, int);
312         }
313
314         va_end(ap);
315
316         return 0;
317 }
318
319 int nl_socket_add_membership(struct nl_sock *sk, int group)
320 {
321         return nl_socket_add_memberships(sk, group, 0);
322 }
323
324 /**
325  * Leave groups
326  * @arg sk              Netlink socket
327  * @arg group           Group identifier
328  *
329  * Leaves the specified groups using the modern socket option
330  * which is available since kernel version 2.6.14. The list of groups
331  * has to terminated by 0 (%NFNLGRP_NONE).
332  *
333  * @see nl_socket_add_membership
334  * @return 0 on success or a negative error code.
335  */
336 int nl_socket_drop_memberships(struct nl_sock *sk, int group, ...)
337 {
338         int err;
339         va_list ap;
340
341         if (sk->s_fd == -1)
342                 return -NLE_BAD_SOCK;
343
344         va_start(ap, group);
345
346         while (group != 0) {
347                 if (group < 0)
348                         return -NLE_INVAL;
349
350                 err = setsockopt(sk->s_fd, SOL_NETLINK, NETLINK_DROP_MEMBERSHIP,
351                                                  &group, sizeof(group));
352                 if (err < 0)
353                         return -nl_syserr2nlerr(errno);
354
355                 group = va_arg(ap, int);
356         }
357
358         va_end(ap);
359
360         return 0;
361 }
362
363 int nl_socket_drop_membership(struct nl_sock *sk, int group)
364 {
365         return nl_socket_drop_memberships(sk, group, 0);
366 }
367
368
369 /**
370  * Join multicast groups (deprecated)
371  * @arg sk              Netlink socket.
372  * @arg groups          Bitmask of groups to join.
373  *
374  * This function defines the old way of joining multicast group which
375  * has to be done prior to calling nl_connect(). It works on any kernel
376  * version but is very limited as only 32 groups can be joined.
377  */
378 void nl_join_groups(struct nl_sock *sk, int groups)
379 {
380         sk->s_local.nl_groups |= groups;
381 }
382
383
384 /** @} */
385
386 /**
387  * @name Peer Identfication
388  * @{
389  */
390
391 uint32_t nl_socket_get_peer_port(struct nl_sock *sk)
392 {
393         return sk->s_peer.nl_pid;
394 }
395
396 void nl_socket_set_peer_port(struct nl_sock *sk, uint32_t port)
397 {
398         sk->s_peer.nl_pid = port;
399 }
400
401 uint32_t nl_socket_get_peer_groups(struct nl_sock *sk)
402 {
403         return sk->s_peer.nl_groups;
404 }
405
406 void nl_socket_set_peer_groups(struct nl_sock *sk, uint32_t groups)
407 {
408         sk->s_peer.nl_groups = groups;
409 }
410
411
412
413 /** @} */
414
415 /**
416  * @name File Descriptor
417  * @{
418  */
419
420 int nl_socket_get_fd(struct nl_sock *sk)
421 {
422         return sk->s_fd;
423 }
424
425 /**
426  * Set file descriptor of socket to non-blocking state
427  * @arg sk              Netlink socket.
428  *
429  * @return 0 on success or a negative error code.
430  */
431 int nl_socket_set_nonblocking(struct nl_sock *sk)
432 {
433         if (sk->s_fd == -1)
434                 return -NLE_BAD_SOCK;
435
436         if (fcntl(sk->s_fd, F_SETFL, O_NONBLOCK) < 0)
437                 return -nl_syserr2nlerr(errno);
438
439         return 0;
440 }
441
442 /**
443  * Enable use of MSG_PEEK when reading from socket
444  * @arg sk              Netlink socket.
445  */
446 void nl_socket_enable_msg_peek(struct nl_sock *sk)
447 {
448         sk->s_flags |= NL_MSG_PEEK;
449 }
450
451 /**
452  * Disable use of MSG_PEEK when reading from socket
453  * @arg sk              Netlink socket.
454  */
455 void nl_socket_disable_msg_peek(struct nl_sock *sk)
456 {
457         sk->s_flags &= ~NL_MSG_PEEK;
458 }
459
460 /** @} */
461
462 /**
463  * @name Callback Handler
464  * @{
465  */
466
467 struct nl_cb *nl_socket_get_cb(struct nl_sock *sk)
468 {
469         return nl_cb_get(sk->s_cb);
470 }
471
472 void nl_socket_set_cb(struct nl_sock *sk, struct nl_cb *cb)
473 {
474         nl_cb_put(sk->s_cb);
475         sk->s_cb = nl_cb_get(cb);
476 }
477
478 /**
479  * Modify the callback handler associated to the socket
480  * @arg sk              Netlink socket.
481  * @arg type            which type callback to set
482  * @arg kind            kind of callback
483  * @arg func            callback function
484  * @arg arg             argument to be passwd to callback function
485  *
486  * @see nl_cb_set
487  */
488 int nl_socket_modify_cb(struct nl_sock *sk, enum nl_cb_type type,
489                         enum nl_cb_kind kind, nl_recvmsg_msg_cb_t func,
490                         void *arg)
491 {
492         return nl_cb_set(sk->s_cb, type, kind, func, arg);
493 }
494
495 /** @} */
496
497 /**
498  * @name Utilities
499  * @{
500  */
501
502 /**
503  * Set socket buffer size of netlink socket.
504  * @arg sk              Netlink socket.
505  * @arg rxbuf           New receive socket buffer size in bytes.
506  * @arg txbuf           New transmit socket buffer size in bytes.
507  *
508  * Sets the socket buffer size of a netlink socket to the specified
509  * values \c rxbuf and \c txbuf. Providing a value of \c 0 assumes a
510  * good default value.
511  *
512  * @note It is not required to call this function prior to nl_connect().
513  * @return 0 on sucess or a negative error code.
514  */
515 int nl_socket_set_buffer_size(struct nl_sock *sk, int rxbuf, int txbuf)
516 {
517         int err;
518
519         if (rxbuf <= 0)
520                 rxbuf = 32768;
521
522         if (txbuf <= 0)
523                 txbuf = 32768;
524
525         if (sk->s_fd == -1)
526                 return -NLE_BAD_SOCK;
527         
528         err = setsockopt(sk->s_fd, SOL_SOCKET, SO_SNDBUF,
529                          &txbuf, sizeof(txbuf));
530         if (err < 0)
531                 return -nl_syserr2nlerr(errno);
532
533         err = setsockopt(sk->s_fd, SOL_SOCKET, SO_RCVBUF,
534                          &rxbuf, sizeof(rxbuf));
535         if (err < 0)
536                 return -nl_syserr2nlerr(errno);
537
538         sk->s_flags |= NL_SOCK_BUFSIZE_SET;
539
540         return 0;
541 }
542
543 /**
544  * Enable/disable credential passing on netlink socket.
545  * @arg sk              Netlink socket.
546  * @arg state           New state (0 - disabled, 1 - enabled)
547  *
548  * @return 0 on success or a negative error code
549  */
550 int nl_socket_set_passcred(struct nl_sock *sk, int state)
551 {
552         int err;
553
554         if (sk->s_fd == -1)
555                 return -NLE_BAD_SOCK;
556
557         err = setsockopt(sk->s_fd, SOL_SOCKET, SO_PASSCRED,
558                          &state, sizeof(state));
559         if (err < 0)
560                 return -nl_syserr2nlerr(errno);
561
562         if (state)
563                 sk->s_flags |= NL_SOCK_PASSCRED;
564         else
565                 sk->s_flags &= ~NL_SOCK_PASSCRED;
566
567         return 0;
568 }
569
570 /**
571  * Enable/disable receival of additional packet information
572  * @arg sk              Netlink socket.
573  * @arg state           New state (0 - disabled, 1 - enabled)
574  *
575  * @return 0 on success or a negative error code
576  */
577 int nl_socket_recv_pktinfo(struct nl_sock *sk, int state)
578 {
579         int err;
580
581         if (sk->s_fd == -1)
582                 return -NLE_BAD_SOCK;
583
584         err = setsockopt(sk->s_fd, SOL_NETLINK, NETLINK_PKTINFO,
585                          &state, sizeof(state));
586         if (err < 0)
587                 return -nl_syserr2nlerr(errno);
588
589         return 0;
590 }
591
592 /** @} */
593
594 /** @} */