summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2004-10-12 15:48:30 +0000
committerNick Mathewson <nickm@torproject.org>2004-10-12 15:48:30 +0000
commit8b037509f3b6f065a467900a5f4d01e21b98f152 (patch)
tree24d57f0050d07a280dc2700e76e9d42c6263ef70
parent1efad74164fb02fbe493bd2c0366936940c879aa (diff)
downloadtor-8b037509f3b6f065a467900a5f4d01e21b98f152.tar.gz
tor-8b037509f3b6f065a467900a5f4d01e21b98f152.zip
Add functions to parse addr[:port] consistently
svn:r2440
-rw-r--r--src/common/util.c56
-rw-r--r--src/common/util.h2
-rw-r--r--src/or/test.c31
3 files changed, 89 insertions, 0 deletions
diff --git a/src/common/util.c b/src/common/util.c
index 5d5f3b5545..4391ac2411 100644
--- a/src/common/util.c
+++ b/src/common/util.c
@@ -2028,6 +2028,62 @@ int tor_lookup_hostname(const char *name, uint32_t *addr)
}
}
+/** Parse a string of the form "host[:port]" from <b>addrport</b>. If
+ * <b>address</b> is provided, set *<b>address</b> to a copy of the
+ * host portion of the string. If <b>addr</b> is provided, try to
+ * resolve the host portion of the string and store it into
+ * *<b>addr</b>. If <b>port</b> is provided, store the port number
+ * into *<b>port</b>, or 0 if no port is given. Return 0 on success,
+ * -1 on failure.
+ */
+int
+parse_addr_port(const char *addrport, char **address, uint32_t *addr,
+ uint16_t *port)
+{
+ const char *colon;
+ char *_address = NULL;
+ int _port;
+ int ok = 1;
+
+ tor_assert(addrport);
+ tor_assert(port);
+
+ colon = strchr(addrport, ':');
+ if (colon) {
+ _address = tor_strndup(addrport, colon-addrport);
+ _port = atoi(colon+1);
+ if (_port<1 || _port>65536) {
+ log_fn(LOG_WARN, "Port '%s' out of range", colon+1);
+ _port = 0;
+ ok = 0;
+ }
+ } else {
+ _address = tor_strdup(addrport);
+ _port = 0;
+ }
+
+ if (addr) {
+ /* There's an addr pointer, so we need to resolve the hostname. */
+ if (tor_lookup_hostname(_address,addr)) {
+ log_fn(LOG_WARN, "Couldn't look up '%s'", _address);
+ ok = 0;
+ *addr = 0;
+ }
+ }
+
+ if (address && ok) {
+ *address = _address;
+ } else {
+ if (address)
+ *address = NULL;
+ tor_free(_address);
+ }
+ if (port)
+ *port = ok ? ((uint16_t) _port) : 0;
+
+ return ok ? 0 : -1;
+}
+
#ifndef MS_WINDOWS
struct tor_mutex_t {
};
diff --git a/src/common/util.h b/src/common/util.h
index 2b13f92b47..d3a3d62413 100644
--- a/src/common/util.h
+++ b/src/common/util.h
@@ -260,6 +260,8 @@ int switch_id(char *user, char *group);
struct in_addr;
int tor_inet_aton(const char *cp, struct in_addr *addr);
int tor_lookup_hostname(const char *name, uint32_t *addr);
+int parse_addr_port(const char *addrport, char **address, uint32_t *addr,
+ uint16_t *port);
/* For stupid historical reasons, windows sockets have an independent
* set of errnos, and an independent way to get them. Also, you can't
diff --git a/src/or/test.c b/src/or/test.c
index 8b4917f381..4d74651edc 100644
--- a/src/or/test.c
+++ b/src/or/test.c
@@ -500,6 +500,9 @@ test_util() {
char buf[1024];
time_t t_res;
int i;
+ uint32_t u32;
+ uint16_t u16;
+ char *cp;
start.tv_sec = 5;
start.tv_usec = 5000;
@@ -633,6 +636,34 @@ test_util() {
NEVER_TERMINATE));
test_streq(buf, "abc##def##ghi");
+ /* Test parse_addr_port */
+ cp = NULL; u32 = 3; u16 = 3;
+ test_assert(!parse_addr_port("1.2.3.4", &cp, &u32, &u16));
+ test_streq(cp, "1.2.3.4");
+ test_eq(u32, 0x01020304u);
+ test_eq(u16, 0);
+ tor_free(cp);
+ test_assert(!parse_addr_port("4.3.2.1:99", &cp, &u32, &u16));
+ test_streq(cp, "4.3.2.1");
+ test_eq(u32, 0x04030201u);
+ test_eq(u16, 99);
+ tor_free(cp);
+ test_assert(!parse_addr_port("nonexistent.address:4040", &cp, NULL, &u16));
+ test_streq(cp, "nonexistent.address");
+ test_eq(u16, 4040);
+ tor_free(cp);
+ test_assert(!parse_addr_port("localhost:9999", &cp, &u32, &u16));
+ test_streq(cp, "localhost");
+ test_eq(u32, 0x7f000001u);
+ test_eq(u16, 9999);
+ tor_free(cp);
+ u32 = 3;
+ test_assert(!parse_addr_port("localhost", NULL, &u32, &u16));
+ test_eq(cp, NULL);
+ test_eq(u32, 0x7f000001u);
+ test_eq(u16, 0);
+ tor_free(cp);
+
/* XXXX test older functions. */
smartlist_free(sl);
}