Beispiel #1
0
/** Called after the remote hostname has been resolved. */
void
address_resolved(int result, char type, int count, int ttl
                 __attribute__ ((__unused__)), void *addresses, void *data)
{
  struct conn *c = data;
  struct sockaddr_un addr;
  struct hostname_info *ipaddr;

  c->resolver_req = NULL;

  if (result == DNS_ERR_CANCEL) {
    /*  Called on a connection that gets dropped while still doing the hostname lookup */
    return;
  }

  if (result != DNS_ERR_NONE || !addresses || type != DNS_PTR || count == 0) {
    ipaddr = ip_convert(&c->remote_addr.addr, c->remote_addrlen);
    c->remote_host = strdup(ipaddr->hostname);
    c->remote_ip = strdup(ipaddr->hostname);
  } else {
    const char *hostname = ((const char **) addresses)[0];
    c->remote_host = strdup(hostname);
    ipaddr = ip_convert(&c->remote_addr.addr, c->remote_addrlen);
    c->remote_ip = strdup(ipaddr->hostname);
  }

#if SSL_DEBUG_LEVEL > 0
  errprintf(stdout,
	    "ssl_slave: resolved hostname as '%s(%s)'. Opening local connection to mush.\n",
	    c->remote_host, c->remote_ip);
#endif

  c->state = C_LOCAL_CONNECTING;

  addr.sun_family = AF_LOCAL;
  strncpy(addr.sun_path, socket_file, sizeof(addr.sun_path) - 1);
  c->local_bev =
    bufferevent_socket_new(main_loop, -1,
                           BEV_OPT_CLOSE_ON_FREE | BEV_OPT_DEFER_CALLBACKS);
  bufferevent_socket_connect(c->local_bev, (struct sockaddr *) &addr,
                             sizeof addr);
  bufferevent_setcb(c->local_bev, NULL, NULL, ssl_event_cb, data);
  bufferevent_enable(c->local_bev, EV_WRITE);
}
void
query_info_slave(int fd)
{
  struct request_dgram req;
  struct hostname_info *hi;
  char buf[BUFFER_LEN], *bp;
  ssize_t slen;

  FD_SET(fd, &info_pending);
  if (fd > pending_max)
    pending_max = fd + 1;

  info_queue_time = time(NULL);

  if (info_slave_state == INFO_SLAVE_DOWN) {
    if (!make_info_slave()) {
      FD_CLR(fd, &info_pending);
      closesocket(fd);          /* Just drop the connection if the slave gets halted.
                                   A subsequent reconnect will work. */
    }
    return;
  }


  memset(&req, 0, sizeof req);

  req.rlen = MAXSOCKADDR;
  if (getpeername(fd, (struct sockaddr *) req.remote.data, &req.rlen) < 0) {
    penn_perror("socket peer vanished");
    shutdown(fd, 2);
    closesocket(fd);
    FD_CLR(fd, &info_pending);
    return;
  }

  /* Check for forbidden sites before bothering with ident */
  bp = buf;
  hi = ip_convert(&req.remote.addr, req.rlen);
  safe_str(hi ? hi->hostname : "Not found", buf, &bp);
  *bp = '\0';
  if (Forbidden_Site(buf)) {
    char port[NI_MAXSERV];
    if (getnameinfo(&req.remote.addr, req.rlen, NULL, 0, port, sizeof port,
                    NI_NUMERICHOST | NI_NUMERICSERV) != 0)
      penn_perror("getting remote port number");
    else {
      if (!Deny_Silent_Site(buf, AMBIGUOUS)) {
        do_log(LT_CONN, 0, 0, "[%d/%s] Refused connection (remote port %s)",
               fd, buf, port);
      }
    }
    closesocket(fd);
    FD_CLR(fd, &info_pending);
    return;
  }

  req.llen = MAXSOCKADDR;
  if (getsockname(fd, (struct sockaddr *) req.local.data, &req.llen) < 0) {
    penn_perror("socket self vanished");
    closesocket(fd);
    FD_CLR(fd, &info_pending);
    return;
  }

  req.fd = fd;
  req.use_dns = USE_DNS;

  slen = send(info_slave, &req, sizeof req, 0);
  if (slen < 0) {
    penn_perror("info slave query: write error");
    make_info_slave();
    return;
  } else if (slen != (int) sizeof req) {
    /* Shouldn't happen! */
    penn_perror("info slave query: partial packet");
    make_info_slave();
    return;
  }
  info_slave_state = INFO_SLAVE_PENDING;
}