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