aboutsummaryrefslogtreecommitdiff
path: root/src/common/compat.c
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2007-07-19 18:46:09 +0000
committerNick Mathewson <nickm@torproject.org>2007-07-19 18:46:09 +0000
commitbbbf50428102156359974e33bbcb70537132ace9 (patch)
treeb044617b7528202e88808a67b3acfaae503d638e /src/common/compat.c
parent70aef18db1b0b712416a92389d30ad2548f0d499 (diff)
downloadtor-bbbf50428102156359974e33bbcb70537132ace9.tar
tor-bbbf50428102156359974e33bbcb70537132ace9.tar.gz
r13827@catbus: nickm | 2007-07-19 14:42:25 -0400
Merge in some generic address manipulation code from croup. Needs some work. svn:r10880
Diffstat (limited to 'src/common/compat.c')
-rw-r--r--src/common/compat.c85
1 files changed, 71 insertions, 14 deletions
diff --git a/src/common/compat.c b/src/common/compat.c
index cefba439f..6d68c2dac 100644
--- a/src/common/compat.c
+++ b/src/common/compat.c
@@ -1004,7 +1004,7 @@ tor_inet_pton(int af, const char *src, void *dst)
}
/** Similar behavior to Unix gethostbyname: resolve <b>name</b>, and set
- * *addr to the proper IP address, in network byte order. Returns 0
+ * *<b>addr</b> to the proper IP address, in host byte order. Returns 0
* on success, -1 on failure; 1 on transient failure.
*
* (This function exists because standard windows gethostbyname
@@ -1013,38 +1013,90 @@ tor_inet_pton(int af, const char *src, void *dst)
int
tor_lookup_hostname(const char *name, uint32_t *addr)
{
+ tor_addr_t myaddr;
+ int ret;
+
+ if ((ret = tor_addr_lookup(name, AF_INET, &myaddr)))
+ return ret;
+
+ if (IN_FAMILY(&myaddr) == AF_INET) {
+ *addr = IPV4IPh(&myaddr);
+ return ret;
+ }
+
+ return -1;
+}
+
+/** Similar behavior to Unix gethostbyname: resolve <b>name</b>, and set
+ * *<b>addr</b> to the proper IP address and family.
+ * Return 0 on success, -1 on failure; 1 on transient failure.
+ * DOCDOC family argument.
+ */
+int
+tor_addr_lookup(const char *name, uint16_t family, tor_addr_t *addr)
+{
/* Perhaps eventually this should be replaced by a tor_getaddrinfo or
* something.
*/
struct in_addr iaddr;
+ struct in6_addr iaddr6;
tor_assert(name);
tor_assert(addr);
+ tor_assert(family == AF_INET || family == AF_UNSPEC);
+ memset(addr, 0, sizeof(addr)); /* Clear the extraneous fields. */
if (!*name) {
/* Empty address is an error. */
return -1;
- } else if (tor_inet_aton(name, &iaddr)) {
- /* It's an IP. */
- memcpy(addr, &iaddr.s_addr, 4);
+ } else if (tor_inet_pton(AF_INET, name, &iaddr)) {
+ /* It's an IPv4 IP. */
+ addr->sa.sin_family = AF_INET;
+ memcpy(&addr->sa.sin_addr, &iaddr, sizeof(struct in_addr));
+ return 0;
+ } else if (tor_inet_pton(AF_INET6, name, &iaddr6)) {
+ addr->sa6.sin6_family = AF_INET6;
+ memcpy(&addr->sa6.sin6_addr, &iaddr6, sizeof(struct in6_addr));
return 0;
} else {
#ifdef HAVE_GETADDRINFO
int err;
struct addrinfo *res=NULL, *res_p;
+ struct addrinfo *best=NULL;
struct addrinfo hints;
int result = -1;
memset(&hints, 0, sizeof(hints));
- hints.ai_family = PF_INET;
+ hints.ai_family = family;
hints.ai_socktype = SOCK_STREAM;
err = getaddrinfo(name, NULL, &hints, &res);
if (!err) {
+ best = NULL;
for (res_p = res; res_p; res_p = res_p->ai_next) {
- if (res_p->ai_family == AF_INET) {
- struct sockaddr_in *sin = (struct sockaddr_in *)res_p->ai_addr;
- memcpy(addr, &sin->sin_addr, 4);
- result = 0;
+ if (family == AF_UNSPEC) {
+ if (res_p->ai_family == AF_INET) {
+ best = res_p;
+ break;
+ } else if (res_p->ai_family == AF_INET6 && !best) {
+ best = res_p;
+ }
+ } else if (family == res_p->ai_family) {
+ best = res_p;
break;
}
}
+ if (!best)
+ best = res;
+ if (best->ai_family == AF_INET) {
+ addr->sa.sin_family = AF_INET;
+ memcpy(&addr->sa.sin_addr,
+ &((struct sockaddr_in*)best->ai_addr)->sin_addr,
+ sizeof(struct in_addr));
+ result = 0;
+ } else if (best->ai_family == AF_INET6) {
+ addr->sa6.sin6_family = AF_INET6;
+ memcpy(&addr->sa6.sin6_addr,
+ &((struct sockaddr_in6*)best->ai_addr)->sin6_addr,
+ sizeof(struct in6_addr));
+ result = 0;
+ }
freeaddrinfo(res);
return result;
}
@@ -1074,14 +1126,19 @@ tor_lookup_hostname(const char *name, uint32_t *addr)
#else
err = h_errno;
#endif
-#endif
+#endif /* endif HAVE_GETHOSTBYNAME_R_6_ARG. */
if (ent) {
- /* break to remind us if we move away from IPv4 */
- tor_assert(ent->h_length == 4);
- memcpy(addr, ent->h_addr, 4);
+ addr->sa.sin_family = ent->h_addrtype;
+ if (ent->h_addrtype == AF_INET) {
+ memcpy(addr->sa.sin_addr, ent->h_addr, sizeof(struct in_addr));
+ } else if (ent->h_addrtype == AF_INET6) {
+ memcpy(addr->sa.sin6_addr, ent->h_addr, sizeof(struct in6_addr));
+ } else {
+ tor_assert(0) /* gethostbyname() returned a bizarre addrtype */
+ }
return 0;
}
- memset(addr, 0, 4);
+ memset(addr, 0, sizeof(tor_addr_t)); /* XXXX020 is this redundant? */
#ifdef MS_WINDOWS
return (err == WSATRY_AGAIN) ? 1 : -1;
#else