00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include <netlink-local.h>
00013 #include <netlink/netlink.h>
00014 #include <netlink/utils.h>
00015 #include <netlink/addr.h>
00016 #include <netlink/attr.h>
00017 #include <netlink/msg.h>
00018 #include <linux/socket.h>
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 int nla_attr_size(int payload)
00111 {
00112 return NLA_HDRLEN + payload;
00113 }
00114
00115
00116
00117
00118
00119 int nla_total_size(int payload)
00120 {
00121 return NLA_ALIGN(nla_attr_size(payload));
00122 }
00123
00124
00125
00126
00127
00128 int nla_padlen(int payload)
00129 {
00130 return nla_total_size(payload) - nla_attr_size(payload);
00131 }
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144 void *nla_data(const struct nlattr *nla)
00145 {
00146 return (char *) nla + NLA_HDRLEN;
00147 }
00148
00149
00150
00151
00152
00153 int nla_len(const struct nlattr *nla)
00154 {
00155 return nla->nla_len - NLA_HDRLEN;
00156 }
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170 int nla_ok(const struct nlattr *nla, int remaining)
00171 {
00172 return remaining >= sizeof(*nla) &&
00173 nla->nla_len >= sizeof(*nla) &&
00174 nla->nla_len <= remaining;
00175 }
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185 struct nlattr *nla_next(const struct nlattr *nla, int *remaining)
00186 {
00187 int totlen = NLA_ALIGN(nla->nla_len);
00188
00189 *remaining -= totlen;
00190 return (struct nlattr *) ((char *) nla + totlen);
00191 }
00192
00193 static uint16_t nla_attr_minlen[NLA_TYPE_MAX+1] = {
00194 [NLA_U8] = sizeof(uint8_t),
00195 [NLA_U16] = sizeof(uint16_t),
00196 [NLA_U32] = sizeof(uint32_t),
00197 [NLA_U64] = sizeof(uint64_t),
00198 [NLA_STRING] = 1,
00199 [NLA_NESTED] = NLA_HDRLEN,
00200 };
00201
00202 static int validate_nla(struct nlattr *nla, int maxtype,
00203 struct nla_policy *policy)
00204 {
00205 struct nla_policy *pt;
00206 int minlen = 0;
00207
00208 if (nla->nla_type <= 0 || nla->nla_type > maxtype)
00209 return 0;
00210
00211 pt = &policy[nla->nla_type];
00212
00213 if (pt->type > NLA_TYPE_MAX)
00214 BUG();
00215
00216 if (pt->minlen)
00217 minlen = pt->minlen;
00218 else if (pt->type != NLA_UNSPEC)
00219 minlen = nla_attr_minlen[pt->type];
00220
00221 if (pt->type == NLA_FLAG && nla_len(nla) > 0)
00222 return -ERANGE;
00223
00224 if (nla_len(nla) < minlen)
00225 return -ERANGE;
00226
00227 if (pt->maxlen && nla_len(nla) > pt->maxlen)
00228 return -ERANGE;
00229
00230 if (pt->type == NLA_STRING) {
00231 char *data = nla_data(nla);
00232 if (data[nla_len(nla) - 1] != '\0')
00233 return -EINVAL;
00234 }
00235
00236 return 0;
00237 }
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255 int nla_parse(struct nlattr *tb[], int maxtype, struct nlattr *head, int len,
00256 struct nla_policy *policy)
00257 {
00258 struct nlattr *nla;
00259 int rem, err;
00260
00261 memset(tb, 0, sizeof(struct nlattr *) * (maxtype + 1));
00262
00263 nla_for_each_attr(nla, head, len, rem) {
00264 uint16_t type = nla->nla_type;
00265
00266 if (type == 0) {
00267 fprintf(stderr, "Illegal nla->nla_type == 0\n");
00268 continue;
00269 }
00270
00271 if (type <= maxtype) {
00272 if (policy) {
00273 err = validate_nla(nla, maxtype, policy);
00274 if (err < 0)
00275 goto errout;
00276 }
00277
00278 tb[type] = nla;
00279 }
00280 }
00281
00282 if (rem > 0)
00283 fprintf(stderr, "netlink: %d bytes leftover after parsing "
00284 "attributes.\n", rem);
00285
00286 err = 0;
00287 errout:
00288 return err;
00289 }
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301 int nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla,
00302 struct nla_policy *policy)
00303 {
00304 return nla_parse(tb, maxtype, nla_data(nla), nla_len(nla), policy);
00305 }
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321 int nla_validate(struct nlattr *head, int len, int maxtype,
00322 struct nla_policy *policy)
00323 {
00324 struct nlattr *nla;
00325 int rem, err;
00326
00327 nla_for_each_attr(nla, head, len, rem) {
00328 err = validate_nla(nla, maxtype, policy);
00329 if (err < 0)
00330 goto errout;
00331 }
00332
00333 err = 0;
00334 errout:
00335 return err;
00336 }
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346 struct nlattr *nla_find(struct nlattr *head, int len, int attrtype)
00347 {
00348 struct nlattr *nla;
00349 int rem;
00350
00351 nla_for_each_attr(nla, head, len, rem)
00352 if (nla->nla_type == attrtype)
00353 return nla;
00354
00355 return NULL;
00356 }
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376 int nla_memcpy(void *dest, struct nlattr *src, int count)
00377 {
00378 int minlen;
00379
00380 if (!src)
00381 return 0;
00382
00383 minlen = min_t(int, count, nla_len(src));
00384 memcpy(dest, nla_data(src), minlen);
00385
00386 return minlen;
00387 }
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401 size_t nla_strlcpy(char *dst, const struct nlattr *nla, size_t dstsize)
00402 {
00403 size_t srclen = nla_len(nla);
00404 char *src = nla_data(nla);
00405
00406 if (srclen > 0 && src[srclen - 1] == '\0')
00407 srclen--;
00408
00409 if (dstsize > 0) {
00410 size_t len = (srclen >= dstsize) ? dstsize - 1 : srclen;
00411
00412 memset(dst, 0, dstsize);
00413 memcpy(dst, src, len);
00414 }
00415
00416 return srclen;
00417 }
00418
00419
00420
00421
00422
00423
00424
00425 int nla_memcmp(const struct nlattr *nla, const void *data,
00426 size_t size)
00427 {
00428 int d = nla_len(nla) - size;
00429
00430 if (d == 0)
00431 d = memcmp(nla_data(nla), data, size);
00432
00433 return d;
00434 }
00435
00436
00437
00438
00439
00440
00441 int nla_strcmp(const struct nlattr *nla, const char *str)
00442 {
00443 int len = strlen(str) + 1;
00444 int d = nla_len(nla) - len;
00445
00446 if (d == 0)
00447 d = memcmp(nla_data(nla), str, len);
00448
00449 return d;
00450 }
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468 struct nlattr *nla_reserve(struct nl_msg *n, int attrtype, int attrlen)
00469 {
00470 struct nlattr *nla;
00471 int tlen;
00472
00473 tlen = NLMSG_ALIGN(n->nm_nlh->nlmsg_len) + nla_total_size(attrlen);
00474
00475 n->nm_nlh = realloc(n->nm_nlh, tlen);
00476 if (!n->nm_nlh) {
00477 nl_errno(ENOMEM);
00478 return NULL;
00479 }
00480
00481 nla = (struct nlattr *) nlmsg_tail(n->nm_nlh);
00482 nla->nla_type = attrtype;
00483 nla->nla_len = nla_attr_size(attrlen);
00484
00485 memset((unsigned char *) nla + nla->nla_len, 0, nla_padlen(attrlen));
00486 n->nm_nlh->nlmsg_len = tlen;
00487
00488 return nla;
00489 }
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501 int nla_put(struct nl_msg *n, int attrtype, int attrlen, const void *data)
00502 {
00503 struct nlattr *nla;
00504
00505 nla = nla_reserve(n, attrtype, attrlen);
00506 if (!nla)
00507 return nl_errno(ENOMEM);
00508
00509 memcpy(nla_data(nla), data, attrlen);
00510
00511 return 0;
00512 }
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523 int nla_put_nested(struct nl_msg *n, int attrtype, struct nl_msg *nested)
00524 {
00525 return nla_put(n, attrtype, nlmsg_len(nested->nm_nlh),
00526 nlmsg_data(nested->nm_nlh));
00527 }
00528
00529
00530
00531
00532
00533
00534
00535 int nla_put_u8(struct nl_msg *n, int attrtype, uint8_t value)
00536 {
00537 return nla_put(n, attrtype, sizeof(uint8_t), &value);
00538 }
00539
00540
00541
00542
00543
00544
00545
00546 int nla_put_u16(struct nl_msg *n, int attrtype, uint16_t value)
00547 {
00548 return nla_put(n, attrtype, sizeof(uint16_t), &value);
00549 }
00550
00551
00552
00553
00554
00555
00556
00557 int nla_put_u32(struct nl_msg *n, int attrtype, uint32_t value)
00558 {
00559 return nla_put(n, attrtype, sizeof(uint32_t), &value);
00560 }
00561
00562
00563
00564
00565
00566
00567
00568 int nla_put_u64(struct nl_msg *n, int attrtype, uint64_t value)
00569 {
00570 return nla_put(n, attrtype, sizeof(uint64_t), &value);
00571 }
00572
00573
00574
00575
00576
00577
00578
00579 int nla_put_string(struct nl_msg *n, int attrtype, const char *str)
00580 {
00581 return nla_put(n, attrtype, strlen(str) + 1, str);
00582 }
00583
00584
00585
00586
00587
00588
00589 int nla_put_flag(struct nl_msg *n, int attrtype)
00590 {
00591 return nla_put(n, attrtype, 0, NULL);
00592 }
00593
00594
00595
00596
00597
00598
00599
00600 int nla_put_msecs(struct nl_msg *n, int attrtype, unsigned long msecs)
00601 {
00602 return nla_put_u64(n, attrtype, msecs);
00603 }
00604
00605
00606
00607
00608
00609
00610
00611 int nla_put_data(struct nl_msg *n, int attrtype, struct nl_data *data)
00612 {
00613 return nla_put(n, attrtype, nl_data_get_size(data),
00614 nl_data_get(data));
00615 }
00616
00617
00618
00619
00620
00621
00622
00623 int nla_put_addr(struct nl_msg *n, int attrtype, struct nl_addr *addr)
00624 {
00625 return nla_put(n, attrtype, nl_addr_get_len(addr),
00626 nl_addr_get_binary_addr(addr));
00627 }
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643 struct nlattr *nla_nest_start(struct nl_msg *n, int attrtype)
00644 {
00645 struct nlattr *start = (struct nlattr *) nlmsg_tail(n->nm_nlh);
00646
00647 if (nla_put(n, attrtype, 0, NULL) < 0)
00648 return NULL;
00649
00650 return start;
00651 }
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663 int nla_nest_end(struct nl_msg *n, struct nlattr *start)
00664 {
00665 start->nla_len = (unsigned char *) nlmsg_tail(n->nm_nlh) -
00666 (unsigned char *) start;
00667 return 0;
00668 }
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681 uint32_t nla_get_u32(struct nlattr *nla)
00682 {
00683 return *(uint32_t *) nla_data(nla);
00684 }
00685
00686
00687
00688
00689
00690 uint16_t nla_get_u16(struct nlattr *nla)
00691 {
00692 return *(uint16_t *) nla_data(nla);
00693 }
00694
00695
00696
00697
00698
00699 uint8_t nla_get_u8(struct nlattr *nla)
00700 {
00701 return *(uint8_t *) nla_data(nla);
00702 }
00703
00704
00705
00706
00707
00708 uint64_t nla_get_u64(struct nlattr *nla)
00709 {
00710 uint64_t tmp;
00711
00712 nla_memcpy(&tmp, nla, sizeof(tmp));
00713
00714 return tmp;
00715 }
00716
00717
00718
00719
00720
00721 int nla_get_flag(struct nlattr *nla)
00722 {
00723 return !!nla;
00724 }
00725
00726
00727
00728
00729
00730
00731
00732 unsigned long nla_get_msecs(struct nlattr *nla)
00733 {
00734 return nla_get_u64(nla);
00735 }
00736
00737
00738
00739
00740
00741
00742
00743
00744 struct nl_addr *nla_get_addr(struct nlattr *nla, int family)
00745 {
00746 return nl_addr_build(family, nla_data(nla), nla_len(nla));
00747 }
00748
00749
00750
00751
00752
00753
00754
00755 struct nl_data *nla_get_data(struct nlattr *nla)
00756 {
00757 return nl_data_alloc(nla_data(nla), nla_len(nla));
00758 }
00759
00760
00761
00762