~ubuntu-branches/ubuntu/trusty/libnl3/trusty

« back to all changes in this revision

Viewing changes to lib/socket.c

  • Committer: Bazaar Package Importer
  • Author(s): Heiko Stuebner
  • Date: 2011-05-21 19:25:13 UTC
  • Revision ID: james.westby@ubuntu.com-20110521192513-1ieyu9w9kym4bt16
Tags: upstream-3.0
ImportĀ upstreamĀ versionĀ 3.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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(const 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(const 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(const 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(const 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(const 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(const 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
/** @} */