00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <netlink-local.h>
00019 #include <netlink/netlink.h>
00020 #include <netlink/utils.h>
00021 #include <netlink/handlers.h>
00022 #include <netlink/msg.h>
00023 #include <netlink/attr.h>
00024
00025 static int default_cb = NL_CB_DEFAULT;
00026
00027 static void __init init_default_cb(void)
00028 {
00029 char *nlcb;
00030
00031 if ((nlcb = getenv("NLCB"))) {
00032 if (!strcasecmp(nlcb, "default"))
00033 default_cb = NL_CB_DEFAULT;
00034 else if (!strcasecmp(nlcb, "verbose"))
00035 default_cb = NL_CB_VERBOSE;
00036 else if (!strcasecmp(nlcb, "debug"))
00037 default_cb = NL_CB_DEBUG;
00038 else {
00039 fprintf(stderr, "Unknown value for NLCB, valid values: "
00040 "{default | verbose | debug}\n");
00041 }
00042 }
00043 }
00044
00045 static uint32_t used_ports_map[32];
00046
00047 static uint32_t generate_local_port(void)
00048 {
00049 int i, n;
00050 uint32_t pid = getpid() & 0x3FFFFF;
00051
00052 for (i = 0; i < 32; i++) {
00053 if (used_ports_map[i] == 0xFFFFFFFF)
00054 continue;
00055
00056 for (n = 0; n < 32; n++) {
00057 if (1UL & (used_ports_map[i] >> n))
00058 continue;
00059
00060 used_ports_map[i] |= (1UL << n);
00061 n += (i * 32);
00062
00063
00064
00065 return pid + (n << 22);
00066
00067 }
00068 }
00069
00070
00071 return UINT_MAX;
00072 }
00073
00074 static void release_local_port(uint32_t port)
00075 {
00076 int nr;
00077
00078 if (port == UINT_MAX)
00079 return;
00080
00081 nr = port >> 22;
00082 used_ports_map[nr / 32] &= ~(1 << nr % 32);
00083 }
00084
00085
00086
00087
00088
00089
00090 static struct nl_sock *__alloc_socket(struct nl_cb *cb)
00091 {
00092 struct nl_sock *sk;
00093
00094 sk = calloc(1, sizeof(*sk));
00095 if (!sk)
00096 return NULL;
00097
00098 sk->s_fd = -1;
00099 sk->s_cb = cb;
00100 sk->s_local.nl_family = AF_NETLINK;
00101 sk->s_peer.nl_family = AF_NETLINK;
00102 sk->s_seq_expect = sk->s_seq_next = time(0);
00103 sk->s_local.nl_pid = generate_local_port();
00104 if (sk->s_local.nl_pid == UINT_MAX) {
00105 nl_socket_free(sk);
00106 return NULL;
00107 }
00108
00109 return sk;
00110 }
00111
00112
00113
00114
00115
00116
00117 struct nl_sock *nl_socket_alloc(void)
00118 {
00119 struct nl_cb *cb;
00120
00121 cb = nl_cb_alloc(default_cb);
00122 if (!cb)
00123 return NULL;
00124
00125 return __alloc_socket(cb);
00126 }
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137 struct nl_sock *nl_socket_alloc_cb(struct nl_cb *cb)
00138 {
00139 if (cb == NULL)
00140 BUG();
00141
00142 return __alloc_socket(nl_cb_get(cb));
00143 }
00144
00145
00146
00147
00148
00149 void nl_socket_free(struct nl_sock *sk)
00150 {
00151 if (!sk)
00152 return;
00153
00154 if (sk->s_fd >= 0)
00155 close(sk->s_fd);
00156
00157 if (!(sk->s_flags & NL_OWN_PORT))
00158 release_local_port(sk->s_local.nl_pid);
00159
00160 nl_cb_put(sk->s_cb);
00161 free(sk);
00162 }
00163
00164
00165
00166
00167
00168
00169
00170
00171 static int noop_seq_check(struct nl_msg *msg, void *arg)
00172 {
00173 return NL_OK;
00174 }
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188 void nl_socket_disable_seq_check(struct nl_sock *sk)
00189 {
00190 nl_cb_set(sk->s_cb, NL_CB_SEQ_CHECK,
00191 NL_CB_CUSTOM, noop_seq_check, NULL);
00192 }
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203 unsigned int nl_socket_use_seq(struct nl_sock *sk)
00204 {
00205 return sk->s_seq_next++;
00206 }
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220 void nl_socket_disable_auto_ack(struct nl_sock *sk)
00221 {
00222 sk->s_flags |= NL_NO_AUTO_ACK;
00223 }
00224
00225
00226
00227
00228
00229
00230 void nl_socket_enable_auto_ack(struct nl_sock *sk)
00231 {
00232 sk->s_flags &= ~NL_NO_AUTO_ACK;
00233 }
00234
00235
00236
00237
00238
00239
00240
00241
00242 uint32_t nl_socket_get_local_port(const struct nl_sock *sk)
00243 {
00244 return sk->s_local.nl_pid;
00245 }
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255 void nl_socket_set_local_port(struct nl_sock *sk, uint32_t port)
00256 {
00257 if (port == 0) {
00258 port = generate_local_port();
00259 sk->s_flags &= ~NL_OWN_PORT;
00260 } else {
00261 if (!(sk->s_flags & NL_OWN_PORT))
00262 release_local_port(sk->s_local.nl_pid);
00263 sk->s_flags |= NL_OWN_PORT;
00264 }
00265
00266 sk->s_local.nl_pid = port;
00267 }
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292 int nl_socket_add_memberships(struct nl_sock *sk, int group, ...)
00293 {
00294 int err;
00295 va_list ap;
00296
00297 if (sk->s_fd == -1)
00298 return -NLE_BAD_SOCK;
00299
00300 va_start(ap, group);
00301
00302 while (group != 0) {
00303 if (group < 0)
00304 return -NLE_INVAL;
00305
00306 err = setsockopt(sk->s_fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP,
00307 &group, sizeof(group));
00308 if (err < 0)
00309 return -nl_syserr2nlerr(errno);
00310
00311 group = va_arg(ap, int);
00312 }
00313
00314 va_end(ap);
00315
00316 return 0;
00317 }
00318
00319 int nl_socket_add_membership(struct nl_sock *sk, int group)
00320 {
00321 return nl_socket_add_memberships(sk, group, 0);
00322 }
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336 int nl_socket_drop_memberships(struct nl_sock *sk, int group, ...)
00337 {
00338 int err;
00339 va_list ap;
00340
00341 if (sk->s_fd == -1)
00342 return -NLE_BAD_SOCK;
00343
00344 va_start(ap, group);
00345
00346 while (group != 0) {
00347 if (group < 0)
00348 return -NLE_INVAL;
00349
00350 err = setsockopt(sk->s_fd, SOL_NETLINK, NETLINK_DROP_MEMBERSHIP,
00351 &group, sizeof(group));
00352 if (err < 0)
00353 return -nl_syserr2nlerr(errno);
00354
00355 group = va_arg(ap, int);
00356 }
00357
00358 va_end(ap);
00359
00360 return 0;
00361 }
00362
00363 int nl_socket_drop_membership(struct nl_sock *sk, int group)
00364 {
00365 return nl_socket_drop_memberships(sk, group, 0);
00366 }
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378 void nl_join_groups(struct nl_sock *sk, int groups)
00379 {
00380 sk->s_local.nl_groups |= groups;
00381 }
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391 uint32_t nl_socket_get_peer_port(const struct nl_sock *sk)
00392 {
00393 return sk->s_peer.nl_pid;
00394 }
00395
00396 void nl_socket_set_peer_port(struct nl_sock *sk, uint32_t port)
00397 {
00398 sk->s_peer.nl_pid = port;
00399 }
00400
00401 uint32_t nl_socket_get_peer_groups(const struct nl_sock *sk)
00402 {
00403 return sk->s_peer.nl_groups;
00404 }
00405
00406 void nl_socket_set_peer_groups(struct nl_sock *sk, uint32_t groups)
00407 {
00408 sk->s_peer.nl_groups = groups;
00409 }
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420 int nl_socket_get_fd(const struct nl_sock *sk)
00421 {
00422 return sk->s_fd;
00423 }
00424
00425
00426
00427
00428
00429
00430
00431 int nl_socket_set_nonblocking(const struct nl_sock *sk)
00432 {
00433 if (sk->s_fd == -1)
00434 return -NLE_BAD_SOCK;
00435
00436 if (fcntl(sk->s_fd, F_SETFL, O_NONBLOCK) < 0)
00437 return -nl_syserr2nlerr(errno);
00438
00439 return 0;
00440 }
00441
00442
00443
00444
00445
00446 void nl_socket_enable_msg_peek(struct nl_sock *sk)
00447 {
00448 sk->s_flags |= NL_MSG_PEEK;
00449 }
00450
00451
00452
00453
00454
00455 void nl_socket_disable_msg_peek(struct nl_sock *sk)
00456 {
00457 sk->s_flags &= ~NL_MSG_PEEK;
00458 }
00459
00460
00461
00462
00463
00464
00465
00466
00467 struct nl_cb *nl_socket_get_cb(const struct nl_sock *sk)
00468 {
00469 return nl_cb_get(sk->s_cb);
00470 }
00471
00472 void nl_socket_set_cb(struct nl_sock *sk, struct nl_cb *cb)
00473 {
00474 nl_cb_put(sk->s_cb);
00475 sk->s_cb = nl_cb_get(cb);
00476 }
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488 int nl_socket_modify_cb(struct nl_sock *sk, enum nl_cb_type type,
00489 enum nl_cb_kind kind, nl_recvmsg_msg_cb_t func,
00490 void *arg)
00491 {
00492 return nl_cb_set(sk->s_cb, type, kind, func, arg);
00493 }
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515 int nl_socket_set_buffer_size(struct nl_sock *sk, int rxbuf, int txbuf)
00516 {
00517 int err;
00518
00519 if (rxbuf <= 0)
00520 rxbuf = 32768;
00521
00522 if (txbuf <= 0)
00523 txbuf = 32768;
00524
00525 if (sk->s_fd == -1)
00526 return -NLE_BAD_SOCK;
00527
00528 err = setsockopt(sk->s_fd, SOL_SOCKET, SO_SNDBUF,
00529 &txbuf, sizeof(txbuf));
00530 if (err < 0)
00531 return -nl_syserr2nlerr(errno);
00532
00533 err = setsockopt(sk->s_fd, SOL_SOCKET, SO_RCVBUF,
00534 &rxbuf, sizeof(rxbuf));
00535 if (err < 0)
00536 return -nl_syserr2nlerr(errno);
00537
00538 sk->s_flags |= NL_SOCK_BUFSIZE_SET;
00539
00540 return 0;
00541 }
00542
00543
00544
00545
00546
00547
00548
00549
00550 int nl_socket_set_passcred(struct nl_sock *sk, int state)
00551 {
00552 int err;
00553
00554 if (sk->s_fd == -1)
00555 return -NLE_BAD_SOCK;
00556
00557 err = setsockopt(sk->s_fd, SOL_SOCKET, SO_PASSCRED,
00558 &state, sizeof(state));
00559 if (err < 0)
00560 return -nl_syserr2nlerr(errno);
00561
00562 if (state)
00563 sk->s_flags |= NL_SOCK_PASSCRED;
00564 else
00565 sk->s_flags &= ~NL_SOCK_PASSCRED;
00566
00567 return 0;
00568 }
00569
00570
00571
00572
00573
00574
00575
00576
00577 int nl_socket_recv_pktinfo(struct nl_sock *sk, int state)
00578 {
00579 int err;
00580
00581 if (sk->s_fd == -1)
00582 return -NLE_BAD_SOCK;
00583
00584 err = setsockopt(sk->s_fd, SOL_NETLINK, NETLINK_PKTINFO,
00585 &state, sizeof(state));
00586 if (err < 0)
00587 return -nl_syserr2nlerr(errno);
00588
00589 return 0;
00590 }
00591
00592
00593
00594