From 14cbecfcae19694019f0ac68cfc6daceb33cb016 Mon Sep 17 00:00:00 2001 From: Christian Spielberger Date: Mon, 21 Jun 2021 09:13:00 +0200 Subject: [PATCH] sa: add support for interface suffix for IPv6ll --- include/re_sa.h | 2 ++ src/sa/sa.c | 39 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/include/re_sa.h b/include/re_sa.h index f17ce0b20..77183bc6b 100644 --- a/include/re_sa.h +++ b/include/re_sa.h @@ -47,6 +47,8 @@ int sa_decode(struct sa *sa, const char *str, size_t len); int sa_af(const struct sa *sa); uint32_t sa_in(const struct sa *sa); void sa_in6(const struct sa *sa, uint8_t *addr); +int sa_addrinfo(const char *addr, struct sa *sa); + int sa_ntop(const struct sa *sa, char *buf, int size); int sa_pton(const char *addr, struct sa *sa); uint16_t sa_port(const struct sa *sa); diff --git a/src/sa/sa.c b/src/sa/sa.c index b2b20663e..f04c69430 100644 --- a/src/sa/sa.c +++ b/src/sa/sa.c @@ -12,6 +12,9 @@ #include #endif #include +#include +#include +#include #include #include #include @@ -58,6 +61,33 @@ int sa_set(struct sa *sa, const struct pl *addr, uint16_t port) } +int sa_addrinfo(const char *addr, struct sa *sa) +{ + struct addrinfo *res, *res0 = NULL; + struct addrinfo hints; + int err = 0; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_flags = AI_V4MAPPED | AI_ADDRCONFIG | AI_NUMERICHOST; + + if (getaddrinfo(addr, NULL, &hints, &res0)) + return EADDRNOTAVAIL; + + for (res = res0; res; res = res->ai_next) { + + err = sa_set_sa(sa, res->ai_addr); + if (err) + continue; + + break; + } + + freeaddrinfo(res0); + return err; +} + + /** * Convert character string to a network address structure * @@ -68,13 +98,18 @@ int sa_set(struct sa *sa, const struct pl *addr, uint16_t port) */ int sa_pton(const char *addr, struct sa *sa) { - if (!addr) + int err = 0; + + if (!addr || !sa) return EINVAL; if (inet_pton(AF_INET, addr, &sa->u.in.sin_addr) > 0) { sa->u.in.sin_family = AF_INET; } #ifdef HAVE_INET6 + else if (!strncmp(addr, "fe80:", 5)) { + err = sa_addrinfo(addr, sa); + } else if (inet_pton(AF_INET6, addr, &sa->u.in6.sin6_addr) > 0) { if (IN6_IS_ADDR_V4MAPPED(&sa->u.in6.sin6_addr)) { @@ -91,7 +126,7 @@ int sa_pton(const char *addr, struct sa *sa) return EINVAL; } - return 0; + return err; }