00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084 #include <netlink-local.h>
00085 #include <netlink/netlink.h>
00086 #include <netlink/utils.h>
00087 #include <netlink/handlers.h>
00088 #include <netlink/msg.h>
00089 #include <netlink/attr.h>
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106 int nl_connect(struct nl_sock *sk, int protocol)
00107 {
00108 int err;
00109 socklen_t addrlen;
00110
00111 sk->s_fd = socket(AF_NETLINK, SOCK_RAW, protocol);
00112 if (sk->s_fd < 0) {
00113 err = -nl_syserr2nlerr(errno);
00114 goto errout;
00115 }
00116
00117 if (!(sk->s_flags & NL_SOCK_BUFSIZE_SET)) {
00118 err = nl_socket_set_buffer_size(sk, 0, 0);
00119 if (err < 0)
00120 goto errout;
00121 }
00122
00123 err = bind(sk->s_fd, (struct sockaddr*) &sk->s_local,
00124 sizeof(sk->s_local));
00125 if (err < 0) {
00126 err = -nl_syserr2nlerr(errno);
00127 goto errout;
00128 }
00129
00130 addrlen = sizeof(sk->s_local);
00131 err = getsockname(sk->s_fd, (struct sockaddr *) &sk->s_local,
00132 &addrlen);
00133 if (err < 0) {
00134 err = -nl_syserr2nlerr(errno);
00135 goto errout;
00136 }
00137
00138 if (addrlen != sizeof(sk->s_local)) {
00139 err = -NLE_NOADDR;
00140 goto errout;
00141 }
00142
00143 if (sk->s_local.nl_family != AF_NETLINK) {
00144 err = -NLE_AF_NOSUPPORT;
00145 goto errout;
00146 }
00147
00148 sk->s_proto = protocol;
00149
00150 return 0;
00151 errout:
00152 close(sk->s_fd);
00153 sk->s_fd = -1;
00154
00155 return err;
00156 }
00157
00158
00159
00160
00161
00162 void nl_close(struct nl_sock *sk)
00163 {
00164 if (sk->s_fd >= 0) {
00165 close(sk->s_fd);
00166 sk->s_fd = -1;
00167 }
00168
00169 sk->s_proto = 0;
00170 }
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186 int nl_sendto(struct nl_sock *sk, void *buf, size_t size)
00187 {
00188 int ret;
00189
00190 ret = sendto(sk->s_fd, buf, size, 0, (struct sockaddr *)
00191 &sk->s_peer, sizeof(sk->s_peer));
00192 if (ret < 0)
00193 return -nl_syserr2nlerr(errno);
00194
00195 return ret;
00196 }
00197
00198
00199
00200
00201
00202
00203
00204
00205 int nl_sendmsg(struct nl_sock *sk, struct nl_msg *msg, struct msghdr *hdr)
00206 {
00207 struct nl_cb *cb;
00208 int ret;
00209
00210 struct iovec iov = {
00211 .iov_base = (void *) nlmsg_hdr(msg),
00212 .iov_len = nlmsg_hdr(msg)->nlmsg_len,
00213 };
00214
00215 hdr->msg_iov = &iov;
00216 hdr->msg_iovlen = 1;
00217
00218 nlmsg_set_src(msg, &sk->s_local);
00219
00220 cb = sk->s_cb;
00221 if (cb->cb_set[NL_CB_MSG_OUT])
00222 if (nl_cb_call(cb, NL_CB_MSG_OUT, msg) != NL_OK)
00223 return 0;
00224
00225 ret = sendmsg(sk->s_fd, hdr, 0);
00226 if (ret < 0)
00227 return -nl_syserr2nlerr(errno);
00228
00229 return ret;
00230 }
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240 int nl_send(struct nl_sock *sk, struct nl_msg *msg)
00241 {
00242 struct sockaddr_nl *dst;
00243 struct ucred *creds;
00244
00245 struct msghdr hdr = {
00246 .msg_name = (void *) &sk->s_peer,
00247 .msg_namelen = sizeof(struct sockaddr_nl),
00248 };
00249
00250
00251
00252
00253 dst = nlmsg_get_dst(msg);
00254 if (dst->nl_family == AF_NETLINK)
00255 hdr.msg_name = dst;
00256
00257
00258 creds = nlmsg_get_creds(msg);
00259 if (creds != NULL) {
00260 char buf[CMSG_SPACE(sizeof(struct ucred))];
00261 struct cmsghdr *cmsg;
00262
00263 hdr.msg_control = buf;
00264 hdr.msg_controllen = sizeof(buf);
00265
00266 cmsg = CMSG_FIRSTHDR(&hdr);
00267 cmsg->cmsg_level = SOL_SOCKET;
00268 cmsg->cmsg_type = SCM_CREDENTIALS;
00269 cmsg->cmsg_len = CMSG_LEN(sizeof(struct ucred));
00270 memcpy(CMSG_DATA(cmsg), creds, sizeof(struct ucred));
00271 }
00272
00273 return nl_sendmsg(sk, msg, &hdr);
00274 }
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288 int nl_send_auto_complete(struct nl_sock *sk, struct nl_msg *msg)
00289 {
00290 struct nlmsghdr *nlh;
00291 struct nl_cb *cb = sk->s_cb;
00292
00293 nlh = nlmsg_hdr(msg);
00294 if (nlh->nlmsg_pid == 0)
00295 nlh->nlmsg_pid = sk->s_local.nl_pid;
00296
00297 if (nlh->nlmsg_seq == 0)
00298 nlh->nlmsg_seq = sk->s_seq_next++;
00299
00300 if (msg->nm_protocol == -1)
00301 msg->nm_protocol = sk->s_proto;
00302
00303 nlh->nlmsg_flags |= NLM_F_REQUEST;
00304
00305 if (!(sk->s_flags & NL_NO_AUTO_ACK))
00306 nlh->nlmsg_flags |= NLM_F_ACK;
00307
00308 if (cb->cb_send_ow)
00309 return cb->cb_send_ow(sk, msg);
00310 else
00311 return nl_send(sk, msg);
00312 }
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328 int nl_send_simple(struct nl_sock *sk, int type, int flags, void *buf,
00329 size_t size)
00330 {
00331 int err;
00332 struct nl_msg *msg;
00333
00334 msg = nlmsg_alloc_simple(type, flags);
00335 if (!msg)
00336 return -NLE_NOMEM;
00337
00338 if (buf && size) {
00339 err = nlmsg_append(msg, buf, size, NLMSG_ALIGNTO);
00340 if (err < 0)
00341 goto errout;
00342 }
00343
00344
00345 err = nl_send_auto_complete(sk, msg);
00346 errout:
00347 nlmsg_free(msg);
00348
00349 return err;
00350 }
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378 int nl_recv(struct nl_sock *sk, struct sockaddr_nl *nla,
00379 unsigned char **buf, struct ucred **creds)
00380 {
00381 int n;
00382 int flags = 0;
00383 static int page_size = 0;
00384 struct iovec iov;
00385 struct msghdr msg = {
00386 .msg_name = (void *) nla,
00387 .msg_namelen = sizeof(struct sockaddr_nl),
00388 .msg_iov = &iov,
00389 .msg_iovlen = 1,
00390 .msg_control = NULL,
00391 .msg_controllen = 0,
00392 .msg_flags = 0,
00393 };
00394 struct cmsghdr *cmsg;
00395
00396 if (sk->s_flags & NL_MSG_PEEK)
00397 flags |= MSG_PEEK;
00398
00399 if (page_size == 0)
00400 page_size = getpagesize();
00401
00402 iov.iov_len = page_size;
00403 iov.iov_base = *buf = malloc(iov.iov_len);
00404
00405 if (sk->s_flags & NL_SOCK_PASSCRED) {
00406 msg.msg_controllen = CMSG_SPACE(sizeof(struct ucred));
00407 msg.msg_control = calloc(1, msg.msg_controllen);
00408 }
00409 retry:
00410
00411 n = recvmsg(sk->s_fd, &msg, flags);
00412 if (!n)
00413 goto abort;
00414 else if (n < 0) {
00415 if (errno == EINTR) {
00416 NL_DBG(3, "recvmsg() returned EINTR, retrying\n");
00417 goto retry;
00418 } else if (errno == EAGAIN) {
00419 NL_DBG(3, "recvmsg() returned EAGAIN, aborting\n");
00420 goto abort;
00421 } else {
00422 free(msg.msg_control);
00423 free(*buf);
00424 return -nl_syserr2nlerr(errno);
00425 }
00426 }
00427
00428 if (iov.iov_len < n ||
00429 msg.msg_flags & MSG_TRUNC) {
00430
00431
00432 iov.iov_len *= 2;
00433 iov.iov_base = *buf = realloc(*buf, iov.iov_len);
00434 goto retry;
00435 } else if (msg.msg_flags & MSG_CTRUNC) {
00436 msg.msg_controllen *= 2;
00437 msg.msg_control = realloc(msg.msg_control, msg.msg_controllen);
00438 goto retry;
00439 } else if (flags != 0) {
00440
00441 flags = 0;
00442 goto retry;
00443 }
00444
00445 if (msg.msg_namelen != sizeof(struct sockaddr_nl)) {
00446 free(msg.msg_control);
00447 free(*buf);
00448 return -NLE_NOADDR;
00449 }
00450
00451 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
00452 if (cmsg->cmsg_level == SOL_SOCKET &&
00453 cmsg->cmsg_type == SCM_CREDENTIALS) {
00454 *creds = calloc(1, sizeof(struct ucred));
00455 memcpy(*creds, CMSG_DATA(cmsg), sizeof(struct ucred));
00456 break;
00457 }
00458 }
00459
00460 free(msg.msg_control);
00461 return n;
00462
00463 abort:
00464 free(msg.msg_control);
00465 free(*buf);
00466 return 0;
00467 }
00468
00469 #define NL_CB_CALL(cb, type, msg) \
00470 do { \
00471 err = nl_cb_call(cb, type, msg); \
00472 switch (err) { \
00473 case NL_OK: \
00474 err = 0; \
00475 break; \
00476 case NL_SKIP: \
00477 goto skip; \
00478 case NL_STOP: \
00479 goto stop; \
00480 default: \
00481 goto out; \
00482 } \
00483 } while (0)
00484
00485 static int recvmsgs(struct nl_sock *sk, struct nl_cb *cb)
00486 {
00487 int n, err = 0, multipart = 0;
00488 unsigned char *buf = NULL;
00489 struct nlmsghdr *hdr;
00490 struct sockaddr_nl nla = {0};
00491 struct nl_msg *msg = NULL;
00492 struct ucred *creds = NULL;
00493
00494 continue_reading:
00495 NL_DBG(3, "Attempting to read from %p\n", sk);
00496 if (cb->cb_recv_ow)
00497 n = cb->cb_recv_ow(sk, &nla, &buf, &creds);
00498 else
00499 n = nl_recv(sk, &nla, &buf, &creds);
00500
00501 if (n <= 0)
00502 return n;
00503
00504 NL_DBG(3, "recvmsgs(%p): Read %d bytes\n", sk, n);
00505
00506 hdr = (struct nlmsghdr *) buf;
00507 while (nlmsg_ok(hdr, n)) {
00508 NL_DBG(3, "recgmsgs(%p): Processing valid message...\n", sk);
00509
00510 nlmsg_free(msg);
00511 msg = nlmsg_convert(hdr);
00512 if (!msg) {
00513 err = -NLE_NOMEM;
00514 goto out;
00515 }
00516
00517 nlmsg_set_proto(msg, sk->s_proto);
00518 nlmsg_set_src(msg, &nla);
00519 if (creds)
00520 nlmsg_set_creds(msg, creds);
00521
00522
00523
00524 if (cb->cb_set[NL_CB_MSG_IN])
00525 NL_CB_CALL(cb, NL_CB_MSG_IN, msg);
00526
00527
00528
00529
00530 if (cb->cb_set[NL_CB_SEQ_CHECK])
00531 NL_CB_CALL(cb, NL_CB_SEQ_CHECK, msg);
00532 else if (hdr->nlmsg_seq != sk->s_seq_expect) {
00533 if (cb->cb_set[NL_CB_INVALID])
00534 NL_CB_CALL(cb, NL_CB_INVALID, msg);
00535 else {
00536 err = -NLE_SEQ_MISMATCH;
00537 goto out;
00538 }
00539 }
00540
00541 if (hdr->nlmsg_type == NLMSG_DONE ||
00542 hdr->nlmsg_type == NLMSG_ERROR ||
00543 hdr->nlmsg_type == NLMSG_NOOP ||
00544 hdr->nlmsg_type == NLMSG_OVERRUN) {
00545
00546
00547 sk->s_seq_expect++;
00548 NL_DBG(3, "recvmsgs(%p): Increased expected " \
00549 "sequence number to %d\n",
00550 sk, sk->s_seq_expect);
00551 }
00552
00553 if (hdr->nlmsg_flags & NLM_F_MULTI)
00554 multipart = 1;
00555
00556
00557 if (hdr->nlmsg_flags & NLM_F_ACK) {
00558 if (cb->cb_set[NL_CB_SEND_ACK])
00559 NL_CB_CALL(cb, NL_CB_SEND_ACK, msg);
00560 else {
00561
00562 }
00563 }
00564
00565
00566
00567
00568
00569 if (hdr->nlmsg_type == NLMSG_DONE) {
00570 multipart = 0;
00571 if (cb->cb_set[NL_CB_FINISH])
00572 NL_CB_CALL(cb, NL_CB_FINISH, msg);
00573 }
00574
00575
00576
00577
00578
00579 else if (hdr->nlmsg_type == NLMSG_NOOP) {
00580 if (cb->cb_set[NL_CB_SKIPPED])
00581 NL_CB_CALL(cb, NL_CB_SKIPPED, msg);
00582 else
00583 goto skip;
00584 }
00585
00586
00587
00588
00589 else if (hdr->nlmsg_type == NLMSG_OVERRUN) {
00590 if (cb->cb_set[NL_CB_OVERRUN])
00591 NL_CB_CALL(cb, NL_CB_OVERRUN, msg);
00592 else {
00593 err = -NLE_MSG_OVERFLOW;
00594 goto out;
00595 }
00596 }
00597
00598
00599 else if (hdr->nlmsg_type == NLMSG_ERROR) {
00600 struct nlmsgerr *e = nlmsg_data(hdr);
00601
00602 if (hdr->nlmsg_len < nlmsg_msg_size(sizeof(*e))) {
00603
00604
00605
00606
00607 if (cb->cb_set[NL_CB_INVALID])
00608 NL_CB_CALL(cb, NL_CB_INVALID, msg);
00609 else {
00610 err = -NLE_MSG_TRUNC;
00611 goto out;
00612 }
00613 } else if (e->error) {
00614
00615 if (cb->cb_err) {
00616 err = cb->cb_err(&nla, e,
00617 cb->cb_err_arg);
00618 if (err < 0)
00619 goto out;
00620 else if (err == NL_SKIP)
00621 goto skip;
00622 else if (err == NL_STOP) {
00623 err = -nl_syserr2nlerr(e->error);
00624 goto out;
00625 }
00626 } else {
00627 err = -nl_syserr2nlerr(e->error);
00628 goto out;
00629 }
00630 } else if (cb->cb_set[NL_CB_ACK])
00631 NL_CB_CALL(cb, NL_CB_ACK, msg);
00632 } else {
00633
00634
00635
00636 if (cb->cb_set[NL_CB_VALID])
00637 NL_CB_CALL(cb, NL_CB_VALID, msg);
00638 }
00639 skip:
00640 err = 0;
00641 hdr = nlmsg_next(hdr, &n);
00642 }
00643
00644 nlmsg_free(msg);
00645 free(buf);
00646 free(creds);
00647 buf = NULL;
00648 msg = NULL;
00649 creds = NULL;
00650
00651 if (multipart) {
00652
00653 goto continue_reading;
00654 }
00655 stop:
00656 err = 0;
00657 out:
00658 nlmsg_free(msg);
00659 free(buf);
00660 free(creds);
00661
00662 return err;
00663 }
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680 int nl_recvmsgs(struct nl_sock *sk, struct nl_cb *cb)
00681 {
00682 if (cb->cb_recvmsgs_ow)
00683 return cb->cb_recvmsgs_ow(sk, cb);
00684 else
00685 return recvmsgs(sk, cb);
00686 }
00687
00688
00689
00690
00691
00692
00693
00694 int nl_recvmsgs_default(struct nl_sock *sk)
00695 {
00696 return nl_recvmsgs(sk, sk->s_cb);
00697
00698 }
00699
00700 static int ack_wait_handler(struct nl_msg *msg, void *arg)
00701 {
00702 return NL_STOP;
00703 }
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713 int nl_wait_for_ack(struct nl_sock *sk)
00714 {
00715 int err;
00716 struct nl_cb *cb;
00717
00718 cb = nl_cb_clone(sk->s_cb);
00719 if (cb == NULL)
00720 return -NLE_NOMEM;
00721
00722 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_wait_handler, NULL);
00723 err = nl_recvmsgs(sk, cb);
00724 nl_cb_put(cb);
00725
00726 return err;
00727 }
00728
00729
00730
00731