#include <unistd.h>
#include <inttypes.h>
#include <stddef.h>
+#include <stdbool.h>
#include <sys/types.h>
#include <netdb.h>
# 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;
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");
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);
}
}
#include <netinet/in.h>
#include <sys/time.h>
#include <unistd.h>
+#include <net/if.h>
#ifdef __cplusplus
extern "C" { /* I really dislike this - iwj. */
* 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 */);
* 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).