From 1a9d7092d093700836945d2c7f5778c0f49c16d9 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Wed, 28 May 2014 18:35:10 +0100 Subject: [PATCH] scope if index to name conversion --- src/addrfam.c | 36 +++++++++++++++++++++++++++++++----- src/adns.h | 7 ++++++- 2 files changed, 37 insertions(+), 6 deletions(-) diff --git a/src/addrfam.c b/src/addrfam.c index 0f4a820..10cb1ce 100644 --- a/src/addrfam.c +++ b/src/addrfam.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -213,6 +214,14 @@ const void *adns__sockaddr_to_inaddr(const struct sockaddr *sa) # define af_debug(fmt,...) ((void)("" fmt "", __VA_ARGS__)) #endif +static bool addrtext_our_errno(int e) { + return + e==EAFNOSUPPORT || + e==EINVAL || + e==ENOSPC || + e==ENOSYS; +} + int adns_text2addr(const char *addr, uint16_t port, struct sockaddr *sa, socklen_t *salen /* set if OK or ENOSPC */) { int af; @@ -313,8 +322,7 @@ int adns_text2addr(const char *addr, uint16_t port, struct sockaddr *sa, strerror(errno)); if (errno==0) { return ENXIO; - } else if (errno==EAFNOSUPPORT || errno==EINVAL || - errno==ENOSPC || errno==ENOSYS) { + } else if (addrtext_our_errno(errno)) { /* we use these for other purposes, urgh. */ perror("adns: adns_text2addr: if_nametoindex" " failed with unexpected error"); @@ -364,9 +372,27 @@ int adns_addr2text(const struct sockaddr *sa, if (scope) { int scopeoffset = strlen(addr_buffer); int remain = *addr_buflen - scopeoffset; - int r = snprintf(addr_buffer + scopeoffset, remain, - "%%%"PRIu32"", scope); - assert(r < *addr_buflen - scopeoffset); + char *scopeptr = addr_buffer + scopeoffset; + assert(remain >= IF_NAMESIZE+1/*%*/); + *scopeptr++= '%'; remain--; + char *ok = scope > UINT_MAX + ? 0 /* we can't pass it to if_indextoname then */ + : if_indextoname(scope, scopeptr); + if (!ok) { + if (errno==ENXIO) { + /* fair enough, show it as a number then */ + } else if (addrtext_our_errno(errno)) { + /* we use these for other purposes, urgh. */ + perror("adns: adns_addr2text: if_indextoname" + " failed with unexpected error"); + return EIO; + } else { + return errno; + } + int r = snprintf(scopeptr, remain, + "%"PRIu32"", scope); + assert(r < *addr_buflen - scopeoffset); + } af_debug("printed scoped address `%s'", addr_buffer); } } diff --git a/src/adns.h b/src/adns.h index bb88395..028d83c 100644 --- a/src/adns.h +++ b/src/adns.h @@ -66,6 +66,7 @@ #include #include #include +#include #ifdef __cplusplus extern "C" { /* I really dislike this - iwj. */ @@ -682,7 +683,10 @@ void adns_finish(adns_state ads); * they will be cancelled. */ -#define ADNS_ADDR2TEXT_BUFLEN (INET6_ADDRSTRLEN +1/*%*/ +9/*uint32*/ +1/*nul*/) +#define ADNS_ADDR2TEXT_BUFLEN \ + (INET6_ADDRSTRLEN + 1/*%*/ \ + + ((IF_NAMESIZE-1) > 9 ? (IF_NAMESIZE-1) : 9/*uint32*/) \ + + 1/* nul; included in IF_NAMESIZE */) int adns_text2addr(const char *addr, uint16_t port, struct sockaddr *sa, socklen_t *salen /* set if OK or ENOSPC; otherwise undef */); @@ -698,6 +702,7 @@ int adns_addr2text(const struct sockaddr *sa, * ENOSYS address is not link local * ENXIO if_nametoindex said it wasn't a valid name * EIO if_nametoindex went crazy (adns prints a message to stderr) + * Extra errors are possible from text2addr and addr2text with scopes: * any other if_nametoindex failed * port is always in host byte order and is simply copied to and * from the appropriate sockaddr field (byteswapped as necessary). -- 2.11.0