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 d = memcmp(a->a_addr, b->a_addr, a->a_len);
00501
00502 if (d == 0)
00503 return (a->a_prefixlen - b->a_prefixlen);
00504 }
00505
00506 return d;
00507 }
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517 int nl_addr_cmp_prefix(struct nl_addr *a, struct nl_addr *b)
00518 {
00519 int d = a->a_family - b->a_family;
00520
00521 if (d == 0) {
00522 int len = min(a->a_prefixlen, b->a_prefixlen);
00523 int bytes = len / 8;
00524
00525 d = memcmp(a->a_addr, b->a_addr, bytes);
00526 if (d == 0) {
00527 int mask = (1UL << (len % 8)) - 1UL;
00528
00529 d = (a->a_addr[bytes] & mask) -
00530 (b->a_addr[bytes] & mask);
00531 }
00532 }
00533
00534 return d;
00535 }
00536
00537
00538
00539
00540
00541 int nl_addr_iszero(struct nl_addr *addr)
00542 {
00543 int i;
00544
00545 for (i = 0; i < addr->a_len; i++)
00546 if (addr->a_addr[i])
00547 return 0;
00548
00549 return 1;
00550 }
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560 int nl_addr_valid(char *addr, int family)
00561 {
00562 int ret;
00563 char buf[32];
00564
00565 switch (family) {
00566 case AF_INET:
00567 case AF_INET6:
00568 ret = inet_pton(family, addr, buf);
00569 if (ret <= 0)
00570 return 0;
00571 break;
00572
00573 case AF_DECnet:
00574 ret = dnet_pton(addr, buf);
00575 if (ret <= 0)
00576 return 0;
00577 break;
00578
00579 case AF_LLC:
00580 if (sscanf(addr, "%*02x:%*02x:%*02x:%*02x:%*02x:%*02x") != 6)
00581 return 0;
00582 break;
00583 }
00584
00585 return 1;
00586 }
00587
00588
00589
00590
00591
00592
00593 int nl_addr_guess_family(struct nl_addr *addr)
00594 {
00595 switch (addr->a_len) {
00596 case 4:
00597 return AF_INET;
00598 case 6:
00599 return AF_LLC;
00600 case 16:
00601 return AF_INET6;
00602 default:
00603 return AF_UNSPEC;
00604 }
00605 }
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620 int nl_addr_fill_sockaddr(struct nl_addr *addr, struct sockaddr *sa,
00621 socklen_t *salen)
00622 {
00623 switch (addr->a_family) {
00624 case AF_INET: {
00625 struct sockaddr_in *sai = (struct sockaddr_in *) sa;
00626
00627 if (*salen < sizeof(*sai))
00628 return -NLE_INVAL;
00629
00630 sai->sin_family = addr->a_family;
00631 memcpy(&sai->sin_addr, addr->a_addr, 4);
00632 *salen = sizeof(*sai);
00633 }
00634 break;
00635
00636 case AF_INET6: {
00637 struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *) sa;
00638
00639 if (*salen < sizeof(*sa6))
00640 return -NLE_INVAL;
00641
00642 sa6->sin6_family = addr->a_family;
00643 memcpy(&sa6->sin6_addr, addr->a_addr, 16);
00644 *salen = sizeof(*sa6);
00645 }
00646 break;
00647
00648 default:
00649 return -NLE_INVAL;
00650 }
00651
00652 return 0;
00653 }
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676 int nl_addr_info(struct nl_addr *addr, struct addrinfo **result)
00677 {
00678 int err;
00679 char buf[INET6_ADDRSTRLEN+5];
00680 struct addrinfo hint = {
00681 .ai_flags = AI_NUMERICHOST,
00682 .ai_family = addr->a_family,
00683 };
00684
00685 nl_addr2str(addr, buf, sizeof(buf));
00686
00687 err = getaddrinfo(buf, NULL, &hint, result);
00688 if (err != 0) {
00689 switch (err) {
00690 case EAI_ADDRFAMILY: return -NLE_AF_NOSUPPORT;
00691 case EAI_AGAIN: return -NLE_AGAIN;
00692 case EAI_BADFLAGS: return -NLE_INVAL;
00693 case EAI_FAIL: return -NLE_NOADDR;
00694 case EAI_FAMILY: return -NLE_AF_NOSUPPORT;
00695 case EAI_MEMORY: return -NLE_NOMEM;
00696 case EAI_NODATA: return -NLE_NOADDR;
00697 case EAI_NONAME: return -NLE_OBJ_NOTFOUND;
00698 case EAI_SERVICE: return -NLE_OPNOTSUPP;
00699 case EAI_SOCKTYPE: return -NLE_BAD_SOCK;
00700 default: return -NLE_FAILURE;
00701 }
00702 }
00703
00704 return 0;
00705 }
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720 int nl_addr_resolve(struct nl_addr *addr, char *host, size_t hostlen)
00721 {
00722 int err;
00723 struct sockaddr_in6 buf;
00724 socklen_t salen = sizeof(buf);
00725
00726 err = nl_addr_fill_sockaddr(addr, (struct sockaddr *) &buf, &salen);
00727 if (err < 0)
00728 return err;
00729
00730 err = getnameinfo((struct sockaddr *) &buf, salen, host, hostlen,
00731 NULL, 0, NI_NAMEREQD);
00732 if (err < 0)
00733 return nl_syserr2nlerr(err);
00734
00735 return 0;
00736 }
00737
00738
00739
00740
00741
00742
00743
00744
00745 void nl_addr_set_family(struct nl_addr *addr, int family)
00746 {
00747 addr->a_family = family;
00748 }
00749
00750 int nl_addr_get_family(struct nl_addr *addr)
00751 {
00752 return addr->a_family;
00753 }
00754
00755
00756
00757
00758
00759
00760
00761 int nl_addr_set_binary_addr(struct nl_addr *addr, void *buf, size_t len)
00762 {
00763 if (len > addr->a_maxsize)
00764 return -NLE_RANGE;
00765
00766 addr->a_len = len;
00767 memcpy(addr->a_addr, buf, len);
00768
00769 return 0;
00770 }
00771
00772
00773
00774
00775
00776 void *nl_addr_get_binary_addr(struct nl_addr *addr)
00777 {
00778 return addr->a_addr;
00779 }
00780
00781
00782
00783
00784
00785 unsigned int nl_addr_get_len(struct nl_addr *addr)
00786 {
00787 return addr->a_len;
00788 }
00789
00790 void nl_addr_set_prefixlen(struct nl_addr *addr, int prefixlen)
00791 {
00792 addr->a_prefixlen = prefixlen;
00793 }
00794
00795
00796
00797
00798
00799 unsigned int nl_addr_get_prefixlen(struct nl_addr *addr)
00800 {
00801 return addr->a_prefixlen;
00802 }
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822 char *nl_addr2str(struct nl_addr *addr, char *buf, size_t size)
00823 {
00824 int i;
00825 char tmp[16];
00826
00827 if (!addr || !addr->a_len) {
00828 snprintf(buf, size, "none");
00829 if (addr)
00830 goto prefix;
00831 else
00832 return buf;
00833 }
00834
00835 switch (addr->a_family) {
00836 case AF_INET:
00837 inet_ntop(AF_INET, addr->a_addr, buf, size);
00838 break;
00839
00840 case AF_INET6:
00841 inet_ntop(AF_INET6, addr->a_addr, buf, size);
00842 break;
00843
00844 case AF_DECnet:
00845 dnet_ntop(addr->a_addr, addr->a_len, buf, size);
00846 break;
00847
00848 case AF_LLC:
00849 default:
00850 snprintf(buf, size, "%02x",
00851 (unsigned char) addr->a_addr[0]);
00852 for (i = 1; i < addr->a_len; i++) {
00853 snprintf(tmp, sizeof(tmp), ":%02x",
00854 (unsigned char) addr->a_addr[i]);
00855 strncat(buf, tmp, size - strlen(buf) - 1);
00856 }
00857 break;
00858 }
00859
00860 prefix:
00861 if (addr->a_prefixlen != (8 * addr->a_len)) {
00862 snprintf(tmp, sizeof(tmp), "/%u", addr->a_prefixlen);
00863 strncat(buf, tmp, size - strlen(buf) - 1);
00864 }
00865
00866 return buf;
00867 }
00868
00869
00870
00871
00872
00873
00874
00875
00876 static const struct trans_tbl afs[] = {
00877 __ADD(AF_UNSPEC,unspec)
00878 __ADD(AF_UNIX,unix)
00879 __ADD(AF_LOCAL,local)
00880 __ADD(AF_INET,inet)
00881 __ADD(AF_AX25,ax25)
00882 __ADD(AF_IPX,ipx)
00883 __ADD(AF_APPLETALK,appletalk)
00884 __ADD(AF_NETROM,netrom)
00885 __ADD(AF_BRIDGE,bridge)
00886 __ADD(AF_ATMPVC,atmpvc)
00887 __ADD(AF_X25,x25)
00888 __ADD(AF_INET6,inet6)
00889 __ADD(AF_ROSE,rose)
00890 __ADD(AF_DECnet,decnet)
00891 __ADD(AF_NETBEUI,netbeui)
00892 __ADD(AF_SECURITY,security)
00893 __ADD(AF_KEY,key)
00894 __ADD(AF_NETLINK,netlink)
00895 __ADD(AF_ROUTE,route)
00896 __ADD(AF_PACKET,packet)
00897 __ADD(AF_ASH,ash)
00898 __ADD(AF_ECONET,econet)
00899 __ADD(AF_ATMSVC,atmsvc)
00900 __ADD(AF_SNA,sna)
00901 __ADD(AF_IRDA,irda)
00902 __ADD(AF_PPPOX,pppox)
00903 __ADD(AF_WANPIPE,wanpipe)
00904 __ADD(AF_LLC,llc)
00905 __ADD(AF_BLUETOOTH,bluetooth)
00906 };
00907
00908 char *nl_af2str(int family, char *buf, size_t size)
00909 {
00910 return __type2str(family, buf, size, afs, ARRAY_SIZE(afs));
00911 }
00912
00913 int nl_str2af(const char *name)
00914 {
00915 int fam = __str2type(name, afs, ARRAY_SIZE(afs));
00916 return fam >= 0 ? fam : -EINVAL;
00917 }
00918
00919
00920
00921