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