Esempio n. 1
0
int upscli_connect(UPSCONN *ups, const char *host, int port, int flags)
{
	struct	sockaddr_in	local, server;
	struct	hostent	*serv;
	unsigned long numericIPAddr=INADDR_NONE;

	/* clear out any lingering junk */
	ups->fd = INVALID_SOCKET;
	ups->host = NULL;
	ups->flags = 0;
	ups->upserror = 0;
	ups->syserrno = 0;
	ups->upsclient_magic = UPSCLIENT_MAGIC;

	ups->pc_ctx = malloc(sizeof(PCONF_CTX));

	if (!ups->pc_ctx) {
		ups->upserror = UPSCLI_ERR_NOMEM;
		return -1;		
	}

	pconf_init(ups->pc_ctx, NULL);

	ups->ssl_ctx = NULL;
	ups->ssl = NULL;

	if (!host) {
		ups->upserror = UPSCLI_ERR_NOSUCHHOST;
		return -1;
	}

	memset(&local, '\0', sizeof(struct sockaddr_in));
	local.sin_family = AF_INET;
	local.sin_port = htons(INADDR_ANY);

	memset(&server, '\0', sizeof(struct sockaddr_in));
	server.sin_family = AF_INET;
	server.sin_port = htons((u_short)port);

	//Windows is brain dead when it comes to gethostbyname and numeric ip addresses.  GRRrrrr
	numericIPAddr = inet_addr(host);
	if(numericIPAddr != INADDR_NONE)
	{
		/* the string is a numeric IP address, just set it on the
		   server addr struct */
		server.sin_addr.s_addr = numericIPAddr;
	}
	else if((serv = gethostbyname(host)) != (struct hostent *) NULL)
	{
		/* the string is a DNS name, we resolved and stored 
		   it to the serv structure so now set it on the 
		   server struct */
		memcpy (&server.sin_addr, serv->h_addr, serv->h_length);
	}
	else /* could not resolve name or IP */
	{
		ups->upserror = UPSCLI_ERR_NOSUCHHOST;
		ups->syserrno = errno = WSAGetLastError();
		return (-1);
	}

	if ((ups->fd = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {
		ups->upserror = UPSCLI_ERR_SOCKFAILURE;
		ups->syserrno = errno = WSAGetLastError();
		return -1;
	}

	if (bind(ups->fd, (struct sockaddr *) &local, 
		sizeof(struct sockaddr_in)) == -1) {
		ups->upserror = UPSCLI_ERR_BINDFAILURE;
		ups->syserrno = errno;
		close(ups->fd);
		ups->fd = INVALID_SOCKET;

		return -1;
	}

	if (connect(ups->fd, (struct sockaddr *) &server, 
		sizeof(struct sockaddr_in)) == -1) {
		ups->upserror = UPSCLI_ERR_CONNFAILURE;
		ups->syserrno = errno;
		close(ups->fd);
		ups->fd = INVALID_SOCKET;

		return -1;
	}

	/* don't use xstrdup for cleaner linking (fewer dependencies) */
	ups->host = strdup(host);

	if (!ups->host) {
		close(ups->fd);
		ups->fd = INVALID_SOCKET;

		ups->upserror = UPSCLI_ERR_NOMEM;
		return -1;
	}

	ups->port = port;

	if (flags & UPSCLI_CONN_TRYSSL) {
		upscli_sslinit(ups);

		/* see if something made us die inside sslinit */
		if (ups->upserror != 0)
			return -1;
	}

	if (flags & UPSCLI_CONN_REQSSL) {
		if (upscli_sslinit(ups) != 1) {
			ups->upserror = UPSCLI_ERR_SSLFAIL;
			upscli_closefd(ups);
			return -1;
		}
	}

	return 0;
}
Esempio n. 2
0
int upscli_tryconnect(UPSCONN_t *ups, const char *host, int port, int flags,struct timeval * timeout)
{
	int	sock_fd;
	struct addrinfo	hints, *res, *ai;
	char			sport[NI_MAXSERV];
	int			v;
	fd_set 			wfds;
	int			error;
	socklen_t		error_size;
	long			fd_flags;

	if (!ups) {
		return -1;
	}

	/* clear out any lingering junk */
	memset(ups, 0, sizeof(*ups));
	ups->upsclient_magic = UPSCLIENT_MAGIC;
	ups->fd = -1;

	if (!host) {
		ups->upserror = UPSCLI_ERR_NOSUCHHOST;
		return -1;
	}

	snprintf(sport, sizeof(sport), "%hu", (unsigned short int)port);

	memset(&hints, 0, sizeof(hints));

	if (flags & UPSCLI_CONN_INET6) {
		hints.ai_family = AF_INET6;
	} else if (flags & UPSCLI_CONN_INET) {
		hints.ai_family = AF_INET;
	} else {
		hints.ai_family = AF_UNSPEC;
	}

	hints.ai_socktype = SOCK_STREAM;
	hints.ai_protocol = IPPROTO_TCP;

	while ((v = getaddrinfo(host, sport, &hints, &res)) != 0) {
		switch (v)
		{
		case EAI_AGAIN:
			continue;
		case EAI_NONAME:
			ups->upserror = UPSCLI_ERR_NOSUCHHOST;
			return -1;
		case EAI_MEMORY:
			ups->upserror = UPSCLI_ERR_NOMEM;
			return -1;
		case EAI_SYSTEM:
			ups->syserrno = errno;
			break;
		}

		ups->upserror = UPSCLI_ERR_UNKNOWN;
		return -1;
	}

	for (ai = res; ai != NULL; ai = ai->ai_next) {

		sock_fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);

		if (sock_fd < 0) {
			switch (errno)
			{
			case EAFNOSUPPORT:
			case EINVAL:
                                break;
			default:
				ups->upserror = UPSCLI_ERR_SOCKFAILURE;
				ups->syserrno = errno;
			}
			continue;
		}

		/* non blocking connect */
		if(timeout != NULL) {
			fd_flags = fcntl(sock_fd, F_GETFL);
			fd_flags |= O_NONBLOCK;
			fcntl(sock_fd, F_SETFL, fd_flags);
		}

		while ((v = connect(sock_fd, ai->ai_addr, ai->ai_addrlen)) < 0) {
			if(errno == EINPROGRESS) {
				FD_ZERO(&wfds);
				FD_SET(sock_fd, &wfds);
				select(sock_fd+1,NULL,&wfds,NULL,
						timeout);
				if (FD_ISSET(sock_fd, &wfds)) {
					error_size = sizeof(error);
					getsockopt(sock_fd,SOL_SOCKET,SO_ERROR,
							&error,&error_size);
					if( error == 0) {
						/* connect successful */
						v = 0;
						break;
					}
					errno = error;
				}
				else {
					/* Timeout */
					v = -1;
					break;
				}
			}

			switch (errno)
			{
			case EAFNOSUPPORT:
				break;
			case EINTR:
			case EAGAIN:
				continue;
			default:
				ups->upserror = UPSCLI_ERR_CONNFAILURE;
				ups->syserrno = errno;
			}
			break;
		}

		if (v < 0) {
			close(sock_fd);
			continue;
		}

		/* switch back to blocking operation */
		if(timeout != NULL) {
			fd_flags = fcntl(sock_fd, F_GETFL);
			fd_flags &= ~O_NONBLOCK;
			fcntl(sock_fd, F_SETFL, fd_flags);
		}

		ups->fd = sock_fd;
		ups->upserror = 0;
		ups->syserrno = 0;
		break;
	}

	freeaddrinfo(res);

	if (ups->fd < 0) {
		return -1;
	}

	pconf_init(&ups->pc_ctx, NULL);

	ups->host = strdup(host);

	if (!ups->host) {
		ups->upserror = UPSCLI_ERR_NOMEM;
		upscli_disconnect(ups);
		return -1;
	}

	ups->port = port;

	if (flags & UPSCLI_CONN_TRYSSL) {
		upscli_sslinit(ups);

		/* see if something made us die inside sslinit */
		if (ups->upserror != 0) {
			upscli_disconnect(ups);
			return -1;
		}
	}

	if ((flags & UPSCLI_CONN_REQSSL) && (upscli_sslinit(ups) != 1)) {
		ups->upserror = UPSCLI_ERR_SSLFAIL;
		upscli_disconnect(ups);
		return -1;
	}
		
	return 0;
}