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 #include <netlink-local.h>
00117 #include <netlink/netlink.h>
00118 #include <netlink/utils.h>
00119 #include <netlink/handlers.h>
00120 #include <netlink/msg.h>
00121 #include <netlink/attr.h>
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140 struct nl_handle *nl_handle_alloc_nondefault(enum nl_cb_kind kind)
00141 {
00142 struct nl_handle *handle;
00143
00144 handle = calloc(1, sizeof(*handle));
00145 if (!handle)
00146 goto errout;
00147
00148 handle->h_cb = nl_cb_new(kind);
00149 if (!handle->h_cb)
00150 goto errout;
00151
00152 handle->h_local.nl_family = AF_NETLINK;
00153 handle->h_peer.nl_family = AF_NETLINK;
00154 handle->h_local.nl_pid = getpid();
00155 handle->h_seq_expect = handle->h_seq_next = time(0);
00156
00157 return handle;
00158 errout:
00159 nl_handle_destroy(handle);
00160 nl_errno(ENOMEM);
00161 return NULL;
00162 }
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176 struct nl_handle *nl_handle_alloc(void)
00177 {
00178 return nl_handle_alloc_nondefault(NL_CB_DEFAULT);
00179 }
00180
00181
00182
00183
00184
00185 void nl_handle_destroy(struct nl_handle *handle)
00186 {
00187 if (!handle)
00188 return;
00189
00190 nl_cb_destroy(handle->h_cb);
00191 free(handle);
00192 }
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214 int nl_set_buffer_size(struct nl_handle *handle, int rxbuf, int txbuf)
00215 {
00216 int err;
00217
00218 if (rxbuf <= 0)
00219 rxbuf = 32768;
00220
00221 if (txbuf <= 0)
00222 txbuf = 32768;
00223
00224 err = setsockopt(handle->h_fd, SOL_SOCKET, SO_SNDBUF,
00225 &txbuf, sizeof(txbuf));
00226 if (err < 0)
00227 return nl_error(errno, "setsockopt(SO_SNDBUF) failed");
00228
00229 err = setsockopt(handle->h_fd, SOL_SOCKET, SO_RCVBUF,
00230 &rxbuf, sizeof(rxbuf));
00231 if (err < 0)
00232 return nl_error(errno, "setsockopt(SO_RCVBUF) failed");
00233
00234 handle->h_flags |= NL_SOCK_BUFSIZE_SET;
00235
00236 return 0;
00237 }
00238
00239
00240
00241
00242
00243
00244 int nl_set_passcred(struct nl_handle *handle, int state)
00245 {
00246 int err;
00247
00248 err = setsockopt(handle->h_fd, SOL_SOCKET, SO_PASSCRED,
00249 &state, sizeof(state));
00250 if (err < 0)
00251 return nl_error(errno, "setsockopt(SO_PASSCRED) failed");
00252
00253 if (state)
00254 handle->h_flags |= NL_SOCK_PASSCRED;
00255 else
00256 handle->h_flags &= ~NL_SOCK_PASSCRED;
00257
00258 return 0;
00259 }
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269 void nl_join_groups(struct nl_handle *handle, int groups)
00270 {
00271 handle->h_local.nl_groups |= groups;
00272 }
00273
00274 #ifndef SOL_NETLINK
00275 #define SOL_NETLINK 270
00276 #endif
00277
00278 int nl_join_group(struct nl_handle *handle, int group)
00279 {
00280 int err;
00281
00282 err = setsockopt(handle->h_fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP,
00283 &group, sizeof(group));
00284 if (err < 0)
00285 return nl_error(errno, "setsockopt(NETLINK_ADD_MEMBERSHIP) "
00286 "failed");
00287
00288 return 0;
00289 }
00290
00291 static int noop_seq_check(struct nl_msg *msg, void *arg)
00292 {
00293 return NL_PROCEED;
00294 }
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304 void nl_disable_sequence_check(struct nl_handle *handle)
00305 {
00306 nl_cb_set(nl_handle_get_cb(handle), NL_CB_SEQ_CHECK,
00307 NL_CB_CUSTOM, noop_seq_check, NULL);
00308 }
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322 pid_t nl_handle_get_pid(struct nl_handle *handle)
00323 {
00324 return handle->h_local.nl_pid;
00325 }
00326
00327
00328
00329
00330
00331
00332 void nl_handle_set_pid(struct nl_handle *handle, pid_t pid)
00333 {
00334 handle->h_local.nl_pid = pid;
00335 }
00336
00337
00338
00339
00340
00341
00342 pid_t nl_handle_get_peer_pid(struct nl_handle *handle)
00343 {
00344 return handle->h_peer.nl_pid;
00345 }
00346
00347
00348
00349
00350
00351
00352 void nl_handle_set_peer_pid(struct nl_handle *handle, pid_t pid)
00353 {
00354 handle->h_peer.nl_pid = pid;
00355 }
00356
00357
00358
00359
00360
00361
00362 int nl_handle_get_fd(struct nl_handle *handle)
00363 {
00364 return handle->h_fd;
00365 }
00366
00367
00368
00369
00370
00371
00372 struct sockaddr_nl *nl_handle_get_local_addr(struct nl_handle *handle)
00373 {
00374 return &handle->h_local;
00375 }
00376
00377
00378
00379
00380
00381
00382
00383 struct sockaddr_nl *nl_handle_get_peer_addr(struct nl_handle *handle)
00384 {
00385 return &handle->h_peer;
00386 }
00387
00388
00389
00390
00391
00392
00393 struct nl_cb *nl_handle_get_cb(struct nl_handle *handle)
00394 {
00395 return handle->h_cb;
00396 }
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415 int nl_connect(struct nl_handle *handle, int protocol)
00416 {
00417 int err;
00418 socklen_t addrlen;
00419
00420 handle->h_fd = socket(AF_NETLINK, SOCK_RAW, protocol);
00421 if (handle->h_fd < 0)
00422 return nl_error(1, "socket(AF_NETLINK, ...) failed");
00423
00424 if (!(handle->h_flags & NL_SOCK_BUFSIZE_SET)) {
00425 err = nl_set_buffer_size(handle, 0, 0);
00426 if (err < 0)
00427 return err;
00428 }
00429
00430 err = bind(handle->h_fd, (struct sockaddr*) &handle->h_local,
00431 sizeof(handle->h_local));
00432 if (err < 0)
00433 return nl_error(1, "bind() failed");
00434
00435 addrlen = sizeof(handle->h_local);
00436 err = getsockname(handle->h_fd, (struct sockaddr *) &handle->h_local,
00437 &addrlen);
00438 if (err < 0)
00439 return nl_error(1, "getsockname failed");
00440
00441 if (addrlen != sizeof(handle->h_local))
00442 return nl_error(EADDRNOTAVAIL, "Invalid address length");
00443
00444 if (handle->h_local.nl_family != AF_NETLINK)
00445 return nl_error(EPFNOSUPPORT, "Address format not supported");
00446
00447 handle->h_proto = protocol;
00448
00449 return 0;
00450 }
00451
00452
00453
00454
00455
00456 void nl_close(struct nl_handle *handle)
00457 {
00458 if (handle->h_fd >= 0) {
00459 close(handle->h_fd);
00460 handle->h_fd = -1;
00461 }
00462
00463 handle->h_proto = 0;
00464 }
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480 int nl_sendto(struct nl_handle *handle, void *buf, size_t size)
00481 {
00482 int ret;
00483
00484 ret = sendto(handle->h_fd, buf, size, 0, (struct sockaddr *)
00485 &handle->h_peer, sizeof(handle->h_peer));
00486 if (ret < 0)
00487 return nl_errno(errno);
00488
00489 return ret;
00490 }
00491
00492
00493
00494
00495
00496
00497
00498
00499 int nl_sendmsg(struct nl_handle *handle, struct nl_msg *msg, struct msghdr *hdr)
00500 {
00501 struct nl_cb *cb;
00502 int ret;
00503
00504 struct iovec iov = {
00505 .iov_base = (void *) nlmsg_hdr(msg),
00506 .iov_len = nlmsg_hdr(msg)->nlmsg_len,
00507 };
00508
00509 hdr->msg_iov = &iov;
00510 hdr->msg_iovlen = 1;
00511
00512 nlmsg_set_src(msg, &handle->h_local);
00513
00514 cb = nl_handle_get_cb(handle);
00515 if (cb->cb_set[NL_CB_MSG_OUT])
00516 if (nl_cb_call(cb, NL_CB_MSG_OUT, msg) != NL_PROCEED)
00517 return 0;
00518
00519 ret = sendmsg(handle->h_fd, hdr, 0);
00520 if (ret < 0)
00521 return nl_errno(errno);
00522
00523 return ret;
00524 }
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534 int nl_send(struct nl_handle *handle, struct nl_msg *msg)
00535 {
00536 struct sockaddr_nl *dst;
00537 struct ucred *creds;
00538
00539 struct msghdr hdr = {
00540 .msg_name = (void *) &handle->h_peer,
00541 .msg_namelen = sizeof(struct sockaddr_nl),
00542 };
00543
00544
00545
00546
00547 dst = nlmsg_get_dst(msg);
00548 if (dst->nl_family == AF_NETLINK)
00549 hdr.msg_name = dst;
00550
00551
00552 creds = nlmsg_get_creds(msg);
00553 if (creds != NULL) {
00554 char buf[CMSG_SPACE(sizeof(struct ucred))];
00555 struct cmsghdr *cmsg;
00556
00557 hdr.msg_control = buf;
00558 hdr.msg_controllen = sizeof(buf);
00559
00560 cmsg = CMSG_FIRSTHDR(&hdr);
00561 cmsg->cmsg_level = SOL_SOCKET;
00562 cmsg->cmsg_type = SCM_CREDENTIALS;
00563 cmsg->cmsg_len = CMSG_LEN(sizeof(struct ucred));
00564 memcpy(CMSG_DATA(cmsg), creds, sizeof(struct ucred));
00565 }
00566
00567 return nl_sendmsg(handle, msg, &hdr);
00568 }
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582 int nl_send_auto_complete(struct nl_handle *handle, struct nl_msg *msg)
00583 {
00584 struct nlmsghdr *nlh;
00585
00586 nlh = nlmsg_hdr(msg);
00587 if (nlh->nlmsg_pid == 0)
00588 nlh->nlmsg_pid = handle->h_local.nl_pid;
00589
00590 if (nlh->nlmsg_seq == 0)
00591 nlh->nlmsg_seq = handle->h_seq_next++;
00592
00593 nlh->nlmsg_flags |= (NLM_F_REQUEST | NLM_F_ACK);
00594
00595 if (handle->h_cb->cb_send_ow)
00596 return handle->h_cb->cb_send_ow(handle, msg);
00597 else
00598 return nl_send(handle, msg);
00599 }
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615 int nl_send_simple(struct nl_handle *handle, int type, int flags, void *buf,
00616 size_t size)
00617 {
00618 int err;
00619 struct nl_msg *msg;
00620 struct nlmsghdr nlh = {
00621 .nlmsg_len = nlmsg_msg_size(0),
00622 .nlmsg_type = type,
00623 .nlmsg_flags = flags,
00624 };
00625
00626 msg = nlmsg_build(&nlh);
00627 if (!msg)
00628 return nl_errno(ENOMEM);
00629
00630 if (buf && size)
00631 nlmsg_append(msg, buf, size, 1);
00632
00633 err = nl_send_auto_complete(handle, msg);
00634 nlmsg_free(msg);
00635
00636 return err;
00637 }
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665 int nl_recv(struct nl_handle *handle, struct sockaddr_nl *nla,
00666 unsigned char **buf, struct ucred **creds)
00667 {
00668 int n;
00669 int flags = MSG_PEEK;
00670
00671 struct iovec iov = {
00672 .iov_len = 4096,
00673 };
00674
00675 struct msghdr msg = {
00676 .msg_name = (void *) nla,
00677 .msg_namelen = sizeof(sizeof(struct sockaddr_nl)),
00678 .msg_iov = &iov,
00679 .msg_iovlen = 1,
00680 .msg_control = NULL,
00681 .msg_controllen = 0,
00682 .msg_flags = 0,
00683 };
00684 struct cmsghdr *cmsg;
00685
00686 iov.iov_base = *buf = calloc(1, iov.iov_len);
00687
00688 if (handle->h_flags & NL_SOCK_PASSCRED) {
00689 msg.msg_controllen = CMSG_SPACE(sizeof(struct ucred));
00690 msg.msg_control = calloc(1, msg.msg_controllen);
00691 }
00692 retry:
00693
00694 if ((n = recvmsg(handle->h_fd, &msg, flags)) <= 0) {
00695 if (!n)
00696 goto abort;
00697 else if (n < 0) {
00698 if (errno == EINTR)
00699 goto retry;
00700 else if (errno == EAGAIN)
00701 goto abort;
00702 else {
00703 free(msg.msg_control);
00704 free(*buf);
00705 return nl_error(errno, "recvmsg failed");
00706 }
00707 }
00708 }
00709
00710 if (iov.iov_len < n) {
00711
00712
00713 iov.iov_len *= 2;
00714 iov.iov_base = *buf = realloc(*buf, iov.iov_len);
00715 goto retry;
00716 } else if (msg.msg_flags & MSG_CTRUNC) {
00717 msg.msg_controllen *= 2;
00718 msg.msg_control = realloc(msg.msg_control, msg.msg_controllen);
00719 goto retry;
00720 } else if (flags != 0) {
00721
00722 flags = 0;
00723 goto retry;
00724 }
00725
00726 if (msg.msg_namelen != sizeof(struct sockaddr_nl)) {
00727 free(msg.msg_control);
00728 free(*buf);
00729 return nl_error(EADDRNOTAVAIL, "socket address size mismatch");
00730 }
00731
00732 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
00733 if (cmsg->cmsg_level == SOL_SOCKET &&
00734 cmsg->cmsg_type == SCM_CREDENTIALS) {
00735 *creds = calloc(1, sizeof(struct ucred));
00736 memcpy(*creds, CMSG_DATA(cmsg), sizeof(struct ucred));
00737 break;
00738 }
00739 }
00740
00741 free(msg.msg_control);
00742 return n;
00743
00744 abort:
00745 free(msg.msg_control);
00746 free(*buf);
00747 return 0;
00748 }
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765 int nl_recvmsgs(struct nl_handle *handle, struct nl_cb *cb)
00766 {
00767 int n, err = 0;
00768 unsigned char *buf = NULL;
00769 struct nlmsghdr *hdr;
00770 struct sockaddr_nl nla = {0};
00771 struct nl_msg *msg = NULL;
00772 struct ucred *creds = NULL;
00773
00774 continue_reading:
00775 if (cb->cb_recv_ow)
00776 n = cb->cb_recv_ow(handle, &nla, &buf, &creds);
00777 else
00778 n = nl_recv(handle, &nla, &buf, &creds);
00779
00780 if (n <= 0)
00781 return n;
00782
00783 NL_DBG(3, "recvmsgs(%p): Read %d bytes\n", handle, n);
00784
00785 hdr = (struct nlmsghdr *) buf;
00786 while (nlmsg_ok(hdr, n)) {
00787 NL_DBG(3, "recgmsgs(%p): Processing valid message...\n",
00788 handle);
00789
00790 nlmsg_free(msg);
00791 msg = nlmsg_convert(hdr);
00792 if (!msg) {
00793 err = nl_errno(ENOMEM);
00794 goto out;
00795 }
00796
00797 nlmsg_set_proto(msg, handle->h_proto);
00798 nlmsg_set_src(msg, &nla);
00799 if (creds)
00800 nlmsg_set_creds(msg, creds);
00801
00802
00803
00804 if (cb->cb_set[NL_CB_MSG_IN]) {
00805 err = nl_cb_call(cb, NL_CB_MSG_IN, msg);
00806 if (err == NL_SKIP)
00807 goto skip;
00808 else if (err == NL_EXIT || err < 0)
00809 goto out;
00810 }
00811
00812
00813
00814
00815 if (cb->cb_set[NL_CB_SEQ_CHECK]) {
00816 err = nl_cb_call(cb, NL_CB_SEQ_CHECK, msg);
00817 if (err == NL_SKIP)
00818 goto skip;
00819 else if (err == NL_EXIT || err < 0)
00820 goto out;
00821 } else if (hdr->nlmsg_seq != handle->h_seq_expect) {
00822 if (cb->cb_set[NL_CB_INVALID]) {
00823 err = nl_cb_call(cb, NL_CB_INVALID, msg);
00824 if (err == NL_SKIP)
00825 goto skip;
00826 else if (err == NL_EXIT || err < 0)
00827 goto out;
00828 } else
00829 goto out;
00830 }
00831
00832 if (hdr->nlmsg_type == NLMSG_DONE ||
00833 hdr->nlmsg_type == NLMSG_ERROR ||
00834 hdr->nlmsg_type == NLMSG_NOOP ||
00835 hdr->nlmsg_type == NLMSG_OVERRUN) {
00836
00837
00838 handle->h_seq_expect++;
00839 NL_DBG(3, "recvmsgs(%p): Increased expected " \
00840 "sequence number to %d\n",
00841 handle, handle->h_seq_expect);
00842 }
00843
00844
00845 if (hdr->nlmsg_flags & NLM_F_ACK) {
00846 if (cb->cb_set[NL_CB_SEND_ACK]) {
00847 err = nl_cb_call(cb, NL_CB_SEND_ACK, msg);
00848 if (err == NL_SKIP)
00849 goto skip;
00850 else if (err == NL_EXIT || err < 0)
00851 goto out;
00852 } else {
00853
00854 }
00855 }
00856
00857
00858
00859
00860
00861 if (hdr->nlmsg_type == NLMSG_DONE) {
00862 if (cb->cb_set[NL_CB_FINISH]) {
00863 err = nl_cb_call(cb, NL_CB_FINISH, msg);
00864 if (err == NL_SKIP)
00865 goto skip;
00866 else if (err == NL_EXIT || err < 0)
00867 goto out;
00868 }
00869 err = 0;
00870 goto out;
00871 }
00872
00873
00874
00875
00876
00877 else if (hdr->nlmsg_type == NLMSG_NOOP) {
00878 if (cb->cb_set[NL_CB_SKIPPED]) {
00879 err = nl_cb_call(cb, NL_CB_SKIPPED, msg);
00880 if (err == NL_SKIP)
00881 goto skip;
00882 else if (err == NL_EXIT || err < 0)
00883 goto out;
00884 } else
00885 goto skip;
00886 }
00887
00888
00889
00890
00891 else if (hdr->nlmsg_type == NLMSG_OVERRUN) {
00892 if (cb->cb_set[NL_CB_OVERRUN]) {
00893 err = nl_cb_call(cb, NL_CB_OVERRUN, msg);
00894 if (err == NL_SKIP)
00895 goto skip;
00896 else if (err == NL_EXIT || err < 0)
00897 goto out;
00898 } else
00899 goto out;
00900 }
00901
00902
00903 else if (hdr->nlmsg_type == NLMSG_ERROR) {
00904 struct nlmsgerr *e = nlmsg_data(hdr);
00905
00906 if (hdr->nlmsg_len < nlmsg_msg_size(sizeof(*e))) {
00907
00908
00909
00910
00911 if (cb->cb_set[NL_CB_INVALID]) {
00912 err = nl_cb_call(cb, NL_CB_INVALID,
00913 msg);
00914 if (err == NL_SKIP)
00915 goto skip;
00916 else if (err == NL_EXIT || err < 0)
00917 goto out;
00918 } else
00919 goto out;
00920 } else if (e->error) {
00921
00922 if (cb->cb_err) {
00923 err = cb->cb_err(&nla, e,
00924 cb->cb_err_arg);
00925 if (err == NL_SKIP)
00926 goto skip;
00927 else if (err == NL_EXIT || err < 0) {
00928 nl_error(-e->error,
00929 "Netlink Error");
00930 err = e->error;
00931 goto out;
00932 }
00933 } else {
00934 nl_error(-e->error, "Netlink Error");
00935 err = e->error;
00936 goto out;
00937 }
00938 } else if (cb->cb_set[NL_CB_ACK]) {
00939
00940 err = nl_cb_call(cb, NL_CB_ACK, msg);
00941 if (err == NL_SKIP)
00942 goto skip;
00943 else if (err == NL_EXIT || err < 0)
00944 goto out;
00945 }
00946 } else {
00947
00948
00949
00950 if (cb->cb_set[NL_CB_VALID]) {
00951 err = nl_cb_call(cb, NL_CB_VALID, msg);
00952 if (err == NL_SKIP)
00953 goto skip;
00954 else if (err == NL_EXIT || err < 0)
00955 goto out;
00956 }
00957 }
00958 skip:
00959 hdr = nlmsg_next(hdr, &n);
00960 }
00961
00962 nlmsg_free(msg);
00963 free(buf);
00964 free(creds);
00965 buf = NULL;
00966 msg = NULL;
00967 creds = NULL;
00968
00969
00970 goto continue_reading;
00971
00972 out:
00973 nlmsg_free(msg);
00974 free(buf);
00975 free(creds);
00976
00977 return err;
00978 }
00979
00980
00981
00982
00983
00984
00985
00986 int nl_recvmsgs_def(struct nl_handle *handle)
00987 {
00988 if (handle->h_cb->cb_recvmsgs_ow)
00989 return handle->h_cb->cb_recvmsgs_ow(handle, handle->h_cb);
00990 else
00991 return nl_recvmsgs(handle, handle->h_cb);
00992 }
00993
00994 static int ack_wait_handler(struct nl_msg *msg, void *arg)
00995 {
00996 return NL_EXIT;
00997 }
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007 int nl_wait_for_ack(struct nl_handle *handle)
01008 {
01009 int err;
01010 struct nl_cb *cb = nl_cb_clone(nl_handle_get_cb(handle));
01011
01012 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_wait_handler, NULL);
01013
01014 err = nl_recvmsgs(handle, cb);
01015 nl_cb_destroy(cb);
01016
01017 return err;
01018 }
01019
01020
01021
01022
01023
01024
01025
01026
01027 static struct trans_tbl nlfamilies[] = {
01028 __ADD(NETLINK_ROUTE,route)
01029 __ADD(NETLINK_W1,w1)
01030 __ADD(NETLINK_USERSOCK,usersock)
01031 __ADD(NETLINK_FIREWALL,firewall)
01032 __ADD(NETLINK_INET_DIAG,inetdiag)
01033 __ADD(NETLINK_NFLOG,nflog)
01034 __ADD(NETLINK_XFRM,xfrm)
01035 __ADD(NETLINK_SELINUX,selinux)
01036 __ADD(NETLINK_ISCSI,iscsi)
01037 __ADD(NETLINK_AUDIT,audit)
01038 __ADD(NETLINK_FIB_LOOKUP,fib_lookup)
01039 __ADD(NETLINK_CONNECTOR,connector)
01040 __ADD(NETLINK_NETFILTER,netfilter)
01041 __ADD(NETLINK_IP6_FW,ip6_fw)
01042 __ADD(NETLINK_DNRTMSG,dnrtmsg)
01043 __ADD(NETLINK_KOBJECT_UEVENT,kobject_uevent)
01044 __ADD(NETLINK_GENERIC,generic)
01045 };
01046
01047
01048
01049
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059 char * nl_nlfamily2str(int family, char *buf, size_t size)
01060 {
01061 return __type2str(family, buf, size, nlfamilies,
01062 ARRAY_SIZE(nlfamilies));
01063 }
01064
01065
01066
01067
01068
01069
01070
01071
01072
01073
01074 int nl_str2nlfamily(const char *name)
01075 {
01076 return __str2type(name, nlfamilies, ARRAY_SIZE(nlfamilies));
01077 }
01078
01079
01080