|  | @@ -66,9 +66,16 @@ static ssize_t rend_service_parse_intro_for_v3(
 | 
	
		
			
				|  |  |   * a real port on some IP.
 | 
	
		
			
				|  |  |   */
 | 
	
		
			
				|  |  |  typedef struct rend_service_port_config_t {
 | 
	
		
			
				|  |  | +  /* The incoming HS virtual port we're mapping */
 | 
	
		
			
				|  |  |    uint16_t virtual_port;
 | 
	
		
			
				|  |  | +  /* Is this an AF_UNIX port? */
 | 
	
		
			
				|  |  | +  unsigned int is_unix_addr:1;
 | 
	
		
			
				|  |  | +  /* The outgoing TCP port to use, if !is_unix_addr */
 | 
	
		
			
				|  |  |    uint16_t real_port;
 | 
	
		
			
				|  |  | +  /* The outgoing IPv4 or IPv6 address to use, if !is_unix_addr */
 | 
	
		
			
				|  |  |    tor_addr_t real_addr;
 | 
	
		
			
				|  |  | +  /* The socket path to connect to, if is_unix_addr */
 | 
	
		
			
				|  |  | +  char unix_addr[FLEXIBLE_ARRAY_MEMBER];
 | 
	
		
			
				|  |  |  } rend_service_port_config_t;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /** Try to maintain this many intro points per service by default. */
 | 
	
	
		
			
				|  | @@ -279,8 +286,24 @@ rend_add_service(rend_service_t *service)
 | 
	
		
			
				|  |  |                service->directory);
 | 
	
		
			
				|  |  |      for (i = 0; i < smartlist_len(service->ports); ++i) {
 | 
	
		
			
				|  |  |        p = smartlist_get(service->ports, i);
 | 
	
		
			
				|  |  | -      log_debug(LD_REND,"Service maps port %d to %s",
 | 
	
		
			
				|  |  | -                p->virtual_port, fmt_addrport(&p->real_addr, p->real_port));
 | 
	
		
			
				|  |  | +      if (!(p->is_unix_addr)) {
 | 
	
		
			
				|  |  | +        log_debug(LD_REND,
 | 
	
		
			
				|  |  | +                  "Service maps port %d to %s",
 | 
	
		
			
				|  |  | +                  p->virtual_port,
 | 
	
		
			
				|  |  | +                  fmt_addrport(&p->real_addr, p->real_port));
 | 
	
		
			
				|  |  | +      } else {
 | 
	
		
			
				|  |  | +#ifdef HAVE_SYS_UN_H
 | 
	
		
			
				|  |  | +        log_debug(LD_REND,
 | 
	
		
			
				|  |  | +                  "Service maps port %d to socket at \"%s\"",
 | 
	
		
			
				|  |  | +                  p->virtual_port, p->unix_addr);
 | 
	
		
			
				|  |  | +#else
 | 
	
		
			
				|  |  | +        log_debug(LD_REND,
 | 
	
		
			
				|  |  | +                  "Service maps port %d to an AF_UNIX socket, but we "
 | 
	
		
			
				|  |  | +                  "have no AF_UNIX support on this platform.  This is "
 | 
	
		
			
				|  |  | +                  "probably a bug.",
 | 
	
		
			
				|  |  | +                  p->virtual_port);
 | 
	
		
			
				|  |  | +#endif /* defined(HAVE_SYS_UN_H) */
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  }
 | 
	
	
		
			
				|  | @@ -345,6 +368,8 @@ parse_port_config(const char *string)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    result = tor_malloc(sizeof(rend_service_port_config_t));
 | 
	
		
			
				|  |  |    result->virtual_port = virtport;
 | 
	
		
			
				|  |  | +  /* TODO actually support AF_UNIX here */
 | 
	
		
			
				|  |  | +  result->is_unix_addr = 0;
 | 
	
		
			
				|  |  |    result->real_port = realport;
 | 
	
		
			
				|  |  |    tor_addr_copy(&result->real_addr, &addr);
 | 
	
		
			
				|  |  |   err:
 | 
	
	
		
			
				|  | @@ -3416,6 +3441,7 @@ rend_service_set_connection_addr_port(edge_connection_t *conn,
 | 
	
		
			
				|  |  |    char serviceid[REND_SERVICE_ID_LEN_BASE32+1];
 | 
	
		
			
				|  |  |    smartlist_t *matching_ports;
 | 
	
		
			
				|  |  |    rend_service_port_config_t *chosen_port;
 | 
	
		
			
				|  |  | +  int unix_addrs;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    tor_assert(circ->base_.purpose == CIRCUIT_PURPOSE_S_REND_JOINED);
 | 
	
		
			
				|  |  |    tor_assert(circ->rend_data);
 | 
	
	
		
			
				|  | @@ -3431,10 +3457,19 @@ rend_service_set_connection_addr_port(edge_connection_t *conn,
 | 
	
		
			
				|  |  |      return -2;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |    matching_ports = smartlist_new();
 | 
	
		
			
				|  |  | +  unix_addrs = 0;
 | 
	
		
			
				|  |  |    SMARTLIST_FOREACH(service->ports, rend_service_port_config_t *, p,
 | 
	
		
			
				|  |  |    {
 | 
	
		
			
				|  |  | +    /*
 | 
	
		
			
				|  |  | +     * TODO don't just ignore AF_UNIX ports, but set up edge_connection_t
 | 
	
		
			
				|  |  | +     * properly to use them.
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  |      if (conn->base_.port == p->virtual_port) {
 | 
	
		
			
				|  |  | -      smartlist_add(matching_ports, p);
 | 
	
		
			
				|  |  | +      if (!(p->is_unix_addr)) {
 | 
	
		
			
				|  |  | +        smartlist_add(matching_ports, p);
 | 
	
		
			
				|  |  | +      } else {
 | 
	
		
			
				|  |  | +        ++unix_addrs;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |    });
 | 
	
		
			
				|  |  |    chosen_port = smartlist_choose(matching_ports);
 | 
	
	
		
			
				|  | @@ -3444,8 +3479,23 @@ rend_service_set_connection_addr_port(edge_connection_t *conn,
 | 
	
		
			
				|  |  |      conn->base_.port = chosen_port->real_port;
 | 
	
		
			
				|  |  |      return 0;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | -  log_info(LD_REND, "No virtual port mapping exists for port %d on service %s",
 | 
	
		
			
				|  |  | -           conn->base_.port,serviceid);
 | 
	
		
			
				|  |  | +  if (!unix_addrs) {
 | 
	
		
			
				|  |  | +    log_info(LD_REND,
 | 
	
		
			
				|  |  | +             "No virtual port mapping exists for port %d on service %s",
 | 
	
		
			
				|  |  | +             conn->base_.port, serviceid);
 | 
	
		
			
				|  |  | +  } else {
 | 
	
		
			
				|  |  | +#ifdef HAVE_SYS_UN_H
 | 
	
		
			
				|  |  | +    log_info(LD_REND,
 | 
	
		
			
				|  |  | +             "Only AF_UNIX virtual port mappings exists for port %d "
 | 
	
		
			
				|  |  | +             "on service %s, and support is not yet implemented",
 | 
	
		
			
				|  |  | +             conn->base_.port, serviceid);
 | 
	
		
			
				|  |  | +#else
 | 
	
		
			
				|  |  | +    log_info(LD_REND,
 | 
	
		
			
				|  |  | +             "Only AF_UNIX virtual port mappings exists for port %d "
 | 
	
		
			
				|  |  | +             "on service %s, and support is not available on this platform",
 | 
	
		
			
				|  |  | +             conn->base_.port, serviceid);
 | 
	
		
			
				|  |  | +#endif /* defined(HAVE_SYS_UN_H) */
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  |    if (service->allow_unknown_ports)
 | 
	
		
			
				|  |  |      return -1;
 | 
	
		
			
				|  |  |    else
 |