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 #include <netlink-local.h>
00029 #include <netlink/netlink.h>
00030 #include <netlink/utils.h>
00031 #include <netlink/addr.h>
00032 #include <linux/socket.h>
00033
00034
00035
00036 static inline uint16_t dn_ntohs(uint16_t addr)
00037 {
00038 union {
00039 uint8_t byte[2];
00040 uint16_t word;
00041 } u = {
00042 .word = addr,
00043 };
00044
00045 return ((uint16_t) u.byte[0]) | (((uint16_t) u.byte[1]) << 8);
00046 }
00047
00048 static inline int do_digit(char *str, uint16_t *addr, uint16_t scale,
00049 size_t *pos, size_t len, int *started)
00050 {
00051 uint16_t tmp = *addr / scale;
00052
00053 if (*pos == len)
00054 return 1;
00055
00056 if (((tmp) > 0) || *started || (scale == 1)) {
00057 *str = tmp + '0';
00058 *started = 1;
00059 (*pos)++;
00060 *addr -= (tmp * scale);
00061 }
00062
00063 return 0;
00064 }
00065
00066 static const char *dnet_ntop(char *addrbuf, size_t addrlen, char *str,
00067 size_t len)
00068 {
00069 uint16_t addr = dn_ntohs(*(uint16_t *)addrbuf);
00070 uint16_t area = addr >> 10;
00071 size_t pos = 0;
00072 int started = 0;
00073
00074 if (addrlen != 2)
00075 return NULL;
00076
00077 addr &= 0x03ff;
00078
00079 if (len == 0)
00080 return str;
00081
00082 if (do_digit(str + pos, &area, 10, &pos, len, &started))
00083 return str;
00084
00085 if (do_digit(str + pos, &area, 1, &pos, len, &started))
00086 return str;
00087
00088 if (pos == len)
00089 return str;
00090
00091 *(str + pos) = '.';
00092 pos++;
00093 started = 0;
00094
00095 if (do_digit(str + pos, &addr, 1000, &pos, len, &started))
00096 return str;
00097
00098 if (do_digit(str + pos, &addr, 100, &pos, len, &started))
00099 return str;
00100
00101 if (do_digit(str + pos, &addr, 10, &pos, len, &started))
00102 return str;
00103
00104 if (do_digit(str + pos, &addr, 1, &pos, len, &started))
00105 return str;
00106
00107 if (pos == len)
00108 return str;
00109
00110 *(str + pos) = 0;
00111
00112 return str;
00113 }
00114
00115 static int dnet_num(const char *src, uint16_t * dst)
00116 {
00117 int rv = 0;
00118 int tmp;
00119 *dst = 0;
00120
00121 while ((tmp = *src++) != 0) {
00122 tmp -= '0';
00123 if ((tmp < 0) || (tmp > 9))
00124 return rv;
00125
00126 rv++;
00127 (*dst) *= 10;
00128 (*dst) += tmp;
00129 }
00130
00131 return rv;
00132 }
00133
00134 static inline int dnet_pton(const char *src, char *addrbuf)
00135 {
00136 uint16_t area = 0;
00137 uint16_t node = 0;
00138 int pos;
00139
00140 pos = dnet_num(src, &area);
00141 if ((pos == 0) || (area > 63) ||
00142 ((*(src + pos) != '.') && (*(src + pos) != ',')))
00143 return -NLE_INVAL;
00144
00145 pos = dnet_num(src + pos + 1, &node);
00146 if ((pos == 0) || (node > 1023))
00147 return -NLE_INVAL;
00148
00149 *(uint16_t *)addrbuf = dn_ntohs((area << 10) | node);
00150
00151 return 1;
00152 }
00153
00154 static void addr_destroy(struct nl_addr *addr)
00155 {
00156 if (!addr)
00157 return;
00158
00159 if (addr->a_refcnt != 1)
00160 BUG();
00161
00162 free(addr);
00163 }
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175 struct nl_addr *nl_addr_alloc(size_t maxsize)
00176 {
00177 struct nl_addr *addr;
00178
00179 addr = calloc(1, sizeof(*addr) + maxsize);
00180 if (!addr)
00181 return NULL;
00182
00183 addr->a_refcnt = 1;
00184 addr->a_maxsize = maxsize;
00185
00186 return addr;
00187 }
00188
00189
00190
00191
00192
00193
00194
00195
00196 struct nl_addr *nl_addr_build(int family, void *buf, size_t size)
00197 {
00198 struct nl_addr *addr;
00199
00200 addr = nl_addr_alloc(size);
00201 if (!addr)
00202 return NULL;
00203
00204 addr->a_family = family;
00205 addr->a_len = size;
00206 addr->a_prefixlen = size*8;
00207
00208 if (size)
00209 memcpy(addr->a_addr, buf, size);
00210
00211 return addr;
00212 }
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224 struct nl_addr *nl_addr_alloc_attr(struct nlattr *nla, int family)
00225 {
00226 return nl_addr_build(family, nla_data(nla), nla_len(nla));
00227 }
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256 int nl_addr_parse(const char *addrstr, int hint, struct nl_addr **result)
00257 {
00258 int err, copy = 0, len = 0, family = AF_UNSPEC;
00259 char *str, *prefix, buf[32];
00260 struct nl_addr *addr = NULL;
00261
00262 str = strdup(addrstr);
00263 if (!str) {
00264 err = -NLE_NOMEM;
00265 goto errout;
00266 }
00267
00268 prefix = strchr(str, '/');
00269 if (prefix)
00270 *prefix = '\0';
00271
00272 if (!strcasecmp(str, "none")) {
00273 family = hint;
00274 goto prefix;
00275 }
00276
00277 if (!strcasecmp(str, "default") ||
00278 !strcasecmp(str, "all") ||
00279 !strcasecmp(str, "any")) {
00280
00281 switch (hint) {
00282 case AF_INET:
00283 case AF_UNSPEC:
00284
00285
00286
00287 family = AF_INET;
00288 len = 4;
00289 goto prefix;
00290
00291 case AF_INET6:
00292 family = AF_INET6;
00293 len = 16;
00294 goto prefix;
00295
00296 case AF_LLC:
00297 family = AF_LLC;
00298 len = 6;
00299 goto prefix;
00300
00301 default:
00302 err = -NLE_AF_NOSUPPORT;
00303 goto errout;
00304 }
00305 }
00306
00307 copy = 1;
00308
00309 if (hint == AF_INET || hint == AF_UNSPEC) {
00310 if (inet_pton(AF_INET, str, buf) > 0) {
00311 family = AF_INET;
00312 len = 4;
00313 goto prefix;
00314 }
00315 if (hint == AF_INET) {
00316 err = -NLE_NOADDR;
00317 goto errout;
00318 }
00319 }
00320
00321 if (hint == AF_INET6 || hint == AF_UNSPEC) {
00322 if (inet_pton(AF_INET6, str, buf) > 0) {
00323 family = AF_INET6;
00324 len = 16;
00325 goto prefix;
00326 }
00327 if (hint == AF_INET6) {
00328 err = -NLE_NOADDR;
00329 goto errout;
00330 }
00331 }
00332
00333 if ((hint == AF_LLC || hint == AF_UNSPEC) && strchr(str, ':')) {
00334 unsigned int a, b, c, d, e, f;
00335
00336 if (sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",
00337 &a, &b, &c, &d, &e, &f) == 6) {
00338 family = AF_LLC;
00339 len = 6;
00340 buf[0] = (unsigned char) a;
00341 buf[1] = (unsigned char) b;
00342 buf[2] = (unsigned char) c;
00343 buf[3] = (unsigned char) d;
00344 buf[4] = (unsigned char) e;
00345 buf[5] = (unsigned char) f;
00346 goto prefix;
00347 }
00348
00349 if (hint == AF_LLC) {
00350 err = -NLE_NOADDR;
00351 goto errout;
00352 }
00353 }
00354
00355 if ((hint == AF_DECnet || hint == AF_UNSPEC) &&
00356 (strchr(str, '.') || strchr(str, ','))) {
00357 if (dnet_pton(str, buf) > 0) {
00358 family = AF_DECnet;
00359 len = 2;
00360 goto prefix;
00361 }
00362 if (hint == AF_DECnet) {
00363 err = -NLE_NOADDR;
00364 goto errout;
00365 }
00366 }
00367
00368 if (hint == AF_UNSPEC && strchr(str, ':')) {
00369 int i = 0;
00370 char *s = str, *p;
00371 for (;;) {
00372 long l = strtol(s, &p, 16);
00373
00374 if (s == p || l > 0xff || i >= sizeof(buf)) {
00375 err = -NLE_INVAL;
00376 goto errout;
00377 }
00378
00379 buf[i++] = (unsigned char) l;
00380 if (*p == '\0')
00381 break;
00382 s = ++p;
00383 }
00384
00385 len = i;
00386 family = AF_UNSPEC;
00387 goto prefix;
00388 }
00389
00390 err = -NLE_NOADDR;
00391 goto errout;
00392
00393 prefix:
00394 addr = nl_addr_alloc(len);
00395 if (!addr) {
00396 err = -NLE_NOMEM;
00397 goto errout;
00398 }
00399
00400 nl_addr_set_family(addr, family);
00401
00402 if (copy)
00403 nl_addr_set_binary_addr(addr, buf, len);
00404
00405 if (prefix) {
00406 char *p;
00407 long pl = strtol(++prefix, &p, 0);
00408 if (p == prefix) {
00409 addr_destroy(addr);
00410 err = -NLE_INVAL;
00411 goto errout;
00412 }
00413 nl_addr_set_prefixlen(addr, pl);
00414 } else
00415 nl_addr_set_prefixlen(addr, len * 8);
00416
00417 *result = addr;
00418 err = 0;
00419 errout:
00420 free(str);
00421
00422 return err;
00423 }
00424
00425
00426
00427
00428
00429
00430
00431 struct nl_addr *nl_addr_clone(struct nl_addr *addr)
00432 {
00433 struct nl_addr *new;
00434
00435 new = nl_addr_build(addr->a_family, addr->a_addr, addr->a_len);
00436 if (new)
00437 new->a_prefixlen = addr->a_prefixlen;
00438
00439 return new;
00440 }
00441
00442
00443
00444
00445
00446
00447
00448
00449 struct nl_addr *nl_addr_get(struct nl_addr *addr)
00450 {
00451 addr->a_refcnt++;
00452
00453 return addr;
00454 }
00455
00456 void nl_addr_put(struct nl_addr *addr)
00457 {
00458 if (!addr)
00459 return;
00460
00461 if (addr->a_refcnt == 1)
00462 addr_destroy(addr);
00463 else
00464 addr->a_refcnt--;
00465 }
00466
00467
00468
00469
00470
00471
00472 int nl_addr_shared(struct nl_addr *addr)
00473 {
00474 return addr->a_refcnt > 1;
00475 }
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492 int nl_addr_cmp(struct nl_addr *a, struct nl_addr *b)
00493 {
00494 int d = a->a_family - b->a_family;
00495
00496 if (d == 0) {
00497 d = a->a_len - b->a_len;
00498
00499 if (a->a_len && d == 0)
00500 return memcmp(a->a_addr, b->a_addr, a->a_len);
00501 }
00502
00503 return d;
00504 }
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514 int nl_addr_cmp_prefix(struct nl_addr *a, struct nl_addr *b)
00515 {
00516 int d = a->a_family - b->a_family;
00517
00518 if (d == 0) {
00519 int len = min(a->a_prefixlen, b->a_prefixlen);
00520 int bytes = len / 8;
00521
00522 d = memcmp(a->a_addr, b->a_addr, bytes);
00523 if (d == 0) {
00524 int mask = (1UL << (len % 8)) - 1UL;
00525
00526 d = (a->a_addr[bytes] & mask) -
00527 (b->a_addr[bytes] & mask);
00528 }
00529 }
00530
00531 return d;
00532 }
00533
00534
00535
00536
00537
00538 int nl_addr_iszero(struct nl_addr *addr)
00539 {
00540 int i;
00541
00542 for (i = 0; i < addr->a_len; i++)
00543 if (addr->a_addr[i])
00544 return 0;
00545
00546 return 1;
00547 }
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557 int nl_addr_valid(char *addr, int family)
00558 {
00559 int ret;
00560 char buf[32];
00561
00562 switch (family) {
00563 case AF_INET:
00564 case AF_INET6:
00565 ret = inet_pton(family, addr, buf);
00566 if (ret <= 0)
00567 return 0;
00568 break;
00569
00570 case AF_DECnet:
00571 ret = dnet_pton(addr, buf);
00572 if (ret <= 0)
00573 return 0;
00574 break;
00575
00576 case AF_LLC:
00577 if (sscanf(addr, "%*02x:%*02x:%*02x:%*02x:%*02x:%*02x") != 6)
00578 return 0;
00579 break;
00580 }
00581
00582 return 1;
00583 }
00584
00585
00586
00587
00588
00589
00590 int nl_addr_guess_family(struct nl_addr *addr)
00591 {
00592 switch (addr->a_len) {
00593 case 4:
00594 return AF_INET;
00595 case 6:
00596 return AF_LLC;
00597 case 16:
00598 return AF_INET6;
00599 default:
00600 return AF_UNSPEC;
00601 }
00602 }
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617 int nl_addr_fill_sockaddr(struct nl_addr *addr, struct sockaddr *sa,
00618 socklen_t *salen)
00619 {
00620 switch (addr->a_family) {
00621 case AF_INET: {
00622 struct sockaddr_in *sai = (struct sockaddr_in *) sa;
00623
00624 if (*salen < sizeof(*sai))
00625 return -NLE_INVAL;
00626
00627 sai->sin_family = addr->a_family;
00628 memcpy(&sai->sin_addr, addr->a_addr, 4);
00629 *salen = sizeof(*sai);
00630 }
00631 break;
00632
00633 case AF_INET6: {
00634 struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *) sa;
00635
00636 if (*salen < sizeof(*sa6))
00637 return -NLE_INVAL;
00638
00639 sa6->sin6_family = addr->a_family;
00640 memcpy(&sa6->sin6_addr, addr->a_addr, 16);
00641 *salen = sizeof(*sa6);
00642 }
00643 break;
00644
00645 default:
00646 return -NLE_INVAL;
00647 }
00648
00649 return 0;
00650 }
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673 int nl_addr_info(struct nl_addr *addr, struct addrinfo **result)
00674 {
00675 int err;
00676 char buf[INET6_ADDRSTRLEN+5];
00677 struct addrinfo hint = {
00678 .ai_flags = AI_NUMERICHOST,
00679 .ai_family = addr->a_family,
00680 };
00681
00682 nl_addr2str(addr, buf, sizeof(buf));
00683
00684 err = getaddrinfo(buf, NULL, &hint, result);
00685 if (err != 0) {
00686 switch (err) {
00687 case EAI_ADDRFAMILY: return -NLE_AF_NOSUPPORT;
00688 case EAI_AGAIN: return -NLE_AGAIN;
00689 case EAI_BADFLAGS: return -NLE_INVAL;
00690 case EAI_FAIL: return -NLE_NOADDR;
00691 case EAI_FAMILY: return -NLE_AF_NOSUPPORT;
00692 case EAI_MEMORY: return -NLE_NOMEM;
00693 case EAI_NODATA: return -NLE_NOADDR;
00694 case EAI_NONAME: return -NLE_OBJ_NOTFOUND;
00695 case EAI_SERVICE: return -NLE_OPNOTSUPP;
00696 case EAI_SOCKTYPE: return -NLE_BAD_SOCK;
00697 default: return -NLE_FAILURE;
00698 }
00699 }
00700
00701 return 0;
00702 }
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717 int nl_addr_resolve(struct nl_addr *addr, char *host, size_t hostlen)
00718 {
00719 int err;
00720 struct sockaddr_in6 buf;
00721 socklen_t salen = sizeof(buf);
00722
00723 err = nl_addr_fill_sockaddr(addr, (struct sockaddr *) &buf, &salen);
00724 if (err < 0)
00725 return err;
00726
00727 err = getnameinfo((struct sockaddr *) &buf, salen, host, hostlen,
00728 NULL, 0, NI_NAMEREQD);
00729 if (err < 0)
00730 return nl_syserr2nlerr(err);
00731
00732 return 0;
00733 }
00734
00735
00736
00737
00738
00739
00740
00741
00742 void nl_addr_set_family(struct nl_addr *addr, int family)
00743 {
00744 addr->a_family = family;
00745 }
00746
00747 int nl_addr_get_family(struct nl_addr *addr)
00748 {
00749 return addr->a_family;
00750 }
00751
00752
00753
00754
00755
00756
00757
00758 int nl_addr_set_binary_addr(struct nl_addr *addr, void *buf, size_t len)
00759 {
00760 if (len > addr->a_maxsize)
00761 return -NLE_RANGE;
00762
00763 addr->a_len = len;
00764 memcpy(addr->a_addr, buf, len);
00765
00766 return 0;
00767 }
00768
00769
00770
00771
00772
00773 void *nl_addr_get_binary_addr(struct nl_addr *addr)
00774 {
00775 return addr->a_addr;
00776 }
00777
00778
00779
00780
00781
00782 unsigned int nl_addr_get_len(struct nl_addr *addr)
00783 {
00784 return addr->a_len;
00785 }
00786
00787 void nl_addr_set_prefixlen(struct nl_addr *addr, int prefixlen)
00788 {
00789 addr->a_prefixlen = prefixlen;
00790 }
00791
00792
00793
00794
00795
00796 unsigned int nl_addr_get_prefixlen(struct nl_addr *addr)
00797 {
00798 return addr->a_prefixlen;
00799 }
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819 char *nl_addr2str(struct nl_addr *addr, char *buf, size_t size)
00820 {
00821 int i;
00822 char tmp[16];
00823
00824 if (!addr || !addr->a_len) {
00825 snprintf(buf, size, "none");
00826 if (addr)
00827 goto prefix;
00828 else
00829 return buf;
00830 }
00831
00832 switch (addr->a_family) {
00833 case AF_INET:
00834 inet_ntop(AF_INET, addr->a_addr, buf, size);
00835 break;
00836
00837 case AF_INET6:
00838 inet_ntop(AF_INET6, addr->a_addr, buf, size);
00839 break;
00840
00841 case AF_DECnet:
00842 dnet_ntop(addr->a_addr, addr->a_len, buf, size);
00843 break;
00844
00845 case AF_LLC:
00846 default:
00847 snprintf(buf, size, "%02x",
00848 (unsigned char) addr->a_addr[0]);
00849 for (i = 1; i < addr->a_len; i++) {
00850 snprintf(tmp, sizeof(tmp), ":%02x",
00851 (unsigned char) addr->a_addr[i]);
00852 strncat(buf, tmp, size - strlen(buf) - 1);
00853 }
00854 break;
00855 }
00856
00857 prefix:
00858 if (addr->a_prefixlen != (8 * addr->a_len)) {
00859 snprintf(tmp, sizeof(tmp), "/%u", addr->a_prefixlen);
00860 strncat(buf, tmp, size - strlen(buf) - 1);
00861 }
00862
00863 return buf;
00864 }
00865
00866
00867
00868
00869
00870
00871
00872
00873 static const struct trans_tbl afs[] = {
00874 __ADD(AF_UNSPEC,unspec)
00875 __ADD(AF_UNIX,unix)
00876 __ADD(AF_LOCAL,local)
00877 __ADD(AF_INET,inet)
00878 __ADD(AF_AX25,ax25)
00879 __ADD(AF_IPX,ipx)
00880 __ADD(AF_APPLETALK,appletalk)
00881 __ADD(AF_NETROM,netrom)
00882 __ADD(AF_BRIDGE,bridge)
00883 __ADD(AF_ATMPVC,atmpvc)
00884 __ADD(AF_X25,x25)
00885 __ADD(AF_INET6,inet6)
00886 __ADD(AF_ROSE,rose)
00887 __ADD(AF_DECnet,decnet)
00888 __ADD(AF_NETBEUI,netbeui)
00889 __ADD(AF_SECURITY,security)
00890 __ADD(AF_KEY,key)
00891 __ADD(AF_NETLINK,netlink)
00892 __ADD(AF_ROUTE,route)
00893 __ADD(AF_PACKET,packet)
00894 __ADD(AF_ASH,ash)
00895 __ADD(AF_ECONET,econet)
00896 __ADD(AF_ATMSVC,atmsvc)
00897 __ADD(AF_SNA,sna)
00898 __ADD(AF_IRDA,irda)
00899 __ADD(AF_PPPOX,pppox)
00900 __ADD(AF_WANPIPE,wanpipe)
00901 __ADD(AF_LLC,llc)
00902 __ADD(AF_BLUETOOTH,bluetooth)
00903 };
00904
00905 char *nl_af2str(int family, char *buf, size_t size)
00906 {
00907 return __type2str(family, buf, size, afs, ARRAY_SIZE(afs));
00908 }
00909
00910 int nl_str2af(const char *name)
00911 {
00912 int fam = __str2type(name, afs, ARRAY_SIZE(afs));
00913 return fam >= 0 ? fam : -EINVAL;
00914 }
00915
00916
00917
00918