Beispiel #1
0
/* connect remote host */
NOEXPORT int connect_remote(CLI *c) {
    int fd, ind_start, ind_try, ind_cur;

    setup_connect_addr(c);
    ind_start=c->connect_addr.cur;
    /* the race condition here can be safely ignored */
    if(c->opt->failover==FAILOVER_RR)
        c->connect_addr.cur=(ind_start+1)%c->connect_addr.num;

    /* try to connect each host from the list */
    for(ind_try=0; ind_try<c->connect_addr.num; ind_try++) {
        ind_cur=(ind_start+ind_try)%c->connect_addr.num;
        c->fd=s_socket(c->connect_addr.addr[ind_cur].sa.sa_family,
            SOCK_STREAM, 0, 1, "remote socket");
        if(c->fd<0)
            longjmp(c->err, 1);

        local_bind(c); /* explicit local bind or transparent proxy */

        if(s_connect(c, &c->connect_addr.addr[ind_cur],
                addr_len(&c->connect_addr.addr[ind_cur]))) {
            closesocket(c->fd);
            c->fd=-1;
            continue; /* next IP */
        }
        print_bound_address(c);
        fd=c->fd;
        c->fd=-1;
        return fd; /* success! */
    }
    longjmp(c->err, 1);
    return -1; /* some C compilers require a return value */
}
Beispiel #2
0
/** Send a message through the socket
 *
 * If a disconnection occurs, 0 will be returned, as no data was sent.  To
 * differentiate from cases where data couldn't be written just yet, the socket
 * should be inspected with socket_is_disconnected().
 *
 * \param socket Socket to send message through
 * \param buf data to send
 * \param buf_size amount of data to read from buf
 * \return the amount of data sent, or -1 on error
 *
 * \see socket_is_disconnected, sendto(3)
 */
int
socket_sendto(Socket* socket, char* buf, int buf_size)
{
  SocketInt *self = (SocketInt*)socket;
  int sent;


  if (self->is_disconnected) {
    if(!s_connect(self)) {
      return 0;
    }

  } else if((sent = recv(self->sockfd, NULL, 0, MSG_DONTWAIT)) == 0) {
    /* Test that the server kept the other side of the connection alive */
    if (!(sent < 0 && EAGAIN == errno)) {
      /* EAGAIN is the expected case: connection alive but no data,
       * everything else is a problem */
      logwarn("socket(%s): Server appears to have closed the connection\n", self->name);

      self->is_disconnected = 1;
      /* We want higher levels to be aware of this disconnection */
      return 0;
    }

  }

  if ((sent = sendto(self->sockfd, buf, buf_size, MSG_NOSIGNAL,
                    &(self->servAddr.sa),
                    sizeof(self->servAddr.sa_stor))) < 0) {
    if (errno == EPIPE || errno == ECONNRESET) {
      // The other end closed the connection.
      self->is_disconnected = 1;
      o_log(O_LOG_ERROR, "socket(%s): The remote peer closed the connection: %s\n",
            self->name, strerror(errno));
      return 0;
    } else if (errno == ECONNREFUSED) {
      self->is_disconnected = 1;
      o_log(O_LOG_DEBUG, "socket(%s): Connection refused, trying next AI\n",
            self->name);
      self->rp = self->rp->ai_next;
      return 0;
    } else if (errno == EINTR) {
      o_log(O_LOG_WARN, "socket(%s): Sending data interrupted: %s\n",
            self->name, strerror(errno));
      return 0;
    } else {
      o_log(O_LOG_ERROR, "socket(%s): Sending data failed: %s\n",
            self->name, strerror(errno));
    }
    return -1;
  }
  return sent;
}
Beispiel #3
0
/** Attempt to reconnect an OComm Socket.
 *
 * \param socket OComm socket
 * \return 0 on failure, the new socket number otherwise
 * \see s_connect
 */
int socket_reconnect(Socket* socket) {
  SocketInt* self = (SocketInt*)socket;

  if (self == NULL) {
    o_log(O_LOG_ERROR, "Missing socket definition\n");
    return 0;
  }

  if (!s_socket(self)) {
    return 0;
  }
  return s_connect(self, NULL, -1);
}
Beispiel #4
0
int main (int argc, char *argv [])
{
    char *sock = (argc > 1)? argv [1]: "";
    if (streq(sock,""))
    {
        zclock_log("cannot start broker for %s", sock);
        return -1;
    }
    char *job = (argc > 2)? argv [2]: "";
    if (streq(job,"")) 
    {
		zclock_log("cannot start broker job %s", job);
		return -1;
	}
    
    if (s_connect(sock)<0) {
        zclock_log("cannot connect to %s", sock);
        return -1;
    }
    else {
        zclock_log("broker connected to %s", sock);
    }
    
    
    struct sigaction sa;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags=0;
    sa.sa_handler = s_signal_handler;
    sigaction(SIGHUP, &sa, 0);
    sigaction(SIGINT, &sa, 0);
    sigaction(SIGQUIT, &sa, 0);
    sigaction(SIGABRT, &sa, 0);
    sigaction(SIGTERM, &sa, 0);
	if (streq(job,"loop")) 
	{
		char *arg = (argc > 3)? argv [3]: "1";
		int count = atoi(arg);
		start_loop(count);
	}
	if (streq(job,"sleep"))
	{
		char *arg = (argc > 3)? argv [3]: "1000";
		start_echo(arg);
	}
    exit(0);
}
Beispiel #5
0
Socket*
socket_tcp_out_new(
  char* name,   //! Name used for debugging
  char* addr,   //! IP address of the server to connect to.
  int port //! Port of remote service
) {
  SocketInt* self;

  if (addr == NULL) {
    o_log(O_LOG_ERROR, "socket:%s: Missing address\n", name);
    return NULL;
  }

  if ((self = (SocketInt*)socket_new(name, TRUE)) == NULL)
    return NULL;

  if (!s_connect(self, addr, port)) {
    free(self);
    return NULL;
  }

  //  eventloop_on_out_channel((Socket*)self, on_self_connected, NULL);
  return (Socket*)self;
}
Beispiel #6
0
const char *tcpremoteinfo(const RFC1035_ADDR *laddr, int lport,
	const RFC1035_ADDR *raddr, int rport, const char **ostype)
{
int	fd;
time_t	current_time, max_time;
fd_set	fds;
struct	timeval	tv;
static char buf[512];
char	*bufptr;
int	bufleft, n;
char	*p;
char	*q;
RFC1035_NETADDR	sin;
const struct sockaddr *addr;
int	addrlen;

	fd=rfc1035_mksocket(SOCK_STREAM, 0, &n);
	if (fd < 0)	return (0);

	if (rfc1035_mkaddress(n, &sin, laddr, 0, &addr, &addrlen) < 0)
	{
		close(fd);
		return (0);
	}

	if (sox_bind(fd, addr, addrlen) < 0)
	{
		sox_close(fd);
		return (0);
	}

	time (&current_time);
	max_time=current_time+30;

	if (rfc1035_mkaddress(n, &sin, raddr, htons(113), &addr, &addrlen) < 0)
	{
		sox_close(fd);
		return (0);
	}

	if (s_connect(fd, addr, addrlen, max_time - current_time) < 0)
	{
		sox_close(fd);
		return (0);
	}

	sprintf(buf, "%d,%d\r\n", ntohs(rport), ntohs(lport));
	bufptr=buf;
	bufleft=strlen(buf);
	while (bufleft)
	{
		time(&current_time);
		if (current_time >= max_time)
		{
			sox_close(fd);
			return (0);
		}

		FD_ZERO(&fds);
		FD_SET(fd, &fds);
		tv.tv_sec=max_time-current_time;
		tv.tv_usec=0;
		if (sox_select(fd+1, 0, &fds, 0, &tv) != 1 ||
			!FD_ISSET(fd, &fds))
		{
			sox_close(fd);
			return (0);
		}
		n=sox_write(fd, bufptr, bufleft);
		if (n <= 0)
		{
			sox_close(fd);
			return (0);
		}
		bufptr += n;
		bufleft -= n;
	}

	bufptr=buf;
	bufleft=sizeof(buf);
	do
	{
		if (bufleft == 0)
		{
			sox_close(fd);
			return (0);
		}

		time(&current_time);
		if (current_time >= max_time)
		{
			sox_close(fd);
			return (0);
		}

		FD_ZERO(&fds);
		FD_SET(fd, &fds);
		tv.tv_sec=max_time-current_time;
		tv.tv_usec=0;
		if (sox_select(fd+1, &fds, 0, 0, &tv) != 1 ||
			!FD_ISSET(fd, &fds))
		{
			sox_close(fd);
			return (0);
		}

		n=sox_read(fd, bufptr, bufleft);
		if (n <= 0)
		{
			sox_close(fd);
			return (0);
		}
		bufptr += n;
		bufleft -= n;
	} while (bufptr[-1] != '\n');
	sox_close(fd);
	bufptr[-1]=0;
	--bufptr;
	if (bufptr > buf && bufptr[-1] == '\r')
		bufptr[-1]=0;

	if ((p=strchr(buf, ':')) == 0)
		return (0);

	q=++p;
	if ((p=strchr(p, ':')) == 0)
		return (0);

	*p++=0;
	q=strtok(q, " \t");
	if (!q || strcmp(q, "USERID"))	return (0);
	if (ostype)	*ostype=p;
	if ((p=strchr(p, ':')) == 0)
		return (0);
	*p++=0;
	while (*p && (*p == ' ' || *p == '\t'))	p++;
	return (p);
}
Beispiel #7
0
NOEXPORT OCSP_RESPONSE *ocsp_get_response(CLI *c,
        OCSP_REQUEST *req, char *url) {
    BIO *bio=NULL;
    OCSP_REQ_CTX *req_ctx=NULL;
    OCSP_RESPONSE *resp=NULL;
    int err;
    char *host=NULL, *port=NULL, *path=NULL;
    SOCKADDR_UNION addr;
    int ssl;

    /* parse the OCSP URL */
    if(!OCSP_parse_url(url, &host, &port, &path, &ssl)) {
        s_log(LOG_ERR, "OCSP: Failed to parse the OCSP URL");
        goto cleanup;
    }
    if(ssl) {
        s_log(LOG_ERR, "OCSP: SSL not supported for OCSP"
            " - additional stunnel service needs to be defined");
        goto cleanup;
    }
    memset(&addr, 0, sizeof addr);
    addr.in.sin_family=AF_INET;
    if(!hostport2addr(&addr, host, port)) {
        s_log(LOG_ERR, "OCSP: Failed to resolve the OCSP server address");
        goto cleanup;
    }

    /* connect specified OCSP server (responder) */
    c->fd=s_socket(addr.sa.sa_family, SOCK_STREAM, 0, 1, "OCSP: socket");
    if(c->fd<0)
        goto cleanup;
    if(s_connect(c, &addr, addr_len(&addr)))
        goto cleanup;
    bio=BIO_new_fd(c->fd, BIO_NOCLOSE);
    if(!bio)
        goto cleanup;
    s_log(LOG_DEBUG, "OCSP: response retrieved");

    /* OCSP protocol communication loop */
    req_ctx=OCSP_sendreq_new(bio, path, req, -1);
    if(!req_ctx) {
        sslerror("OCSP: OCSP_sendreq_new");
        goto cleanup;
    }
    while(OCSP_sendreq_nbio(&resp, req_ctx)==-1) {
        s_poll_init(c->fds);
        s_poll_add(c->fds, c->fd, BIO_should_read(bio), BIO_should_write(bio));
        err=s_poll_wait(c->fds, c->opt->timeout_busy, 0);
        if(err==-1)
            sockerror("OCSP: s_poll_wait");
        if(err==0)
            s_log(LOG_INFO, "OCSP: s_poll_wait: TIMEOUTbusy exceeded");
        if(err<=0)
            goto cleanup;
    }
#if 0
    s_log(LOG_DEBUG, "OCSP: context state: 0x%x", *(int *)req_ctx);
#endif
    /* http://www.mail-archive.com/[email protected]/msg61691.html */
    if(resp) {
        s_log(LOG_DEBUG, "OCSP: request completed");
    } else {
        if(ERR_peek_error())
            sslerror("OCSP: OCSP_sendreq_nbio");
        else /* OpenSSL error: OCSP_sendreq_nbio does not use OCSPerr */
            s_log(LOG_ERR, "OCSP: OCSP_sendreq_nbio: OpenSSL internal error");
    }

cleanup:
    if(req_ctx)
        OCSP_REQ_CTX_free(req_ctx);
    if(bio)
        BIO_free_all(bio);
    if(c->fd>=0) {
        closesocket(c->fd);
        c->fd=-1; /* avoid double close on cleanup */
    }
    if(host)
        OPENSSL_free(host);
    if(port)
        OPENSSL_free(port);
    if(path)
        OPENSSL_free(path);
    return resp;
}
Beispiel #8
0
NOEXPORT void auth_user(CLI *c, char *accepted_address) {
#ifndef _WIN32_WCE
    struct servent *s_ent;    /* structure for getservbyname */
#endif
    SOCKADDR_UNION ident;     /* IDENT socket name */
    char *line, *type, *system, *user;

    if(!c->opt->username)
        return; /* -u option not specified */
#ifdef HAVE_STRUCT_SOCKADDR_UN
    if(c->peer_addr.sa.sa_family==AF_UNIX) {
        s_log(LOG_INFO, "IDENT not supported on Unix sockets");
        return;
    }
#endif
    c->fd=s_socket(c->peer_addr.sa.sa_family, SOCK_STREAM,
        0, 1, "socket (auth_user)");
    if(c->fd<0)
        longjmp(c->err, 1);
    memcpy(&ident, &c->peer_addr, c->peer_addr_len);
#ifndef _WIN32_WCE
    s_ent=getservbyname("auth", "tcp");
    if(s_ent) {
        ident.in.sin_port=s_ent->s_port;
    } else
#endif
    {
        s_log(LOG_WARNING, "Unknown service 'auth': using default 113");
        ident.in.sin_port=htons(113);
    }
    if(s_connect(c, &ident, addr_len(&ident)))
        longjmp(c->err, 1);
    s_log(LOG_DEBUG, "IDENT server connected");
    fd_printf(c, c->fd, "%u , %u",
        ntohs(c->peer_addr.in.sin_port),
        ntohs(c->opt->local_addr.in.sin_port));
    line=fd_getline(c, c->fd);
    closesocket(c->fd);
    c->fd=-1; /* avoid double close on cleanup */
    type=strchr(line, ':');
    if(!type) {
        s_log(LOG_ERR, "Malformed IDENT response");
        str_free(line);
        longjmp(c->err, 1);
    }
    *type++='\0';
    system=strchr(type, ':');
    if(!system) {
        s_log(LOG_ERR, "Malformed IDENT response");
        str_free(line);
        longjmp(c->err, 1);
    }
    *system++='\0';
    if(strcmp(type, " USERID ")) {
        s_log(LOG_ERR, "Incorrect INETD response type");
        str_free(line);
        longjmp(c->err, 1);
    }
    user=strchr(system, ':');
    if(!user) {
        s_log(LOG_ERR, "Malformed IDENT response");
        str_free(line);
        longjmp(c->err, 1);
    }
    *user++='\0';
    while(*user==' ') /* skip leading spaces */
        ++user;
    if(strcmp(user, c->opt->username)) {
        safestring(user);
        s_log(LOG_WARNING, "Connection from %s REFUSED by IDENT (user %s)",
            accepted_address, user);
        str_free(line);
        longjmp(c->err, 1);
    }
    s_log(LOG_INFO, "IDENT authentication passed");
    str_free(line);
}