diff options
author | Rich Felker <dalias@aerifal.cx> | 2014-06-04 16:53:39 -0400 |
---|---|---|
committer | Rich Felker <dalias@aerifal.cx> | 2014-06-04 16:53:39 -0400 |
commit | 01dc3f4fea73e4df31cc3e3bb1cd5580fc0d7938 (patch) | |
tree | 2f2df4e89bd0f01b63fda221ef9e6f147367afd9 /src/network/lookup_ipliteral.c | |
parent | 934aa1350b96461f205ad69c95e8f6f035f6b62c (diff) | |
download | musl-01dc3f4fea73e4df31cc3e3bb1cd5580fc0d7938.tar.gz musl-01dc3f4fea73e4df31cc3e3bb1cd5580fc0d7938.tar.xz musl-01dc3f4fea73e4df31cc3e3bb1cd5580fc0d7938.zip |
add support for reverse name lookups from hosts file to getnameinfo
this also affects the legacy gethostbyaddr family, which uses getnameinfo as its backend. some other minor changes associated with the refactoring of source files are also made; in particular, the resolv.conf parser now uses the same code that's used elsewhere to handle ip literals, so as a side effect it can now accept a scope id for nameserver addressed with link-local scope.
Diffstat (limited to 'src/network/lookup_ipliteral.c')
-rw-r--r-- | src/network/lookup_ipliteral.c | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/src/network/lookup_ipliteral.c b/src/network/lookup_ipliteral.c new file mode 100644 index 00000000..8dacffc1 --- /dev/null +++ b/src/network/lookup_ipliteral.c @@ -0,0 +1,51 @@ +#include <sys/socket.h> +#include <netinet/in.h> +#include <netdb.h> +#include <net/if.h> +#include <arpa/inet.h> +#include <limits.h> +#include <stdlib.h> +#include <ctype.h> +#include "lookup.h" + +int __inet_aton(const char *, struct in_addr *); + +int __lookup_ipliteral(struct address buf[static 1], const char *name, int family) +{ + struct in_addr a4; + struct in6_addr a6; + if (family != AF_INET6 && __inet_aton(name, &a4)>0) { + memcpy(&buf[0].addr, &a4, sizeof a4); + buf[0].family = AF_INET; + buf[0].scopeid = 0; + return 1; + } + if (family != AF_INET) { + char tmp[64]; + char *p = strchr(name, '%'), *z; + unsigned long long scopeid; + if (p && p-name < 64) { + memcpy(tmp, name, p-name); + tmp[p-name] = 0; + name = tmp; + } + if (inet_pton(AF_INET6, name, &a6)<=0) return 0; + memcpy(&buf[0].addr, &a6, sizeof a6); + buf[0].family = AF_INET6; + if (p) { + if (isdigit(*++p)) scopeid = strtoull(p, &z, 10); + else z = p-1; + if (*z) { + if (!IN6_IS_ADDR_LINKLOCAL(&a6) && + !IN6_IS_ADDR_MC_LINKLOCAL(&a6)) + return EAI_NONAME; + scopeid = if_nametoindex(p); + if (!scopeid) return EAI_NONAME; + } + if (scopeid > UINT_MAX) return EAI_NONAME; + buf[0].scopeid = scopeid; + } + return 1; + } + return 0; +} |