mirror of
https://github.com/yarrick/iodine.git
synced 2024-11-25 02:55:15 +00:00
Refactor client code to use client_instance
This commit is contained in:
parent
506c1de67e
commit
147119afee
953
src/client.c
953
src/client.c
File diff suppressed because it is too large
Load Diff
125
src/client.h
125
src/client.h
@ -23,13 +23,124 @@
|
|||||||
extern int debug;
|
extern int debug;
|
||||||
extern int stats;
|
extern int stats;
|
||||||
|
|
||||||
#define PENDING_QUERIES_LENGTH (MAX(windowsize_up, windowsize_down) * 3)
|
#define PENDING_QUERIES_LENGTH (MAX(this.windowsize_up, this.windowsize_down) * 4)
|
||||||
|
#define INSTANCE this
|
||||||
|
|
||||||
|
struct client_instance {
|
||||||
|
int max_downstream_frag_size;
|
||||||
|
int autodetect_frag_size;
|
||||||
|
int hostname_maxlen;
|
||||||
|
int raw_mode;
|
||||||
|
int foreground;
|
||||||
|
char password[33];
|
||||||
|
|
||||||
|
/* DNS nameserver info */
|
||||||
|
char **nameserv_hosts;
|
||||||
|
size_t nameserv_hosts_len;
|
||||||
|
struct sockaddr_storage *nameserv_addrs;
|
||||||
|
size_t nameserv_addrs_len;
|
||||||
|
int current_nameserver;
|
||||||
|
struct sockaddr_storage raw_serv;
|
||||||
|
int raw_serv_len;
|
||||||
|
char *topdomain;
|
||||||
|
|
||||||
|
int tun_fd;
|
||||||
|
int dns_fd;
|
||||||
|
|
||||||
|
#ifdef OPENBSD
|
||||||
|
int rtable;
|
||||||
|
#endif
|
||||||
|
int running;
|
||||||
|
|
||||||
|
/* Output flags for debug and time between stats update */
|
||||||
|
int debug;
|
||||||
|
int stats;
|
||||||
|
|
||||||
|
uint16_t rand_seed;
|
||||||
|
|
||||||
|
/* Current up/downstream window data */
|
||||||
|
struct frag_buffer *outbuf;
|
||||||
|
struct frag_buffer *inbuf;
|
||||||
|
size_t windowsize_up;
|
||||||
|
size_t windowsize_down;
|
||||||
|
size_t maxfragsize_up;
|
||||||
|
|
||||||
|
/* Next downstream seqID to be ACK'd (-1 if none pending) */
|
||||||
|
int next_downstream_ack;
|
||||||
|
|
||||||
|
/* Remembering queries we sent for tracking purposes */
|
||||||
|
struct query_tuple *pending_queries;
|
||||||
|
size_t num_pending;
|
||||||
|
time_t max_timeout_ms;
|
||||||
|
time_t send_interval_ms;
|
||||||
|
time_t min_send_interval_ms;
|
||||||
|
|
||||||
|
/* Server response timeout in ms and downstream window timeout */
|
||||||
|
time_t server_timeout_ms;
|
||||||
|
time_t downstream_timeout_ms;
|
||||||
|
int autodetect_server_timeout;
|
||||||
|
|
||||||
|
/* Cumulative Round-Trip-Time in ms */
|
||||||
|
time_t rtt_total_ms;
|
||||||
|
size_t num_immediate;
|
||||||
|
|
||||||
|
/* Connection statistics */
|
||||||
|
size_t num_timeouts;
|
||||||
|
size_t num_untracked;
|
||||||
|
size_t num_servfail;
|
||||||
|
size_t num_badip;
|
||||||
|
size_t num_sent;
|
||||||
|
size_t num_recv;
|
||||||
|
size_t send_query_sendcnt;
|
||||||
|
size_t send_query_recvcnt;
|
||||||
|
size_t num_frags_sent;
|
||||||
|
size_t num_frags_recv;
|
||||||
|
size_t num_pings;
|
||||||
|
|
||||||
|
/* My userid at the server */
|
||||||
|
char userid;
|
||||||
|
char userid_char; /* used when sending (lowercase) */
|
||||||
|
char userid_char2; /* also accepted when receiving (uppercase) */
|
||||||
|
|
||||||
|
uint16_t chunkid;
|
||||||
|
|
||||||
|
/* Base32 encoder used for non-data packets and replies */
|
||||||
|
struct encoder *b32;
|
||||||
|
/* Base64 etc encoders for replies */
|
||||||
|
struct encoder *b64;
|
||||||
|
struct encoder *b64u;
|
||||||
|
struct encoder *b128;
|
||||||
|
|
||||||
|
/* The encoder used for data packets
|
||||||
|
* Defaults to Base32, can be changed after handshake */
|
||||||
|
struct encoder *dataenc;
|
||||||
|
|
||||||
|
/* Upstream/downstream compression flags */
|
||||||
|
int compression_up;
|
||||||
|
int compression_down;
|
||||||
|
|
||||||
|
/* The encoder to use for downstream data */
|
||||||
|
char downenc;
|
||||||
|
|
||||||
|
/* set query type to send */
|
||||||
|
uint16_t do_qtype;
|
||||||
|
|
||||||
|
/* My connection mode */
|
||||||
|
enum connection conn;
|
||||||
|
int connected;
|
||||||
|
|
||||||
|
int lazymode;
|
||||||
|
long send_ping_soon;
|
||||||
|
time_t lastdownstreamtime;
|
||||||
|
};
|
||||||
|
|
||||||
struct query_tuple {
|
struct query_tuple {
|
||||||
int id; /* DNS query / response ID */
|
int id; /* DNS query / response ID */
|
||||||
struct timeval time; /* time sent or 0 if cleared */
|
struct timeval time; /* time sent or 0 if cleared */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern struct client_instance this;
|
||||||
|
|
||||||
void client_init();
|
void client_init();
|
||||||
void client_stop();
|
void client_stop();
|
||||||
|
|
||||||
@ -37,18 +148,10 @@ enum connection client_get_conn();
|
|||||||
const char *client_get_raw_addr();
|
const char *client_get_raw_addr();
|
||||||
|
|
||||||
void client_rotate_nameserver();
|
void client_rotate_nameserver();
|
||||||
void client_set_nameservers(struct sockaddr_storage *, int);
|
|
||||||
void client_set_topdomain(const char *cp);
|
|
||||||
void client_set_password(const char *cp);
|
|
||||||
int client_set_qtype(char *qtype);
|
int client_set_qtype(char *qtype);
|
||||||
char *client_get_qtype();
|
char *format_qtype();
|
||||||
void client_set_downenc(char *encoding);
|
char parse_encoding(char *encoding);
|
||||||
void client_set_compression(int up, int down);
|
|
||||||
void client_set_dnstimeout(double, double, double, int);
|
|
||||||
void client_set_lazymode(int lazy_mode);
|
|
||||||
void client_set_windowsize(size_t, size_t);
|
|
||||||
void client_set_hostname_maxlen(size_t i);
|
void client_set_hostname_maxlen(size_t i);
|
||||||
void client_set_interval(double, double);
|
|
||||||
|
|
||||||
int client_handshake(int dns_fd, int raw_mode, int autodetect_frag_size, int fragsize);
|
int client_handshake(int dns_fd, int raw_mode, int autodetect_frag_size, int fragsize);
|
||||||
int client_tunnel(int tun_fd, int dns_fd);
|
int client_tunnel(int tun_fd, int dns_fd);
|
||||||
|
405
src/iodine.c
405
src/iodine.c
@ -21,6 +21,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <getopt.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
@ -40,6 +41,8 @@
|
|||||||
#include "tun.h"
|
#include "tun.h"
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
#include "encoding.h"
|
||||||
|
#include "base32.h"
|
||||||
|
|
||||||
#ifdef WINDOWS32
|
#ifdef WINDOWS32
|
||||||
WORD req_version = MAKEWORD(2, 2);
|
WORD req_version = MAKEWORD(2, 2);
|
||||||
@ -52,10 +55,46 @@ static char *__progname;
|
|||||||
|
|
||||||
#define PASSWORD_ENV_VAR "IODINE_PASS"
|
#define PASSWORD_ENV_VAR "IODINE_PASS"
|
||||||
|
|
||||||
|
struct client_instance this;
|
||||||
|
|
||||||
|
static struct client_instance preset_default = {
|
||||||
|
.foreground = 0,
|
||||||
|
#ifdef OPENBSD
|
||||||
|
.rtable = 0,
|
||||||
|
#endif
|
||||||
|
.debug = 0,
|
||||||
|
.stats = 0,
|
||||||
|
.raw_mode = 1,
|
||||||
|
.lazymode = 1,
|
||||||
|
.max_timeout_ms = 5000,
|
||||||
|
.send_interval_ms = 0,
|
||||||
|
.server_timeout_ms = 4000,
|
||||||
|
.downstream_timeout_ms = 2000,
|
||||||
|
.autodetect_server_timeout = 1,
|
||||||
|
.dataenc = &base32_encoder,
|
||||||
|
.autodetect_frag_size = 1,
|
||||||
|
.max_downstream_frag_size = MAX_FRAGSIZE,
|
||||||
|
.compression_up = 1,
|
||||||
|
.compression_down = 1,
|
||||||
|
.windowsize_up = 8,
|
||||||
|
.windowsize_down = 8,
|
||||||
|
.hostname_maxlen = 0xFF,
|
||||||
|
|
||||||
|
/* static startup values - should not be changed in presets */
|
||||||
|
.conn = CONN_DNS_NULL,
|
||||||
|
.send_ping_soon = 1,
|
||||||
|
.downenc = ' ',
|
||||||
|
.do_qtype = T_UNSET,
|
||||||
|
.maxfragsize_up = 100,
|
||||||
|
.next_downstream_ack = -1,
|
||||||
|
.num_immediate = 1,
|
||||||
|
.rtt_total_ms = 200
|
||||||
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
sighandler(int sig)
|
sighandler(int sig)
|
||||||
{
|
{
|
||||||
client_stop();
|
this.running = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(__GNUC__) || defined(__clang__)
|
#if defined(__GNUC__) || defined(__clang__)
|
||||||
@ -69,7 +108,7 @@ print_usage()
|
|||||||
{
|
{
|
||||||
extern char *__progname;
|
extern char *__progname;
|
||||||
|
|
||||||
fprintf(stderr, "Usage: %s [-v] [-h] [-V sec] [-f] [-r] [-u user] [-t chrootdir] [-d device] "
|
fprintf(stderr, "Usage: %s [-v] [-h] [-V sec] [-X port] [-f] [-r] [-u user] [-t chrootdir] [-d device] "
|
||||||
"[-w downfrags] [-W upfrags] [-i sec -j sec] [-I sec] [-c 0|1] [-C 0|1] [-s ms] "
|
"[-w downfrags] [-W upfrags] [-i sec -j sec] [-I sec] [-c 0|1] [-C 0|1] [-s ms] "
|
||||||
"[-P password] [-m maxfragsize] [-M maxlen] [-T type] [-O enc] [-L 0|1] [-R rdomain] "
|
"[-P password] [-m maxfragsize] [-M maxlen] [-T type] [-O enc] [-L 0|1] [-R rdomain] "
|
||||||
"[-z context] [-F pidfile] topdomain [nameserver1 [nameserver2 [...]]]\n", __progname);
|
"[-z context] [-F pidfile] topdomain [nameserver1 [nameserver2 [...]]]\n", __progname);
|
||||||
@ -88,38 +127,41 @@ help()
|
|||||||
fprintf(stderr, "iodine IP over DNS tunneling client\n");
|
fprintf(stderr, "iodine IP over DNS tunneling client\n");
|
||||||
print_usage();
|
print_usage();
|
||||||
fprintf(stderr, "\nOptions to try if connection doesn't work:\n");
|
fprintf(stderr, "\nOptions to try if connection doesn't work:\n");
|
||||||
fprintf(stderr, " -T force dns type: NULL, PRIVATE, TXT, SRV, MX, CNAME, A (default: autodetect)\n");
|
fprintf(stderr, " -T use 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, " -O use specific downstream encoding for queries: Base32, Base64, Base64u,\n");
|
||||||
fprintf(stderr, " Base128, or (only for TXT:) Raw (default: autodetect)\n");
|
fprintf(stderr, " Base128, or (only for TXT:) Raw (default: autodetect)\n");
|
||||||
fprintf(stderr, " -I target interval between sending and receiving requests (default: 4 secs)\n");
|
fprintf(stderr, " -I target interval between sending and receiving requests (default: 4 secs)\n");
|
||||||
fprintf(stderr, " or ping interval in immediate mode (default: 1 sec)\n");
|
fprintf(stderr, " or ping interval in immediate mode (default: 1 sec)\n");
|
||||||
fprintf(stderr, " -s minimum interval between queries (default: 0ms)\n");
|
fprintf(stderr, " -s minimum interval between queries (default: 0ms)\n");
|
||||||
fprintf(stderr, " -L 1: use lazy mode for low-latency (default). 0: don't (implies -I1)\n");
|
fprintf(stderr, " -L 1: use lazy mode for low-latency (default). 0: don't (implies -I1)\n");
|
||||||
fprintf(stderr, " -m max size of downstream fragments (default: autodetect)\n");
|
fprintf(stderr, " -m max size of downstream fragments (default: autodetect)\n");
|
||||||
fprintf(stderr, " -M max size of upstream hostnames (~100-255, default: 255)\n");
|
fprintf(stderr, " -M max size of upstream hostnames (~100-255, default: 255)\n");
|
||||||
fprintf(stderr, " -r to skip raw UDP mode attempt\n");
|
fprintf(stderr, " -r skip raw UDP mode attempt\n");
|
||||||
fprintf(stderr, " -P password used for authentication (max 32 chars will be used)\n\n");
|
fprintf(stderr, " -P password used for authentication (max 32 chars will be used)\n\n");
|
||||||
|
|
||||||
fprintf(stderr, "Fine-tuning options:\n");
|
fprintf(stderr, "Fine-tuning options:\n");
|
||||||
fprintf(stderr, " -w downstream fragment window size (default: 8 frags)\n");
|
fprintf(stderr, " -w downstream fragment window size (default: 8 frags)\n");
|
||||||
fprintf(stderr, " -W upstream fragment window size (default: 8 frags)\n");
|
fprintf(stderr, " -W upstream fragment window size (default: 8 frags)\n");
|
||||||
fprintf(stderr, " -i server-side request timeout in lazy mode (default: auto)\n");
|
fprintf(stderr, " -i server-side request timeout in lazy mode (default: auto)\n");
|
||||||
fprintf(stderr, " -j downstream fragment ACK timeout, implies -i4 (default: 2 sec)\n");
|
fprintf(stderr, " -j downstream fragment ACK timeout, implies -i4 (default: 2 sec)\n");
|
||||||
fprintf(stderr, " -c 1: use downstream compression (default), 0: disable\n");
|
fprintf(stderr, " -c 1: use downstream compression (default), 0: disable\n");
|
||||||
fprintf(stderr, " -C 1: use upstream compression (default), 0: disable\n\n");
|
fprintf(stderr, " -C 1: use upstream compression (default), 0: disable\n\n");
|
||||||
|
|
||||||
fprintf(stderr, "Other options:\n");
|
fprintf(stderr, "Other options:\n");
|
||||||
fprintf(stderr, " -v to print version info and exit\n");
|
fprintf(stderr, " -v, --version print version info and exit\n");
|
||||||
fprintf(stderr, " -h to print this help and exit\n");
|
fprintf(stderr, " -h, --help print this help and exit\n");
|
||||||
fprintf(stderr, " -V sec to print connection statistics at specified intervals\n");
|
fprintf(stderr, " -V, --stats print connection statistics at given intervals (default: 5 sec)\n");
|
||||||
fprintf(stderr, " -f to keep running in foreground\n");
|
fprintf(stderr, " -X skip tun device and forward data to/from stdin/out, telling the iodined to\n");
|
||||||
fprintf(stderr, " -D enable debug mode (add more D's to increase debug level)\n");
|
fprintf(stderr, " connect to the specified port listening on the server host.\n");
|
||||||
fprintf(stderr, " -u name to drop privileges and run as user 'name'\n");
|
fprintf(stderr, " Can be used with SSH ProxyCommand option. (-X 22)\n");
|
||||||
fprintf(stderr, " -t dir to chroot to directory dir\n");
|
fprintf(stderr, " -f keep running in foreground\n");
|
||||||
fprintf(stderr, " -d device to set tunnel device name\n");
|
fprintf(stderr, " -D enable debug mode (add more D's to increase debug level)\n");
|
||||||
fprintf(stderr, " -z context, to apply specified SELinux context after initialization\n");
|
fprintf(stderr, " -d set tunnel device name\n");
|
||||||
fprintf(stderr, " -R routing domain (OpenBSD only)\n");
|
fprintf(stderr, " -u drop privileges and run as specified user\n");
|
||||||
fprintf(stderr, " -F pidfile to write pid to a file\n\n");
|
fprintf(stderr, " -F write PID to specified file\n");
|
||||||
|
fprintf(stderr, " --chroot chroot to given directory\n");
|
||||||
|
fprintf(stderr, " --context apply specified SELinux context after initialization\n");
|
||||||
|
fprintf(stderr, " --rdomain use specified routing domain (OpenBSD only)\n\n");
|
||||||
|
|
||||||
fprintf(stderr, "nameserver is the IP/hostname of the relaying nameserver(s).\n");
|
fprintf(stderr, "nameserver is the IP/hostname of the relaying nameserver(s).\n");
|
||||||
fprintf(stderr, " multiple nameservers can be specified (used in round-robin). \n");
|
fprintf(stderr, " multiple nameservers can be specified (used in round-robin). \n");
|
||||||
@ -140,96 +182,32 @@ version()
|
|||||||
int
|
int
|
||||||
main(int argc, char **argv)
|
main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
char *topdomain;
|
char *errormsg = NULL;
|
||||||
char *errormsg;
|
|
||||||
#ifndef WINDOWS32
|
#ifndef WINDOWS32
|
||||||
struct passwd *pw;
|
struct passwd *pw = NULL;
|
||||||
#endif
|
#endif
|
||||||
char *username;
|
|
||||||
char password[33];
|
|
||||||
int foreground;
|
|
||||||
char *newroot;
|
|
||||||
char *context;
|
|
||||||
char *device;
|
|
||||||
char *pidfile;
|
|
||||||
int choice;
|
int choice;
|
||||||
int tun_fd;
|
|
||||||
int dns_fd;
|
|
||||||
int max_downstream_frag_size;
|
|
||||||
int autodetect_frag_size;
|
|
||||||
int hostname_maxlen;
|
|
||||||
|
|
||||||
int retval;
|
int retval;
|
||||||
int raw_mode;
|
|
||||||
int lazymode;
|
|
||||||
double target_interval_sec;
|
|
||||||
double server_timeout_sec;
|
|
||||||
double downstream_timeout_sec;
|
|
||||||
int min_interval_ms;
|
|
||||||
int autodetect_server_timeout;
|
|
||||||
int up_compression;
|
|
||||||
int down_compression;
|
|
||||||
|
|
||||||
int up_windowsize;
|
char *username = NULL;
|
||||||
int down_windowsize;
|
char *newroot = NULL;
|
||||||
|
char *context = NULL;
|
||||||
|
char *device = NULL;
|
||||||
|
char *pidfile = NULL;
|
||||||
|
|
||||||
#ifdef OPENBSD
|
char *nameserv_host = NULL;
|
||||||
int rtable = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
char *nameserv_host;
|
|
||||||
char **nameserv_hosts;
|
|
||||||
int nameserv_hosts_len;
|
|
||||||
struct sockaddr_storage nameservaddr;
|
struct sockaddr_storage nameservaddr;
|
||||||
struct sockaddr_storage *nameserv_addrs;
|
int nameservaddr_len = 0;
|
||||||
size_t nameserv_addrs_len;
|
int nameserv_family = AF_UNSPEC;
|
||||||
int nameservaddr_len;
|
|
||||||
int nameserv_family;
|
|
||||||
|
|
||||||
/* Set default values */
|
|
||||||
nameserv_addrs_len = 0;
|
|
||||||
nameservaddr_len = 0;
|
|
||||||
nameserv_host = NULL;
|
|
||||||
topdomain = NULL;
|
|
||||||
errormsg = NULL;
|
|
||||||
#ifndef WINDOWS32
|
|
||||||
pw = NULL;
|
|
||||||
#endif
|
|
||||||
username = NULL;
|
|
||||||
memset(password, 0, 33);
|
|
||||||
srand(time(NULL));
|
|
||||||
foreground = 0;
|
|
||||||
newroot = NULL;
|
|
||||||
context = NULL;
|
|
||||||
device = NULL;
|
|
||||||
pidfile = NULL;
|
|
||||||
debug = 0;
|
|
||||||
stats = 0;
|
|
||||||
|
|
||||||
autodetect_frag_size = 1;
|
|
||||||
max_downstream_frag_size = 3072;
|
|
||||||
retval = 0;
|
|
||||||
raw_mode = 1;
|
|
||||||
lazymode = 1;
|
|
||||||
target_interval_sec = 5; /* DNS RFC says 5 seconds minimum */
|
|
||||||
min_interval_ms = 0;
|
|
||||||
server_timeout_sec = 4; /* Safe value for RTT <1s */
|
|
||||||
downstream_timeout_sec = 2;
|
|
||||||
autodetect_server_timeout = 1;
|
|
||||||
hostname_maxlen = 0xFF;
|
|
||||||
nameserv_family = AF_UNSPEC;
|
|
||||||
up_compression = 1;
|
|
||||||
down_compression = 1;
|
|
||||||
|
|
||||||
up_windowsize = 8;
|
|
||||||
down_windowsize = 8;
|
|
||||||
|
|
||||||
#ifdef WINDOWS32
|
#ifdef WINDOWS32
|
||||||
WSAStartup(req_version, &wsa_data);
|
WSAStartup(req_version, &wsa_data);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
srand((unsigned) time(NULL));
|
srand((unsigned) time(NULL));
|
||||||
client_init();
|
this.rand_seed = (uint16_t) rand();
|
||||||
|
this.chunkid = (uint16_t) rand();
|
||||||
|
this.running = 1;
|
||||||
|
|
||||||
#if !defined(BSD) && !defined(__GLIBC__)
|
#if !defined(BSD) && !defined(__GLIBC__)
|
||||||
__progname = strrchr(argv[0], '/');
|
__progname = strrchr(argv[0], '/');
|
||||||
@ -239,8 +217,24 @@ main(int argc, char **argv)
|
|||||||
__progname++;
|
__progname++;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
while ((choice = getopt(argc, argv, "46vfDhrs:V:c:C:i:j:u:t:d:R:P:w:W:m:M:F:T:O:L:I:")) != -1) {
|
/* each option has format:
|
||||||
switch(choice) {
|
* char *name, int has_arg, int *flag, int val */
|
||||||
|
static struct option iodine_args[] = {
|
||||||
|
{"version", no_argument, 0, 'v'},
|
||||||
|
{"help", no_argument, 0, 'h'},
|
||||||
|
{"stats", optional_argument, 0, 'V'},
|
||||||
|
{"context", required_argument, 0, 'z'},
|
||||||
|
{"rdomain", required_argument, 0, 'R'},
|
||||||
|
{"chrootdir", required_argument, 0, 't'},
|
||||||
|
{"proxycommand", no_argument, 0, 'X'},
|
||||||
|
{NULL, 0, 0, 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
static char *iodine_args_short = "46vfDhrXs:V:c:C:i:j:u:t:d:R:P:w:W:m:M:F:T:O:L:I:";
|
||||||
|
|
||||||
|
|
||||||
|
while ((choice = getopt_long(argc, argv, iodine_args_short, iodine_args, NULL)) != -1) {
|
||||||
|
switch (choice) {
|
||||||
case '4':
|
case '4':
|
||||||
nameserv_family = AF_INET;
|
nameserv_family = AF_INET;
|
||||||
break;
|
break;
|
||||||
@ -252,22 +246,22 @@ main(int argc, char **argv)
|
|||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
break;
|
break;
|
||||||
case 'V':
|
case 'V':
|
||||||
stats = atoi(optarg);
|
this.stats = atoi(optarg);
|
||||||
if (stats < 0)
|
if (this.stats < 0)
|
||||||
stats = 0;
|
this.stats = 0;
|
||||||
break;
|
break;
|
||||||
case 'f':
|
case 'f':
|
||||||
foreground = 1;
|
this.foreground = 1;
|
||||||
break;
|
break;
|
||||||
case 'D':
|
case 'D':
|
||||||
debug++;
|
this.debug++;
|
||||||
break;
|
break;
|
||||||
case 'h':
|
case 'h':
|
||||||
help();
|
help();
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
break;
|
break;
|
||||||
case 'r':
|
case 'r':
|
||||||
raw_mode = 0;
|
this.raw_mode = 0;
|
||||||
break;
|
break;
|
||||||
case 'u':
|
case 'u':
|
||||||
username = optarg;
|
username = optarg;
|
||||||
@ -284,22 +278,22 @@ main(int argc, char **argv)
|
|||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
case 'P':
|
case 'P':
|
||||||
strncpy(password, optarg, sizeof(password));
|
strncpy(this.password, optarg, sizeof(this.password));
|
||||||
password[sizeof(password)-1] = 0;
|
this.password[sizeof(this.password)-1] = 0;
|
||||||
|
|
||||||
/* XXX: find better way of cleaning up ps(1) */
|
/* XXX: find better way of cleaning up ps(1) */
|
||||||
memset(optarg, 0, strlen(optarg));
|
memset(optarg, 0, strlen(optarg));
|
||||||
break;
|
break;
|
||||||
case 'm':
|
case 'm':
|
||||||
autodetect_frag_size = 0;
|
this.autodetect_frag_size = 0;
|
||||||
max_downstream_frag_size = atoi(optarg);
|
this.max_downstream_frag_size = atoi(optarg);
|
||||||
break;
|
break;
|
||||||
case 'M':
|
case 'M':
|
||||||
hostname_maxlen = atoi(optarg);
|
this.hostname_maxlen = atoi(optarg);
|
||||||
if (hostname_maxlen > 255)
|
if (this.hostname_maxlen > 255)
|
||||||
hostname_maxlen = 255;
|
this.hostname_maxlen = 255;
|
||||||
if (hostname_maxlen < 10)
|
if (this.hostname_maxlen < 10)
|
||||||
hostname_maxlen = 10;
|
this.hostname_maxlen = 10;
|
||||||
break;
|
break;
|
||||||
case 'z':
|
case 'z':
|
||||||
context = optarg;
|
context = optarg;
|
||||||
@ -312,45 +306,48 @@ main(int argc, char **argv)
|
|||||||
errx(5, "Invalid query type '%s'", optarg);
|
errx(5, "Invalid query type '%s'", optarg);
|
||||||
break;
|
break;
|
||||||
case 'O':
|
case 'O':
|
||||||
client_set_downenc(optarg);
|
if ((this.downenc = parse_encoding(optarg)) == 0)
|
||||||
|
errx(6, "Invalid encoding type '%s'", optarg);
|
||||||
break;
|
break;
|
||||||
case 'L':
|
case 'L':
|
||||||
lazymode = atoi(optarg);
|
this.lazymode = atoi(optarg);
|
||||||
if (lazymode > 1)
|
if (this.lazymode > 1)
|
||||||
lazymode = 1;
|
this.lazymode = 1;
|
||||||
if (lazymode < 0)
|
if (this.lazymode < 0)
|
||||||
lazymode = 0;
|
this.lazymode = 0;
|
||||||
break;
|
break;
|
||||||
case 'I':
|
case 'I':
|
||||||
target_interval_sec = strtod(optarg, NULL);
|
this.max_timeout_ms = strtod(optarg, NULL) * 1000;
|
||||||
break;
|
break;
|
||||||
case 'i':
|
case 'i':
|
||||||
server_timeout_sec = strtod(optarg, NULL);
|
this.server_timeout_ms = strtod(optarg, NULL) * 1000;
|
||||||
autodetect_server_timeout = 0;
|
this.autodetect_server_timeout = 0;
|
||||||
break;
|
break;
|
||||||
case 'j':
|
case 'j':
|
||||||
downstream_timeout_sec = strtod(optarg, NULL);
|
this.downstream_timeout_ms = strtod(optarg, NULL) * 1000;
|
||||||
if (autodetect_server_timeout) {
|
if (this.autodetect_server_timeout) {
|
||||||
autodetect_server_timeout = 0;
|
this.autodetect_server_timeout = 0;
|
||||||
server_timeout_sec = 4;
|
this.server_timeout_ms = 4000;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 's':
|
case 's':
|
||||||
min_interval_ms = atoi(optarg);
|
this.send_interval_ms = atoi(optarg);
|
||||||
if (min_interval_ms < 0)
|
if (this.send_interval_ms < 0)
|
||||||
min_interval_ms = 0;
|
this.send_interval_ms = 0;
|
||||||
case 'w':
|
case 'w':
|
||||||
down_windowsize = atoi(optarg);
|
this.windowsize_down = atoi(optarg);
|
||||||
break;
|
break;
|
||||||
case 'W':
|
case 'W':
|
||||||
up_windowsize = atoi(optarg);
|
this.windowsize_up = atoi(optarg);
|
||||||
break;
|
|
||||||
case 'C':
|
|
||||||
up_compression = atoi(optarg) & 1;
|
|
||||||
break;
|
break;
|
||||||
case 'c':
|
case 'c':
|
||||||
down_compression = atoi(optarg) & 1;
|
this.compression_down = atoi(optarg) & 1;
|
||||||
break;
|
break;
|
||||||
|
case 'C':
|
||||||
|
this.compression_up = atoi(optarg) & 1;
|
||||||
|
break;
|
||||||
|
case 'X':
|
||||||
|
// TODO implement option for remote host/port to pipe stdin/out
|
||||||
default:
|
default:
|
||||||
usage();
|
usage();
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
@ -362,120 +359,124 @@ main(int argc, char **argv)
|
|||||||
argc -= optind;
|
argc -= optind;
|
||||||
argv += optind;
|
argv += optind;
|
||||||
|
|
||||||
if (debug) {
|
if (this.debug) {
|
||||||
fprintf(stderr, "Debug level %d enabled, will stay in foreground.\n", debug);
|
fprintf(stderr, "Debug level %d enabled, will stay in foreground.\n", this.debug);
|
||||||
fprintf(stderr, "Add more -D switches to set higher debug level.\n");
|
fprintf(stderr, "Add more -D switches to set higher debug level.\n");
|
||||||
foreground = 1;
|
this.foreground = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
nameserv_hosts_len = argc - 1;
|
this.nameserv_hosts_len = argc - 1;
|
||||||
if (nameserv_hosts_len <= 0)
|
if (this.nameserv_hosts_len <= 0)
|
||||||
nameserv_hosts_len = 1;
|
/* if no hosts specified, use resolv.conf */
|
||||||
|
this.nameserv_hosts_len = 1;
|
||||||
|
|
||||||
// Preallocate memory with expected number of hosts
|
// Preallocate memory with expected number of hosts
|
||||||
nameserv_hosts = malloc(sizeof(char *) * nameserv_hosts_len);
|
this.nameserv_hosts = malloc(sizeof(char *) * this.nameserv_hosts_len);
|
||||||
nameserv_addrs = malloc(sizeof(struct sockaddr_storage) * nameserv_hosts_len);
|
this.nameserv_addrs = malloc(sizeof(struct sockaddr_storage) * this.nameserv_hosts_len);
|
||||||
|
|
||||||
if (argc == 0) {
|
if (argc == 0) {
|
||||||
usage();
|
usage();
|
||||||
/* NOT REACHED */
|
/* NOT REACHED */
|
||||||
} else if (argc == 1) {
|
} else if (argc == 1) {
|
||||||
nameserv_hosts[0] = get_resolvconf_addr();
|
this.nameserv_hosts[0] = get_resolvconf_addr();
|
||||||
} else if (argc > 1)
|
} else if (argc > 1)
|
||||||
for (int h = 0; h < nameserv_hosts_len; h++) nameserv_hosts[h] = strdup(argv[h + 1]);
|
for (int h = 0; h < this.nameserv_hosts_len; h++)
|
||||||
topdomain = strdup(argv[0]);
|
this.nameserv_hosts[h] = strdup(argv[h + 1]);
|
||||||
|
this.topdomain = strdup(argv[0]);
|
||||||
|
|
||||||
for (int n = 0; n < nameserv_hosts_len; n++) {
|
for (int n = 0; n < this.nameserv_hosts_len; n++) {
|
||||||
nameserv_host = nameserv_hosts[n];
|
nameserv_host = this.nameserv_hosts[n];
|
||||||
if (!nameserv_host) {
|
if (!nameserv_host) {
|
||||||
errx(1, "Error processing nameserver hostnames!\n");
|
errx(1, "Error processing nameserver hostnames!");
|
||||||
}
|
}
|
||||||
nameservaddr_len = get_addr(nameserv_host, DNS_PORT, nameserv_family, 0, &nameservaddr);
|
nameservaddr_len = get_addr(nameserv_host, DNS_PORT, nameserv_family, 0, &nameservaddr);
|
||||||
if (nameservaddr_len < 0) {
|
if (nameservaddr_len < 0) {
|
||||||
errx(1, "Cannot lookup nameserver '%s': %s ",
|
errx(1, "Cannot lookup nameserver '%s': %s ",
|
||||||
nameserv_host, gai_strerror(nameservaddr_len));
|
nameserv_host, gai_strerror(nameservaddr_len));
|
||||||
}
|
}
|
||||||
memcpy(&nameserv_addrs[n], &nameservaddr, sizeof(struct sockaddr_storage));
|
memcpy(&this.nameserv_addrs[n], &nameservaddr, sizeof(struct sockaddr_storage));
|
||||||
nameserv_addrs_len ++;
|
this.nameserv_addrs_len ++;
|
||||||
nameserv_host = NULL;
|
nameserv_host = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nameserv_addrs_len <= 0 || !nameserv_hosts[0]) {
|
if (this.nameserv_addrs_len <= 0 || !this.nameserv_hosts[0]) {
|
||||||
warnx("No nameserver found - not connected to any network?\n");
|
warnx("No nameservers found - not connected to any network?");
|
||||||
usage();
|
usage();
|
||||||
}
|
}
|
||||||
|
|
||||||
client_set_nameservers(nameserv_addrs, nameserv_addrs_len);
|
// TODO remove client_set_... functions
|
||||||
|
// client_set_nameservers(nameserv_addrs, nameserv_addrs_len);
|
||||||
|
|
||||||
if (max_downstream_frag_size < 1 || max_downstream_frag_size > 0xffff) {
|
if (this.max_downstream_frag_size < 10 || this.max_downstream_frag_size > MAX_FRAGSIZE) {
|
||||||
warnx("Use a max frag size between 1 and 65535 bytes.\n");
|
warnx("Use a max frag size between 10 and %d bytes.", MAX_FRAGSIZE);
|
||||||
usage();
|
usage();
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
}
|
}
|
||||||
|
|
||||||
if(check_topdomain(topdomain, &errormsg)) {
|
if(check_topdomain(this.topdomain, &errormsg)) {
|
||||||
warnx("Invalid topdomain: %s", errormsg);
|
warnx("Invalid topdomain: %s", errormsg);
|
||||||
usage();
|
usage();
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (up_windowsize < 1 || down_windowsize < 1) {
|
int max_ws = MAX_SEQ_ID / 2;
|
||||||
warnx("Windowsize (-w or -W) must be greater than 0!");
|
if (this.windowsize_up < 1 || this.windowsize_down < 1 ||
|
||||||
|
this.windowsize_up > max_ws || this.windowsize_down > max_ws) {
|
||||||
|
warnx("Window sizes (-w or -W) must be between 0 and %d!", max_ws);
|
||||||
usage();
|
usage();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (target_interval_sec < 0.1) {
|
if (this.max_timeout_ms < 100) {
|
||||||
warnx("Target interval must be greater than 0.1 seconds!");
|
warnx("Target interval (-I) must be greater than 0.1 seconds!");
|
||||||
usage();
|
usage();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (server_timeout_sec < 0.1 || server_timeout_sec >= target_interval_sec) {
|
if (this.server_timeout_ms < 100 || this.server_timeout_ms >= this.max_timeout_ms) {
|
||||||
warnx("Server timeout must be greater than 0.1 sec and less than target interval!");
|
warnx("Server timeout (-i) must be greater than 0.1 sec and less than target interval!");
|
||||||
usage();
|
usage();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (downstream_timeout_sec < 0.1) {
|
if (this.downstream_timeout_ms < 100) {
|
||||||
warnx("Downstream fragment timeout must be more than 0.1 sec to prevent excessive retransmits.");
|
warnx("Downstream fragment timeout must be more than 0.1 sec to prevent excessive retransmits.");
|
||||||
usage();
|
usage();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!lazymode && target_interval_sec > 1) {
|
if (!this.lazymode && this.max_timeout_ms > 1000) {
|
||||||
warnx("Warning: Target interval of >1 second in immediate mode will cause high latency.");
|
fprintf(stderr, "Warning: Target interval of >1 second in immediate mode will cause high latency.\n");
|
||||||
usage();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
client_set_compression(up_compression, down_compression);
|
// client_set_compression(up_compression, down_compression);
|
||||||
client_set_dnstimeout(target_interval_sec, server_timeout_sec, downstream_timeout_sec, autodetect_server_timeout);
|
// client_set_dnstimeout(target_interval_sec, server_timeout_sec, downstream_timeout_sec, autodetect_server_timeout);
|
||||||
client_set_interval(target_interval_sec * 1000.0, min_interval_ms);
|
// client_set_interval(target_interval_sec * 1000.0, min_interval_ms);
|
||||||
client_set_lazymode(lazymode);
|
// client_set_lazymode(lazymode);
|
||||||
client_set_topdomain(topdomain);
|
// client_set_topdomain(topdomain);
|
||||||
client_set_hostname_maxlen(hostname_maxlen);
|
// client_set_hostname_maxlen(hostname_maxlen);
|
||||||
client_set_windowsize(up_windowsize, down_windowsize);
|
// client_set_windowsize(up_windowsize, down_windowsize);
|
||||||
|
|
||||||
if (username != NULL) {
|
if (username != NULL) {
|
||||||
#ifndef WINDOWS32
|
#ifndef WINDOWS32
|
||||||
if ((pw = getpwnam(username)) == NULL) {
|
if ((pw = getpwnam(username)) == NULL) {
|
||||||
warnx("User %s does not exist!\n", username);
|
warnx("User %s does not exist!", username);
|
||||||
usage();
|
usage();
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
warnx("Warning: Cannot switch user on Windows systems.");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strlen(password) == 0) {
|
if (strlen(this.password) == 0) {
|
||||||
if (NULL != getenv(PASSWORD_ENV_VAR))
|
if (NULL != getenv(PASSWORD_ENV_VAR))
|
||||||
snprintf(password, sizeof(password), "%s", getenv(PASSWORD_ENV_VAR));
|
snprintf(this.password, sizeof(this.password), "%s", getenv(PASSWORD_ENV_VAR));
|
||||||
else
|
else
|
||||||
read_password(password, sizeof(password));
|
read_password(this.password, sizeof(this.password));
|
||||||
}
|
}
|
||||||
|
|
||||||
client_set_password(password);
|
if ((this.tun_fd = open_tun(device)) == -1) {
|
||||||
|
|
||||||
if ((tun_fd = open_tun(device)) == -1) {
|
|
||||||
retval = 1;
|
retval = 1;
|
||||||
goto cleanup1;
|
goto cleanup1;
|
||||||
}
|
}
|
||||||
if ((dns_fd = open_dns_from_host(NULL, 0, nameservaddr.ss_family, AI_PASSIVE)) < 0) {
|
if ((this.dns_fd = open_dns_from_host(NULL, 0, nameservaddr.ss_family, AI_PASSIVE)) < 0) {
|
||||||
retval = 1;
|
retval = 1;
|
||||||
goto cleanup2;
|
goto cleanup2;
|
||||||
}
|
}
|
||||||
@ -487,24 +488,25 @@ main(int argc, char **argv)
|
|||||||
signal(SIGINT, sighandler);
|
signal(SIGINT, sighandler);
|
||||||
signal(SIGTERM, sighandler);
|
signal(SIGTERM, sighandler);
|
||||||
|
|
||||||
fprintf(stderr, "Sending DNS queries for %s to ", topdomain);
|
fprintf(stderr, "Sending DNS queries for %s to ", this.topdomain);
|
||||||
for (int a = 0; a < nameserv_addrs_len; a++)
|
for (int a = 0; a < this.nameserv_addrs_len; a++)
|
||||||
fprintf(stderr, "%s%s", format_addr(&nameserv_addrs[a], nameservaddr_len),
|
fprintf(stderr, "%s%s", format_addr(&this.nameserv_addrs[a], sizeof(struct sockaddr_storage)),
|
||||||
(a != nameserv_addrs_len-1) ? ", " : "");
|
(a != this.nameserv_addrs_len - 1) ? ", " : "");
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
|
|
||||||
if (client_handshake(dns_fd, raw_mode, autodetect_frag_size, max_downstream_frag_size)) {
|
// TODO not pass args to client stuff - use "this" as shared instance
|
||||||
|
if (client_handshake(this.dns_fd, this.raw_mode, this.autodetect_frag_size, this.max_downstream_frag_size)) {
|
||||||
retval = 1;
|
retval = 1;
|
||||||
goto cleanup2;
|
goto cleanup2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (client_get_conn() == CONN_RAW_UDP) {
|
if (this.conn == CONN_RAW_UDP) {
|
||||||
fprintf(stderr, "Sending raw traffic directly to %s\n", client_get_raw_addr());
|
fprintf(stderr, "Sending raw UDP traffic directly to %s\n", client_get_raw_addr());
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(stderr, "Connection setup complete, transmitting data.\n");
|
fprintf(stderr, "Connection setup complete, transmitting data.\n");
|
||||||
|
|
||||||
if (foreground == 0)
|
if (this.foreground == 0)
|
||||||
do_detach();
|
do_detach();
|
||||||
|
|
||||||
if (pidfile != NULL)
|
if (pidfile != NULL)
|
||||||
@ -528,11 +530,12 @@ main(int argc, char **argv)
|
|||||||
if (context != NULL)
|
if (context != NULL)
|
||||||
do_setcon(context);
|
do_setcon(context);
|
||||||
|
|
||||||
client_tunnel(tun_fd, dns_fd);
|
// todo don't pass args again.
|
||||||
|
client_tunnel(this.tun_fd, this.dns_fd);
|
||||||
|
|
||||||
cleanup2:
|
cleanup2:
|
||||||
close_dns(dns_fd);
|
close_dns(this.dns_fd);
|
||||||
close_tun(tun_fd);
|
close_tun(this.tun_fd);
|
||||||
cleanup1:
|
cleanup1:
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
|
Loading…
Reference in New Issue
Block a user