Ejemplo n.º 1
0
/* call must be locked */
void dtls_shutdown(struct packet_stream *ps) {
	struct dtls_connection *d;
	struct sockaddr_in6 sin;

	if (!ps || !ps->sfd)
		return;

	__DBG("dtls_shutdown");

	d = &ps->sfd->dtls;
	if (!d->init)
		return;

	if (d->connected && d->ssl) {
		ZERO(sin);
		sin.sin6_family = AF_INET6;
		sin.sin6_addr = ps->endpoint.ip46;
		sin.sin6_port = htons(ps->endpoint.port);

		SSL_shutdown(d->ssl);
		dtls(ps, NULL, &sin);
	}

	dtls_connection_cleanup(d);

	if (ps->dtls_cert) {
		X509_free(ps->dtls_cert);
		ps->dtls_cert = NULL;
	}

	crypto_reset(&ps->crypto);
	crypto_reset(&ps->sfd->crypto);
}
Ejemplo n.º 2
0
void vpn_thread(void *arg)
{
    struct Ctunnel *ct;
    struct Network *n;
    int ret = 0;
    time_t t, tl;
    unsigned char *data = NULL;
    unsigned char *rwind = NULL;
    struct timeval tv;
    fd_set rfd;
#ifdef HAVE_OPENSSL
    do_encrypt = openssl_do_encrypt;
    do_decrypt = openssl_do_decrypt;
    crypto_init = openssl_crypto_init;
    crypto_deinit = openssl_crypto_deinit;
    crypto_reset = openssl_crypto_reset;
#else
    do_encrypt = gcrypt_do_encrypt;
    do_decrypt = gcrypt_do_decrypt;
    crypto_init = gcrypt_crypto_init;
    crypto_deinit = gcrypt_crypto_deinit;
    crypto_reset = gcrypt_crypto_reset;
#endif
    struct xfer_stats rx_st, tx_st;

    t = tl = time(NULL);
    ct = (struct Ctunnel *) arg;

    if (ct->opt.comp == 1)
	ct->comp = z_compress_init(ct->opt);

    /* Data size, plus int for channel */
    data = malloc(ct->opt.packet_size);
    rwind = data;

    xfer_stats_init(&tx_st, (int) t);
    xfer_stats_init(&rx_st, (int) t);
    if (ct->opt.stats == 1)
	xfer_stats_print(stdout, &tx_st, &rx_st);

    while (1) {
	FD_ZERO(&rfd);
	FD_SET(ct->net_srv->sockfd, &rfd);
	FD_SET(ct->tunfd, &rfd);
	//FD_SET(ct->p[0], &rfd);

	tv.tv_sec = 10;
	tv.tv_usec = 0;

	if (ct->opt.proto == UDP) {
            crypto_reset(ct->ectx, ct->opt, 1);
            crypto_reset(ct->dctx, ct->opt, 0);
	}
	ret = select(ct->net_srv->sockfd + ct->tunfd, &rfd,
		     NULL, NULL, &tv);
	// for ppp
	//ret = select(ct->net_srv->sockfd + ct->tunfd, &rfd,
	//	     NULL, NULL, NULL);
	t = time(NULL);

	if (ct->opt.stats == 1)
	    xfer_stats_print(stdout, &tx_st, &rx_st);

        /* Not functioning 
	if (ret == 0 || (t > tl+10)) { 
	    if (ct->opt.role != SERVER) {
	    	ping(ct, ct->net_srv);
	    }
	    tl = t;
	}
	Need to redial server if connection timeout, make sure to
	re-resolv address before connect
	*/

	if (ret > 0) {
            n = ct->net_srv;
	    if (FD_ISSET(ct->tunfd, &rfd)) {
		*data++ = PACKET_DATA;
		ret = read(ct->tunfd, data, ct->opt.packet_size);
		data = rwind;
		if (ret > 0 && n) {
		    if ((ret = net_write(ct, n, data,
			           ret + sizeof(int), 1)) < 0)
			ctunnel_log(stderr, LOG_CRIT, 
			            "net_write:%d %s", __LINE__,
				    strerror(errno));
		    xfer_stats_update(&tx_st, ct->net_srv->rate.tx.total, t);
		} else {
		    ctunnel_log(stderr, LOG_CRIT,
		                "tunfd read:%d %s", __LINE__,
				strerror(errno));
		}
	    }
	    if (FD_ISSET(ct->net_srv->sockfd, &rfd)) {
		ret = net_read(ct, n, data,
			       ct->opt.packet_size, 1);
		if (ret > 0) {
		    xfer_stats_update(&rx_st, ct->net_srv->rate.rx.total, t);
		    if (*data == PACKET_DATA) {
			if ((connected(n) < 0) && (ct->opt.role == SERVER)) {
			    data = rwind;
			    *data++ = PACKET_REUP;
			    data = rwind;
			    net_write(ct, n, data, sizeof(int) * 2, 1);
			} else {
			    data++;
			    write(ct->tunfd, data, ret - sizeof(int));
			    data = rwind;
			}
		    }
		    if (*data == PACKET_CONRQ) {
			ctunnel_log(stdout, LOG_INFO, "Connect request from %s",
		                   inet_ntoa((struct in_addr)
			           ct->net_srv->addr.sin_addr));
		       vpn_handshake(ct);
		   }
		   /* Not functioning
		   if (*data == PACKET_PING) {
		       ct->seen = time(NULL);
		       if (ct->opt.role == SERVER) 
			   ping(ct, ct->net_srv);
		   }
		   */
		   if ((*data == PACKET_REUP) && ct->opt.role != SERVER) {
		       vpn_handshake(ct);
		   }

		} else {
		    ctunnel_log(stderr, LOG_CRIT, "net_read:74 %s",
				strerror(errno));
		    break;
		}
	    }
	}
    }
    FD_CLR(ct->net_srv->sockfd, &rfd);
    FD_CLR(ct->tunfd, &rfd);
    pthread_mutex_lock(&mutex);
    threads[ct->id] = 2;
    pthread_mutex_unlock(&mutex);
    net_close(ct->net_srv);
    free(data);
    fprintf(stdout, "VPN Disconnect\n");
    crypto_deinit(ct->ectx);
    crypto_deinit(ct->dctx);
    pthread_exit(0);
}