Ejemplo n.º 1
0
/* Clear datagram connection */
void v_conn_dgram_clear(struct VDgramConn *dgram_conn)
{
	/* Debug print */
	if(is_log_level(VRS_PRINT_DEBUG_MSG)) {
		v_print_log(VRS_PRINT_DEBUG_MSG, "Free connection ");
		v_print_log_simple(VRS_PRINT_DEBUG_MSG, "%d ", dgram_conn->host_id);
		v_print_addr_port(VRS_PRINT_DEBUG_MSG, &dgram_conn->peer_address);
		v_print_log_simple(VRS_PRINT_DEBUG_MSG, "\n");
	}

#ifdef WITH_OPENSSL
	if(dgram_conn->io_ctx.bio != NULL) {
		BIO_vfree(dgram_conn->io_ctx.bio);
		dgram_conn->io_ctx.bio = NULL;
	}
#endif

	close(dgram_conn->io_ctx.sockfd);

	v_conn_dgram_init(dgram_conn);
}
Ejemplo n.º 2
0
/* Create new UDP connection to the server */
struct VDgramConn *vc_create_client_dgram_conn(struct vContext *C)
{
	struct VSession *vsession = CTX_current_session(C);
	struct VDgramConn *dgram_conn = NULL;
	struct addrinfo hints, *result, *rp;
	int sockfd = -1;
	int flag, ret;
	struct VURL url;

	/* Seed random number generator,  */
#ifdef __APPLE__
	sranddev();
	/* Other BSD based systems probably support this or similar function too. */
#else
	/* Other systems have to use this evil trick */
	struct timeval tv;
	gettimeofday(&tv, NULL);
	srand(tv.tv_sec - tv.tv_usec);
#endif

	if (v_url_parse(vsession->host_url, &url) != 1) {
		goto end;
	} else {
		/* v_print_url(VRS_PRINT_DEBUG_MSG, &url); */
	}

	memset(&hints, 0, sizeof(struct addrinfo));
	hints.ai_family = AF_UNSPEC;		/* Allow IPv4 or IPv6 */
	hints.ai_socktype = SOCK_DGRAM;		/* Allow datagram protocol */
	hints.ai_flags = 0;					/* No flags required */
	hints.ai_protocol = IPPROTO_UDP;	/* Allow UDP protocol only */

	if(is_log_level(VRS_PRINT_DEBUG_MSG)) {
		if(url.ip_ver==IPV6) {
			v_print_log(VRS_PRINT_DEBUG_MSG,
						"Try to connect to: [%s]:%s\n",
						url.node, url.service);
		} else {
			v_print_log(VRS_PRINT_DEBUG_MSG,
						"Try to connect to: %s:%s\n",
						url.node, url.service);
		}
	}

	if( (ret = getaddrinfo(url.node, url.service, &hints, &result)) !=0 ) {
		v_print_log(VRS_PRINT_ERROR,
					"getaddrinfo(): %s\n", gai_strerror(ret));
		goto end;
	}

	/* Try to use addrinfo from getaddrinfo() */
	for(rp=result; rp!=NULL; rp=rp->ai_next) {
		if( (sockfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol)) == -1) {
			v_print_log(VRS_PRINT_ERROR, "socket(): %s\n", strerror(errno));
			continue;
		}
		else {
			/* Try to "connect" to this address ... the client will be able to send and
			 * receive packets only from this address. */
			if(connect(sockfd, rp->ai_addr, rp->ai_addrlen) != -1)
				break;
			close(sockfd);
			sockfd = -1;
		}
	}

	if(rp == NULL) {
		if(is_log_level(VRS_PRINT_ERROR)) {
			if(url.ip_ver==IPV6) {
				v_print_log(VRS_PRINT_ERROR,
							"Could not connect to the [%s]:%s\n",
							url.node, url.service);
			} else {
				v_print_log(VRS_PRINT_ERROR,
							"Could not connect to the %s:%s\n",
							url.node, url.service);
			}
		}
		freeaddrinfo(result);
		goto end;
	}

	if( (dgram_conn = (struct VDgramConn*)calloc(1, sizeof(struct VDgramConn))) == NULL) {
		v_print_log(VRS_PRINT_ERROR, "calloc(): %s\n", strerror(errno));
		freeaddrinfo(result);
		if(sockfd != -1) {
			close(sockfd);
		}
		goto end;
	}

	/* Initialize datagram connection */
	v_conn_dgram_init(dgram_conn);

	/* Use first successfully assigned socket */
	dgram_conn->io_ctx.sockfd = sockfd;

	/* Set socket non-blocking */
	flag = fcntl(dgram_conn->io_ctx.sockfd, F_GETFL, 0);
	if( (fcntl(dgram_conn->io_ctx.sockfd, F_SETFL, flag | O_NONBLOCK)) == -1) {
		v_print_log(VRS_PRINT_ERROR, "fcntl(): %s\n", strerror(errno));
		free(dgram_conn);
		dgram_conn = NULL;
		if(sockfd != -1) {
			close(sockfd);
		}
		freeaddrinfo(result);
		goto end;
	}

	/* Set socket to reuse address */
	flag = 1;
	if( setsockopt(dgram_conn->io_ctx.sockfd, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag)) == -1) {
		v_print_log(VRS_PRINT_ERROR, "setsockopt(): %s\n", strerror(errno));
		free(dgram_conn);
		if(sockfd != -1) {
			close(sockfd);
		}
		dgram_conn = NULL;
		goto end;
	}

	/* Set address of peer and host */
	if(rp->ai_family==AF_INET) {
		/* Address type of client */
		dgram_conn->io_ctx.host_addr.ip_ver = IPV4;
		dgram_conn->io_ctx.host_addr.protocol = UDP;
		/* Address of peer */
		dgram_conn->io_ctx.peer_addr.ip_ver = IPV4;
		dgram_conn->io_ctx.peer_addr.protocol = UDP;
		dgram_conn->io_ctx.peer_addr.port = ntohs(((struct sockaddr_in*)rp->ai_addr)->sin_port);
		memcpy(&dgram_conn->io_ctx.peer_addr.addr.ipv4, rp->ai_addr, rp->ai_addrlen);
		/* Address of peer (reference in connection) */
		dgram_conn->peer_address.ip_ver = IPV4;
		dgram_conn->peer_address.protocol = UDP;
		dgram_conn->peer_address.port = ntohs(((struct sockaddr_in*)rp->ai_addr)->sin_port);
		memcpy(&dgram_conn->peer_address.addr.ipv4, rp->ai_addr, rp->ai_addrlen);
	}
	else if(rp->ai_family==AF_INET6) {
		/* Address type of client */
		dgram_conn->io_ctx.host_addr.ip_ver = IPV6;
		dgram_conn->io_ctx.host_addr.protocol = UDP;
		/* Address of peer */
		dgram_conn->io_ctx.peer_addr.ip_ver = IPV6;
		dgram_conn->io_ctx.peer_addr.protocol = UDP;
		dgram_conn->io_ctx.peer_addr.port = ntohs(((struct sockaddr_in6*)rp->ai_addr)->sin6_port);
		memcpy(&dgram_conn->io_ctx.peer_addr.addr.ipv6, rp->ai_addr, rp->ai_addrlen);
		/* Address of peer (reference in connection) */
		dgram_conn->peer_address.ip_ver = IPV6;
		dgram_conn->peer_address.protocol = UDP;
		dgram_conn->peer_address.port = ntohs(((struct sockaddr_in6*)rp->ai_addr)->sin6_port);
		memcpy(&dgram_conn->peer_address.addr.ipv6, rp->ai_addr, rp->ai_addrlen);
	}

	freeaddrinfo(result);

	/* When DTLS was negotiated, then set flag */
	if(url.security_protocol == VRS_SEC_DATA_TLS) {
#if (defined WITH_OPENSSL) && OPENSSL_VERSION_NUMBER>=0x10000000
		dgram_conn->io_ctx.flags |= SOCKET_SECURED;
#else
		v_print_log(VRS_PRINT_ERROR,
					"Server tries to force client to use secured connection, but it is not supported\n");
		goto end;
#endif
	}

#ifdef WITH_OPENSSL
	/* Create BIO, connect and set to already connected */
	if( (dgram_conn->io_ctx.bio = BIO_new_dgram(dgram_conn->io_ctx.sockfd, BIO_CLOSE)) == NULL) {
		v_print_log(VRS_PRINT_ERROR, "BIO_new_dgram()\n");
		goto end;
	}

	/* Try to do PMTU discovery */
	if( BIO_ctrl(dgram_conn->io_ctx.bio, BIO_CTRL_DGRAM_MTU_DISCOVER, 0, NULL) < 0) {
		v_print_log(VRS_PRINT_ERROR, "BIO_ctrl()\n");
		goto end;
	}

	/* Try to get MTU from the bio */
	ret = BIO_ctrl(dgram_conn->io_ctx.bio, BIO_CTRL_DGRAM_QUERY_MTU, 0, NULL);
	if(ret > 0) {
		dgram_conn->io_ctx.mtu = ret;
		v_print_log(VRS_PRINT_DEBUG_MSG, "PMTU: %d\n", dgram_conn->io_ctx.mtu);
	} else {
		dgram_conn->io_ctx.mtu = DEFAULT_MTU;
		v_print_log(VRS_PRINT_DEBUG_MSG, "Default MTU: %d\n", dgram_conn->io_ctx.mtu);
	}
#else
	dgram_conn->io_ctx.mtu = DEFAULT_MTU;
#endif

	/* Set up necessary flag for V_CTX (client will be able to send and receive packets only to/from server) */
	dgram_conn->io_ctx.flags |= SOCKET_CONNECTED;

	dgram_conn->host_id = (unsigned int)rand();

end:
	v_url_clear(&url);
	
	return dgram_conn;
}