Ejemplo n.º 1
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;
}
Ejemplo n.º 2
0
static int esp_send_probes(struct openconnect_info *vpninfo)
{
	struct pkt *pkt;
	int pktlen;

	if (vpninfo->dtls_fd == -1) {
		int fd = udp_connect(vpninfo);
		if (fd < 0)
			return fd;

		/* We are not connected until we get an ESP packet back */
		vpninfo->dtls_state = DTLS_SLEEPING;
		vpninfo->dtls_fd = fd;
		monitor_fd_new(vpninfo, dtls);
		monitor_read_fd(vpninfo, dtls);
		monitor_except_fd(vpninfo, dtls);
	}

	pkt = malloc(sizeof(*pkt) + 1 + vpninfo->pkt_trailer);
	if (!pkt)
		return -ENOMEM;

	pkt->len = 1;
	pkt->data[0] = 0;
	pktlen = encrypt_esp_packet(vpninfo, pkt);
	if (pktlen >= 0)
		send(vpninfo->dtls_fd, (void *)&pkt->esp, pktlen, 0);

	pkt->len = 1;
	pkt->data[0] = 0;
	pktlen = encrypt_esp_packet(vpninfo, pkt);
	if (pktlen >= 0)
		send(vpninfo->dtls_fd, (void *)&pkt->esp, pktlen, 0);

	free(pkt);

	vpninfo->dtls_times.last_tx = time(&vpninfo->new_dtls_started);

	return 0;
};
Ejemplo n.º 3
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);
}