aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2007-05-25 18:22:37 +0000
committerNick Mathewson <nickm@torproject.org>2007-05-25 18:22:37 +0000
commitbb524e99c9dd9555b0f77275bbb5574d47689fc8 (patch)
tree699a0e8d7597094186ec21b0a3305b81506a2690
parent39fe91b9a281a3ec8504bf7933a63918038a9b5a (diff)
downloadtor-bb524e99c9dd9555b0f77275bbb5574d47689fc8.tar
tor-bb524e99c9dd9555b0f77275bbb5574d47689fc8.tar.gz
r12955@catbus: nickm | 2007-05-25 13:17:30 -0400
First bare stubs of ipv6 work: commit some (untested, hence doublessly broken) implementations of inet_ntop/pton for systems that lack them. svn:r10326
-rw-r--r--configure.in2
-rw-r--r--doc/TODO6
-rw-r--r--src/common/compat.c161
-rw-r--r--src/common/compat.h12
-rw-r--r--src/common/util.c2
-rw-r--r--src/common/util.h2
6 files changed, 182 insertions, 3 deletions
diff --git a/configure.in b/configure.in
index 1df038c96..bac5d91db 100644
--- a/configure.in
+++ b/configure.in
@@ -152,7 +152,7 @@ dnl -------------------------------------------------------------------
dnl Check for functions before libevent, since libevent-1.2 apparently
dnl exports strlcpy without defining it in a header.
-AC_CHECK_FUNCS(gettimeofday ftime socketpair uname inet_aton strptime getrlimit strlcat strlcpy strtoull ftello getaddrinfo localtime_r gmtime_r memmem strtok_r)
+AC_CHECK_FUNCS(gettimeofday ftime socketpair uname inet_aton strptime getrlimit strlcat strlcpy strtoull ftello getaddrinfo localtime_r gmtime_r memmem strtok_r inet_pton inet_ntop)
if test $enable_threads = "yes"; then
AC_CHECK_HEADERS(pthread.h)
diff --git a/doc/TODO b/doc/TODO
index 943d9d9f8..b52d989a5 100644
--- a/doc/TODO
+++ b/doc/TODO
@@ -238,6 +238,12 @@ Things we'd like to do in 0.2.0.x:
- Let controller set router flags for authority to transmit, and for
client to use.
- Support relaying streams to ipv6.
+ - Internal code support for ipv6:
+ o Clone ipv6 functions (inet_ntop, inet_pton) where they don't exist.
+ - Most address variables need to become sockaddrs.
+ - Teach resolving code how to handle ipv6.
+ - Teach exit policies about ipv6 (consider ipv4/ipv6 interaction!)
+ - ...
- Let servers decide to support BEGIN_DIR but not DirPort.
- Tor should bind its ports before dropping privs, so users don't
have to do the ipchains dance.
diff --git a/src/common/compat.c b/src/common/compat.c
index a15d09367..b9888d9a5 100644
--- a/src/common/compat.c
+++ b/src/common/compat.c
@@ -807,6 +807,167 @@ tor_inet_aton(const char *c, struct in_addr* addr)
#endif
}
+/** DOCDOC */
+const char *
+tor_inet_ntop(int af, const void *src, char *dst, size_t len)
+{
+#ifdef HAVE_INET_NTOP
+ return inet_ntop(af,src,dst,(socklen_t)len);
+#else
+ /* XXXX needs testing. !!!! */
+ if (af == AF_INET) {
+ if (tor_inet_ntoa(src, dst, len) < 0)
+ return NULL;
+ else
+ return dst;
+ } else if (af == AF_INET6) {
+ const struct in6_addr *addr = src;
+ char buf[64], *cp;
+ int longestGapLen = 0, longestGapPos = -1, i,
+ curGapPos = -1, curGapLen = 0;
+ uint16_t words[8];
+ for (i = 0; i < 8; ++i) {
+ words[i] = (((uint16_t)addr->s6_addr[2*i])<<8) + addr->s6_addr[2*i+1];
+ }
+ if (words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0 &&
+ words[4] == 0 && (words[5] == 0 || words[5] == 0xffff) && words[6]) {
+ /* This is an IPv4 address. */
+ tor_snprintf(buf, sizeof(buf), "::%x:%d.%d.%d.%d", words[5],
+ addr->s6_addr[12], addr->s6_addr[13],
+ addr->s6_addr[14], addr->s6_addr[15]);
+ if (strlen(buf) > len)
+ return NULL;
+ strlcpy(dst, buf, len);
+ return dst;
+ }
+ i = 0;
+ while (i < 8) {
+ if (words[i] == 0) {
+ curGapPos = i++;
+ curGapLen = 1;
+ while (i<8 && words[i] == 0) {
+ ++i; ++curGapLen;
+ }
+ if (curGapLen > longestGapLen) {
+ longestGapPos = curGapPos;
+ longestGapLen = curGapLen;
+ }
+ } else {
+ ++i;
+ }
+ }
+ cp = buf;
+ for (i = 0; i < 8; ++i) {
+ if (words[i] == 0 && longestGapPos == i) {
+ *cp++ = ':';
+ *cp++ = ':';
+ while (i < 8 && words[i] == 0)
+ ++i;
+ --i; /* to compensate for loop increment. */
+ } else {
+ tor_snprintf(cp, sizeof(buf)-(cp-buf), "%x", (unsigned)words[i]);
+ cp += strlen(cp);
+ if (i != 7)
+ *cp++ = ':';
+ }
+ }
+ if (strlen(buf) > len)
+ return NULL;
+ strlcpy(dst, buf, len);
+ return dst;
+ } else {
+ return NULL;
+ }
+#endif
+}
+
+/** DOCDOC */
+int
+tor_inet_pton(int af, const char *src, void *dst)
+{
+#ifdef HAVE_INET_PTON
+ return inet_pton(af, src, dst);
+#else
+ /* XXXX needs testing. !!!! */
+ if (af == AF_INET) {
+ return tor_inet_aton(src, dst);
+ } else if (af == AF_INET6) {
+ struct in6_addr *out = dst;
+ uint16_t words[8];
+ struct in_addr in;
+ int gapPos = -1, i, setWords=0;
+ const char *dot = strchr(src, '.');
+ const char *eow; /* end of words. */
+ if (dot == src)
+ return 0;
+ else if (!dot)
+ eow = src+strlen(src);
+ else {
+ uint32_t a;
+ for (eow = dot-1; eow >= src && TOR_ISDIGIT(*eow); --eow)
+ ;
+ ++eow;
+
+ if (inet_aton(eow, &in) != 1)
+ return 0;
+ a = ntohl(in.s_addr);
+ words[6] = a >> 16;
+ words[7] = a & 0xFFFF;
+ setWords += 2;
+ }
+
+ i = 0;
+ while (src < eow) {
+ if (i > 7)
+ return 0;
+ if (TOR_ISXDIGIT(*src)) {
+ char *next;
+ int r = strtol(src, &next, 16);
+ if (next > 4+src)
+ return 0;
+ if (next == src)
+ return 0;
+ if (r<0 || r>65536)
+ return 0;
+
+ words[i++] = (uint16_t)r;
+ setWords++;
+ src = next;
+ if (*src != ':')
+ return 0;
+ ++src;
+ } else if (*src == ':' && i > 0 && gapPos==-1) {
+ gapPos = i;
+ ++src;
+ } else if (*src == ':' && i == 0 && src[1] == ':') {
+ gapPos = i;
+ src += 2;
+ } else {
+ return 0;
+ }
+ }
+
+ if (setWords > 8 || (setWords < 8 && gapPos == -1))
+ return 0;
+
+ if (gapPos >= 0) {
+ int gapLen = 8 - setWords;
+ memmove(&words[gapPos+gapLen], &words[gapPos],
+ sizeof(uint16_t)*(8-gapPos));
+ }
+ for (i = 0; i < 8; ++i) {
+ out->s6_addr[2*i ] = words[i] >> 8;
+ out->s6_addr[2*i+1] = words[i] & 0xff;
+ }
+
+ return 1;
+ } else {
+ return -1;
+ }
+#endif
+}
+
+
/** Similar behavior to Unix gethostbyname: resolve <b>name</b>, and set
* *addr to the proper IP address, in network byte order. Returns 0
* on success, -1 on failure; 1 on transient failure.
diff --git a/src/common/compat.h b/src/common/compat.h
index cd3643740..be8e19eee 100644
--- a/src/common/compat.h
+++ b/src/common/compat.h
@@ -32,6 +32,9 @@
#ifdef HAVE_STRING_H
#include <string.h>
#endif
+#ifdef HAVE_CTYPE_H
+#include <ctype.h>
+#endif
#include <stdarg.h>
#ifndef NULL_REP_IS_ZERO_BYTES
@@ -241,8 +244,17 @@ int get_n_open_sockets(void);
typedef int socklen_t;
#endif
+#ifndef HAVE_STRUCT_IN6_ADDR
+struct in6_addr
+{
+ uint8_t s6_addr[16];
+};
+#endif
+
struct in_addr;
int tor_inet_aton(const char *cp, struct in_addr *addr) ATTR_NONNULL((1,2));
+const char *tor_inet_ntop(int af, const void *src, char *dst, size_t len);
+int tor_inet_pton(int af, const char *src, void *dst);
int tor_lookup_hostname(const char *name, uint32_t *addr) ATTR_NONNULL((1,2));
void set_socket_nonblocking(int socket);
int tor_socketpair(int family, int type, int protocol, int fd[2]);
diff --git a/src/common/util.c b/src/common/util.c
index 7ca08363d..889ede100 100644
--- a/src/common/util.c
+++ b/src/common/util.c
@@ -1952,7 +1952,7 @@ parse_addr_and_port_range(const char *s, uint32_t *addr_out,
* <b>buf</b>.
*/
int
-tor_inet_ntoa(struct in_addr *in, char *buf, size_t buf_len)
+tor_inet_ntoa(const struct in_addr *in, char *buf, size_t buf_len)
{
uint32_t a = ntohl(in->s_addr);
return tor_snprintf(buf, buf_len, "%d.%d.%d.%d",
diff --git a/src/common/util.h b/src/common/util.h
index f04160935..ab8aea86e 100644
--- a/src/common/util.h
+++ b/src/common/util.h
@@ -250,7 +250,7 @@ int parse_addr_and_port_range(const char *s, uint32_t *addr_out,
uint16_t *port_max_out);
int addr_mask_get_bits(uint32_t mask);
#define INET_NTOA_BUF_LEN 16
-int tor_inet_ntoa(struct in_addr *in, char *buf, size_t buf_len);
+int tor_inet_ntoa(const struct in_addr *in, char *buf, size_t buf_len);
char *tor_dup_addr(uint32_t addr) ATTR_MALLOC;
int get_interface_address(int severity, uint32_t *addr);