diff options
Diffstat (limited to 'jni/iodine/src/iodine.c')
-rw-r--r-- | jni/iodine/src/iodine.c | 106 |
1 files changed, 70 insertions, 36 deletions
diff --git a/jni/iodine/src/iodine.c b/jni/iodine/src/iodine.c index 03efb18..5c19576 100644 --- a/jni/iodine/src/iodine.c +++ b/jni/iodine/src/iodine.c @@ -1,5 +1,6 @@ /* - * Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se> + * Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>, + * 2006-2009 Bjorn Andersson <flex@kryo.se> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -32,6 +33,7 @@ #else #include <grp.h> #include <pwd.h> +#include <netdb.h> #endif #include "common.h" @@ -51,11 +53,17 @@ static char *__progname; #define PASSWORD_ENV_VAR "IODINE_PASS" static void -sighandler(int sig) +sighandler(int sig) { client_stop(); } +#if defined(__GNUC__) || defined(__clang__) +/* mark as no return to help some compilers to avoid warnings + * about use of uninitialized variables */ +static void usage() __attribute__((noreturn)); +#endif + static void usage() { extern char *__progname; @@ -75,7 +83,7 @@ help() { "[-P password] [-m maxfragsize] [-M maxlen] [-T type] [-O enc] [-L 0|1] [-I sec] " "[-z context] [-F pidfile] [nameserver] topdomain\n", __progname); fprintf(stderr, "Options to try if connection doesn't work:\n"); - fprintf(stderr, " -T force dns type: NULL, TXT, SRV, MX, CNAME, A (default: autodetect)\n"); + fprintf(stderr, " -T force dns type: NULL, PRIVATE, TXT, SRV, MX, CNAME, A (default: autodetect)\n"); fprintf(stderr, " -O force downstream encoding for -T other than NULL: Base32, Base64, Base64u,\n"); fprintf(stderr, " Base128, or (only for TXT:) Raw (default: autodetect)\n"); fprintf(stderr, " -I max interval between requests (default 4 sec) to prevent DNS timeouts\n"); @@ -101,8 +109,9 @@ help() { static void version() { + fprintf(stderr, "iodine IP over DNS tunneling client\n"); - fprintf(stderr, "version: 0.6.0-rc1 from 2010-02-13\n"); + fprintf(stderr, "version: 0.7.0 from 2014-06-16\n"); exit(0); } @@ -110,8 +119,9 @@ version() { int main(int argc, char **argv) { - char *nameserv_addr; + char *nameserv_host; char *topdomain; + char *errormsg; #ifndef WINDOWS32 struct passwd *pw; #endif @@ -132,9 +142,16 @@ main(int argc, char **argv) int lazymode; int selecttimeout; int hostname_maxlen; +#ifdef OPENBSD + int rtable = 0; +#endif + struct sockaddr_storage nameservaddr; + int nameservaddr_len; + int nameserv_family; - nameserv_addr = NULL; + nameserv_host = NULL; topdomain = NULL; + errormsg = NULL; #ifndef WINDOWS32 pw = NULL; #endif @@ -154,6 +171,7 @@ main(int argc, char **argv) lazymode = 1; selecttimeout = 4; hostname_maxlen = 0xFF; + nameserv_family = AF_UNSPEC; #ifdef WINDOWS32 WSAStartup(req_version, &wsa_data); @@ -161,7 +179,7 @@ main(int argc, char **argv) srand((unsigned) time(NULL)); client_init(); - + #if !defined(BSD) && !defined(__GLIBC__) __progname = strrchr(argv[0], '/'); if (__progname == NULL) @@ -170,8 +188,14 @@ main(int argc, char **argv) __progname++; #endif - while ((choice = getopt(argc, argv, "vfhru:t:d:P:m:M:F:T:O:L:I:")) != -1) { + while ((choice = getopt(argc, argv, "46vfhru:t:d:R:P:m:M:F:T:O:L:I:")) != -1) { switch(choice) { + case '4': + nameserv_family = AF_INET; + break; + case '6': + nameserv_family = AF_INET6; + break; case 'v': version(); /* NOTREACHED */ @@ -185,6 +209,7 @@ main(int argc, char **argv) break; case 'r': raw_mode = 0; + break; case 'u': username = optarg; break; @@ -194,12 +219,17 @@ main(int argc, char **argv) case 'd': device = optarg; break; +#ifdef OPENBSD + case 'R': + rtable = atoi(optarg); + break; +#endif case 'P': strncpy(password, optarg, sizeof(password)); password[sizeof(password)-1] = 0; - + /* XXX: find better way of cleaning up ps(1) */ - memset(optarg, 0, strlen(optarg)); + memset(optarg, 0, strlen(optarg)); break; case 'm': autodetect_frag_size = 0; @@ -217,12 +247,13 @@ main(int argc, char **argv) break; case 'F': pidfile = optarg; - break; + break; case 'T': - set_qtype(optarg); + if (client_set_qtype(optarg)) + errx(5, "Invalid query type '%s'", optarg); break; case 'O': /* not -D, is Debug in server */ - set_downenc(optarg); + client_set_downenc(optarg); break; case 'L': lazymode = atoi(optarg); @@ -243,7 +274,7 @@ main(int argc, char **argv) /* NOTREACHED */ } } - + check_superuser(usage); argc -= optind; @@ -251,11 +282,11 @@ main(int argc, char **argv) switch (argc) { case 1: - nameserv_addr = get_resolvconf_addr(); + nameserv_host = get_resolvconf_addr(); topdomain = strdup(argv[0]); break; case 2: - nameserv_addr = argv[0]; + nameserv_host = argv[0]; topdomain = strdup(argv[1]); break; default: @@ -269,22 +300,21 @@ main(int argc, char **argv) /* NOTREACHED */ } - if (nameserv_addr) { - client_set_nameserver(nameserv_addr, DNS_PORT); + if (nameserv_host) { + nameservaddr_len = get_addr(nameserv_host, DNS_PORT, nameserv_family, 0, &nameservaddr); + if (nameservaddr_len < 0) { + errx(1, "Cannot lookup nameserver '%s': %s ", + nameserv_host, gai_strerror(nameservaddr_len)); + } + client_set_nameserver(&nameservaddr, nameservaddr_len); } else { warnx("No nameserver found - not connected to any network?\n"); usage(); /* NOTREACHED */ - } + } - if (strlen(topdomain) <= 128) { - if(check_topdomain(topdomain)) { - warnx("Topdomain contains invalid characters.\n"); - usage(); - /* NOTREACHED */ - } - } else { - warnx("Use a topdomain max 128 chars long.\n"); + if(check_topdomain(topdomain, &errormsg)) { + warnx("Invalid topdomain: %s", errormsg); usage(); /* NOTREACHED */ } @@ -293,7 +323,7 @@ main(int argc, char **argv) client_set_lazymode(lazymode); client_set_topdomain(topdomain); client_set_hostname_maxlen(hostname_maxlen); - + if (username != NULL) { #ifndef WINDOWS32 if ((pw = getpwnam(username)) == NULL) { @@ -303,51 +333,55 @@ main(int argc, char **argv) } #endif } - + if (strlen(password) == 0) { if (NULL != getenv(PASSWORD_ENV_VAR)) snprintf(password, sizeof(password), "%s", getenv(PASSWORD_ENV_VAR)); else read_password(password, sizeof(password)); } - + client_set_password(password); if ((tun_fd = open_tun(device)) == -1) { retval = 1; goto cleanup1; } - if ((dns_fd = open_dns(0, INADDR_ANY)) == -1) { + if ((dns_fd = open_dns_from_host(NULL, 0, nameservaddr.ss_family, AI_PASSIVE)) < 0) { retval = 1; goto cleanup2; } +#ifdef OPENBSD + if (rtable > 0) + socket_setrtable(dns_fd, rtable); +#endif signal(SIGINT, sighandler); signal(SIGTERM, sighandler); fprintf(stderr, "Sending DNS queries for %s to %s\n", - topdomain, nameserv_addr); + topdomain, format_addr(&nameservaddr, nameservaddr_len)); if (client_handshake(dns_fd, raw_mode, autodetect_frag_size, max_downstream_frag_size)) { retval = 1; goto cleanup2; } - + if (client_get_conn() == CONN_RAW_UDP) { fprintf(stderr, "Sending raw traffic directly to %s\n", client_get_raw_addr()); } fprintf(stderr, "Connection setup complete, transmitting data.\n"); - if (foreground == 0) + if (foreground == 0) do_detach(); - + if (pidfile != NULL) do_pidfile(pidfile); if (newroot != NULL) do_chroot(newroot); - + if (username != NULL) { #ifndef WINDOWS32 gid_t gids[1]; |