/* * Resolve a hostname through Tor and set the ip address in the given pointer. * * Return 0 on success else a negative value and the result addr is untouched. */ int tsocks_tor_resolve(const char *hostname, uint32_t *ip_addr) { int ret; struct connection conn; assert(hostname); assert(ip_addr); ret = hosts_file_resolve(hostname, ip_addr); if (!ret) { goto end; } DBG("Resolving %s on the Tor network", hostname); /* * Tor hidden service address have no IP address so we send back an onion * reserved IP address that acts as a cookie that we will use to find the * onion hostname at the connect() stage. */ if (utils_strcasecmpend(hostname, ".onion") == 0) { struct onion_entry *entry; entry = get_onion_entry(hostname, &tsocks_onion_pool); if (entry) { memcpy(ip_addr, &entry->ip, sizeof(entry->ip)); ret = 0; goto end; } } conn.fd = tsocks_libc_socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); if (conn.fd < 0) { PERROR("socket"); ret = -errno; goto error; } ret = setup_tor_connection(&conn); if (ret < 0) { goto error; } ret = socks5_send_resolve_request(hostname, &conn); if (ret < 0) { goto error; } /* Force IPv4 resolution for now. */ ret = socks5_recv_resolve_reply(&conn, ip_addr, sizeof(uint32_t)); if (ret < 0) { goto error; } ret = close(conn.fd); if (ret < 0) { PERROR("close"); } end: error: return ret; }
/* * Resolve a hostname through Tor and set the ip address in the given pointer. * * Return 0 on success else a negative value and the result addr is untouched. */ int tsocks_tor_resolve(int af, const char *hostname, void *ip_addr) { int ret; size_t addr_len; struct connection conn; assert(hostname); assert(ip_addr); if (af == AF_INET) { addr_len = sizeof(uint32_t); conn.dest_addr.domain = CONNECTION_DOMAIN_INET; } else if (af == AF_INET6) { addr_len = 16; conn.dest_addr.domain = CONNECTION_DOMAIN_INET6; /* Tor daemon does not support IPv6 DNS resolution yet. */ ret = -ENOSYS; goto error; } else { ret = -EINVAL; goto error; } ret = utils_localhost_resolve(hostname, af, ip_addr, addr_len); if (ret) { /* Found to be a localhost name. */ ret = 0; goto end; } DBG("Resolving %s on the Tor network", hostname); /* * Tor hidden service address have no IP address so we send back an onion * reserved IP address that acts as a cookie that we will use to find the * onion hostname at the connect() stage. */ if (utils_strcasecmpend(hostname, ".onion") == 0) { struct onion_entry *entry; entry = get_onion_entry(hostname, &tsocks_onion_pool); if (entry) { memcpy(ip_addr, &entry->ip, sizeof(entry->ip)); ret = 0; goto end; } } conn.fd = tsocks_libc_socket(af, SOCK_STREAM, IPPROTO_TCP); if (conn.fd < 0) { PERROR("socket"); ret = -errno; goto error; } ret = setup_tor_connection(&conn, SOCKS5_NO_AUTH_METHOD); if (ret < 0) { goto end_close; } ret = socks5_send_resolve_request(hostname, &conn); if (ret < 0) { goto end_close; } /* Force IPv4 resolution for now. */ ret = socks5_recv_resolve_reply(&conn, ip_addr, addr_len); if (ret < 0) { goto end_close; } end_close: if (tsocks_libc_close(conn.fd) < 0) { PERROR("close"); } end: error: return ret; }