Exemplo n.º 1
0
int main(int argc, char *argv[]) {
    asyncns_t* asyncns = NULL;
    asyncns_query_t *q1, *q2, *q3;
    int r = 1, ret;
    struct addrinfo *ai, hints;
    struct sockaddr_in sa;
    char host[NI_MAXHOST] = "", serv[NI_MAXSERV] = "";
    unsigned char *srv;

    signal(SIGCHLD, SIG_IGN);

    if (!(asyncns = asyncns_new(2))) {
        fprintf(stderr, "asyncns_new() failed\n");
        goto fail;
    }

    /* Make a name -> address query */
    memset(&hints, 0, sizeof(hints));
    hints.ai_family = PF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;

    q1 = asyncns_getaddrinfo(asyncns, argc >= 2 ? argv[1] : "www.heise.de", NULL, &hints);

    if (!q1)
        fprintf(stderr, "asyncns_getaddrinfo(): %s\n", strerror(errno));

    /* Make an address -> name query */
    memset(&sa, 0, sizeof(sa));
    sa.sin_family = AF_INET;
    sa.sin_addr.s_addr = inet_addr(argc >= 3 ? argv[2] : "193.99.144.71");
    sa.sin_port = htons(80);

    q2 = asyncns_getnameinfo(asyncns, (struct sockaddr*) &sa, sizeof(sa), 0, 1, 1);

    if (!q2)
        fprintf(stderr, "asyncns_getnameinfo(): %s\n", strerror(errno));

    /* Make a res_query() call */
    q3 = asyncns_res_query(asyncns, "_xmpp-client._tcp.gmail.com", C_IN, T_SRV);

    if (!q3)
        fprintf(stderr, "asyncns_res_query(): %s\n", strerror(errno));

    /* Wait until the three queries are completed */
    while (!asyncns_isdone(asyncns, q1)
           || !asyncns_isdone(asyncns, q2)
           || !asyncns_isdone(asyncns, q3)) {
        if (asyncns_wait(asyncns, 1) < 0) {
            fprintf(stderr, "asyncns_wait(): %s\n", strerror(errno));
            goto fail;
        }
    }

    /* Interpret the result of the name -> addr query */
    if ((ret = asyncns_getaddrinfo_done(asyncns, q1, &ai)))
        fprintf(stderr, "error: %s %i\n", gai_strerror(ret), ret);
    else {
        struct addrinfo *i;

        for (i = ai; i; i = i->ai_next) {
            char t[256];
            const char *p = NULL;

            if (i->ai_family == PF_INET)
                p = inet_ntop(AF_INET, &((struct sockaddr_in*) i->ai_addr)->sin_addr, t, sizeof(t));
            else if (i->ai_family == PF_INET6)
                p = inet_ntop(AF_INET6, &((struct sockaddr_in6*) i->ai_addr)->sin6_addr, t, sizeof(t));

            printf("%s\n", p);
        }

        asyncns_freeaddrinfo(ai);
    }

    /* Interpret the result of the addr -> name query */
    if ((ret = asyncns_getnameinfo_done(asyncns, q2, host, sizeof(host), serv, sizeof(serv))))
        fprintf(stderr, "error: %s %i\n", gai_strerror(ret), ret);
    else
        printf("%s -- %s\n", host, serv);

    /* Interpret the result of the SRV lookup */
    if ((ret = asyncns_res_done(asyncns, q3, &srv)) < 0) {
        fprintf(stderr, "error: %s %i\n", strerror(errno), ret);
    } else if (ret == 0) {
        fprintf(stderr, "No reply for SRV lookup\n");
    } else {
        int qdcount;
        int ancount;
        int len;
        const unsigned char *pos = srv + sizeof(HEADER);
        unsigned char *end = srv + ret;
        HEADER *head = (HEADER *)srv;
        char name[256];

        qdcount = ntohs(head->qdcount);
        ancount = ntohs(head->ancount);

        printf("%d answers for srv lookup:\n", ancount);

        /* Ignore the questions */
        while (qdcount-- > 0 && (len = dn_expand(srv, end, pos, name, 255)) >= 0) {
            assert(len >= 0);
            pos += len + QFIXEDSZ;
        }

        /* Parse the answers */
        while (ancount-- > 0 && (len = dn_expand(srv, end, pos, name, 255)) >= 0) {
            /* Ignore the initial string */
            uint16_t pref, weight, port;
            assert(len >= 0);
            pos += len;
            /* Ignore type, ttl, class and dlen */
            pos += 10;

            GETSHORT(pref, pos);
            GETSHORT(weight, pos);
            GETSHORT(port, pos);
            len = dn_expand(srv, end, pos, name, 255);
            printf("\tpreference: %2d weight: %2d port: %d host: %s\n",
                   pref, weight, port, name);

            pos += len;
        }

        asyncns_freeanswer(srv);
    }

    r = 0;

fail:

    if (asyncns)
        asyncns_free(asyncns);

    return r;
}
Exemplo n.º 2
0
int main (int argc, char **argv)
{

    int i, c;
    int pid_flags = 0;
    char *user = NULL;
    char *password = NULL;
    char *timeout = NULL;
    char *method = NULL;
    char *pid_path = NULL;
    char *conf_path = NULL;
    char *iface = NULL;

    int server_num = 0;
    const char *server_host[MAX_REMOTE_NUM];
    const char *server_port = NULL;

    int dns_thread_num = DNS_THREAD_NUM;

    int option_index = 0;
    static struct option long_options[] =
    {
        {"fast-open", no_argument, 0,  0 },
        {"port-start", required_argument, 0, 0 },
        {"port-end", required_argument, 0, 0 },
        {0,           0,           0,  0 }
    };

    opterr = 0;

    while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:c:i:d:a:uv",
                            long_options, &option_index)) != -1)
    {
        printf("option_index %d\n", option_index);
        switch (c)
        {
        case 0:

            if (option_index == 0)
            {
#ifdef TCP_FASTOPEN
                fast_open = 1;
                LOGD("using tcp fast open");
#else
                LOGE("tcp fast open is not supported by this environment");
#endif
            } else
            if (option_index == 1) 
            {
                start_port = atoi(optarg);
            } else
            if (option_index == 2) 
            {
                end_port = atoi(optarg);
            }

            break;
        case 's':
            server_host[server_num++] = optarg;
            break;
        case 'p':
            server_port = optarg;
            break;
        case 'k':
            password = optarg;
            break;
        case 'f':
            pid_flags = 1;
            pid_path = optarg;
            break;
        case 't':
            timeout = optarg;
            break;
        case 'm':
            method = optarg;
            break;
        case 'c':
            conf_path = optarg;
            break;
        case 'i':
            iface = optarg;
            break;
        case 'd':
            dns_thread_num = atoi(optarg);
            if (!dns_thread_num) FATAL("Invalid DNS thread number");
            break;
        case 'a':
            user = optarg;
            break;
        case 'u':
            udprelay = 1;
            break;
        case 'v':
            verbose = 1;
            break;
        }
    }

    printf("start %d end %d\n", start_port, end_port);

    if (opterr)
    {
        usage();
        exit(EXIT_FAILURE);
    }

    if (conf_path != NULL)
    {
        jconf_t *conf = read_jconf(conf_path);
        if (server_num == 0)
        {
            server_num = conf->remote_num;
            for (i = 0; i < server_num; i++)
            {
                server_host[i] = conf->remote_addr[i].host;
            }
        }
        if (server_port == NULL) server_port = conf->remote_port;
        if (password == NULL) password = conf->password;
        if (method == NULL) method = conf->method;
        if (timeout == NULL) timeout = conf->timeout;
#ifdef TCP_FASTOPEN
        if (fast_open == 0) fast_open = conf->fast_open;
#endif
#ifdef HAVE_SETRLIMIT
        if (nofile == 0) nofile = conf->nofile;
        /*
         * no need to check the return value here since we will show
         * the user an error message if setrlimit(2) fails
         */
        if (nofile)
        {
            if (verbose)
            {
                LOGD("setting NOFILE to %d", nofile);
            }
            set_nofile(nofile);
        }
#endif
    }

    if ((start_port > 0 && end_port <= 0) || (start_port <= 0 && end_port > 0)) {
        printf("Both start_prot and end_port needs to be specified\n");
        usage();
        exit(EXIT_FAILURE);
    }

    if (server_port != NULL && start_port > 0) {
        printf("server port can't be set if you want to use a port range\n");
        usage();
        exit(EXIT_FAILURE);
    }

    if (server_num == 0 || (server_port == NULL && start_port <= 0) || password == NULL)
    {
        usage();
        exit(EXIT_FAILURE);
    }

    if (timeout == NULL) timeout = "60";

    if (pid_flags)
    {
        USE_SYSLOG(argv[0]);
        daemonize(pid_path);
    }

    // ignore SIGPIPE
    signal(SIGPIPE, SIG_IGN);
    signal(SIGCHLD, SIG_IGN);
    signal(SIGABRT, SIG_IGN);

    // setup asyncns
    asyncns_t *asyncns;
    if (!(asyncns = asyncns_new(dns_thread_num)))
    {
        FATAL("asyncns failed");
    }

    // setup keys
    LOGD("initialize ciphers... %s", method);
    int m = enc_init(password, method);

    // inilitialize ev loop
    struct ev_loop *loop = EV_DEFAULT;

    // inilitialize listen context
    struct listen_ctx listen_ctx_list[server_num + 1];

    // bind to each interface
    while (server_num > 0)
    {
        int index = --server_num;
        const char* host = server_host[index];
        int success = 1;
        int listenfd;

        if (start_port > 0) {
            server_port = itoa(start_port);
        }
        do {
            // Bind to port
            
            listenfd = create_and_bind(host, server_port);
            success = 1;
            if (listenfd < 0)
            {
                success = 0;
            }
            if (listen(listenfd, SOMAXCONN) == -1)
            {
                success = 0;
            }
            if (!success) {
                if (start_port < end_port) {
                    start_port++;
                    server_port = itoa(start_port);
                } else
                {
                    FATAL("Out of listen ports!");
                    exit(1);
                }
            }
        } while (!success);
        setnonblocking(listenfd);
        LOGD("server listening at port %s.", server_port);

        struct listen_ctx *listen_ctx = &listen_ctx_list[index + 1];

        // Setup proxy context
        listen_ctx->timeout = atoi(timeout);
        listen_ctx->asyncns = asyncns;
        listen_ctx->fd = listenfd;
        listen_ctx->method = m;
        listen_ctx->iface = iface;

        ev_io_init (&listen_ctx->io, accept_cb, listenfd, EV_READ);
        ev_io_start (loop, &listen_ctx->io);
    }

    // initialize the DNS
    struct listen_ctx *listen_ctx = &listen_ctx_list[0];
    int asyncnsfd = asyncns_fd(asyncns);
    listen_ctx->timeout = atoi(timeout);
    listen_ctx->asyncns = asyncns;
    listen_ctx->fd = asyncnsfd;
    listen_ctx->method = m;
    listen_ctx->iface = iface;
    ev_io_init (&listen_ctx->io, server_resolve_cb, asyncnsfd, EV_READ);
    ev_io_start (loop, &listen_ctx->io);

    // Setup UDP
    if (udprelay)
    {
        LOGD("udprelay enabled.");
        udprelay_init(server_host[0], server_port, dns_thread_num, m, listen_ctx->timeout, iface);
    }

    // setuid
    if (user != NULL)
        run_as(user);

    // start ev loop
    ev_run (loop, 0);
    return 0;
}
Exemplo n.º 3
0
int
main(int argc, char **argv)
{
	asyncns_t *asyncns;
	asyncns_query_t *query;
	struct addrinfo *result;
	struct pollfd pollfd = { .events = POLLIN };
	int status;

	asyncns = asyncns_new(10);
	assert(asyncns);
	assert(asyncns_getnqueries(asyncns) == 0);
	assert(asyncns_getnext(asyncns) == NULL);

	pollfd.fd = asyncns_fd(asyncns);
	assert(pollfd.fd > 2);

	query = asyncns_getaddrinfo(asyncns, "127.0.0.1", NULL, NULL);
	assert(query);
	assert(asyncns_getnqueries(asyncns) == 1);
	assert(asyncns_getnext(asyncns) == NULL);

	asyncns_cancel(asyncns, query);
	query = NULL;
	assert(asyncns_getnqueries(asyncns) == 0);
	assert(asyncns_getnext(asyncns) == NULL);

	query = asyncns_getaddrinfo(asyncns, "127.0.0.1", NULL, NULL);
	assert(query);
	assert(asyncns_getnqueries(asyncns) == 1);
	assert(asyncns_getnext(asyncns) == NULL);

	usleep(100000);
	status = poll(&pollfd, 1, 0);
	assert(status == 1);
	status = asyncns_wait(asyncns, 0);
	assert(status == 0);
	assert(asyncns_isdone(asyncns, query));
	assert(asyncns_getnqueries(asyncns) == 1);
	assert(asyncns_getnext(asyncns) == query);

	status = poll(&pollfd, 1, 100);
	assert(status == 0);

	status = asyncns_getaddrinfo_done(asyncns, query, &result);
	assert(asyncns_getnqueries(asyncns) == 0);

	/* Intuitively, this should not be needed but the docs state that
	 * a call to `asyncns_wait()` is necessary so that `asyncns_getnext()`
	 * provides meaningful results.
	 */
	status = asyncns_wait(asyncns, 0);
	assert(status == 0);

	/* There were two queries issued, one of which has been cancelled
	 * and the other has been freed afterwards. As none of them can be
	 * returned, the only meaningful result of `asyncns_getnext()` is
	 * NULL.
	 */
	assert(asyncns_getnext(asyncns) == NULL);

	asyncns_free(asyncns);
	asyncns_freeaddrinfo(result);

	return EXIT_SUCCESS;
}
Exemplo n.º 4
0
int main (int argc, char **argv) {

    int i, c;
    int pid_flags = 0;
    char *password = NULL;
    char *timeout = NULL;
    char *method = NULL;
    char *pid_path = NULL;
    char *conf_path = NULL;
    char *iface = NULL;

    int server_num = 0;
    char *server_host[MAX_REMOTE_NUM];
    char *server_port = NULL;

    int dns_thread_num = DNS_THREAD_NUM;

    opterr = 0;

    while ((c = getopt (argc, argv, "f:s:p:l:k:t:m:c:i:d:v")) != -1) {
        switch (c) {
            case 's':
                server_host[server_num++] = optarg;
                break;
            case 'p':
                server_port = optarg;
                break;
            case 'k':
                password = optarg;
                break;
            case 'f':
                pid_flags = 1;
                pid_path = optarg;
                break;
            case 't':
                timeout = optarg;
                break;
            case 'm':
                method = optarg;
                break;
            case 'c':
                conf_path = optarg;
                break;
            case 'i':
                iface = optarg;
                break;
            case 'd':
                dns_thread_num = atoi(optarg);
                if (!dns_thread_num) FATAL("Invalid DNS thread number");
                break;
            case 'v':
                verbose = 1;
                break;
        }
    }

    if (opterr) {
        usage();
        exit(EXIT_FAILURE);
    }

    if (conf_path != NULL) {
        jconf_t *conf = read_jconf(conf_path);
        if (server_num == 0) {
            server_num = conf->remote_num;
            for (i = 0; i < server_num; i++) {
                server_host[i] = conf->remote_host[i];
            }
        }
        if (server_port == NULL) server_port = conf->remote_port;
        if (password == NULL) password = conf->password;
        if (method == NULL) method = conf->method;
        if (timeout == NULL) timeout = conf->timeout;
    }

    if (server_num == 0 || server_port == NULL || password == NULL) {
        usage();
        exit(EXIT_FAILURE);
    }

    if (timeout == NULL) timeout = "60";

    if (pid_flags) {
        demonize(pid_path);
    }

    // ignore SIGPIPE
    signal(SIGPIPE, SIG_IGN);
    signal(SIGCHLD, SIG_IGN);
    signal(SIGABRT, SIG_IGN);

    // setup asyncns
    asyncns_t *asyncns;
    if (!(asyncns = asyncns_new(dns_thread_num))) {
        FATAL("asyncns failed");
    }

    // setup keys
    LOGD("initialize cihpers... %s", method);
    int m = enc_init(password, method);

    // inilitialize ev loop
    struct ev_loop *loop = EV_DEFAULT;

    // bind to each interface
    while (server_num > 0) {
        int index = --server_num;
        const char* host = server_host[index];

        // Bind to port
        int listenfd;
        listenfd = create_and_bind(host, server_port);
        if (listenfd < 0) {
            FATAL("bind() error..");
        }
        if (listen(listenfd, SOMAXCONN) == -1) {
            FATAL("listen() error.");
        }
        setnonblocking(listenfd);
        LOGD("server listening at port %s.", server_port);

        // Setup proxy context
        struct listen_ctx *listen_ctx = malloc(sizeof(struct listen_ctx));
        listen_ctx->timeout = atoi(timeout);
        listen_ctx->asyncns = asyncns;
        listen_ctx->fd = listenfd;
        listen_ctx->method = m;
        listen_ctx->iface = iface;

        ev_io_init (&listen_ctx->io, accept_cb, listenfd, EV_READ);
        ev_io_start (loop, &listen_ctx->io);
    }

    // start ev loop
    ev_run (loop, 0);
    return 0;
}
Exemplo n.º 5
0
int init_udprelay(const char *server_host, const char *server_port,
#ifdef UDPRELAY_LOCAL
                  const char *remote_host, const char *remote_port,
#ifdef UDPRELAY_TUNNEL
                  const ss_addr_t tunnel_addr,
#endif
#endif
#ifdef UDPRELAY_REMOTE
                  int dns_thread_num,
#endif
                  int method, int timeout, const char *iface)
{
    // Inilitialize ev loop
    struct ev_loop *loop = EV_DEFAULT;

    // Inilitialize cache
    struct cache *conn_cache;
    cache_create(&conn_cache, MAX_UDP_CONN_NUM, free_cb);

    //////////////////////////////////////////////////
    // Setup server context

#ifdef UDPRELAY_REMOTE
    // setup asyncns
    asyncns_t *asyncns;
    if (!(asyncns = asyncns_new(dns_thread_num))) {
        FATAL("[udp] asyncns failed");
    }
    resolve_ctx = malloc(sizeof(struct resolve_ctx));

    int asyncnsfd = asyncns_fd(asyncns);
    ev_io_init(&resolve_ctx->io, query_resolve_cb, asyncnsfd, EV_READ);
    ev_io_start(loop, &resolve_ctx->io);

    resolve_ctx->asyncns = asyncns;
    resolve_ctx->asyncnsfd = asyncnsfd;
#endif

    // Bind to port
    int serverfd = create_server_socket(server_host, server_port);
    if (serverfd < 0) {
        FATAL("[udp] bind() error..");
    }
    setnonblocking(serverfd);

    server_ctx = new_server_ctx(serverfd);
    server_ctx->timeout = min(timeout, MAX_CONNECT_TIMEOUT);
    server_ctx->method = method;
    server_ctx->iface = iface;
    server_ctx->conn_cache = conn_cache;
#ifdef UDPRELAY_LOCAL
    server_ctx->remote_host = remote_host;
    server_ctx->remote_port = remote_port;
#ifdef UDPRELAY_TUNNEL
    server_ctx->tunnel_addr = tunnel_addr;
#endif
#endif
#ifdef UDPRELAY_REMOTE
    server_ctx->asyncns = asyncns;
#endif

    ev_io_start(loop, &server_ctx->io);

    return 0;
}