示例#1
0
文件: ssl.c 项目: neshema/openconnect
static int cancellable_connect(struct openconnect_info *vpninfo, int sockfd,
                               const struct sockaddr *addr, socklen_t addrlen)
{
    struct sockaddr_storage peer;
    socklen_t peerlen = sizeof(peer);
    fd_set wr_set, rd_set;
    int maxfd = sockfd;

    set_sock_nonblock(sockfd);
    if (vpninfo->protect_socket)
        vpninfo->protect_socket(vpninfo->cbdata, sockfd);

    if (connect(sockfd, addr, addrlen) < 0 && !connect_pending())
        return -1;

    do {
        FD_ZERO(&wr_set);
        FD_ZERO(&rd_set);
        FD_SET(sockfd, &wr_set);
        cmd_fd_set(vpninfo, &rd_set, &maxfd);

        select(maxfd + 1, &rd_set, &wr_set, NULL, NULL);
        if (is_cancel_pending(vpninfo, &rd_set)) {
            vpn_progress(vpninfo, PRG_ERR, _("Socket connect cancelled\n"));
            errno = EINTR;
            return -1;
        }
    } while (!FD_ISSET(sockfd, &wr_set) && !vpninfo->got_pause_cmd);

    /* Check whether connect() succeeded or failed by using
       getpeername(). See http://cr.yp.to/docs/connect.html */
    return getpeername(sockfd, (void *)&peer, &peerlen);
}
示例#2
0
文件: io.c 项目: CMONO/libfuncs
int do_connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen, int timeout) {
	set_sock_nonblock(sockfd);
	// Trying to connect with timeout
	int result = connect(sockfd, serv_addr, addrlen);
	if (result < 0) { // Not connected
		if (errno != EINPROGRESS) { // Not in progress
			return -1;
		} else { // Wait a timeout ms for socket to become ready to write into
			struct pollfd fdset[1];
			fdset[0].fd = sockfd;
			fdset[0].events = POLLOUT | POLLERR | POLLHUP | POLLNVAL | POLLRDHUP;
			do {
				int fdready = poll(fdset, 1, timeout);
				if (fdready == -1 && errno == EINTR)
					continue;
				if (fdready < 1 || (fdready == 1 && fdset[0].revents != POLLOUT)) { // Timeout || error
					// Get socket error
					unsigned int err_val=0, sz = sizeof(int); 
					getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void*)(&err_val), &sz);
					errno = err_val;
					if (!errno) // It can't be success, so simulate timeout
						errno = ENETDOWN;
					return -1;
				}
				break;
			} while (1);
		}
	}
	set_sock_block(sockfd);
	return 0;
}
示例#3
0
OPENCONNECT_CMD_SOCKET openconnect_setup_cmd_pipe(struct openconnect_info *vpninfo)
{
	OPENCONNECT_CMD_SOCKET pipefd[2];

#ifdef _WIN32
	if (dumb_socketpair(pipefd, 0))
		return CMD_PIPE_ERR;
#else
	if (pipe(pipefd) < 0)
		return CMD_PIPE_ERR;
#endif

	if (set_sock_nonblock(pipefd[0]) || set_sock_nonblock(pipefd[1])) {
		closesocket(pipefd[0]);
		closesocket(pipefd[1]);
		return CMD_PIPE_ERR;
	}
	vpninfo->cmd_fd = pipefd[0];
	vpninfo->cmd_fd_write = pipefd[1];
	return vpninfo->cmd_fd_write;
}
示例#4
0
int openconnect_setup_tun_fd(struct openconnect_info *vpninfo, int tun_fd)
{
	set_fd_cloexec(tun_fd);

	if (vpninfo->tun_fd != -1)
		unmonitor_read_fd(vpninfo, tun);

	vpninfo->tun_fd = tun_fd;

	monitor_fd_new(vpninfo, tun);
	monitor_read_fd(vpninfo, tun);

	set_sock_nonblock(tun_fd);

	return 0;
}
示例#5
0
文件: udp.c 项目: LiminWang/tsdecrypt
static int get_socket(const char *hostname, const char *service, int socktype, struct sockaddr_storage *addr, int *addrlen, int *sock, bool is_output) {
	struct addrinfo hints, *res, *ressave;
	int n, ret = -1;

	memset(&hints, 0, sizeof(struct addrinfo));
	hints.ai_family = ai_family;
	hints.ai_socktype = socktype;

	n = getaddrinfo(hostname, service, &hints, &res);
	if (n < 0) {
		ts_LOGf("ERROR: getaddrinfo(%s): %s\n", hostname, gai_strerror(n));
		return ret;
	}

	ressave = res;
	while (res) {
		*sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
		if (*sock > -1) {
			int on = 1;
			setsockopt(*sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
			set_sock_nonblock(*sock);
			if (is_output) {
				memcpy(addr, res->ai_addr, res->ai_addrlen);
				*addrlen = res->ai_addrlen;
				ret = 0;
				break;
			}
			if (bind(*sock, res->ai_addr, res->ai_addrlen) == 0) {
				memcpy(addr, res->ai_addr, res->ai_addrlen);
				*addrlen = res->ai_addrlen;
				ret = 0;
				break;
			} else {
				char str_addr[INET6_ADDRSTRLEN];
				my_inet_ntop(res->ai_family, res->ai_addr, str_addr, sizeof(str_addr));
				ts_LOGf("ERROR: bind: %s:%s (%s): %s\n",
					hostname, service, str_addr, strerror(errno));
			}
			close(*sock);
			*sock = -1;
		}
		res = res->ai_next;
	}
	freeaddrinfo(ressave);

	return ret;
}
示例#6
0
/* Windows is interminably horrid, and has disjoint errno spaces.
 * So if we return a positive value, that's a WSA Error and should
 * be handled with openconnect__win32_strerror(). But if we return a
 * negative value, that's a normal errno and should be handled with
 * strerror(). No, you can't just pass the latter value (negated) to
 * openconnect__win32_strerror() because it gives nonsense results. */
static int cancellable_connect(struct openconnect_info *vpninfo, int sockfd,
			       const struct sockaddr *addr, socklen_t addrlen)
{
	struct sockaddr_storage peer;
	socklen_t peerlen = sizeof(peer);
	fd_set wr_set, rd_set, ex_set;
	int maxfd = sockfd;
	int err;

	set_sock_nonblock(sockfd);
	if (vpninfo->protect_socket)
		vpninfo->protect_socket(vpninfo->cbdata, sockfd);

	if (connect(sockfd, addr, addrlen) < 0 && !connect_pending()) {
#ifdef _WIN32
		return WSAGetLastError();
#else
		return -errno;
#endif
	}

	do {
		FD_ZERO(&wr_set);
		FD_ZERO(&rd_set);
		FD_ZERO(&ex_set);
		FD_SET(sockfd, &wr_set);
#ifdef _WIN32 /* Windows indicates failure this way, not in wr_set */
		FD_SET(sockfd, &ex_set);
#endif
		cmd_fd_set(vpninfo, &rd_set, &maxfd);
		select(maxfd + 1, &rd_set, &wr_set, &ex_set, NULL);
		if (is_cancel_pending(vpninfo, &rd_set)) {
			vpn_progress(vpninfo, PRG_ERR, _("Socket connect cancelled\n"));
			return -EINTR;
		}
	} while (!FD_ISSET(sockfd, &wr_set) && !FD_ISSET(sockfd, &ex_set) &&
		 !vpninfo->got_pause_cmd);

	/* Check whether connect() succeeded or failed by using
	   getpeername(). See http://cr.yp.to/docs/connect.html */
	if (!getpeername(sockfd, (void *)&peer, &peerlen))
		return 0;

#ifdef _WIN32 /* On Windows, use getsockopt() to determine the error.
	       * We don't ddo this on Windows because it just reports
	       * -ENOTCONN, which we already knew. */

	err = WSAGetLastError();
	if (err == WSAENOTCONN) {
		socklen_t errlen = sizeof(err);

		getsockopt(sockfd, SOL_SOCKET, SO_ERROR,
			   (void *)&err, &errlen);
	}
#else
	err = -errno;
	if (err == -ENOTCONN) {
		int ch;

		if (read(sockfd, &ch, 1) < 0)
			err = -errno;
		/* It should *always* fail! */
	}
#endif
	return err;
}
示例#7
0
int connect_dtls_socket(struct openconnect_info *vpninfo)
{
	int dtls_fd, ret, sndbuf;

	/* Sanity check for the removal of new_dtls_{fd,ssl} */
	if (vpninfo->dtls_fd != -1) {
		vpn_progress(vpninfo, PRG_ERR, _("DTLS connection attempted with an existing fd\n"));
		vpninfo->dtls_attempt_period = 0;
		return -EINVAL;
	}

	if (!vpninfo->dtls_addr) {
		vpn_progress(vpninfo, PRG_ERR, _("No DTLS address\n"));
		vpninfo->dtls_attempt_period = 0;
		return -EINVAL;
	}

	if (!vpninfo->dtls_cipher) {
		/* We probably didn't offer it any ciphers it liked */
		vpn_progress(vpninfo, PRG_ERR, _("Server offered no DTLS cipher option\n"));
		vpninfo->dtls_attempt_period = 0;
		return -EINVAL;
	}

	if (vpninfo->proxy) {
		/* XXX: Theoretically, SOCKS5 proxies can do UDP too */
		vpn_progress(vpninfo, PRG_ERR, _("No DTLS when connected via proxy\n"));
		vpninfo->dtls_attempt_period = 0;
		return -EINVAL;
	}

	dtls_fd = socket(vpninfo->peer_addr->sa_family, SOCK_DGRAM, IPPROTO_UDP);
	if (dtls_fd < 0) {
		perror(_("Open UDP socket for DTLS:"));
		return -EINVAL;
	}
	if (vpninfo->protect_socket)
		vpninfo->protect_socket(vpninfo->cbdata, dtls_fd);

	sndbuf = vpninfo->ip_info.mtu * 2;
	setsockopt(dtls_fd, SOL_SOCKET, SO_SNDBUF, (void *)&sndbuf, sizeof(sndbuf));

	if (vpninfo->dtls_local_port) {
		union {
			struct sockaddr_in in;
			struct sockaddr_in6 in6;
		} dtls_bind_addr;
		int dtls_bind_addrlen;
		memset(&dtls_bind_addr, 0, sizeof(dtls_bind_addr));

		if (vpninfo->peer_addr->sa_family == AF_INET) {
			struct sockaddr_in *addr = &dtls_bind_addr.in;
			dtls_bind_addrlen = sizeof(*addr);
			addr->sin_family = AF_INET;
			addr->sin_addr.s_addr = INADDR_ANY;
			addr->sin_port = htons(vpninfo->dtls_local_port);
		} else if (vpninfo->peer_addr->sa_family == AF_INET6) {
			struct sockaddr_in6 *addr = &dtls_bind_addr.in6;
			dtls_bind_addrlen = sizeof(*addr);
			addr->sin6_family = AF_INET6;
			addr->sin6_addr = in6addr_any;
			addr->sin6_port = htons(vpninfo->dtls_local_port);
		} else {
			vpn_progress(vpninfo, PRG_ERR,
				     _("Unknown protocol family %d. Cannot do DTLS\n"),
				     vpninfo->peer_addr->sa_family);
			vpninfo->dtls_attempt_period = 0;
			closesocket(dtls_fd);
			return -EINVAL;
		}

		if (bind(dtls_fd, (struct sockaddr *)&dtls_bind_addr, dtls_bind_addrlen)) {
			perror(_("Bind UDP socket for DTLS"));
			closesocket(dtls_fd);
			return -EINVAL;
		}
	}

	if (connect(dtls_fd, vpninfo->dtls_addr, vpninfo->peer_addrlen)) {
		perror(_("UDP (DTLS) connect:\n"));
		closesocket(dtls_fd);
		return -EINVAL;
	}

	set_fd_cloexec(dtls_fd);
	set_sock_nonblock(dtls_fd);

	ret = start_dtls_handshake(vpninfo, dtls_fd);
	if (ret) {
		closesocket(dtls_fd);
		return ret;
	}

	vpninfo->dtls_state = DTLS_CONNECTING;

	vpninfo->dtls_fd = dtls_fd;
	monitor_fd_new(vpninfo, dtls);
	monitor_read_fd(vpninfo, dtls);
	monitor_except_fd(vpninfo, dtls);

	time(&vpninfo->new_dtls_started);

	return dtls_try_handshake(vpninfo);
}