28 #include <netlink-local.h> 29 #include <netlink/netlink.h> 30 #include <netlink/utils.h> 31 #include <netlink/addr.h> 32 #include <linux/socket.h> 36 static inline uint16_t dn_ntohs(uint16_t addr)
45 return ((uint16_t) u.byte[0]) | (((uint16_t) u.byte[1]) << 8);
48 static inline int do_digit(
char *str, uint16_t *addr, uint16_t scale,
49 size_t *pos,
size_t len,
int *started)
51 uint16_t tmp = *addr / scale;
56 if (((tmp) > 0) || *started || (scale == 1)) {
60 *addr -= (tmp * scale);
66 static const char *dnet_ntop(
char *addrbuf,
size_t addrlen,
char *str,
69 uint16_t addr = dn_ntohs(*(uint16_t *)addrbuf);
70 uint16_t area = addr >> 10;
82 if (do_digit(str + pos, &area, 10, &pos, len, &started))
85 if (do_digit(str + pos, &area, 1, &pos, len, &started))
95 if (do_digit(str + pos, &addr, 1000, &pos, len, &started))
98 if (do_digit(str + pos, &addr, 100, &pos, len, &started))
101 if (do_digit(str + pos, &addr, 10, &pos, len, &started))
104 if (do_digit(str + pos, &addr, 1, &pos, len, &started))
115 static int dnet_num(
const char *src, uint16_t * dst)
121 while ((tmp = *src++) != 0) {
123 if ((tmp < 0) || (tmp > 9))
134 static inline int dnet_pton(
const char *src,
char *addrbuf)
140 pos = dnet_num(src, &area);
141 if ((pos == 0) || (area > 63) ||
142 ((*(src + pos) !=
'.') && (*(src + pos) !=
',')))
145 pos = dnet_num(src + pos + 1, &node);
146 if ((pos == 0) || (node > 1023))
149 *(uint16_t *)addrbuf = dn_ntohs((area << 10) | node);
166 struct nl_addr *addr;
168 addr = calloc(1,
sizeof(*addr) + maxsize);
175 addr->a_maxsize = maxsize;
189 struct nl_addr *addr;
195 addr->a_family = family;
197 addr->a_prefixlen = size*8;
200 memcpy(addr->a_addr, buf, size);
233 int err, copy = 0, len = 0, family = AF_UNSPEC;
234 char *str, *prefix, buf[32];
235 struct nl_addr *addr = NULL;
237 str = strdup(addrstr);
239 err = nl_errno(ENOMEM);
243 prefix = strchr(str,
'/');
247 if (!strcasecmp(str,
"none")) {
252 if (!strcasecmp(str,
"default") ||
253 !strcasecmp(str,
"all") ||
254 !strcasecmp(str,
"any")) {
277 err = nl_error(EINVAL,
"Unsuported address" \
278 "family for default address");
285 if (hint == AF_INET || hint == AF_UNSPEC) {
286 if (inet_pton(AF_INET, str, buf) > 0) {
291 if (hint == AF_INET) {
292 err = nl_error(EINVAL,
"Invalid IPv4 address");
297 if (hint == AF_INET6 || hint == AF_UNSPEC) {
298 if (inet_pton(AF_INET6, str, buf) > 0) {
303 if (hint == AF_INET6) {
304 err = nl_error(EINVAL,
"Invalid IPv6 address");
309 if ((hint == AF_LLC || hint == AF_UNSPEC) && strchr(str,
':')) {
310 unsigned int a, b, c, d, e, f;
312 if (sscanf(str,
"%02x:%02x:%02x:%02x:%02x:%02x",
313 &a, &b, &c, &d, &e, &f) == 6) {
316 buf[0] = (
unsigned char) a;
317 buf[1] = (
unsigned char) b;
318 buf[2] = (
unsigned char) c;
319 buf[3] = (
unsigned char) d;
320 buf[4] = (
unsigned char) e;
321 buf[5] = (
unsigned char) f;
325 if (hint == AF_LLC) {
326 err = nl_error(EINVAL,
"Invalid link layer address");
331 if ((hint == AF_DECnet || hint == AF_UNSPEC) &&
332 (strchr(str,
'.') || strchr(str,
','))) {
333 if (dnet_pton(str, buf) > 0) {
338 if (hint == AF_DECnet) {
339 err = nl_error(EINVAL,
"Invalid DECnet address");
344 if (hint == AF_UNSPEC && strchr(str,
':')) {
348 long l = strtol(s, &p, 16);
350 if (s == p || l > 0xff || i >=
sizeof(buf)) {
355 buf[i++] = (
unsigned char) l;
366 err = nl_error(EINVAL,
"Invalid address");
372 err = nl_errno(ENOMEM);
376 nl_addr_set_family(addr, family);
383 long pl = strtol(++prefix, &p, 0);
389 nl_addr_set_prefixlen(addr, pl);
391 nl_addr_set_prefixlen(addr, len * 8);
397 return err ? NULL : addr;
410 new =
nl_addr_build(addr->a_family, addr->a_addr, addr->a_len);
412 new->a_prefixlen = addr->a_prefixlen;
433 if (addr->a_refcnt != 1)
446 struct nl_addr *nl_addr_get(
struct nl_addr *addr)
453 void nl_addr_put(
struct nl_addr *addr)
458 if (addr->a_refcnt == 1)
471 return addr->a_refcnt > 1;
491 int d = a->a_family - b->a_family;
494 d = a->a_len - b->a_len;
496 if (a->a_len && d == 0)
497 return memcmp(a->a_addr, b->a_addr, a->a_len);
513 int d = a->a_family - b->a_family;
516 int len = min(a->a_prefixlen, b->a_prefixlen);
519 d = memcmp(a->a_addr, b->a_addr, bytes);
521 int mask = (1UL << (len % 8)) - 1UL;
523 d = (a->a_addr[bytes] & mask) -
524 (b->a_addr[bytes] & mask);
539 for (i = 0; i < addr->a_len; i++)
562 ret = inet_pton(family, addr, buf);
568 ret = dnet_pton(addr, buf);
574 if (sscanf(addr,
"%*02x:%*02x:%*02x:%*02x:%*02x:%*02x") != 6)
589 switch (addr->a_len) {
617 switch (addr->a_family) {
619 struct sockaddr_in *sai = (
struct sockaddr_in *) sa;
621 if (*salen <
sizeof(*sai))
624 sai->sin_family = addr->a_family;
625 memcpy(&sai->sin_addr, addr->a_addr, 4);
626 *salen =
sizeof(*sai);
631 struct sockaddr_in6 *sa6 = (
struct sockaddr_in6 *) sa;
633 if (*salen <
sizeof(*sa6))
636 sa6->sin6_family = addr->a_family;
637 memcpy(&sa6->sin6_addr, addr->a_addr, 16);
638 *salen =
sizeof(*sa6);
673 struct addrinfo *res;
674 char buf[INET6_ADDRSTRLEN+5];
675 struct addrinfo hint = {
676 .ai_flags = AI_NUMERICHOST,
677 .ai_family = addr->a_family,
682 err = getaddrinfo(buf, NULL, &hint, &res);
684 nl_error(err, gai_strerror(err));
707 struct sockaddr_in6 buf;
708 socklen_t salen =
sizeof(buf);
714 return getnameinfo((
struct sockaddr *) &buf, salen,
715 host, hostlen, NULL, 0, NI_NAMEREQD);
725 void nl_addr_set_family(
struct nl_addr *addr,
int family)
727 addr->a_family = family;
730 int nl_addr_get_family(
struct nl_addr *addr)
732 return addr->a_family;
743 if (len > addr->a_maxsize)
747 memcpy(addr->a_addr, buf, len);
770 void nl_addr_set_prefixlen(
struct nl_addr *addr,
int prefixlen)
772 addr->a_prefixlen = prefixlen;
781 return addr->a_prefixlen;
808 snprintf(buf, size,
"none");
812 switch (addr->a_family) {
814 inet_ntop(AF_INET, addr->a_addr, buf, size);
818 inet_ntop(AF_INET6, addr->a_addr, buf, size);
822 dnet_ntop(addr->a_addr, addr->a_len, buf, size);
827 snprintf(buf, size,
"%02x",
828 (
unsigned char) addr->a_addr[0]);
829 for (i = 1; i < addr->a_len; i++) {
830 snprintf(tmp,
sizeof(tmp),
":%02x",
831 (
unsigned char) addr->a_addr[i]);
832 strncat(buf, tmp, size - strlen(buf) - 1);
838 if (addr->a_prefixlen != (8 * addr->a_len)) {
839 snprintf(tmp,
sizeof(tmp),
"/%u", addr->a_prefixlen);
840 strncat(buf, tmp, size - strlen(buf) - 1);
853 static struct trans_tbl afs[] = {
854 __ADD(AF_UNSPEC,unspec)
856 __ADD(AF_LOCAL,local)
860 __ADD(AF_APPLETALK,appletalk)
861 __ADD(AF_NETROM,netrom)
862 __ADD(AF_BRIDGE,bridge)
863 __ADD(AF_ATMPVC,atmpvc)
865 __ADD(AF_INET6,inet6)
867 __ADD(AF_DECnet,decnet)
868 __ADD(AF_NETBEUI,netbeui)
869 __ADD(AF_SECURITY,security)
871 __ADD(AF_NETLINK,netlink)
872 __ADD(AF_ROUTE,route)
873 __ADD(AF_PACKET,packet)
875 __ADD(AF_ECONET,econet)
876 __ADD(AF_ATMSVC,atmsvc)
879 __ADD(AF_PPPOX,pppox)
880 __ADD(AF_WANPIPE,wanpipe)
882 __ADD(AF_BLUETOOTH,bluetooth)
885 char *nl_af2str(
int family,
char *buf,
size_t size)
887 return __type2str(family, buf, size, afs, ARRAY_SIZE(afs));
890 int nl_str2af(
const char *name)
892 int fam = __str2type(name, afs, ARRAY_SIZE(afs));
893 return fam >= 0 ? fam : AF_UNSPEC;
int nl_addr_cmp_prefix(struct nl_addr *a, struct nl_addr *b)
Compares the prefix of two abstract address objects.
struct nl_addr * nl_addr_alloc(size_t maxsize)
Allocate new abstract address object.
char * nl_addr2str(struct nl_addr *addr, char *buf, size_t size)
Convert abstract address object to character string.
struct addrinfo * nl_addr_info(struct nl_addr *addr)
Call getaddrinfo() for an abstract address object.
struct nl_addr * nl_addr_clone(struct nl_addr *addr)
Clone existing abstract address object.
int nl_addr_set_binary_addr(struct nl_addr *addr, void *buf, size_t len)
Set binary address of abstract address object.
int nl_addr_fill_sockaddr(struct nl_addr *addr, struct sockaddr *sa, socklen_t *salen)
Fill out sockaddr structure with values from abstract address object.
int nl_addr_shared(struct nl_addr *addr)
Check whether an abstract address object is shared.
struct nl_addr * nl_addr_parse(const char *addrstr, int hint)
Allocate abstract address object based on a character string.
unsigned int nl_addr_get_len(struct nl_addr *addr)
Get length of binary address of abstract address object.
void * nl_addr_get_binary_addr(struct nl_addr *addr)
Get binary address of abstract address object.
int nl_addr_resolve(struct nl_addr *addr, char *host, size_t hostlen)
Resolve abstract address object to a name using getnameinfo().
void nl_addr_destroy(struct nl_addr *addr)
Destroy abstract address object.
unsigned int nl_addr_get_prefixlen(struct nl_addr *addr)
Get prefix length of abstract address object.
int nl_addr_cmp(struct nl_addr *a, struct nl_addr *b)
Compares two abstract address objects.
int nl_addr_guess_family(struct nl_addr *addr)
Guess address family of an abstract address object based on address size.
int nl_addr_valid(char *addr, int family)
Check if an address matches a certain family.
int nl_addr_iszero(struct nl_addr *addr)
Returns true if the address consists of all zeros.
struct nl_addr * nl_addr_build(int family, void *buf, size_t size)
Allocate new abstract address object based on a binary address.