30 #include <netlink-private/netlink.h>
31 #include <netlink/netlink.h>
32 #include <netlink/utils.h>
33 #include <netlink/addr.h>
34 #include <linux/socket.h>
38 static inline uint16_t dn_ntohs(uint16_t addr)
47 return ((uint16_t) u.byte[0]) | (((uint16_t) u.byte[1]) << 8);
50 static inline int do_digit(
char *str, uint16_t *addr, uint16_t scale,
51 size_t *pos,
size_t len,
int *started)
53 uint16_t tmp = *addr / scale;
58 if (((tmp) > 0) || *started || (scale == 1)) {
62 *addr -= (tmp * scale);
68 static const char *dnet_ntop(
char *addrbuf,
size_t addrlen,
char *str,
71 uint16_t addr = dn_ntohs(*(uint16_t *)addrbuf);
72 uint16_t area = addr >> 10;
84 if (do_digit(str + pos, &area, 10, &pos, len, &started))
87 if (do_digit(str + pos, &area, 1, &pos, len, &started))
97 if (do_digit(str + pos, &addr, 1000, &pos, len, &started))
100 if (do_digit(str + pos, &addr, 100, &pos, len, &started))
103 if (do_digit(str + pos, &addr, 10, &pos, len, &started))
106 if (do_digit(str + pos, &addr, 1, &pos, len, &started))
117 static int dnet_num(
const char *src, uint16_t * dst)
123 while ((tmp = *src++) != 0) {
125 if ((tmp < 0) || (tmp > 9))
136 static inline int dnet_pton(
const char *src,
char *addrbuf)
142 pos = dnet_num(src, &area);
143 if ((pos == 0) || (area > 63) ||
144 ((*(src + pos) !=
'.') && (*(src + pos) !=
',')))
147 pos = dnet_num(src + pos + 1, &node);
148 if ((pos == 0) || (node > 1023))
151 *(uint16_t *)addrbuf = dn_ntohs((area << 10) | node);
156 static void addr_destroy(
struct nl_addr *addr)
161 if (addr->a_refcnt != 1)
179 struct nl_addr *addr;
181 addr = calloc(1,
sizeof(*addr) + maxsize);
186 addr->a_maxsize = maxsize;
200 struct nl_addr *addr;
206 addr->a_family = family;
208 addr->a_prefixlen = size*8;
211 memcpy(addr->a_addr, buf, size);
260 int err, copy = 0, len = 0, family = AF_UNSPEC;
261 char *str, *prefix, buf[32];
262 struct nl_addr *addr = NULL;
264 str = strdup(addrstr);
270 prefix = strchr(str,
'/');
274 if (!strcasecmp(str,
"none")) {
279 if (!strcasecmp(str,
"default") ||
280 !strcasecmp(str,
"all") ||
281 !strcasecmp(str,
"any")) {
303 err = -NLE_AF_NOSUPPORT;
310 if (hint == AF_INET || hint == AF_UNSPEC) {
311 if (inet_pton(AF_INET, str, buf) > 0) {
316 if (hint == AF_INET) {
322 if (hint == AF_INET6 || hint == AF_UNSPEC) {
323 if (inet_pton(AF_INET6, str, buf) > 0) {
328 if (hint == AF_INET6) {
334 if ((hint == AF_LLC || hint == AF_UNSPEC) && strchr(str,
':')) {
335 unsigned int a, b, c, d, e, f;
337 if (sscanf(str,
"%02x:%02x:%02x:%02x:%02x:%02x",
338 &a, &b, &c, &d, &e, &f) == 6) {
341 buf[0] = (
unsigned char) a;
342 buf[1] = (
unsigned char) b;
343 buf[2] = (
unsigned char) c;
344 buf[3] = (
unsigned char) d;
345 buf[4] = (
unsigned char) e;
346 buf[5] = (
unsigned char) f;
350 if (hint == AF_LLC) {
356 if ((hint == AF_DECnet || hint == AF_UNSPEC) &&
357 (strchr(str,
'.') || strchr(str,
','))) {
358 if (dnet_pton(str, buf) > 0) {
363 if (hint == AF_DECnet) {
369 if (hint == AF_UNSPEC && strchr(str,
':')) {
373 long l = strtol(s, &p, 16);
375 if (s == p || l > 0xff || i >=
sizeof(buf)) {
380 buf[i++] = (
unsigned char) l;
401 nl_addr_set_family(addr, family);
408 long pl = strtol(++prefix, &p, 0);
414 nl_addr_set_prefixlen(addr, pl);
416 nl_addr_set_prefixlen(addr, len * 8);
436 new =
nl_addr_build(addr->a_family, addr->a_addr, addr->a_len);
438 new->a_prefixlen = addr->a_prefixlen;
450 struct nl_addr *nl_addr_get(
struct nl_addr *addr)
457 void nl_addr_put(
struct nl_addr *addr)
462 if (addr->a_refcnt == 1)
475 return addr->a_refcnt > 1;
495 int d = a->a_family - b->a_family;
498 d = a->a_len - b->a_len;
500 if (a->a_len && d == 0) {
501 d = memcmp(a->a_addr, b->a_addr, a->a_len);
504 return (a->a_prefixlen - b->a_prefixlen);
521 int d = a->a_family - b->a_family;
524 int len = min(a->a_prefixlen, b->a_prefixlen);
527 d = memcmp(a->a_addr, b->a_addr, bytes);
529 int mask = (1UL << (len % 8)) - 1UL;
531 d = (a->a_addr[bytes] & mask) -
532 (b->a_addr[bytes] & mask);
547 for (i = 0; i < addr->a_len; i++)
570 ret = inet_pton(family, addr, buf);
576 ret = dnet_pton(addr, buf);
582 if (sscanf(addr,
"%*02x:%*02x:%*02x:%*02x:%*02x:%*02x") != 6)
597 switch (addr->a_len) {
625 switch (addr->a_family) {
627 struct sockaddr_in *sai = (
struct sockaddr_in *) sa;
629 if (*salen <
sizeof(*sai))
632 sai->sin_family = addr->a_family;
633 memcpy(&sai->sin_addr, addr->a_addr, 4);
634 *salen =
sizeof(*sai);
639 struct sockaddr_in6 *sa6 = (
struct sockaddr_in6 *) sa;
641 if (*salen <
sizeof(*sa6))
644 sa6->sin6_family = addr->a_family;
645 memcpy(&sa6->sin6_addr, addr->a_addr, 16);
646 *salen =
sizeof(*sa6);
681 char buf[INET6_ADDRSTRLEN+5];
682 struct addrinfo hint = {
683 .ai_flags = AI_NUMERICHOST,
684 .ai_family = addr->a_family,
689 err = getaddrinfo(buf, NULL, &hint, result);
692 case EAI_ADDRFAMILY:
return -NLE_AF_NOSUPPORT;
693 case EAI_AGAIN:
return -NLE_AGAIN;
694 case EAI_BADFLAGS:
return -NLE_INVAL;
695 case EAI_FAIL:
return -NLE_NOADDR;
696 case EAI_FAMILY:
return -NLE_AF_NOSUPPORT;
697 case EAI_MEMORY:
return -NLE_NOMEM;
698 case EAI_NODATA:
return -NLE_NOADDR;
699 case EAI_NONAME:
return -NLE_OBJ_NOTFOUND;
700 case EAI_SERVICE:
return -NLE_OPNOTSUPP;
701 case EAI_SOCKTYPE:
return -NLE_BAD_SOCK;
702 default:
return -NLE_FAILURE;
725 struct sockaddr_in6 buf;
726 socklen_t salen =
sizeof(buf);
732 err = getnameinfo((
struct sockaddr *) &buf, salen, host, hostlen,
733 NULL, 0, NI_NAMEREQD);
735 return nl_syserr2nlerr(err);
747 void nl_addr_set_family(
struct nl_addr *addr,
int family)
749 addr->a_family = family;
752 int nl_addr_get_family(
struct nl_addr *addr)
754 return addr->a_family;
765 if (len > addr->a_maxsize)
769 memcpy(addr->a_addr, buf, len);
792 void nl_addr_set_prefixlen(
struct nl_addr *addr,
int prefixlen)
794 addr->a_prefixlen = prefixlen;
803 return addr->a_prefixlen;
829 if (!addr || !addr->a_len) {
830 snprintf(buf, size,
"none");
837 switch (addr->a_family) {
839 inet_ntop(AF_INET, addr->a_addr, buf, size);
843 inet_ntop(AF_INET6, addr->a_addr, buf, size);
847 dnet_ntop(addr->a_addr, addr->a_len, buf, size);
852 snprintf(buf, size,
"%02x",
853 (
unsigned char) addr->a_addr[0]);
854 for (i = 1; i < addr->a_len; i++) {
855 snprintf(tmp,
sizeof(tmp),
":%02x",
856 (
unsigned char) addr->a_addr[i]);
857 strncat(buf, tmp, size - strlen(buf) - 1);
863 if (addr->a_prefixlen != (8 * addr->a_len)) {
864 snprintf(tmp,
sizeof(tmp),
"/%u", addr->a_prefixlen);
865 strncat(buf, tmp, size - strlen(buf) - 1);
878 static const struct trans_tbl afs[] = {
879 __ADD(AF_UNSPEC,unspec)
881 __ADD(AF_LOCAL,local)
885 __ADD(AF_APPLETALK,appletalk)
886 __ADD(AF_NETROM,netrom)
887 __ADD(AF_BRIDGE,bridge)
888 __ADD(AF_ATMPVC,atmpvc)
890 __ADD(AF_INET6,inet6)
892 __ADD(AF_DECnet,decnet)
893 __ADD(AF_NETBEUI,netbeui)
894 __ADD(AF_SECURITY,security)
896 __ADD(AF_NETLINK,netlink)
897 __ADD(AF_ROUTE,route)
898 __ADD(AF_PACKET,packet)
900 __ADD(AF_ECONET,econet)
901 __ADD(AF_ATMSVC,atmsvc)
904 __ADD(AF_PPPOX,pppox)
905 __ADD(AF_WANPIPE,wanpipe)
907 __ADD(AF_BLUETOOTH,bluetooth)
910 char *nl_af2str(
int family,
char *buf,
size_t size)
912 return __type2str(family, buf, size, afs, ARRAY_SIZE(afs));
915 int nl_str2af(
const char *name)
917 int fam = __str2type(name, afs, ARRAY_SIZE(afs));
918 return fam >= 0 ? fam : -EINVAL;