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
00107
00108 int nl_connect(struct nl_sock *sk, int protocol)
00109 {
00110 int err, flags = 0;
00111 socklen_t addrlen;
00112
00113 #ifdef SOCK_CLOEXEC
00114 flags |= SOCK_CLOEXEC;
00115 #endif
00116
00117 sk->s_fd = socket(AF_NETLINK, SOCK_RAW | flags, protocol);
00118 if (sk->s_fd < 0) {
00119 err = -nl_syserr2nlerr(errno);
00120 goto errout;
00121 }
00122
00123 if (!(sk->s_flags & NL_SOCK_BUFSIZE_SET)) {
00124 err = nl_socket_set_buffer_size(sk, 0, 0);
00125 if (err < 0)
00126 goto errout;
00127 }
00128
00129 err = bind(sk->s_fd, (struct sockaddr*) &sk->s_local,
00130 sizeof(sk->s_local));
00131 if (err < 0) {
00132 err = -nl_syserr2nlerr(errno);
00133 goto errout;
00134 }
00135
00136 addrlen = sizeof(sk->s_local);
00137 err = getsockname(sk->s_fd, (struct sockaddr *) &sk->s_local,
00138 &addrlen);
00139 if (err < 0) {
00140 err = -nl_syserr2nlerr(errno);
00141 goto errout;
00142 }
00143
00144 if (addrlen != sizeof(sk->s_local)) {
00145 err = -NLE_NOADDR;
00146 goto errout;
00147 }
00148
00149 if (sk->s_local.nl_family != AF_NETLINK) {
00150 err = -NLE_AF_NOSUPPORT;
00151 goto errout;
00152 }
00153
00154 sk->s_proto = protocol;
00155
00156 return 0;
00157 errout:
00158 close(sk->s_fd);
00159 sk->s_fd = -1;
00160
00161 return err;
00162 }
00163
00164
00165
00166
00167
00168 void nl_close(struct nl_sock *sk)
00169 {
00170 if (sk->s_fd >= 0) {
00171 close(sk->s_fd);
00172 sk->s_fd = -1;
00173 }
00174
00175 sk->s_proto = 0;
00176 }
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192 int nl_sendto(struct nl_sock *sk, void *buf, size_t size)
00193 {
00194 int ret;
00195
00196 ret = sendto(sk->s_fd, buf, size, 0, (struct sockaddr *)
00197 &sk->s_peer, sizeof(sk->s_peer));
00198 if (ret < 0)
00199 return -nl_syserr2nlerr(errno);
00200
00201 return ret;
00202 }
00203
00204
00205
00206
00207
00208
00209
00210
00211 int nl_sendmsg(struct nl_sock *sk, struct nl_msg *msg, struct msghdr *hdr)
00212 {
00213 struct nl_cb *cb;
00214 int ret;
00215
00216 nlmsg_set_src(msg, &sk->s_local);
00217
00218 cb = sk->s_cb;
00219 if (cb->cb_set[NL_CB_MSG_OUT])
00220 if ((ret = nl_cb_call(cb, NL_CB_MSG_OUT, msg)) != NL_OK)
00221 return ret;
00222
00223 ret = sendmsg(sk->s_fd, hdr, 0);
00224 if (ret < 0)
00225 return -nl_syserr2nlerr(errno);
00226
00227 NL_DBG(4, "sent %d bytes\n", ret);
00228 return ret;
00229 }
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241 int nl_send_iovec(struct nl_sock *sk, struct nl_msg *msg, struct iovec *iov, unsigned iovlen)
00242 {
00243 struct sockaddr_nl *dst;
00244 struct ucred *creds;
00245 struct msghdr hdr = {
00246 .msg_name = (void *) &sk->s_peer,
00247 .msg_namelen = sizeof(struct sockaddr_nl),
00248 .msg_iov = iov,
00249 .msg_iovlen = iovlen,
00250 };
00251
00252
00253
00254
00255 dst = nlmsg_get_dst(msg);
00256 if (dst->nl_family == AF_NETLINK)
00257 hdr.msg_name = dst;
00258
00259
00260 creds = nlmsg_get_creds(msg);
00261 if (creds != NULL) {
00262 char buf[CMSG_SPACE(sizeof(struct ucred))];
00263 struct cmsghdr *cmsg;
00264
00265 hdr.msg_control = buf;
00266 hdr.msg_controllen = sizeof(buf);
00267
00268 cmsg = CMSG_FIRSTHDR(&hdr);
00269 cmsg->cmsg_level = SOL_SOCKET;
00270 cmsg->cmsg_type = SCM_CREDENTIALS;
00271 cmsg->cmsg_len = CMSG_LEN(sizeof(struct ucred));
00272 memcpy(CMSG_DATA(cmsg), creds, sizeof(struct ucred));
00273 }
00274
00275 return nl_sendmsg(sk, msg, &hdr);
00276 }
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287 int nl_send(struct nl_sock *sk, struct nl_msg *msg)
00288 {
00289 struct iovec iov = {
00290 .iov_base = (void *) nlmsg_hdr(msg),
00291 .iov_len = nlmsg_hdr(msg)->nlmsg_len,
00292 };
00293
00294 return nl_send_iovec(sk, msg, &iov, 1);
00295 }
00296
00297 void nl_complete_msg(struct nl_sock *sk, struct nl_msg *msg)
00298 {
00299 struct nlmsghdr *nlh;
00300
00301 nlh = nlmsg_hdr(msg);
00302 if (nlh->nlmsg_pid == 0)
00303 nlh->nlmsg_pid = sk->s_local.nl_pid;
00304
00305 if (nlh->nlmsg_seq == 0)
00306 nlh->nlmsg_seq = sk->s_seq_next++;
00307
00308 if (msg->nm_protocol == -1)
00309 msg->nm_protocol = sk->s_proto;
00310
00311 nlh->nlmsg_flags |= NLM_F_REQUEST;
00312
00313 if (!(sk->s_flags & NL_NO_AUTO_ACK))
00314 nlh->nlmsg_flags |= NLM_F_ACK;
00315 }
00316
00317 void nl_auto_complete(struct nl_sock *sk, struct nl_msg *msg)
00318 {
00319 nl_complete_msg(sk, msg);
00320 }
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337 int nl_send_auto(struct nl_sock *sk, struct nl_msg *msg)
00338 {
00339 struct nl_cb *cb = sk->s_cb;
00340
00341 nl_complete_msg(sk, msg);
00342
00343 if (cb->cb_send_ow)
00344 return cb->cb_send_ow(sk, msg);
00345 else
00346 return nl_send(sk, msg);
00347 }
00348
00349 int nl_send_auto_complete(struct nl_sock *sk, struct nl_msg *msg)
00350 {
00351 return nl_send_auto(sk, msg);
00352 }
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373 int nl_send_sync(struct nl_sock *sk, struct nl_msg *msg)
00374 {
00375 int err;
00376
00377 err = nl_send_auto(sk, msg);
00378 nlmsg_free(msg);
00379 if (err < 0)
00380 return err;
00381
00382 return wait_for_ack(sk);
00383 }
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399 int nl_send_simple(struct nl_sock *sk, int type, int flags, void *buf,
00400 size_t size)
00401 {
00402 int err;
00403 struct nl_msg *msg;
00404
00405 msg = nlmsg_alloc_simple(type, flags);
00406 if (!msg)
00407 return -NLE_NOMEM;
00408
00409 if (buf && size) {
00410 err = nlmsg_append(msg, buf, size, NLMSG_ALIGNTO);
00411 if (err < 0)
00412 goto errout;
00413 }
00414
00415
00416 err = nl_send_auto_complete(sk, msg);
00417 errout:
00418 nlmsg_free(msg);
00419
00420 return err;
00421 }
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449 int nl_recv(struct nl_sock *sk, struct sockaddr_nl *nla,
00450 unsigned char **buf, struct ucred **creds)
00451 {
00452 int n;
00453 int flags = 0;
00454 static int page_size = 0;
00455 struct iovec iov;
00456 struct msghdr msg = {
00457 .msg_name = (void *) nla,
00458 .msg_namelen = sizeof(struct sockaddr_nl),
00459 .msg_iov = &iov,
00460 .msg_iovlen = 1,
00461 .msg_control = NULL,
00462 .msg_controllen = 0,
00463 .msg_flags = 0,
00464 };
00465 struct cmsghdr *cmsg;
00466
00467 memset(nla, 0, sizeof(*nla));
00468
00469 if (sk->s_flags & NL_MSG_PEEK)
00470 flags |= MSG_PEEK;
00471
00472 if (page_size == 0)
00473 page_size = getpagesize();
00474
00475 iov.iov_len = page_size;
00476 iov.iov_base = *buf = malloc(iov.iov_len);
00477
00478 if (sk->s_flags & NL_SOCK_PASSCRED) {
00479 msg.msg_controllen = CMSG_SPACE(sizeof(struct ucred));
00480 msg.msg_control = calloc(1, msg.msg_controllen);
00481 }
00482 retry:
00483
00484 n = recvmsg(sk->s_fd, &msg, flags);
00485 if (!n)
00486 goto abort;
00487 else if (n < 0) {
00488 if (errno == EINTR) {
00489 NL_DBG(3, "recvmsg() returned EINTR, retrying\n");
00490 goto retry;
00491 } else if (errno == EAGAIN) {
00492 NL_DBG(3, "recvmsg() returned EAGAIN, aborting\n");
00493 goto abort;
00494 } else {
00495 free(msg.msg_control);
00496 free(*buf);
00497 return -nl_syserr2nlerr(errno);
00498 }
00499 }
00500
00501 if (iov.iov_len < n ||
00502 msg.msg_flags & MSG_TRUNC) {
00503
00504
00505 iov.iov_len *= 2;
00506 iov.iov_base = *buf = realloc(*buf, iov.iov_len);
00507 goto retry;
00508 } else if (msg.msg_flags & MSG_CTRUNC) {
00509 msg.msg_controllen *= 2;
00510 msg.msg_control = realloc(msg.msg_control, msg.msg_controllen);
00511 goto retry;
00512 } else if (flags != 0) {
00513
00514 flags = 0;
00515 goto retry;
00516 }
00517
00518 if (msg.msg_namelen != sizeof(struct sockaddr_nl)) {
00519 free(msg.msg_control);
00520 free(*buf);
00521 return -NLE_NOADDR;
00522 }
00523
00524 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
00525 if (cmsg->cmsg_level == SOL_SOCKET &&
00526 cmsg->cmsg_type == SCM_CREDENTIALS) {
00527 if (creds) {
00528 *creds = calloc(1, sizeof(struct ucred));
00529 memcpy(*creds, CMSG_DATA(cmsg), sizeof(struct ucred));
00530 }
00531 break;
00532 }
00533 }
00534
00535 free(msg.msg_control);
00536 return n;
00537
00538 abort:
00539 free(msg.msg_control);
00540 free(*buf);
00541 return 0;
00542 }
00543
00544 #define NL_CB_CALL(cb, type, msg) \
00545 do { \
00546 err = nl_cb_call(cb, type, msg); \
00547 switch (err) { \
00548 case NL_OK: \
00549 err = 0; \
00550 break; \
00551 case NL_SKIP: \
00552 goto skip; \
00553 case NL_STOP: \
00554 goto stop; \
00555 default: \
00556 goto out; \
00557 } \
00558 } while (0)
00559
00560 static int recvmsgs(struct nl_sock *sk, struct nl_cb *cb)
00561 {
00562 int n, err = 0, multipart = 0, interrupted = 0;
00563 unsigned char *buf = NULL;
00564 struct nlmsghdr *hdr;
00565 struct sockaddr_nl nla = {0};
00566 struct nl_msg *msg = NULL;
00567 struct ucred *creds = NULL;
00568
00569 continue_reading:
00570 NL_DBG(3, "Attempting to read from %p\n", sk);
00571 if (cb->cb_recv_ow)
00572 n = cb->cb_recv_ow(sk, &nla, &buf, &creds);
00573 else
00574 n = nl_recv(sk, &nla, &buf, &creds);
00575
00576 if (n <= 0)
00577 return n;
00578
00579 NL_DBG(3, "recvmsgs(%p): Read %d bytes\n", sk, n);
00580
00581 hdr = (struct nlmsghdr *) buf;
00582 while (nlmsg_ok(hdr, n)) {
00583 NL_DBG(3, "recvmsgs(%p): Processing valid message...\n", sk);
00584
00585 nlmsg_free(msg);
00586 msg = nlmsg_convert(hdr);
00587 if (!msg) {
00588 err = -NLE_NOMEM;
00589 goto out;
00590 }
00591
00592 nlmsg_set_proto(msg, sk->s_proto);
00593 nlmsg_set_src(msg, &nla);
00594 if (creds)
00595 nlmsg_set_creds(msg, creds);
00596
00597
00598
00599 if (cb->cb_set[NL_CB_MSG_IN])
00600 NL_CB_CALL(cb, NL_CB_MSG_IN, msg);
00601
00602
00603
00604
00605 if (cb->cb_set[NL_CB_SEQ_CHECK]) {
00606 NL_CB_CALL(cb, NL_CB_SEQ_CHECK, msg);
00607
00608
00609 } else if (!(sk->s_flags & NL_NO_AUTO_ACK)) {
00610 if (hdr->nlmsg_seq != sk->s_seq_expect) {
00611 if (cb->cb_set[NL_CB_INVALID])
00612 NL_CB_CALL(cb, NL_CB_INVALID, msg);
00613 else {
00614 err = -NLE_SEQ_MISMATCH;
00615 goto out;
00616 }
00617 }
00618 }
00619
00620 if (hdr->nlmsg_type == NLMSG_DONE ||
00621 hdr->nlmsg_type == NLMSG_ERROR ||
00622 hdr->nlmsg_type == NLMSG_NOOP ||
00623 hdr->nlmsg_type == NLMSG_OVERRUN) {
00624
00625
00626 sk->s_seq_expect++;
00627 NL_DBG(3, "recvmsgs(%p): Increased expected " \
00628 "sequence number to %d\n",
00629 sk, sk->s_seq_expect);
00630 }
00631
00632 if (hdr->nlmsg_flags & NLM_F_MULTI)
00633 multipart = 1;
00634
00635 if (hdr->nlmsg_flags & NLM_F_DUMP_INTR) {
00636 if (cb->cb_set[NL_CB_DUMP_INTR])
00637 NL_CB_CALL(cb, NL_CB_DUMP_INTR, msg);
00638 else {
00639
00640
00641
00642
00643
00644 interrupted = 1;
00645 }
00646 }
00647
00648
00649 if (hdr->nlmsg_flags & NLM_F_ACK) {
00650 if (cb->cb_set[NL_CB_SEND_ACK])
00651 NL_CB_CALL(cb, NL_CB_SEND_ACK, msg);
00652 else {
00653
00654 }
00655 }
00656
00657
00658
00659
00660
00661 if (hdr->nlmsg_type == NLMSG_DONE) {
00662 multipart = 0;
00663 if (cb->cb_set[NL_CB_FINISH])
00664 NL_CB_CALL(cb, NL_CB_FINISH, msg);
00665 }
00666
00667
00668
00669
00670
00671 else if (hdr->nlmsg_type == NLMSG_NOOP) {
00672 if (cb->cb_set[NL_CB_SKIPPED])
00673 NL_CB_CALL(cb, NL_CB_SKIPPED, msg);
00674 else
00675 goto skip;
00676 }
00677
00678
00679
00680
00681 else if (hdr->nlmsg_type == NLMSG_OVERRUN) {
00682 if (cb->cb_set[NL_CB_OVERRUN])
00683 NL_CB_CALL(cb, NL_CB_OVERRUN, msg);
00684 else {
00685 err = -NLE_MSG_OVERFLOW;
00686 goto out;
00687 }
00688 }
00689
00690
00691 else if (hdr->nlmsg_type == NLMSG_ERROR) {
00692 struct nlmsgerr *e = nlmsg_data(hdr);
00693
00694 if (hdr->nlmsg_len < nlmsg_size(sizeof(*e))) {
00695
00696
00697
00698
00699 if (cb->cb_set[NL_CB_INVALID])
00700 NL_CB_CALL(cb, NL_CB_INVALID, msg);
00701 else {
00702 err = -NLE_MSG_TRUNC;
00703 goto out;
00704 }
00705 } else if (e->error) {
00706
00707 if (cb->cb_err) {
00708 err = cb->cb_err(&nla, e,
00709 cb->cb_err_arg);
00710 if (err < 0)
00711 goto out;
00712 else if (err == NL_SKIP)
00713 goto skip;
00714 else if (err == NL_STOP) {
00715 err = -nl_syserr2nlerr(e->error);
00716 goto out;
00717 }
00718 } else {
00719 err = -nl_syserr2nlerr(e->error);
00720 goto out;
00721 }
00722 } else if (cb->cb_set[NL_CB_ACK])
00723 NL_CB_CALL(cb, NL_CB_ACK, msg);
00724 } else {
00725
00726
00727
00728 if (cb->cb_set[NL_CB_VALID])
00729 NL_CB_CALL(cb, NL_CB_VALID, msg);
00730 }
00731 skip:
00732 err = 0;
00733 hdr = nlmsg_next(hdr, &n);
00734 }
00735
00736 nlmsg_free(msg);
00737 free(buf);
00738 free(creds);
00739 buf = NULL;
00740 msg = NULL;
00741 creds = NULL;
00742
00743 if (multipart) {
00744
00745 goto continue_reading;
00746 }
00747 stop:
00748 err = 0;
00749 out:
00750 nlmsg_free(msg);
00751 free(buf);
00752 free(creds);
00753
00754 if (interrupted)
00755 err = -NLE_DUMP_INTR;
00756
00757 return err;
00758 }
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775 int nl_recvmsgs(struct nl_sock *sk, struct nl_cb *cb)
00776 {
00777 if (cb->cb_recvmsgs_ow)
00778 return cb->cb_recvmsgs_ow(sk, cb);
00779 else
00780 return recvmsgs(sk, cb);
00781 }
00782
00783
00784
00785
00786
00787
00788
00789 int nl_recvmsgs_default(struct nl_sock *sk)
00790 {
00791 return nl_recvmsgs(sk, sk->s_cb);
00792
00793 }
00794
00795 static int ack_wait_handler(struct nl_msg *msg, void *arg)
00796 {
00797 return NL_STOP;
00798 }
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808 int nl_wait_for_ack(struct nl_sock *sk)
00809 {
00810 int err;
00811 struct nl_cb *cb;
00812
00813 cb = nl_cb_clone(sk->s_cb);
00814 if (cb == NULL)
00815 return -NLE_NOMEM;
00816
00817 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_wait_handler, NULL);
00818 err = nl_recvmsgs(sk, cb);
00819 nl_cb_put(cb);
00820
00821 return err;
00822 }
00823
00824
00825 struct pickup_param
00826 {
00827 int (*parser)(struct nl_cache_ops *, struct sockaddr_nl *,
00828 struct nlmsghdr *, struct nl_parser_param *);
00829 struct nl_object *result;
00830 };
00831
00832 static int __store_answer(struct nl_object *obj, struct nl_parser_param *p)
00833 {
00834 struct pickup_param *pp = p->pp_arg;
00835
00836
00837
00838
00839 nl_object_get(obj);
00840 pp->result = obj;
00841
00842 return 0;
00843 }
00844
00845 static int __pickup_answer(struct nl_msg *msg, void *arg)
00846 {
00847 struct pickup_param *pp = arg;
00848 struct nl_parser_param parse_arg = {
00849 .pp_cb = __store_answer,
00850 .pp_arg = pp,
00851 };
00852
00853 return pp->parser(NULL, &msg->nm_src, msg->nm_nlh, &parse_arg);
00854 }
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866 int nl_pickup(struct nl_sock *sk,
00867 int (*parser)(struct nl_cache_ops *, struct sockaddr_nl *,
00868 struct nlmsghdr *, struct nl_parser_param *),
00869 struct nl_object **result)
00870 {
00871 struct nl_cb *cb;
00872 int err;
00873 struct pickup_param pp = {
00874 .parser = parser,
00875 };
00876
00877 cb = nl_cb_clone(sk->s_cb);
00878 if (cb == NULL)
00879 return -NLE_NOMEM;
00880
00881 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, __pickup_answer, &pp);
00882
00883 err = nl_recvmsgs(sk, cb);
00884 if (err < 0)
00885 goto errout;
00886
00887 *result = pp.result;
00888 errout:
00889 nl_cb_put(cb);
00890
00891 return err;
00892 }
00893
00894
00895
00896