Exemplo n.º 1
0
int main(int argc, char *argv[]) {
    static struct WSAData wsa_state;
    TCHAR *c, stunnel_exe_path[MAX_PATH];

    /* set current working directory and engine path */
    GetModuleFileName(0, stunnel_exe_path, MAX_PATH);
    c=_tcsrchr(stunnel_exe_path, TEXT('\\')); /* last backslash */
    if(c) /* found */
        c[1]=TEXT('\0'); /* truncate program name */
#ifndef _WIN32_WCE
    if(!SetCurrentDirectory(stunnel_exe_path)) {
        /* log to stderr, as s_log() is not initialized */
        _ftprintf(stderr, TEXT("Cannot set directory to %s"),
            stunnel_exe_path);
        return 1;
    }
#endif
    _tputenv_s(TEXT("OPENSSL_ENGINES"), stunnel_exe_path);

    str_init(); /* initialize per-thread string management */
    if(WSAStartup(MAKEWORD(1, 1), &wsa_state))
        return 1;
    resolver_init();
    main_init();
    if(!main_configure(argc>1 ? argv[1] : NULL, argc>2 ? argv[2] : NULL))
        daemon_loop();
    main_cleanup();
    return 0;
}
Exemplo n.º 2
0
static gint sock_connect_by_hostname(gint sock, const gchar *hostname,
				     gushort port)
{
	struct hostent *hp;
	struct sockaddr_in ad;

	resolver_init();

	memset(&ad, 0, sizeof(ad));
	ad.sin_family = AF_INET;
	ad.sin_port = htons(port);

	if (!my_inet_aton(hostname, &ad.sin_addr)) {
		if ((hp = my_gethostbyname(hostname)) == NULL) {
			fprintf(stderr, "%s: unknown host.\n", hostname);
			errno = 0;
			return -1;
		}

		if (hp->h_length != 4 && hp->h_length != 8) {
			fprintf(stderr, "illegal address length received for host %s\n", hostname);
			errno = 0;
			return -1;
		}

		memcpy(&ad.sin_addr, hp->h_addr, hp->h_length);
	}

	return sock_connect_with_timeout(sock, (struct sockaddr *)&ad,
					 sizeof(ad), io_timeout);
}
Exemplo n.º 3
0
/* try to load winsock2 resolver functions from a specified dll name */
NOEXPORT int initialize_winsock() {
    static struct WSAData wsa_state;

    if(WSAStartup(MAKEWORD( 2, 2 ), &wsa_state)) {
        message_box(TEXT("Failed to initialize winsock"), MB_ICONERROR);
        return 1; /* error */
    }
    resolver_init();
    return 0; /* IPv4 detected -> OK */
}
Exemplo n.º 4
0
static SockDesc sock_connect_by_getaddrinfo(const gchar *hostname, gushort port)
{
	SockDesc sock = INVALID_SOCKET;
	gint gai_error;
	struct addrinfo hints, *res, *ai;
	gchar port_str[6];

	resolver_init();

	memset(&hints, 0, sizeof(hints));
	/* hints.ai_flags = AI_CANONNAME; */
	hints.ai_family = AF_UNSPEC;
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_protocol = IPPROTO_TCP;

	/* convert port from integer to string. */
	g_snprintf(port_str, sizeof(port_str), "%d", port);

	if ((gai_error = getaddrinfo(hostname, port_str, &hints, &res)) != 0) {
		fprintf(stderr, "getaddrinfo for %s:%s failed: %s\n",
			hostname, port_str, gai_strerror(gai_error));
		return INVALID_SOCKET;
	}

	for (ai = res; ai != NULL; ai = ai->ai_next) {
		sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
		if (!SOCKET_IS_VALID(sock))
			continue;
		sock_set_buffer_size(sock);

		if (sock_connect_with_timeout
			(sock, ai->ai_addr, ai->ai_addrlen, io_timeout) == 0)
			break;

		fd_close(sock);
	}

	if (res != NULL)
		freeaddrinfo(res);

	if (ai == NULL)
		return INVALID_SOCKET;

	return sock;
}
Exemplo n.º 5
0
void
consumer_start(void *arg) {
    uv_loop_t loop;
    struct server_context *server = arg;

#ifndef CROSS_COMPILE
    char name[24] = {0};
    sprintf(name, "consumer-%d", server->index + 1);
    pthread_setname_np(pthread_self(), name);
#endif

    uv_loop_init(&loop);

    struct resolver_context *res = NULL;
    if (server->nameserver_num >= 0) {
        res = resolver_init(&loop, 0,
          server->nameserver_num == 0 ? NULL : server->nameservers, server->nameserver_num);
        loop.data = res;
    }

    tcp_bind(&loop, server);

    if (server->udprelay) {
        udprelay_start(&loop, server);
    }

    uv_run(&loop, UV_RUN_DEFAULT);

    close_loop(&loop);

    if (server->nameserver_num >= 0) {
        resolver_destroy(res);
    }

    uv_sem_post(&server->semaphore);
}
Exemplo n.º 6
0
int
main(int argc, char *argv[]) {
    int rc;
    uv_loop_t *loop;
    struct sockaddr local_addr;

    parse_opts(argc, argv);

#ifndef _WIN32
    if (xsignal) {
        return signal_process(xsignal, pidfile);
    }

    if (!password) {
        print_usage(argv[0]);
        return 1;
    }
#endif

#ifndef _WIN32
    if (daemon_mode) {
        if (daemonize()) {
            return 1;
        }
        if (already_running(pidfile)) {
            logger_stderr("xsocksd already running.");
            return 1;
        }
    }
#endif

    init();

    loop = uv_default_loop();

    rc = resolve_addr(local_addrbuf, &local_addr);
    if (rc) {
        logger_stderr("invalid local address");
        return 1;
    }

    if (udprelay) {
        udprelay_init();
    }

    if (concurrency <= 1) {
        struct server_context ctx;
        ctx.local_addr = &local_addr;
        ctx.udprelay = udprelay;
        ctx.resolver = 1;
        ctx.udp_fd = create_socket(SOCK_DGRAM, 0);

        uv_tcp_init(loop, &ctx.tcp);
        rc = uv_tcp_bind(&ctx.tcp, &local_addr, 0);
        if (rc) {
            logger_stderr("tcp bind error: %s", uv_strerror(rc));
            return 1;
        }

        rc = uv_listen((uv_stream_t*)&ctx.tcp, 128, client_accept_cb);
        if (rc == 0) {
            logger_log(LOG_INFO, "listening on %s", local_addrbuf);

#ifndef _WIN32
            setup_signal(loop, signal_cb, &ctx);
#endif

            struct resolver_context *dns =
              resolver_init(loop, MODE_IPV4,
                nameserver_num == 0 ? NULL : nameservers, nameserver_num);
            uv_key_set(&thread_resolver_key, dns);

            if (udprelay) {
                udprelay_start(loop, &ctx);
            }

            uv_run(loop, UV_RUN_DEFAULT);

            close_loop(loop);
            resolver_destroy(dns);

        } else {
            logger_stderr("listen error: %s", uv_strerror(rc));
        }

    } else {
#ifndef _WIN32
        struct server_context *servers = calloc(concurrency, sizeof(servers[0]));
        for (int i = 0; i < concurrency; i++) {
            struct server_context *ctx = servers + i;
            ctx->index = i;
            ctx->tcp_fd = create_socket(SOCK_STREAM, 1);
            ctx->udp_fd = create_socket(SOCK_DGRAM, 1);
            ctx->udprelay = udprelay;
            ctx->resolver = 1;
            ctx->accept_cb = client_accept_cb;
            ctx->nameservers = nameservers;
            ctx->nameserver_num = nameserver_num;
            ctx->local_addr = &local_addr;
            rc = uv_sem_init(&ctx->semaphore, 0);
            rc = uv_thread_create(&ctx->thread_id, consumer_start, ctx);
        }

        logger_log(LOG_INFO, "listening on %s", local_addrbuf);

        setup_signal(loop, signal_cb, servers);

        uv_run(loop, UV_RUN_DEFAULT);

        close_loop(loop);

        for (int i = 0; i < concurrency; i++) {
            uv_sem_wait(&servers[i].semaphore);
        }
        free(servers);
#else
        logger_stderr("don't support multithreading.");
        return 1;
#endif
    }

    if (udprelay) {
        udprelay_destroy();
    }

    uv_key_delete(&thread_resolver_key);

#ifndef _WIN32
    if (daemon_mode) {
        delete_pidfile(pidfile);
    }
#endif

    logger_exit();

    return 0;
}
Exemplo n.º 7
0
/******************************************************************************
 * This is the mail loop when running over sockets, receiving packets and
 * sending responses.
 ******************************************************************************/
void
sockets_thread(struct Core *conf)
{
    int err;
    SOCKET fd;
    struct sockaddr_in6 sin;
    static const unsigned port = 53;
    
    /*
     * This software obtains its speed by bypassing the operating system
     * stack. Thus, running on top of 'sockets' is going to be a lot 
     * slower
     */
    fprintf(stderr, "WARNING: running in slow 'sockets' mode\n");
    
    
    /*
     * Legacy Windows is legacy.
     */
#if defined(WIN32)
    {WSADATA x; WSAStartup(0x201, &x);}
#endif
    
    /*
     * Create a socket for incoming UDP packets. By specifying IPv6, we are
     * actually going to allow both IPv4 and IPv6.
     */
    fd = socket(AF_INET6, SOCK_DGRAM, 0);
    if (fd <= 0) {
        LOG(0, "FAIL: couldn't create socket %u\n", WSAGetLastError());
        return;
    }
    
    /*
     * Set the 'reuse' feature of the socket, otherwise restarting the process
     * requires a wait before binding back to the same port number
     */
    {
        int on = 1;
        err = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&on,sizeof(on));
        if (err < 0) {
            perror("setsockopt(SO_REUSEADDR) failed");
            exit(1); 
        }
    }

    /*
     * Enable both IPv4 and IPv6 to be used on the same sockets. This appears to
     * be needed for Windows, but not needed for Mac OS X.
     */
    {
        int on = 0;
        err = setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&on, sizeof(on)); 
        if (err < 0) {
            perror("setsockopt(IPV6_V6ONLY) failed");
            exit(1); 
        }
    }
    
    
    /*
     * Listen on any IPv4 or IPv6 address in the system
     */
    memset(&sin, 0, sizeof(sin));
    sin.sin6_family = AF_INET6;
    sin.sin6_addr = in6addr_any;
    sin.sin6_port = htons(port);
    err = bind(fd, (struct sockaddr*)&sin, sizeof(sin));
    if (err) {
        switch (WSAGetLastError()) {
            case WSA(EACCES):
                LOG(0, "FAIL: couldn't bind to port %u: %s\n", port, 
                    "access denied");
                if (port <= 1024)
                    LOG(0, "  hint... need to be root for ports below 1024\n");
                break;
            case WSA(EADDRINUSE):
                LOG(0, "FAIL: couldn't bind to port %u: %s\n", port, 
                    "address in use");
                LOG(0, "  hint... some other server is running on that port\n");
                break;
            default:
                LOG(0, "FAIL: couldn't bind to port %u: %u\n", port,
                    WSAGetLastError());
        }
        exit(1);
    } else {
        fprintf(stderr, "UDP port: %u\n", port);
    }
    
    /*
     * Sit in loop processing incoming UDP packets
     */
    for (;;) {
        unsigned char buf[2048];
        int bytes_received;
        socklen_t sizeof_sin = sizeof(sin);
        struct DNS_Incoming request[1];
        struct DNS_OutgoingResponse response[1];
        struct Packet pkt;
        unsigned char buf2[2048];
        
        /*
         * 1. receive 'packet'
         */
        bytes_received = recvfrom(fd, 
                                  (char*)buf, sizeof(buf),
                                  0, 
                                  (struct sockaddr*)&sin, &sizeof_sin);
        if (bytes_received == 0)
            continue;

        
        /*
         * 2. parse 'packet' into a 'request'
         */
        proto_dns_parse(request, buf, 0, bytes_received);
        if (!request->is_valid)
            continue;


        /*
         * 3. resolve 'request' into a 'repsonse'
         */
        resolver_init(response, 
                      request->query_name.name, 
                      request->query_name.length, 
                      request->query_type,
                      request->id,
                      request->opcode);
            
        resolver_algorithm(conf->db, response, request);
            

        /*
         * 4. format the 'response' into a 'packet'
         */
        pkt.buf = buf2;
        pkt.max = sizeof(buf2);
        pkt.offset = 0;
        dns_format_response(response, &pkt);
            
        /*
         * 5. Transmit the 'packet'
         */
        if (pkt.offset < pkt.max) {
            sendto(fd, 
                   (char*)pkt.buf, pkt.offset, 0,
                   (struct sockaddr*)&sin,
                   sizeof_sin);
        }
    }
}
Exemplo n.º 8
0
static void
thread_worker(void *p)
{
    struct CoreWorkerThread *t = (struct CoreWorkerThread *)p;
    struct Core *core = t->core;

    while (!t->should_end) {
        unsigned i;
        struct CoreSocketSet *sockets;
        fd_set readfds;
        int nfds = 0;
        int x;
        struct timeval ts;

        /* [SYNCHRONIZATION POINT] 
        * mark the fact we are using the new socket-set */
        sockets = (struct CoreSocketSet *)core->socket_run;
        t->loop_count++;

        /* During startup, the sockets argument may be NULL for a time.
         * if that's the case, then just wait for a little bit, and try
         * again */
        if (sockets == NULL) {
            /* Sleep for a 10th of a second */
            pixie_mssleep(10); 
            continue;
        }

        /* 
         * See if there are any packets waiting 
         */
        FD_ZERO(&readfds);
        for (i=0; i<sockets->count; i++) {
            FD_SET(sockets->list[i].fd, &readfds);
            if (nfds < sockets->list[i].fd)
                nfds = sockets->list[i].fd;
        }
        ts.tv_sec = 0;
        ts.tv_usec = 1000; /* one millisecond */

        x = select(nfds, &readfds, 0, 0, &ts);
        if (x < 0) {
            LOG_ERR(C_NETWORK, "select() returned error %u\n", WSAGetLastError());
            pixie_mssleep(1000);
            /* at this point, the errors are probably unrecoverable
             * until the system is manually reconfigured */
            continue;
        }
        if (x == 0)
            continue; /* nothing found */

        /*
         * Process any packets that have arrived
         */
        for (i=0; i<sockets->count; i++) {
            struct sockaddr_storage sin;
            socklen_t sizeof_sin = sizeof(sin);
            unsigned char buf[2048];
            unsigned char buf2[2048];
            int bytes_received;
            struct DNS_Incoming request[1];
            struct DNS_OutgoingResponse response[1];
            struct Packet pkt;
            int fd;

            fd = sockets->list[i].fd;
            if (!FD_ISSET(fd, &readfds))
                continue;
        
            /*
             * 1. receive 'packet'
             */
            bytes_received = recvfrom(fd, 
                                      (char*)buf, sizeof(buf),
                                      0, 
                                      (struct sockaddr*)&sin, &sizeof_sin);
            if (bytes_received == 0)
                continue;

        
            /*
             * 2. parse 'packet' into a 'request'
             */
            proto_dns_parse(request, buf, 0, bytes_received);
            if (!request->is_valid)
                continue;


            /*
             * 3. resolve 'request' into a 'repsonse'
             */
            resolver_init(response, 
                          request->query_name.name, 
                          request->query_name.length, 
                          request->query_type,
                          request->id,
                          request->opcode);
            
            resolver_algorithm(core->db_run, response, request);
            

            /*
             * 4. format the 'response' into a 'packet'
             */
            pkt.buf = buf2;
            pkt.max = sizeof(buf2);
            pkt.offset = 0;
            dns_format_response(response, &pkt);
            
            /*
             * 5. Transmit the 'packet'
             */
            if (pkt.offset < pkt.max) {
                sendto(fd, 
                       (char*)pkt.buf, pkt.offset, 0,
                       (struct sockaddr*)&sin,
                       sizeof_sin);
            }
        }
    }
}
Exemplo n.º 9
0
static SockLookupData *sock_get_address_info_async(const gchar *hostname,
						   gushort port,
						   SockAddrFunc func,
						   gpointer data)
{
	SockLookupData *lookup_data = NULL;
	gint pipe_fds[2];
	pid_t pid;

	resolver_init();

	if (pipe(pipe_fds) < 0) {
		perror("pipe");
		func(NULL, data);
		return NULL;
	}

	if ((pid = fork()) < 0) {
		perror("fork");
		func(NULL, data);
		return NULL;
	}

	/* child process */
	if (pid == 0) {
#ifdef INET6
		gint gai_err;
		struct addrinfo hints, *res, *ai;
		gchar port_str[6];
#else /* !INET6 */
		struct hostent *hp;
		gchar **addr_list_p;
		struct sockaddr_in ad;
#endif /* INET6 */
		gint ai_member[4] = {AF_UNSPEC, 0, 0, 0};

		close(pipe_fds[0]);

#ifdef INET6
		memset(&hints, 0, sizeof(hints));
		/* hints.ai_flags = AI_CANONNAME; */
		hints.ai_family = AF_UNSPEC;
		hints.ai_socktype = SOCK_STREAM;
		hints.ai_protocol = IPPROTO_TCP;

		g_snprintf(port_str, sizeof(port_str), "%d", port);

		gai_err = getaddrinfo(hostname, port_str, &hints, &res);
		if (gai_err != 0) {
			g_warning("getaddrinfo for %s:%s failed: %s\n",
				  hostname, port_str, gai_strerror(gai_err));
			fd_write_all(pipe_fds[1], (gchar *)ai_member,
				     sizeof(ai_member));
			close(pipe_fds[1]);
			_exit(1);
		}

		for (ai = res; ai != NULL; ai = ai->ai_next) {
			ai_member[0] = ai->ai_family;
			ai_member[1] = ai->ai_socktype;
			ai_member[2] = ai->ai_protocol;
			ai_member[3] = ai->ai_addrlen;

			fd_write_all(pipe_fds[1], (gchar *)ai_member,
				     sizeof(ai_member));
			fd_write_all(pipe_fds[1], (gchar *)ai->ai_addr,
				     ai->ai_addrlen);
		}

		if (res != NULL)
			freeaddrinfo(res);
#else /* !INET6 */
		hp = my_gethostbyname(hostname);
		if (hp == NULL || hp->h_addrtype != AF_INET) {
			fd_write_all(pipe_fds[1], (gchar *)ai_member,
				     sizeof(ai_member));
			close(pipe_fds[1]);
			_exit(1);
		}

		ai_member[0] = AF_INET;
		ai_member[1] = SOCK_STREAM;
		ai_member[2] = IPPROTO_TCP;
		ai_member[3] = sizeof(ad);

		memset(&ad, 0, sizeof(ad));
		ad.sin_family = AF_INET;
		ad.sin_port = htons(port);

		for (addr_list_p = hp->h_addr_list; *addr_list_p != NULL;
		     addr_list_p++) {
			memcpy(&ad.sin_addr, *addr_list_p, hp->h_length);
			fd_write_all(pipe_fds[1], (gchar *)ai_member,
				     sizeof(ai_member));
			fd_write_all(pipe_fds[1], (gchar *)&ad, sizeof(ad));
		}
#endif /* INET6 */

		close(pipe_fds[1]);

		_exit(0);
	} else {
		close(pipe_fds[1]);

		lookup_data = g_new0(SockLookupData, 1);
		lookup_data->hostname = g_strdup(hostname);
		lookup_data->child_pid = pid;
		lookup_data->func = func;
		lookup_data->data = data;

		lookup_data->channel = g_io_channel_unix_new(pipe_fds[0]);
		lookup_data->io_tag = g_io_add_watch
			(lookup_data->channel, G_IO_IN,
			 sock_get_address_info_async_cb, lookup_data);
	}

	return lookup_data;
}