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;
00480
00481 if (page_size == 0)
00482 page_size = getpagesize();
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 (iov.iov_len < n ||
00511 msg.msg_flags & MSG_TRUNC) {
00512
00513
00514 iov.iov_len *= 2;
00515 iov.iov_base = *buf = realloc(*buf, iov.iov_len);
00516 goto retry;
00517 } else if (msg.msg_flags & MSG_CTRUNC) {
00518 msg.msg_controllen *= 2;
00519 msg.msg_control = realloc(msg.msg_control, msg.msg_controllen);
00520 goto retry;
00521 } else if (flags != 0) {
00522
00523 flags = 0;
00524 goto retry;
00525 }
00526
00527 if (msg.msg_namelen != sizeof(struct sockaddr_nl)) {
00528 free(msg.msg_control);
00529 free(*buf);
00530 return nl_error(EADDRNOTAVAIL, "socket address size mismatch");
00531 }
00532
00533 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
00534 if (cmsg->cmsg_level == SOL_SOCKET &&
00535 cmsg->cmsg_type == SCM_CREDENTIALS) {
00536 *creds = calloc(1, sizeof(struct ucred));
00537 memcpy(*creds, CMSG_DATA(cmsg), sizeof(struct ucred));
00538 break;
00539 }
00540 }
00541
00542 free(msg.msg_control);
00543 return n;
00544
00545 abort:
00546 free(msg.msg_control);
00547 free(*buf);
00548 return 0;
00549 }
00550
00551 #define NL_CB_CALL(cb, type, msg) \
00552 do { \
00553 err = nl_cb_call(cb, type, msg); \
00554 switch (err) { \
00555 case NL_OK: \
00556 err = 0; \
00557 break; \
00558 case NL_SKIP: \
00559 goto skip; \
00560 case NL_STOP: \
00561 goto stop; \
00562 default: \
00563 goto out; \
00564 } \
00565 } while (0)
00566
00567 static int recvmsgs(struct nl_handle *handle, struct nl_cb *cb)
00568 {
00569 int n, err = 0, multipart = 0;
00570 unsigned char *buf = NULL;
00571 struct nlmsghdr *hdr;
00572 struct sockaddr_nl nla = {0};
00573 struct nl_msg *msg = NULL;
00574 struct ucred *creds = NULL;
00575
00576 continue_reading:
00577 NL_DBG(3, "Attempting to read from %p\n", handle);
00578 if (cb->cb_recv_ow)
00579 n = cb->cb_recv_ow(handle, &nla, &buf, &creds);
00580 else
00581 n = nl_recv(handle, &nla, &buf, &creds);
00582
00583 if (n <= 0)
00584 return n;
00585
00586 NL_DBG(3, "recvmsgs(%p): Read %d bytes\n", handle, n);
00587
00588 hdr = (struct nlmsghdr *) buf;
00589 while (nlmsg_ok(hdr, n)) {
00590 NL_DBG(3, "recgmsgs(%p): Processing valid message...\n",
00591 handle);
00592
00593 nlmsg_free(msg);
00594 msg = nlmsg_convert(hdr);
00595 if (!msg) {
00596 err = nl_errno(ENOMEM);
00597 goto out;
00598 }
00599
00600 nlmsg_set_proto(msg, handle->h_proto);
00601 nlmsg_set_src(msg, &nla);
00602 if (creds)
00603 nlmsg_set_creds(msg, creds);
00604
00605
00606
00607 if (cb->cb_set[NL_CB_MSG_IN])
00608 NL_CB_CALL(cb, NL_CB_MSG_IN, msg);
00609
00610
00611
00612
00613 if (cb->cb_set[NL_CB_SEQ_CHECK])
00614 NL_CB_CALL(cb, NL_CB_SEQ_CHECK, msg);
00615 else if (hdr->nlmsg_seq != handle->h_seq_expect) {
00616 if (cb->cb_set[NL_CB_INVALID])
00617 NL_CB_CALL(cb, NL_CB_INVALID, msg);
00618 else {
00619 err = nl_error(EINVAL,
00620 "Sequence number mismatch");
00621 goto out;
00622 }
00623 }
00624
00625 if (hdr->nlmsg_type == NLMSG_DONE ||
00626 hdr->nlmsg_type == NLMSG_ERROR ||
00627 hdr->nlmsg_type == NLMSG_NOOP ||
00628 hdr->nlmsg_type == NLMSG_OVERRUN) {
00629
00630
00631 handle->h_seq_expect++;
00632 NL_DBG(3, "recvmsgs(%p): Increased expected " \
00633 "sequence number to %d\n",
00634 handle, handle->h_seq_expect);
00635 }
00636
00637 if (hdr->nlmsg_flags & NLM_F_MULTI)
00638 multipart = 1;
00639
00640
00641 if (hdr->nlmsg_flags & NLM_F_ACK) {
00642 if (cb->cb_set[NL_CB_SEND_ACK])
00643 NL_CB_CALL(cb, NL_CB_SEND_ACK, msg);
00644 else {
00645
00646 }
00647 }
00648
00649
00650
00651
00652
00653 if (hdr->nlmsg_type == NLMSG_DONE) {
00654 multipart = 0;
00655 if (cb->cb_set[NL_CB_FINISH])
00656 NL_CB_CALL(cb, NL_CB_FINISH, msg);
00657 }
00658
00659
00660
00661
00662
00663 else if (hdr->nlmsg_type == NLMSG_NOOP) {
00664 if (cb->cb_set[NL_CB_SKIPPED])
00665 NL_CB_CALL(cb, NL_CB_SKIPPED, msg);
00666 else
00667 goto skip;
00668 }
00669
00670
00671
00672
00673 else if (hdr->nlmsg_type == NLMSG_OVERRUN) {
00674 if (cb->cb_set[NL_CB_OVERRUN])
00675 NL_CB_CALL(cb, NL_CB_OVERRUN, msg);
00676 else {
00677 err = nl_error(EOVERFLOW, "Overrun");
00678 goto out;
00679 }
00680 }
00681
00682
00683 else if (hdr->nlmsg_type == NLMSG_ERROR) {
00684 struct nlmsgerr *e = nlmsg_data(hdr);
00685
00686 if (hdr->nlmsg_len < nlmsg_msg_size(sizeof(*e))) {
00687
00688
00689
00690
00691 if (cb->cb_set[NL_CB_INVALID])
00692 NL_CB_CALL(cb, NL_CB_INVALID, msg);
00693 else {
00694 err = nl_error(EINVAL,
00695 "Truncated error message");
00696 goto out;
00697 }
00698 } else if (e->error) {
00699
00700 if (cb->cb_err) {
00701 err = cb->cb_err(&nla, e,
00702 cb->cb_err_arg);
00703 if (err < 0)
00704 goto out;
00705 else if (err == NL_SKIP)
00706 goto skip;
00707 else if (err == NL_STOP) {
00708 err = nl_error(-e->error,
00709 "Netlink Error");
00710 goto out;
00711 }
00712 } else {
00713 err = nl_error(-e->error,
00714 "Netlink Error");
00715 goto out;
00716 }
00717 } else if (cb->cb_set[NL_CB_ACK])
00718 NL_CB_CALL(cb, NL_CB_ACK, msg);
00719 } else {
00720
00721
00722
00723 if (cb->cb_set[NL_CB_VALID])
00724 NL_CB_CALL(cb, NL_CB_VALID, msg);
00725 }
00726 skip:
00727 err = 0;
00728 hdr = nlmsg_next(hdr, &n);
00729 }
00730
00731 nlmsg_free(msg);
00732 free(buf);
00733 free(creds);
00734 buf = NULL;
00735 msg = NULL;
00736 creds = NULL;
00737
00738 if (multipart) {
00739
00740 goto continue_reading;
00741 }
00742 stop:
00743 err = 0;
00744 out:
00745 nlmsg_free(msg);
00746 free(buf);
00747 free(creds);
00748
00749 return err;
00750 }
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767 int nl_recvmsgs(struct nl_handle *handle, struct nl_cb *cb)
00768 {
00769 if (cb->cb_recvmsgs_ow)
00770 return cb->cb_recvmsgs_ow(handle, cb);
00771 else
00772 return recvmsgs(handle, cb);
00773 }
00774
00775
00776
00777
00778
00779
00780
00781 int nl_recvmsgs_default(struct nl_handle *handle)
00782 {
00783 return nl_recvmsgs(handle, handle->h_cb);
00784
00785 }
00786
00787 static int ack_wait_handler(struct nl_msg *msg, void *arg)
00788 {
00789 return NL_STOP;
00790 }
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800 int nl_wait_for_ack(struct nl_handle *handle)
00801 {
00802 int err;
00803 struct nl_cb *cb;
00804
00805 cb = nl_cb_clone(handle->h_cb);
00806 if (cb == NULL)
00807 return nl_get_errno();
00808
00809 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_wait_handler, NULL);
00810 err = nl_recvmsgs(handle, cb);
00811 nl_cb_put(cb);
00812
00813 return err;
00814 }
00815
00816
00817
00818