30 #include <netlink-private/netlink.h> 31 #include <netlink/netlink.h> 32 #include <netlink/utils.h> 33 #include <netlink/addr.h> 34 #include <netlink-private/route/mpls.h> 35 #include <linux/socket.h> 39 static inline uint16_t dn_ntohs(uint16_t addr)
48 return ((uint16_t) u.byte[0]) | (((uint16_t) u.byte[1]) << 8);
51 static inline int do_digit(
char *str, uint16_t *addr, uint16_t scale,
52 size_t *pos,
size_t len,
int *started)
54 uint16_t tmp = *addr / scale;
59 if (((tmp) > 0) || *started || (scale == 1)) {
63 *addr -= (tmp * scale);
69 static const char *dnet_ntop(
const char *addrbuf,
size_t addrlen,
char *str,
72 uint16_t addr = dn_ntohs(*(uint16_t *)addrbuf);
73 uint16_t area = addr >> 10;
85 if (do_digit(str + pos, &area, 10, &pos, len, &started))
88 if (do_digit(str + pos, &area, 1, &pos, len, &started))
98 if (do_digit(str + pos, &addr, 1000, &pos, len, &started))
101 if (do_digit(str + pos, &addr, 100, &pos, len, &started))
104 if (do_digit(str + pos, &addr, 10, &pos, len, &started))
107 if (do_digit(str + pos, &addr, 1, &pos, len, &started))
118 static int dnet_num(
const char *src, uint16_t * dst)
124 while ((tmp = *src++) != 0) {
126 if ((tmp < 0) || (tmp > 9))
137 static inline int dnet_pton(
const char *src,
char *addrbuf)
143 pos = dnet_num(src, &area);
144 if ((pos == 0) || (area > 63) ||
145 ((*(src + pos) !=
'.') && (*(src + pos) !=
',')))
148 pos = dnet_num(src + pos + 1, &node);
149 if ((pos == 0) || (node > 1023))
152 *(uint16_t *)addrbuf = dn_ntohs((area << 10) | node);
157 static void addr_destroy(
struct nl_addr *addr)
162 if (addr->a_refcnt != 1)
188 struct nl_addr *addr;
190 addr = calloc(1,
sizeof(*addr) + maxsize);
195 addr->a_maxsize = maxsize;
219 struct nl_addr *addr;
225 addr->a_family = family;
229 addr->a_prefixlen = 20;
232 addr->a_prefixlen = size*8;
236 memcpy(addr->a_addr, buf, size);
300 int err, copy = 0, len = 0, family = AF_UNSPEC, plen = 0;
301 char *str, *prefix = NULL, buf[256];
302 struct nl_addr *addr = NULL;
304 str = strdup(addrstr);
310 if (hint != AF_MPLS) {
311 prefix = strchr(str,
'/');
316 if (!strcasecmp(str,
"none")) {
321 if (!strcasecmp(str,
"default") ||
322 !strcasecmp(str,
"all") ||
323 !strcasecmp(str,
"any")) {
345 err = -NLE_AF_NOSUPPORT;
352 if (hint == AF_INET || hint == AF_UNSPEC) {
353 if (inet_pton(AF_INET, str, buf) > 0) {
358 if (hint == AF_INET) {
364 if (hint == AF_INET6 || hint == AF_UNSPEC) {
365 if (inet_pton(AF_INET6, str, buf) > 0) {
370 if (hint == AF_INET6) {
376 if ((hint == AF_LLC || hint == AF_UNSPEC) && strchr(str,
':')) {
377 unsigned int a, b, c, d, e, f;
379 if (sscanf(str,
"%02x:%02x:%02x:%02x:%02x:%02x",
380 &a, &b, &c, &d, &e, &f) == 6) {
383 buf[0] = (
unsigned char) a;
384 buf[1] = (
unsigned char) b;
385 buf[2] = (
unsigned char) c;
386 buf[3] = (
unsigned char) d;
387 buf[4] = (
unsigned char) e;
388 buf[5] = (
unsigned char) f;
392 if (hint == AF_LLC) {
398 if ((hint == AF_DECnet || hint == AF_UNSPEC) &&
399 (strchr(str,
'.') || strchr(str,
','))) {
400 if (dnet_pton(str, buf) > 0) {
405 if (hint == AF_DECnet) {
411 if (hint == AF_MPLS) {
412 len = mpls_pton(AF_MPLS, str, buf,
sizeof(buf));
422 if (hint == AF_UNSPEC && strchr(str,
':')) {
426 long l = strtol(s, &p, 16);
428 if (s == p || l > 0xff || i >=
sizeof(buf)) {
433 buf[i++] = (
unsigned char) l;
461 long pl = strtol(++prefix, &p, 0);
497 new =
nl_addr_build(addr->a_family, addr->a_addr, addr->a_len);
499 new->a_prefixlen = addr->a_prefixlen;
544 if (addr->a_refcnt == 1)
558 return addr->a_refcnt > 1;
587 int d = a->a_family - b->a_family;
590 d = a->a_len - b->a_len;
592 if (a->a_len && d == 0) {
593 d = memcmp(a->a_addr, b->a_addr, a->a_len);
596 return (a->a_prefixlen - b->a_prefixlen);
618 int d = a->a_family - b->a_family;
621 int len = min(a->a_prefixlen, b->a_prefixlen);
624 d = memcmp(a->a_addr, b->a_addr, bytes);
625 if (d == 0 && (len % 8) != 0) {
626 int mask = (0xFF00 >> (len % 8)) & 0xFF;
628 d = (a->a_addr[bytes] & mask) -
629 (b->a_addr[bytes] & mask);
646 for (i = 0; i < addr->a_len; i++)
669 ret = inet_pton(family, addr, buf);
675 ret = mpls_pton(family, addr, buf,
sizeof(buf));
681 ret = dnet_pton(addr, buf);
687 if (sscanf(addr,
"%*02x:%*02x:%*02x:%*02x:%*02x:%*02x") != 6)
703 switch (addr->a_len) {
731 switch (addr->a_family) {
733 struct sockaddr_in *sai = (
struct sockaddr_in *) sa;
735 if (*salen <
sizeof(*sai))
738 if (addr->a_len == 4)
739 memcpy(&sai->sin_addr, addr->a_addr, 4);
740 else if (addr->a_len != 0)
743 memset(&sai->sin_addr, 0, 4);
745 sai->sin_family = addr->a_family;
746 *salen =
sizeof(*sai);
751 struct sockaddr_in6 *sa6 = (
struct sockaddr_in6 *) sa;
753 if (*salen <
sizeof(*sa6))
756 if (addr->a_len == 16)
757 memcpy(&sa6->sin6_addr, addr->a_addr, 16);
758 else if (addr->a_len != 0)
761 memset(&sa6->sin6_addr, 0, 16);
763 sa6->sin6_family = addr->a_family;
764 *salen =
sizeof(*sa6);
799 char buf[INET6_ADDRSTRLEN+5];
800 struct addrinfo hint = {
801 .ai_flags = AI_NUMERICHOST,
802 .ai_family = addr->a_family,
807 err = getaddrinfo(buf, NULL, &hint, result);
810 case EAI_ADDRFAMILY:
return -NLE_AF_NOSUPPORT;
811 case EAI_AGAIN:
return -NLE_AGAIN;
812 case EAI_BADFLAGS:
return -NLE_INVAL;
813 case EAI_FAIL:
return -NLE_NOADDR;
814 case EAI_FAMILY:
return -NLE_AF_NOSUPPORT;
815 case EAI_MEMORY:
return -NLE_NOMEM;
816 case EAI_NODATA:
return -NLE_NOADDR;
817 case EAI_NONAME:
return -NLE_OBJ_NOTFOUND;
818 case EAI_SERVICE:
return -NLE_OPNOTSUPP;
819 case EAI_SOCKTYPE:
return -NLE_BAD_SOCK;
820 default:
return -NLE_FAILURE;
843 struct sockaddr_in6 buf;
844 socklen_t salen =
sizeof(buf);
850 err = getnameinfo((
struct sockaddr *) &buf, salen, host, hostlen,
851 NULL, 0, NI_NAMEREQD);
853 return nl_syserr2nlerr(err);
874 addr->a_family = family;
887 return addr->a_family;
912 if (len > addr->a_maxsize)
916 memset(addr->a_addr, 0, addr->a_maxsize);
919 memcpy(addr->a_addr, buf, len);
935 return (
void*)addr->a_addr;
959 addr->a_prefixlen = prefixlen;
970 return addr->a_prefixlen;
991 char *
nl_addr2str(
const struct nl_addr *addr,
char *buf,
size_t size)
996 if (!addr || !addr->a_len) {
997 snprintf(buf, size,
"none");
1004 switch (addr->a_family) {
1006 inet_ntop(AF_INET, addr->a_addr, buf, size);
1010 inet_ntop(AF_INET6, addr->a_addr, buf, size);
1014 mpls_ntop(AF_MPLS, addr->a_addr, buf, size);
1018 dnet_ntop(addr->a_addr, addr->a_len, buf, size);
1023 snprintf(buf, size,
"%02x",
1024 (
unsigned char) addr->a_addr[0]);
1025 for (i = 1; i < addr->a_len; i++) {
1026 snprintf(tmp,
sizeof(tmp),
":%02x",
1027 (
unsigned char) addr->a_addr[i]);
1028 strncat(buf, tmp, size - strlen(buf) - 1);
1034 if (addr->a_family != AF_MPLS &&
1035 addr->a_prefixlen != (8 * addr->a_len)) {
1036 snprintf(tmp,
sizeof(tmp),
"/%u", addr->a_prefixlen);
1037 strncat(buf, tmp, size - strlen(buf) - 1);
1050 static const struct trans_tbl afs[] = {
1051 __ADD(AF_UNSPEC,unspec),
1052 __ADD(AF_UNIX,unix),
1053 __ADD(AF_INET,inet),
1054 __ADD(AF_AX25,ax25),
1056 __ADD(AF_APPLETALK,appletalk),
1057 __ADD(AF_NETROM,netrom),
1058 __ADD(AF_BRIDGE,bridge),
1059 __ADD(AF_ATMPVC,atmpvc),
1061 __ADD(AF_INET6,inet6),
1062 __ADD(AF_ROSE,rose),
1063 __ADD(AF_DECnet,decnet),
1064 __ADD(AF_NETBEUI,netbeui),
1065 __ADD(AF_SECURITY,security),
1067 __ADD(AF_NETLINK,netlink),
1068 __ADD(AF_PACKET,packet),
1070 __ADD(AF_ECONET,econet),
1071 __ADD(AF_ATMSVC,atmsvc),
1076 __ADD(AF_IRDA,irda),
1077 __ADD(AF_PPPOX,pppox),
1078 __ADD(AF_WANPIPE,wanpipe),
1084 __ADD(AF_TIPC,tipc),
1086 __ADD(AF_BLUETOOTH,bluetooth),
1088 __ADD(AF_IUCV,iucv),
1091 __ADD(AF_RXRPC,rxrpc),
1094 __ADD(AF_ISDN,isdn),
1097 __ADD(AF_PHONET,phonet),
1099 #ifdef AF_IEEE802154 1100 __ADD(AF_IEEE802154,ieee802154),
1103 __ADD(AF_CAIF,caif),
1112 __ADD(AF_VSOCK,vsock),
1114 __ADD(AF_MPLS,mpls),
1117 char *nl_af2str(
int family,
char *buf,
size_t size)
1119 return __type2str(family, buf, size, afs, ARRAY_SIZE(afs));
1122 int nl_str2af(
const char *name)
1124 int fam = __str2type(name, afs, ARRAY_SIZE(afs));
1125 return fam >= 0 ? fam : -EINVAL;
struct nl_addr * nl_addr_clone(const struct nl_addr *addr)
Clone existing abstract address object.
struct nl_addr * nl_addr_alloc(size_t maxsize)
Allocate empty abstract address.
int nl_addr_resolve(const struct nl_addr *addr, char *host, size_t hostlen)
Resolve abstract address object to a name using getnameinfo().
void nl_addr_set_prefixlen(struct nl_addr *addr, int prefixlen)
Set the prefix length of an abstract address.
int nl_addr_cmp(const struct nl_addr *a, const struct nl_addr *b)
Compare abstract addresses.
int nl_addr_guess_family(const struct nl_addr *addr)
Guess address family of abstract address based on address size.
unsigned int nl_addr_get_prefixlen(const struct nl_addr *addr)
Return prefix length of abstract address object.
struct nl_addr * nl_addr_build(int family, const void *buf, size_t size)
Allocate abstract address based on a binary address.
int nl_addr_parse(const char *addrstr, int hint, struct nl_addr **result)
Allocate abstract address based on character string.
struct nl_addr * nl_addr_get(struct nl_addr *addr)
Increase the reference counter of an abstract address.
void nl_addr_set_family(struct nl_addr *addr, int family)
Set address family.
struct nl_addr * nl_addr_alloc_attr(const struct nlattr *nla, int family)
Allocate abstract address based on Netlink attribute.
int nl_addr_iszero(const struct nl_addr *addr)
Returns true if the address consists of all zeros.
int nl_addr_set_binary_addr(struct nl_addr *addr, const void *buf, size_t len)
Set binary address of abstract address object.
int nl_addr_info(const struct nl_addr *addr, struct addrinfo **result)
Call getaddrinfo() for an abstract address object.
void * nla_data(const struct nlattr *nla)
Return pointer to the payload section.
int nla_len(const struct nlattr *nla)
Return length of the payload .
void nl_addr_put(struct nl_addr *addr)
Decrease the reference counter of an abstract address.
int nl_addr_valid(const char *addr, int family)
Check if address string is parseable for a specific address family.
int nl_addr_fill_sockaddr(const struct nl_addr *addr, struct sockaddr *sa, socklen_t *salen)
Fill out sockaddr structure with values from abstract address object.
int nl_addr_cmp_prefix(const struct nl_addr *a, const struct nl_addr *b)
Compare the prefix of two abstract addresses.
unsigned int nl_addr_get_len(const struct nl_addr *addr)
Get length of binary address of abstract address object.
void * nl_addr_get_binary_addr(const struct nl_addr *addr)
Get binary address of abstract address object.
int nl_addr_shared(const struct nl_addr *addr)
Check whether an abstract address is shared.
char * nl_addr2str(const struct nl_addr *addr, char *buf, size_t size)
Convert abstract address object to character string.
int nl_addr_get_family(const struct nl_addr *addr)
Return address family.