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 #include <netlink-local.h>
00151 #include <netlink/netlink.h>
00152 #include <netlink/utils.h>
00153 #include <netlink/cache.h>
00154 #include <netlink/attr.h>
00155 #include <linux/socket.h>
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166 int nlmsg_msg_size(int payload)
00167 {
00168 return NLMSG_HDRLEN + payload;
00169 }
00170
00171
00172
00173
00174
00175 int nlmsg_total_size(int payload)
00176 {
00177 return NLMSG_ALIGN(nlmsg_msg_size(payload));
00178 }
00179
00180
00181
00182
00183
00184 int nlmsg_padlen(int payload)
00185 {
00186 return nlmsg_total_size(payload) - nlmsg_msg_size(payload);
00187 }
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200 void *nlmsg_data(const struct nlmsghdr *nlh)
00201 {
00202 return (unsigned char *) nlh + NLMSG_HDRLEN;
00203 }
00204
00205 void *nlmsg_tail(const struct nlmsghdr *nlh)
00206 {
00207 return (unsigned char *) nlh + NLMSG_ALIGN(nlh->nlmsg_len);
00208 }
00209
00210
00211
00212
00213
00214 int nlmsg_len(const struct nlmsghdr *nlh)
00215 {
00216 return nlh->nlmsg_len - NLMSG_HDRLEN;
00217 }
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231 struct nlattr *nlmsg_attrdata(const struct nlmsghdr *nlh, int hdrlen)
00232 {
00233 unsigned char *data = nlmsg_data(nlh);
00234 return (struct nlattr *) (data + NLMSG_ALIGN(hdrlen));
00235 }
00236
00237
00238
00239
00240
00241
00242 int nlmsg_attrlen(const struct nlmsghdr *nlh, int hdrlen)
00243 {
00244 return nlmsg_len(nlh) - NLMSG_ALIGN(hdrlen);
00245 }
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259 int nlmsg_ok(const struct nlmsghdr *nlh, int remaining)
00260 {
00261 return (remaining >= sizeof(struct nlmsghdr) &&
00262 nlh->nlmsg_len >= sizeof(struct nlmsghdr) &&
00263 nlh->nlmsg_len <= remaining);
00264 }
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274 struct nlmsghdr *nlmsg_next(struct nlmsghdr *nlh, int *remaining)
00275 {
00276 int totlen = NLMSG_ALIGN(nlh->nlmsg_len);
00277
00278 *remaining -= totlen;
00279
00280 return (struct nlmsghdr *) ((unsigned char *) nlh + totlen);
00281 }
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293 int nlmsg_parse(struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[],
00294 int maxtype, struct nla_policy *policy)
00295 {
00296 if (nlh->nlmsg_len < nlmsg_msg_size(hdrlen))
00297 return nl_errno(EINVAL);
00298
00299 return nla_parse(tb, maxtype, nlmsg_attrdata(nlh, hdrlen),
00300 nlmsg_attrlen(nlh, hdrlen), policy);
00301 }
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311 struct nlattr *nlmsg_find_attr(struct nlmsghdr *nlh, int hdrlen, int attrtype)
00312 {
00313 return nla_find(nlmsg_attrdata(nlh, hdrlen),
00314 nlmsg_attrlen(nlh, hdrlen), attrtype);
00315 }
00316
00317
00318
00319
00320
00321
00322
00323
00324 int nlmsg_validate(struct nlmsghdr *nlh, int hdrlen, int maxtype,
00325 struct nla_policy *policy)
00326 {
00327 if (nlh->nlmsg_len < nlmsg_msg_size(hdrlen))
00328 return nl_errno(EINVAL);
00329
00330 return nla_validate(nlmsg_attrdata(nlh, hdrlen),
00331 nlmsg_attrlen(nlh, hdrlen), maxtype, policy);
00332 }
00333
00334
00335
00336
00337
00338
00339
00340
00341 struct nl_msg *nlmsg_new(void)
00342 {
00343 struct nl_msg *nm;
00344
00345 nm = calloc(1, sizeof(*nm));
00346 if (!nm)
00347 goto errout;
00348
00349 nm->nm_nlh = calloc(1, nlmsg_msg_size(0));
00350 if (!nm->nm_nlh)
00351 goto errout;
00352
00353 nm->nm_nlh->nlmsg_len = nlmsg_msg_size(0);
00354 return nm;
00355 errout:
00356 free(nm);
00357 nl_errno(ENOMEM);
00358 return NULL;
00359 }
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373 struct nl_msg *nlmsg_build(struct nlmsghdr *hdr)
00374 {
00375 struct nl_msg *nm;
00376
00377 nm = nlmsg_new();
00378 if (nm && hdr) {
00379 int size = nm->nm_nlh->nlmsg_len;
00380 memcpy(nm->nm_nlh, hdr, sizeof(*hdr));
00381 nm->nm_nlh->nlmsg_len = size;
00382 }
00383
00384 return nm;
00385 }
00386
00387 struct nl_msg *nlmsg_build_simple(int nlmsgtype, int flags)
00388 {
00389 struct nlmsghdr nlh = {
00390 .nlmsg_type = nlmsgtype,
00391 .nlmsg_flags = flags,
00392 };
00393
00394 return nlmsg_build(&nlh);
00395 }
00396
00397 struct nl_msg *nlmsg_build_no_hdr(void)
00398 {
00399 return nlmsg_build(NULL);
00400 }
00401
00402 struct nl_msg *nlmsg_convert(struct nlmsghdr *hdr)
00403 {
00404 struct nl_msg *nm;
00405
00406 nm = calloc(1, sizeof(struct nl_msg));
00407 if (!nm)
00408 goto errout;
00409
00410 nm->nm_nlh = calloc(1, NLMSG_ALIGN(hdr->nlmsg_len));
00411 if (!nm->nm_nlh)
00412 goto errout;
00413
00414 memcpy(nm->nm_nlh, hdr, NLMSG_ALIGN(hdr->nlmsg_len));
00415
00416 return nm;
00417 errout:
00418 free(nm);
00419 nl_errno(ENOMEM);
00420 return NULL;
00421 }
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441 int nlmsg_append(struct nl_msg *n, void *data, size_t len, int pad)
00442 {
00443 void *tmp;
00444
00445 if (pad)
00446 len = NLMSG_ALIGN(len);
00447
00448 tmp = realloc(n->nm_nlh, n->nm_nlh->nlmsg_len + len);
00449 if (!tmp)
00450 return nl_errno(ENOMEM);
00451
00452 n->nm_nlh = tmp;
00453 memcpy((void *) n->nm_nlh + n->nm_nlh->nlmsg_len, data, len);
00454 n->nm_nlh->nlmsg_len += len;
00455
00456 return 0;
00457 }
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469 struct nlmsghdr *nlmsg_put(struct nl_msg *n, uint32_t pid, uint32_t seq,
00470 int type, int payload, int flags)
00471 {
00472 struct nlmsghdr *nlh;
00473
00474 if (n->nm_nlh->nlmsg_len < NLMSG_HDRLEN)
00475 BUG();
00476
00477 nlh = (struct nlmsghdr *) n->nm_nlh;
00478 nlh->nlmsg_type = type;
00479 nlh->nlmsg_len = nlmsg_msg_size(payload);
00480 nlh->nlmsg_flags = flags;
00481 nlh->nlmsg_pid = pid;
00482 nlh->nlmsg_seq = seq;
00483
00484 memset((unsigned char *) nlmsg_data(nlh) + payload, 0,
00485 nlmsg_padlen(payload));
00486
00487 return nlh;
00488 }
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499 struct nlmsghdr *nlmsg_hdr(struct nl_msg *n)
00500 {
00501 return n->nm_nlh;
00502 }
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512 void nlmsg_free(struct nl_msg *n)
00513 {
00514 if (!n)
00515 return;
00516
00517 free(n->nm_nlh);
00518 free(n);
00519 }
00520
00521
00522
00523
00524
00525
00526
00527
00528 void nlmsg_set_proto(struct nl_msg *msg, int protocol)
00529 {
00530 msg->nm_protocol = protocol;
00531 }
00532
00533 int nlmsg_get_proto(struct nl_msg *msg)
00534 {
00535 return msg->nm_protocol;
00536 }
00537
00538 void nlmsg_set_src(struct nl_msg *msg, struct sockaddr_nl *addr)
00539 {
00540 memcpy(&msg->nm_src, addr, sizeof(*addr));
00541 }
00542
00543 struct sockaddr_nl *nlmsg_get_src(struct nl_msg *msg)
00544 {
00545 return &msg->nm_src;
00546 }
00547
00548 void nlmsg_set_dst(struct nl_msg *msg, struct sockaddr_nl *addr)
00549 {
00550 memcpy(&msg->nm_dst, addr, sizeof(*addr));
00551 }
00552
00553 struct sockaddr_nl *nlmsg_get_dst(struct nl_msg *msg)
00554 {
00555 return &msg->nm_dst;
00556 }
00557
00558 void nlmsg_set_creds(struct nl_msg *msg, struct ucred *creds)
00559 {
00560 memcpy(&msg->nm_creds, creds, sizeof(*creds));
00561 msg->nm_flags |= NL_MSG_CRED_PRESENT;
00562 }
00563
00564 struct ucred *nlmsg_get_creds(struct nl_msg *msg)
00565 {
00566 if (msg->nm_flags & NL_MSG_CRED_PRESENT)
00567 return &msg->nm_creds;
00568 return NULL;
00569 }
00570
00571
00572
00573
00574
00575
00576
00577
00578 static struct trans_tbl nl_msgtypes[] = {
00579 __ADD(NLMSG_NOOP,NOOP)
00580 __ADD(NLMSG_ERROR,ERROR)
00581 __ADD(NLMSG_DONE,DONE)
00582 __ADD(NLMSG_OVERRUN,OVERRUN)
00583 };
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597 char *nl_nlmsgtype2str(int type, char *buf, size_t size)
00598 {
00599 return __type2str(type, buf, size, nl_msgtypes,
00600 ARRAY_SIZE(nl_msgtypes));
00601 }
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613 int nl_str2nlmsgtype(const char *name)
00614 {
00615 return __str2type(name, nl_msgtypes, ARRAY_SIZE(nl_msgtypes));
00616 }
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636 char *nl_nlmsg_flags2str(int flags, char *buf, size_t len)
00637 {
00638 memset(buf, 0, len);
00639
00640 #define PRINT_FLAG(f) \
00641 if (flags & NLM_F_##f) { \
00642 flags &= ~NLM_F_##f; \
00643 strncat(buf, #f, len - strlen(buf) - 1); \
00644 if (flags) \
00645 strncat(buf, ",", len - strlen(buf) - 1); \
00646 }
00647
00648 PRINT_FLAG(REQUEST);
00649 PRINT_FLAG(MULTI);
00650 PRINT_FLAG(ACK);
00651 PRINT_FLAG(ECHO);
00652 PRINT_FLAG(ROOT);
00653 PRINT_FLAG(MATCH);
00654 PRINT_FLAG(ATOMIC);
00655 PRINT_FLAG(REPLACE);
00656 PRINT_FLAG(EXCL);
00657 PRINT_FLAG(CREATE);
00658 PRINT_FLAG(APPEND);
00659
00660 if (flags) {
00661 char s[32];
00662 snprintf(s, sizeof(s), "0x%x", flags);
00663 strncat(buf, s, len - strlen(buf) - 1);
00664 }
00665 #undef PRINT_FLAG
00666
00667 return buf;
00668 }
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678 struct dp_xdata {
00679 void (*cb)(struct nl_object *, void *);
00680 void *arg;
00681 };
00682
00683
00684 static int parse_cb(struct nl_object *obj, struct nl_parser_param *p)
00685 {
00686 struct dp_xdata *x = p->pp_arg;
00687
00688 x->cb(obj, x->arg);
00689 nl_object_put(obj);
00690 return 0;
00691 }
00692
00693 int nl_msg_parse(struct nl_msg *msg, void (*cb)(struct nl_object *, void *),
00694 void *arg)
00695 {
00696 struct nl_cache_ops *ops;
00697 struct nl_parser_param p = {
00698 .pp_cb = parse_cb
00699 };
00700 struct dp_xdata x = {
00701 .cb = cb,
00702 .arg = arg,
00703 };
00704
00705 ops = nl_cache_mngt_associate(nlmsg_get_proto(msg),
00706 nlmsg_hdr(msg)->nlmsg_type);
00707 if (ops == NULL)
00708 return nl_error(ENOENT, "Unknown message type %d",
00709 nlmsg_hdr(msg)->nlmsg_type);
00710 p.pp_arg = &x;
00711
00712 return nl_cache_parse(ops, NULL, nlmsg_hdr(msg), &p);
00713 }
00714
00715
00716
00717