Commit 8b037509 authored by Nick Mathewson's avatar Nick Mathewson 🦀
Browse files

Add functions to parse addr[:port] consistently


svn:r2440
parent 1efad741
Loading
Loading
Loading
Loading
+56 −0
Original line number Diff line number Diff line
@@ -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 {
};
+2 −0
Original line number Diff line number Diff line
@@ -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
+31 −0
Original line number Diff line number Diff line
@@ -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);
}