mirror of
https://github.com/yarrick/iodine.git
synced 2024-11-25 11:05:15 +00:00
Refactor server code to use global server_instance
This commit is contained in:
parent
eb6d2fae77
commit
506c1de67e
223
src/iodined.c
223
src/iodined.c
@ -72,8 +72,40 @@
|
|||||||
#ifdef WINDOWS32
|
#ifdef WINDOWS32
|
||||||
WORD req_version = MAKEWORD(2, 2);
|
WORD req_version = MAKEWORD(2, 2);
|
||||||
WSADATA wsa_data;
|
WSADATA wsa_data;
|
||||||
|
|
||||||
|
#define LOG_EMERG 0
|
||||||
|
#define LOG_ALERT 1
|
||||||
|
#define LOG_CRIT 2
|
||||||
|
#define LOG_ERR 3
|
||||||
|
#define LOG_WARNING 4
|
||||||
|
#define LOG_NOTICE 5
|
||||||
|
#define LOG_INFO 6
|
||||||
|
#define LOG_DEBUG 7
|
||||||
|
static void
|
||||||
|
syslog(int a, const char *str, ...)
|
||||||
|
{
|
||||||
|
/* TODO: implement (add to event log), move to common.c */
|
||||||
|
;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Definition of main server instance */
|
||||||
|
struct server_instance server;
|
||||||
|
|
||||||
|
static struct server_instance preset_default = {
|
||||||
|
.check_ip = 1,
|
||||||
|
.netmask = 27,
|
||||||
|
.ns_ip = INADDR_ANY,
|
||||||
|
.mtu = 1130, /* Very many relays give fragsize 1150 or slightly
|
||||||
|
higher for NULL; tun/zlib adds ~17 bytes. */
|
||||||
|
.port = 53,
|
||||||
|
.addrfamily = AF_UNSPEC,
|
||||||
|
|
||||||
|
/* Mark both file descriptors as unused */
|
||||||
|
.dns_fds.v4fd = -1,
|
||||||
|
.dns_fds.v6fd = -1
|
||||||
|
};
|
||||||
|
|
||||||
/* Ask ipify.org webservice to get external ip */
|
/* Ask ipify.org webservice to get external ip */
|
||||||
static int
|
static int
|
||||||
get_external_ip(struct in_addr *ip)
|
get_external_ip(struct in_addr *ip)
|
||||||
@ -130,26 +162,9 @@ get_external_ip(struct in_addr *ip)
|
|||||||
static void
|
static void
|
||||||
sigint(int sig)
|
sigint(int sig)
|
||||||
{
|
{
|
||||||
server_stop();
|
server.running = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WINDOWS32
|
|
||||||
#define LOG_EMERG 0
|
|
||||||
#define LOG_ALERT 1
|
|
||||||
#define LOG_CRIT 2
|
|
||||||
#define LOG_ERR 3
|
|
||||||
#define LOG_WARNING 4
|
|
||||||
#define LOG_NOTICE 5
|
|
||||||
#define LOG_INFO 6
|
|
||||||
#define LOG_DEBUG 7
|
|
||||||
static void
|
|
||||||
syslog(int a, const char *str, ...)
|
|
||||||
{
|
|
||||||
/* TODO: implement (add to event log), move to common.c */
|
|
||||||
;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
print_usage() {
|
print_usage() {
|
||||||
extern char *__progname;
|
extern char *__progname;
|
||||||
@ -235,7 +250,7 @@ main(int argc, char **argv)
|
|||||||
char *listen_ip6;
|
char *listen_ip6;
|
||||||
char *errormsg;
|
char *errormsg;
|
||||||
#ifndef WINDOWS32
|
#ifndef WINDOWS32
|
||||||
struct passwd *pw;
|
struct passwd *pw = NULL;
|
||||||
#endif
|
#endif
|
||||||
int foreground;
|
int foreground;
|
||||||
char *username;
|
char *username;
|
||||||
@ -243,59 +258,35 @@ main(int argc, char **argv)
|
|||||||
char *context;
|
char *context;
|
||||||
char *device;
|
char *device;
|
||||||
char *pidfile;
|
char *pidfile;
|
||||||
int addrfamily;
|
|
||||||
struct dnsfd dns_fds;
|
|
||||||
int tun_fd;
|
|
||||||
|
|
||||||
/* settings for forwarding normal DNS to
|
|
||||||
* local real DNS server */
|
|
||||||
int bind_fd;
|
|
||||||
int bind_enable;
|
|
||||||
|
|
||||||
int choice;
|
int choice;
|
||||||
int port;
|
|
||||||
int mtu;
|
|
||||||
int skipipconfig;
|
int skipipconfig;
|
||||||
char *netsize;
|
char *netsize;
|
||||||
int ns_get_externalip;
|
int ns_get_externalip;
|
||||||
int retval;
|
int retval;
|
||||||
int max_idle_time = 0;
|
|
||||||
struct sockaddr_storage dns4addr;
|
|
||||||
int dns4addr_len;
|
|
||||||
struct sockaddr_storage dns6addr;
|
|
||||||
int dns6addr_len;
|
|
||||||
#ifdef HAVE_SYSTEMD
|
#ifdef HAVE_SYSTEMD
|
||||||
int nb_fds;
|
int nb_fds;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef WINDOWS32
|
|
||||||
pw = NULL;
|
|
||||||
#endif
|
|
||||||
errormsg = NULL;
|
errormsg = NULL;
|
||||||
username = NULL;
|
username = NULL;
|
||||||
newroot = NULL;
|
newroot = NULL;
|
||||||
context = NULL;
|
context = NULL;
|
||||||
device = NULL;
|
device = NULL;
|
||||||
foreground = 0;
|
foreground = 0;
|
||||||
bind_enable = 0;
|
|
||||||
bind_fd = 0;
|
|
||||||
mtu = 1130; /* Very many relays give fragsize 1150 or slightly
|
|
||||||
higher for NULL; tun/zlib adds ~17 bytes. */
|
|
||||||
dns4addr_len = 0;
|
|
||||||
dns6addr_len = 0;
|
|
||||||
listen_ip4 = NULL;
|
listen_ip4 = NULL;
|
||||||
listen_ip6 = NULL;
|
listen_ip6 = NULL;
|
||||||
port = 53;
|
|
||||||
|
|
||||||
ns_get_externalip = 0;
|
ns_get_externalip = 0;
|
||||||
addrfamily = AF_UNSPEC;
|
|
||||||
skipipconfig = 0;
|
skipipconfig = 0;
|
||||||
pidfile = NULL;
|
pidfile = NULL;
|
||||||
srand(time(NULL));
|
srand(time(NULL));
|
||||||
|
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
||||||
server_init();
|
|
||||||
|
|
||||||
#ifdef WINDOWS32
|
#ifdef WINDOWS32
|
||||||
WSAStartup(req_version, &wsa_data);
|
WSAStartup(req_version, &wsa_data);
|
||||||
#endif
|
#endif
|
||||||
@ -311,16 +302,16 @@ main(int argc, char **argv)
|
|||||||
while ((choice = getopt(argc, argv, "46vcsfhDu:t:d:m:l:L:p:n:b:P:z:F:i:")) != -1) {
|
while ((choice = getopt(argc, argv, "46vcsfhDu:t:d:m:l:L:p:n:b:P:z:F:i:")) != -1) {
|
||||||
switch(choice) {
|
switch(choice) {
|
||||||
case '4':
|
case '4':
|
||||||
addrfamily = AF_INET;
|
server.addrfamily = AF_INET;
|
||||||
break;
|
break;
|
||||||
case '6':
|
case '6':
|
||||||
addrfamily = AF_INET6;
|
server.addrfamily = AF_INET6;
|
||||||
break;
|
break;
|
||||||
case 'v':
|
case 'v':
|
||||||
version();
|
version();
|
||||||
break;
|
break;
|
||||||
case 'c':
|
case 'c':
|
||||||
check_ip = 0;
|
server.check_ip = 0;
|
||||||
break;
|
break;
|
||||||
case 's':
|
case 's':
|
||||||
skipipconfig = 1;
|
skipipconfig = 1;
|
||||||
@ -332,7 +323,7 @@ main(int argc, char **argv)
|
|||||||
help();
|
help();
|
||||||
break;
|
break;
|
||||||
case 'D':
|
case 'D':
|
||||||
debug++;
|
server.debug++;
|
||||||
break;
|
break;
|
||||||
case 'u':
|
case 'u':
|
||||||
username = optarg;
|
username = optarg;
|
||||||
@ -344,7 +335,7 @@ main(int argc, char **argv)
|
|||||||
device = optarg;
|
device = optarg;
|
||||||
break;
|
break;
|
||||||
case 'm':
|
case 'm':
|
||||||
mtu = atoi(optarg);
|
server.mtu = atoi(optarg);
|
||||||
break;
|
break;
|
||||||
case 'l':
|
case 'l':
|
||||||
listen_ip4 = optarg;
|
listen_ip4 = optarg;
|
||||||
@ -353,28 +344,28 @@ main(int argc, char **argv)
|
|||||||
listen_ip6 = optarg;
|
listen_ip6 = optarg;
|
||||||
break;
|
break;
|
||||||
case 'p':
|
case 'p':
|
||||||
port = atoi(optarg);
|
server.port = atoi(optarg);
|
||||||
break;
|
break;
|
||||||
case 'n':
|
case 'n':
|
||||||
if (optarg && strcmp("auto", optarg) == 0) {
|
if (optarg && strcmp("auto", optarg) == 0) {
|
||||||
ns_get_externalip = 1;
|
ns_get_externalip = 1;
|
||||||
} else {
|
} else {
|
||||||
ns_ip = inet_addr(optarg);
|
server.ns_ip = inet_addr(optarg);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'b':
|
case 'b':
|
||||||
bind_enable = 1;
|
server.bind_enable = 1;
|
||||||
bind_port = atoi(optarg);
|
server.bind_port = atoi(optarg);
|
||||||
break;
|
break;
|
||||||
case 'F':
|
case 'F':
|
||||||
pidfile = optarg;
|
pidfile = optarg;
|
||||||
break;
|
break;
|
||||||
case 'i':
|
case 'i':
|
||||||
max_idle_time = atoi(optarg);
|
server.max_idle_time = atoi(optarg);
|
||||||
break;
|
break;
|
||||||
case 'P':
|
case 'P':
|
||||||
strncpy(password, optarg, sizeof(password));
|
strncpy(server.password, optarg, sizeof(server.password));
|
||||||
password[sizeof(password)-1] = 0;
|
server.password[sizeof(server.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));
|
||||||
@ -400,18 +391,18 @@ main(int argc, char **argv)
|
|||||||
if (netsize) {
|
if (netsize) {
|
||||||
*netsize = 0;
|
*netsize = 0;
|
||||||
netsize++;
|
netsize++;
|
||||||
netmask = atoi(netsize);
|
server.netmask = atoi(netsize);
|
||||||
}
|
}
|
||||||
|
|
||||||
my_ip = inet_addr(argv[0]);
|
server.my_ip = inet_addr(argv[0]);
|
||||||
|
|
||||||
if (my_ip == INADDR_NONE) {
|
if (server.my_ip == INADDR_NONE) {
|
||||||
warnx("Bad IP address to use inside tunnel.");
|
warnx("Bad IP address to use inside tunnel.");
|
||||||
usage();
|
usage();
|
||||||
}
|
}
|
||||||
|
|
||||||
topdomain = strdup(argv[1]);
|
server.topdomain = strdup(argv[1]);
|
||||||
if(check_topdomain(topdomain, &errormsg)) {
|
if(check_topdomain(server.topdomain, &errormsg)) {
|
||||||
warnx("Invalid topdomain: %s", errormsg);
|
warnx("Invalid topdomain: %s", errormsg);
|
||||||
usage();
|
usage();
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
@ -426,57 +417,59 @@ main(int argc, char **argv)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mtu <= 0) {
|
if (server.mtu <= 0) {
|
||||||
warnx("Bad MTU given.");
|
warnx("Bad MTU given.");
|
||||||
usage();
|
usage();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(port < 1 || port > 65535) {
|
if(server.port < 1 || server.port > 65535) {
|
||||||
warnx("Bad port number given.");
|
warnx("Bad port number given.");
|
||||||
usage();
|
usage();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (port != 53) {
|
if (server.port != 53) {
|
||||||
fprintf(stderr, "ALERT! Other dns servers expect you to run on port 53.\n");
|
fprintf(stderr, "ALERT! Other dns servers expect you to run on port 53.\n");
|
||||||
fprintf(stderr, "You must manually forward port 53 to port %d for things to work.\n", port);
|
fprintf(stderr, "You must manually forward port 53 to port %d for things to work.\n", server.port);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (debug) {
|
if (server.debug) {
|
||||||
fprintf(stderr, "Debug level %d enabled, will stay in foreground.\n", debug);
|
fprintf(stderr, "Debug level %d enabled, will stay in foreground.\n", server.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;
|
foreground = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (addrfamily == AF_UNSPEC || addrfamily == AF_INET) {
|
if (server.addrfamily == AF_UNSPEC || server.addrfamily == AF_INET) {
|
||||||
dns4addr_len = get_addr(listen_ip4, port, AF_INET, AI_PASSIVE | AI_NUMERICHOST, &dns4addr);
|
server.dns4addr_len = get_addr(listen_ip4, server.port, AF_INET,
|
||||||
if (dns4addr_len < 0) {
|
AI_PASSIVE | AI_NUMERICHOST, &server.dns4addr);
|
||||||
|
if (server.dns4addr_len < 0) {
|
||||||
warnx("Bad IPv4 address to listen on.");
|
warnx("Bad IPv4 address to listen on.");
|
||||||
usage();
|
usage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (addrfamily == AF_UNSPEC || addrfamily == AF_INET6) {
|
if (server.addrfamily == AF_UNSPEC || server.addrfamily == AF_INET6) {
|
||||||
dns6addr_len = get_addr(listen_ip6, port, AF_INET6, AI_PASSIVE | AI_NUMERICHOST, &dns6addr);
|
server.dns6addr_len = get_addr(listen_ip6, server.port,AF_INET6,
|
||||||
if (dns6addr_len < 0) {
|
AI_PASSIVE | AI_NUMERICHOST, &server.dns6addr);
|
||||||
|
if (server.dns6addr_len < 0) {
|
||||||
warnx("Bad IPv6 address to listen on.");
|
warnx("Bad IPv6 address to listen on.");
|
||||||
usage();
|
usage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(bind_enable) {
|
if(server.bind_enable) {
|
||||||
in_addr_t dns_ip = ((struct sockaddr_in *) &dns4addr)->sin_addr.s_addr;
|
in_addr_t dns_ip = ((struct sockaddr_in *) &server.dns4addr)->sin_addr.s_addr;
|
||||||
if (bind_port < 1 || bind_port > 65535) {
|
if (server.bind_port < 1 || server.bind_port > 65535) {
|
||||||
warnx("Bad DNS server port number given.");
|
warnx("Bad DNS server port number given.");
|
||||||
usage();
|
usage();
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
}
|
}
|
||||||
/* Avoid forwarding loops */
|
/* Avoid forwarding loops */
|
||||||
if (bind_port == port && (dns_ip == INADDR_ANY || dns_ip == htonl(0x7f000001L))) {
|
if (server.bind_port == server.port && (dns_ip == INADDR_ANY || dns_ip == htonl(0x7f000001L))) {
|
||||||
warnx("Forward port is same as listen port (%d), will create a loop!", bind_port);
|
warnx("Forward port is same as listen port (%d), will create a loop!", server.bind_port);
|
||||||
fprintf(stderr, "Use -l to set listen ip to avoid this.\n");
|
fprintf(stderr, "Use -l to set listen ip to avoid this.\n");
|
||||||
usage();
|
usage();
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
}
|
}
|
||||||
fprintf(stderr, "Requests for domains outside of %s will be forwarded to port %d\n",
|
fprintf(stderr, "Requests for domains outside of %s will be forwarded to port %d\n",
|
||||||
topdomain, bind_port);
|
server.topdomain, server.bind_port);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ns_get_externalip) {
|
if (ns_get_externalip) {
|
||||||
@ -486,39 +479,35 @@ main(int argc, char **argv)
|
|||||||
fprintf(stderr, "Failed to get external IP via web service.\n");
|
fprintf(stderr, "Failed to get external IP via web service.\n");
|
||||||
exit(3);
|
exit(3);
|
||||||
}
|
}
|
||||||
ns_ip = extip.s_addr;
|
server.ns_ip = extip.s_addr;
|
||||||
fprintf(stderr, "Using %s as external IP.\n", inet_ntoa(extip));
|
fprintf(stderr, "Using %s as external IP.\n", inet_ntoa(extip));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ns_ip == INADDR_NONE) {
|
if (server.ns_ip == INADDR_NONE) {
|
||||||
warnx("Bad IP address to return as nameserver.");
|
warnx("Bad IP address to return as nameserver.");
|
||||||
usage();
|
usage();
|
||||||
}
|
}
|
||||||
if (netmask > 30 || netmask < 8) {
|
if (server.netmask > 30 || server.netmask < 8) {
|
||||||
warnx("Bad netmask (%d bits). Use 8-30 bits.", netmask);
|
warnx("Bad netmask (%d bits). Use 8-30 bits.", server.netmask);
|
||||||
usage();
|
usage();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strlen(password) == 0) {
|
if (strlen(server.password) == 0) {
|
||||||
if (NULL != getenv(PASSWORD_ENV_VAR))
|
if (NULL != getenv(PASSWORD_ENV_VAR))
|
||||||
snprintf(password, sizeof(password), "%s", getenv(PASSWORD_ENV_VAR));
|
snprintf(server.password, sizeof(server.password), "%s", getenv(PASSWORD_ENV_VAR));
|
||||||
else
|
else
|
||||||
read_password(password, sizeof(password));
|
read_password(server.password, sizeof(server.password));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Mark both file descriptors as unused */
|
created_users = init_users(server.my_ip, server.netmask);
|
||||||
dns_fds.v4fd = -1;
|
|
||||||
dns_fds.v6fd = -1;
|
|
||||||
|
|
||||||
created_users = init_users(my_ip, netmask);
|
if ((server.tun_fd = open_tun(device)) == -1) {
|
||||||
|
|
||||||
if ((tun_fd = open_tun(device)) == -1) {
|
|
||||||
/* nothing to clean up, just return */
|
/* nothing to clean up, just return */
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (!skipipconfig) {
|
if (!skipipconfig) {
|
||||||
const char *other_ip = users_get_first_ip();
|
const char *other_ip = users_get_first_ip();
|
||||||
if (tun_setip(argv[0], other_ip, netmask) != 0 || tun_setmtu(mtu) != 0) {
|
if (tun_setip(argv[0], other_ip, server.netmask) != 0 || tun_setmtu(server.mtu) != 0) {
|
||||||
retval = 1;
|
retval = 1;
|
||||||
free((void*) other_ip);
|
free((void*) other_ip);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
@ -537,15 +526,15 @@ main(int argc, char **argv)
|
|||||||
dns_fds.v4fd = SD_LISTEN_FDS_START;
|
dns_fds.v4fd = SD_LISTEN_FDS_START;
|
||||||
} else {
|
} else {
|
||||||
#endif
|
#endif
|
||||||
if ((addrfamily == AF_UNSPEC || addrfamily == AF_INET) &&
|
if ((server.addrfamily == AF_UNSPEC || server.addrfamily == AF_INET) &&
|
||||||
(dns_fds.v4fd = open_dns(&dns4addr, dns4addr_len)) < 0) {
|
(server.dns_fds.v4fd = open_dns(&server.dns4addr, server.dns4addr_len)) < 0) {
|
||||||
|
|
||||||
retval = 1;
|
retval = 1;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
if ((addrfamily == AF_UNSPEC || addrfamily == AF_INET6) &&
|
if ((server.addrfamily == AF_UNSPEC || server.addrfamily == AF_INET6) &&
|
||||||
/* Set IPv6 socket to V6ONLY */
|
/* Set IPv6 socket to V6ONLY */
|
||||||
(dns_fds.v6fd = open_dns_opt(&dns6addr, dns6addr_len, 1)) < 0) {
|
(server.dns_fds.v6fd = open_dns_opt(&server.dns6addr, server.dns6addr_len, 1)) < 0) {
|
||||||
|
|
||||||
retval = 1;
|
retval = 1;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
@ -555,25 +544,23 @@ main(int argc, char **argv)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Setup dns file descriptors to get destination IP address */
|
/* Setup dns file descriptors to get destination IP address */
|
||||||
if (dns_fds.v4fd >= 0)
|
if (server.dns_fds.v4fd >= 0)
|
||||||
prepare_dns_fd(dns_fds.v4fd);
|
prepare_dns_fd(server.dns_fds.v4fd);
|
||||||
if (dns_fds.v6fd >= 0)
|
if (server.dns_fds.v6fd >= 0)
|
||||||
prepare_dns_fd(dns_fds.v6fd);
|
prepare_dns_fd(server.dns_fds.v6fd);
|
||||||
|
|
||||||
if (bind_enable) {
|
if (server.bind_enable) {
|
||||||
if ((bind_fd = open_dns_from_host(NULL, 0, AF_INET, 0)) < 0) {
|
if ((server.bind_fd = open_dns_from_host(NULL, 0, AF_INET, 0)) < 0) {
|
||||||
retval = 1;
|
retval = 1;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
my_mtu = mtu;
|
|
||||||
|
|
||||||
if (created_users < USERS) {
|
if (created_users < USERS) {
|
||||||
fprintf(stderr, "Limiting to %d simultaneous users because of netmask /%d\n",
|
fprintf(stderr, "Limiting to %d simultaneous users because of netmask /%d\n",
|
||||||
created_users, netmask);
|
created_users, server.netmask);
|
||||||
}
|
}
|
||||||
fprintf(stderr, "Listening to dns for domain %s\n", topdomain);
|
fprintf(stderr, "Listening to dns for domain %s\n", server.topdomain);
|
||||||
|
|
||||||
if (foreground == 0)
|
if (foreground == 0)
|
||||||
do_detach();
|
do_detach();
|
||||||
@ -606,18 +593,18 @@ main(int argc, char **argv)
|
|||||||
if (context != NULL)
|
if (context != NULL)
|
||||||
do_setcon(context);
|
do_setcon(context);
|
||||||
|
|
||||||
syslog(LOG_INFO, "started, listening on port %d", port);
|
syslog(LOG_INFO, "started, listening on port %d", server.port);
|
||||||
|
|
||||||
server_tunnel(tun_fd, &dns_fds, bind_fd, max_idle_time);
|
server_tunnel();
|
||||||
|
|
||||||
syslog(LOG_INFO, "stopping");
|
syslog(LOG_INFO, "stopping");
|
||||||
close_dns(bind_fd);
|
close_dns(server.bind_fd);
|
||||||
cleanup:
|
cleanup:
|
||||||
if (dns_fds.v6fd >= 0)
|
if (server.dns_fds.v6fd >= 0)
|
||||||
close_dns(dns_fds.v6fd);
|
close_dns(server.dns_fds.v6fd);
|
||||||
if (dns_fds.v4fd >= 0)
|
if (server.dns_fds.v4fd >= 0)
|
||||||
close_dns(dns_fds.v4fd);
|
close_dns(server.dns_fds.v4fd);
|
||||||
close_tun(tun_fd);
|
close_tun(server.tun_fd);
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
202
src/server.c
202
src/server.c
@ -58,47 +58,6 @@ WSADATA wsa_data;
|
|||||||
#include <err.h>
|
#include <err.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Global server variables */
|
|
||||||
int running = 1;
|
|
||||||
char *topdomain;
|
|
||||||
char password[33];
|
|
||||||
struct encoder *b32;
|
|
||||||
struct encoder *b64;
|
|
||||||
struct encoder *b64u;
|
|
||||||
struct encoder *b128;
|
|
||||||
|
|
||||||
int check_ip;
|
|
||||||
int my_mtu;
|
|
||||||
in_addr_t my_ip;
|
|
||||||
int netmask;
|
|
||||||
|
|
||||||
in_addr_t ns_ip;
|
|
||||||
|
|
||||||
int bind_port;
|
|
||||||
int debug;
|
|
||||||
|
|
||||||
void
|
|
||||||
server_init()
|
|
||||||
{
|
|
||||||
running = 1;
|
|
||||||
ns_ip = INADDR_ANY;
|
|
||||||
netmask = 27;
|
|
||||||
debug = 0;
|
|
||||||
check_ip = 1;
|
|
||||||
memset(password, 0, sizeof(password));
|
|
||||||
fw_query_init();
|
|
||||||
b32 = get_base32_encoder();
|
|
||||||
b64 = get_base64_encoder();
|
|
||||||
b64u = get_base64u_encoder();
|
|
||||||
b128 = get_base128_encoder();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
server_stop()
|
|
||||||
{
|
|
||||||
running = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
send_raw(int fd, uint8_t *buf, size_t buflen, int user, int cmd, struct sockaddr_storage *from, socklen_t fromlen)
|
send_raw(int fd, uint8_t *buf, size_t buflen, int user, int cmd, struct sockaddr_storage *from, socklen_t fromlen)
|
||||||
{
|
{
|
||||||
@ -143,7 +102,7 @@ send_raw(int fd, uint8_t *buf, size_t buflen, int user, int cmd, struct sockaddr
|
|||||||
during a session (given QMEM_LEN is not very large). */
|
during a session (given QMEM_LEN is not very large). */
|
||||||
|
|
||||||
#define QMEM_DEBUG(l, u, ...) \
|
#define QMEM_DEBUG(l, u, ...) \
|
||||||
if (debug >= l) {\
|
if (server.debug >= l) {\
|
||||||
TIMEPRINT("[QMEM u%d (%lu/%u)] ", u, users[u].qmem.num_pending, users[u].outgoing->windowsize); \
|
TIMEPRINT("[QMEM u%d (%lu/%u)] ", u, users[u].qmem.num_pending, users[u].outgoing->windowsize); \
|
||||||
fprintf(stderr, __VA_ARGS__);\
|
fprintf(stderr, __VA_ARGS__);\
|
||||||
fprintf(stderr, "\n");\
|
fprintf(stderr, "\n");\
|
||||||
@ -284,7 +243,7 @@ qmem_get_next_response(int userid)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static struct timeval
|
static struct timeval
|
||||||
qmem_max_wait(struct dnsfd *dns_fds, int *touser, struct query **sendq)
|
qmem_max_wait(int *touser, struct query **sendq)
|
||||||
/* Gets max interval before the next query has to be responded to
|
/* Gets max interval before the next query has to be responded to
|
||||||
* Response(s) are sent automatically for queries if:
|
* Response(s) are sent automatically for queries if:
|
||||||
* - the query has timed out
|
* - the query has timed out
|
||||||
@ -358,7 +317,7 @@ qmem_max_wait(struct dnsfd *dns_fds, int *touser, struct query **sendq)
|
|||||||
QMEM_DEBUG(4, userid, "ANSWER q id %d, ACK %d; sent %lu of %lu + sending another %lu",
|
QMEM_DEBUG(4, userid, "ANSWER q id %d, ACK %d; sent %lu of %lu + sending another %lu",
|
||||||
q->id, u->next_upstream_ack, sent, total, sending);
|
q->id, u->next_upstream_ack, sent, total, sending);
|
||||||
|
|
||||||
send_data_or_ping(dns_fds, userid, q, 0, immediate);
|
send_data_or_ping(userid, q, 0, immediate);
|
||||||
|
|
||||||
if (sending > 0)
|
if (sending > 0)
|
||||||
sending--;
|
sending--;
|
||||||
@ -377,7 +336,7 @@ qmem_max_wait(struct dnsfd *dns_fds, int *touser, struct query **sendq)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (debug >= 5) {
|
if (server.debug >= 5) {
|
||||||
time_t soonest_ms = timeval_to_ms(&soonest);
|
time_t soonest_ms = timeval_to_ms(&soonest);
|
||||||
if (nextq && nextuser >= 0) {
|
if (nextq && nextuser >= 0) {
|
||||||
QMEM_DEBUG(5, nextuser, "can wait for %lu ms, will send id %d", soonest_ms, nextq->id);
|
QMEM_DEBUG(5, nextuser, "can wait for %lu ms, will send id %d", soonest_ms, nextq->id);
|
||||||
@ -435,7 +394,7 @@ forward_query(int bind_fd, struct query *q)
|
|||||||
newaddr = inet_addr("127.0.0.1");
|
newaddr = inet_addr("127.0.0.1");
|
||||||
myaddr = (struct sockaddr_in *) &(q->from);
|
myaddr = (struct sockaddr_in *) &(q->from);
|
||||||
memcpy(&(myaddr->sin_addr), &newaddr, sizeof(in_addr_t));
|
memcpy(&(myaddr->sin_addr), &newaddr, sizeof(in_addr_t));
|
||||||
myaddr->sin_port = htons(bind_port);
|
myaddr->sin_port = htons(server.bind_port);
|
||||||
|
|
||||||
DEBUG(2, "TX: NS reply");
|
DEBUG(2, "TX: NS reply");
|
||||||
|
|
||||||
@ -471,8 +430,7 @@ send_version_response(int fd, version_ack_t ack, uint32_t payload, int userid, s
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
send_data_or_ping(struct dnsfd *dns_fds, int userid, struct query *q,
|
send_data_or_ping(int userid, struct query *q, int ping, int immediate)
|
||||||
int ping, int immediate)
|
|
||||||
/* Sends current fragment to user, or a ping if no data available.
|
/* Sends current fragment to user, or a ping if no data available.
|
||||||
ping: 1=force send ping (even if data available), 0=only send if no data.
|
ping: 1=force send ping (even if data available), 0=only send if no data.
|
||||||
immediate: 1=not from qmem (ie. fresh query), 0=query is from qmem */
|
immediate: 1=not from qmem (ie. fresh query), 0=query is from qmem */
|
||||||
@ -527,7 +485,7 @@ send_data_or_ping(struct dnsfd *dns_fds, int userid, struct query *q,
|
|||||||
if (f)
|
if (f)
|
||||||
memcpy(pkt + headerlen, f->data, datalen);
|
memcpy(pkt + headerlen, f->data, datalen);
|
||||||
|
|
||||||
write_dns(get_dns_fd(dns_fds, &q->from), q, (char *)pkt,
|
write_dns(get_dns_fd(&server.dns_fds, &q->from), q, (char *)pkt,
|
||||||
datalen + headerlen, users[userid].downenc);
|
datalen + headerlen, users[userid].downenc);
|
||||||
|
|
||||||
/* mark query as answered */
|
/* mark query as answered */
|
||||||
@ -536,7 +494,7 @@ send_data_or_ping(struct dnsfd *dns_fds, int userid, struct query *q,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
user_process_incoming_data(int tun_fd, struct dnsfd *dns_fds, int userid, int ack)
|
user_process_incoming_data(int userid, int ack)
|
||||||
{
|
{
|
||||||
uint8_t pkt[65536];
|
uint8_t pkt[65536];
|
||||||
size_t datalen;
|
size_t datalen;
|
||||||
@ -553,13 +511,12 @@ user_process_incoming_data(int tun_fd, struct dnsfd *dns_fds, int userid, int ac
|
|||||||
|
|
||||||
if (datalen > 0) {
|
if (datalen > 0) {
|
||||||
/* Data reassembled successfully + cleared out of buffer */
|
/* Data reassembled successfully + cleared out of buffer */
|
||||||
handle_full_packet(tun_fd, dns_fds, userid, pkt, datalen, compressed);
|
handle_full_packet(userid, pkt, datalen, compressed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
user_send_data(int userid, struct dnsfd *dns_fds, uint8_t *indata,
|
user_send_data(int userid, uint8_t *indata, size_t len, int compressed)
|
||||||
size_t len, int compressed)
|
|
||||||
/* Appends data to a user's outgoing queue and sends it (in raw mode only) */
|
/* Appends data to a user's outgoing queue and sends it (in raw mode only) */
|
||||||
{
|
{
|
||||||
size_t datalen;
|
size_t datalen;
|
||||||
@ -592,7 +549,7 @@ user_send_data(int userid, struct dnsfd *dns_fds, uint8_t *indata,
|
|||||||
} else if (data && datalen) { /* CONN_RAW_UDP */
|
} else if (data && datalen) { /* CONN_RAW_UDP */
|
||||||
if (!compressed)
|
if (!compressed)
|
||||||
DEBUG(1, "Sending in RAW mode uncompressed to user %d!", userid);
|
DEBUG(1, "Sending in RAW mode uncompressed to user %d!", userid);
|
||||||
int dns_fd = get_dns_fd(dns_fds, &users[userid].host);
|
int dns_fd = get_dns_fd(&server.dns_fds, &users[userid].host);
|
||||||
send_raw(dns_fd, data, datalen, userid, RAW_HDR_CMD_DATA,
|
send_raw(dns_fd, data, datalen, userid, RAW_HDR_CMD_DATA,
|
||||||
&users[userid].host, users[userid].hostlen);
|
&users[userid].host, users[userid].hostlen);
|
||||||
ret = 1;
|
ret = 1;
|
||||||
@ -602,7 +559,7 @@ user_send_data(int userid, struct dnsfd *dns_fds, uint8_t *indata,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
tunnel_bind(int bind_fd, struct dnsfd *dns_fds)
|
tunnel_bind()
|
||||||
{
|
{
|
||||||
char packet[64*1024];
|
char packet[64*1024];
|
||||||
struct sockaddr_storage from;
|
struct sockaddr_storage from;
|
||||||
@ -613,7 +570,7 @@ tunnel_bind(int bind_fd, struct dnsfd *dns_fds)
|
|||||||
int r;
|
int r;
|
||||||
|
|
||||||
fromlen = sizeof(struct sockaddr);
|
fromlen = sizeof(struct sockaddr);
|
||||||
r = recvfrom(bind_fd, packet, sizeof(packet), 0,
|
r = recvfrom(server.bind_fd, packet, sizeof(packet), 0,
|
||||||
(struct sockaddr*)&from, &fromlen);
|
(struct sockaddr*)&from, &fromlen);
|
||||||
|
|
||||||
if (r <= 0)
|
if (r <= 0)
|
||||||
@ -633,7 +590,7 @@ tunnel_bind(int bind_fd, struct dnsfd *dns_fds)
|
|||||||
DEBUG(3, "TX: client %s id %u, %d bytes",
|
DEBUG(3, "TX: client %s id %u, %d bytes",
|
||||||
format_addr(&query->addr, query->addrlen), (id & 0xffff), r);
|
format_addr(&query->addr, query->addrlen), (id & 0xffff), r);
|
||||||
|
|
||||||
dns_fd = get_dns_fd(dns_fds, &query->addr);
|
dns_fd = get_dns_fd(&server.dns_fds, &query->addr);
|
||||||
if (sendto(dns_fd, packet, r, 0, (const struct sockaddr *) &(query->addr),
|
if (sendto(dns_fd, packet, r, 0, (const struct sockaddr *) &(query->addr),
|
||||||
query->addrlen) <= 0) {
|
query->addrlen) <= 0) {
|
||||||
warn("forward reply error");
|
warn("forward reply error");
|
||||||
@ -643,14 +600,14 @@ tunnel_bind(int bind_fd, struct dnsfd *dns_fds)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
tunnel_tun(int tun_fd, struct dnsfd *dns_fds)
|
tunnel_tun()
|
||||||
{
|
{
|
||||||
struct ip *header;
|
struct ip *header;
|
||||||
static uint8_t in[64*1024];
|
static uint8_t in[64*1024];
|
||||||
int userid;
|
int userid;
|
||||||
int read;
|
int read;
|
||||||
|
|
||||||
if ((read = read_tun(tun_fd, in, sizeof(in))) <= 0)
|
if ((read = read_tun(server.tun_fd, in, sizeof(in))) <= 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* find target ip in packet, in is padded with 4 bytes TUN header */
|
/* find target ip in packet, in is padded with 4 bytes TUN header */
|
||||||
@ -662,25 +619,25 @@ tunnel_tun(int tun_fd, struct dnsfd *dns_fds)
|
|||||||
DEBUG(3, "IN: %d byte pkt from tun to user %d; compression %d",
|
DEBUG(3, "IN: %d byte pkt from tun to user %d; compression %d",
|
||||||
read, userid, users[userid].down_compression);
|
read, userid, users[userid].down_compression);
|
||||||
|
|
||||||
return user_send_data(userid, dns_fds, in, read, 0);
|
return user_send_data(userid, in, read, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
tunnel_dns(int tun_fd, int dns_fd, struct dnsfd *dns_fds, int bind_fd)
|
tunnel_dns(int dns_fd)
|
||||||
{
|
{
|
||||||
struct query q;
|
struct query q;
|
||||||
int read;
|
int read;
|
||||||
int domain_len;
|
int domain_len;
|
||||||
int inside_topdomain = 0;
|
int inside_topdomain = 0;
|
||||||
|
|
||||||
if ((read = read_dns(dns_fd, dns_fds, tun_fd, &q)) <= 0)
|
if ((read = read_dns(dns_fd, &q)) <= 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
DEBUG(3, "RX: client %s ID %5d, type %d, name %s",
|
DEBUG(3, "RX: client %s ID %5d, type %d, name %s",
|
||||||
format_addr(&q.from, q.fromlen), q.id, q.type, q.name);
|
format_addr(&q.from, q.fromlen), q.id, q.type, q.name);
|
||||||
|
|
||||||
domain_len = strlen(q.name) - strlen(topdomain);
|
domain_len = strlen(q.name) - strlen(server.topdomain);
|
||||||
if (domain_len >= 0 && !strcasecmp(q.name + domain_len, topdomain))
|
if (domain_len >= 0 && !strcasecmp(q.name + domain_len, server.topdomain))
|
||||||
inside_topdomain = 1;
|
inside_topdomain = 1;
|
||||||
/* require dot before topdomain */
|
/* require dot before topdomain */
|
||||||
if (domain_len >= 1 && q.name[domain_len - 1] != '.')
|
if (domain_len >= 1 && q.name[domain_len - 1] != '.')
|
||||||
@ -719,7 +676,7 @@ tunnel_dns(int tun_fd, int dns_fd, struct dnsfd *dns_fds, int bind_fd)
|
|||||||
case T_SRV:
|
case T_SRV:
|
||||||
case T_TXT:
|
case T_TXT:
|
||||||
/* encoding is "transparent" here */
|
/* encoding is "transparent" here */
|
||||||
handle_null_request(tun_fd, dns_fd, dns_fds, &q, domain_len);
|
handle_null_request(dns_fd, &q, domain_len);
|
||||||
break;
|
break;
|
||||||
case T_NS:
|
case T_NS:
|
||||||
handle_ns_request(dns_fd, &q);
|
handle_ns_request(dns_fd, &q);
|
||||||
@ -730,15 +687,15 @@ tunnel_dns(int tun_fd, int dns_fd, struct dnsfd *dns_fds, int bind_fd)
|
|||||||
} else {
|
} else {
|
||||||
/* Forward query to other port ? */
|
/* Forward query to other port ? */
|
||||||
DEBUG(2, "Requested domain outside our topdomain.");
|
DEBUG(2, "Requested domain outside our topdomain.");
|
||||||
if (bind_fd) {
|
if (server.bind_fd) {
|
||||||
forward_query(bind_fd, &q);
|
forward_query(server.bind_fd, &q);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
server_tunnel(int tun_fd, struct dnsfd *dns_fds, int bind_fd, int max_idle_time)
|
server_tunnel()
|
||||||
{
|
{
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
fd_set fds;
|
fd_set fds;
|
||||||
@ -747,72 +704,72 @@ server_tunnel(int tun_fd, struct dnsfd *dns_fds, int bind_fd, int max_idle_time)
|
|||||||
struct query *answer_now = NULL;
|
struct query *answer_now = NULL;
|
||||||
time_t last_action = time(NULL);
|
time_t last_action = time(NULL);
|
||||||
|
|
||||||
if (debug >= 5)
|
if (server.debug >= 5)
|
||||||
window_debug = debug - 3;
|
window_debug = server.debug - 3;
|
||||||
|
|
||||||
while (running) {
|
while (server.running) {
|
||||||
int maxfd;
|
int maxfd;
|
||||||
/* max wait time based on pending queries */
|
/* max wait time based on pending queries */
|
||||||
tv = qmem_max_wait(dns_fds, &userid, &answer_now);
|
tv = qmem_max_wait(&userid, &answer_now);
|
||||||
|
|
||||||
FD_ZERO(&fds);
|
FD_ZERO(&fds);
|
||||||
maxfd = 0;
|
maxfd = 0;
|
||||||
|
|
||||||
if (dns_fds->v4fd >= 0) {
|
if (server.dns_fds.v4fd >= 0) {
|
||||||
FD_SET(dns_fds->v4fd, &fds);
|
FD_SET(server.dns_fds.v4fd, &fds);
|
||||||
maxfd = MAX(dns_fds->v4fd, maxfd);
|
maxfd = MAX(server.dns_fds.v4fd, maxfd);
|
||||||
}
|
}
|
||||||
if (dns_fds->v6fd >= 0) {
|
if (server.dns_fds.v6fd >= 0) {
|
||||||
FD_SET(dns_fds->v6fd, &fds);
|
FD_SET(server.dns_fds.v6fd, &fds);
|
||||||
maxfd = MAX(dns_fds->v6fd, maxfd);
|
maxfd = MAX(server.dns_fds.v6fd, maxfd);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bind_fd) {
|
if (server.bind_fd) {
|
||||||
/* wait for replies from real DNS */
|
/* wait for replies from real DNS */
|
||||||
FD_SET(bind_fd, &fds);
|
FD_SET(server.bind_fd, &fds);
|
||||||
maxfd = MAX(bind_fd, maxfd);
|
maxfd = MAX(server.bind_fd, maxfd);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Don't read from tun if all users have filled outpacket queues */
|
/* Don't read from tun if all users have filled outpacket queues */
|
||||||
if(!all_users_waiting_to_send()) {
|
if(!all_users_waiting_to_send()) {
|
||||||
FD_SET(tun_fd, &fds);
|
FD_SET(server.tun_fd, &fds);
|
||||||
maxfd = MAX(tun_fd, maxfd);
|
maxfd = MAX(server.tun_fd, maxfd);
|
||||||
}
|
}
|
||||||
|
|
||||||
i = select(maxfd + 1, &fds, NULL, NULL, &tv);
|
i = select(maxfd + 1, &fds, NULL, NULL, &tv);
|
||||||
|
|
||||||
if(i < 0) {
|
if(i < 0) {
|
||||||
if (running)
|
if (server.running)
|
||||||
warn("select");
|
warn("select");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
if (max_idle_time) {
|
if (server.max_idle_time) {
|
||||||
/* only trigger the check if that's worth ( ie, no need to loop over if there
|
/* only trigger the check if that's worth ( ie, no need to loop over if there
|
||||||
is something to send */
|
is something to send */
|
||||||
if (difftime(time(NULL), last_action) > max_idle_time) {
|
if (difftime(time(NULL), last_action) > server.max_idle_time) {
|
||||||
for (userid = 0; userid < created_users; userid++) {
|
for (userid = 0; userid < created_users; userid++) {
|
||||||
last_action = (users[userid].last_pkt > last_action) ? users[userid].last_pkt : last_action;
|
last_action = (users[userid].last_pkt > last_action) ? users[userid].last_pkt : last_action;
|
||||||
}
|
}
|
||||||
if (difftime(time(NULL), last_action) > max_idle_time) {
|
if (difftime(time(NULL), last_action) > server.max_idle_time) {
|
||||||
fprintf(stderr, "Server idle for too long, shutting down...\n");
|
fprintf(stderr, "Server idle for too long, shutting down...\n");
|
||||||
running = 0;
|
server.running = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (FD_ISSET(tun_fd, &fds)) {
|
if (FD_ISSET(server.tun_fd, &fds)) {
|
||||||
tunnel_tun(tun_fd, dns_fds);
|
tunnel_tun();
|
||||||
}
|
}
|
||||||
if (FD_ISSET(dns_fds->v4fd, &fds)) {
|
if (FD_ISSET(server.dns_fds.v4fd, &fds)) {
|
||||||
tunnel_dns(tun_fd, dns_fds->v4fd, dns_fds, bind_fd);
|
tunnel_dns(server.dns_fds.v4fd);
|
||||||
}
|
}
|
||||||
if (FD_ISSET(dns_fds->v6fd, &fds)) {
|
if (FD_ISSET(server.dns_fds.v6fd, &fds)) {
|
||||||
tunnel_dns(tun_fd, dns_fds->v6fd, dns_fds, bind_fd);
|
tunnel_dns(server.dns_fds.v6fd);
|
||||||
}
|
}
|
||||||
if (FD_ISSET(bind_fd, &fds)) {
|
if (FD_ISSET(server.bind_fd, &fds)) {
|
||||||
tunnel_bind(bind_fd, dns_fds);
|
tunnel_bind();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -821,7 +778,7 @@ server_tunnel(int tun_fd, struct dnsfd *dns_fds, int bind_fd, int max_idle_time)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
handle_full_packet(int tun_fd, struct dnsfd *dns_fds, int userid, uint8_t *data, size_t len, int compressed)
|
handle_full_packet(int userid, uint8_t *data, size_t len, int compressed)
|
||||||
{
|
{
|
||||||
size_t rawlen;
|
size_t rawlen;
|
||||||
uint8_t out[64*1024], *rawdata;
|
uint8_t out[64*1024], *rawdata;
|
||||||
@ -846,13 +803,13 @@ handle_full_packet(int tun_fd, struct dnsfd *dns_fds, int userid, uint8_t *data,
|
|||||||
DEBUG(2, "FULL PKT: %lu bytes from user %d (touser %d)", len, userid, touser);
|
DEBUG(2, "FULL PKT: %lu bytes from user %d (touser %d)", len, userid, touser);
|
||||||
if (touser == -1) {
|
if (touser == -1) {
|
||||||
/* send the uncompressed packet to tun device */
|
/* send the uncompressed packet to tun device */
|
||||||
write_tun(tun_fd, rawdata, rawlen);
|
write_tun(server.tun_fd, rawdata, rawlen);
|
||||||
} else {
|
} else {
|
||||||
/* don't re-compress if possible */
|
/* don't re-compress if possible */
|
||||||
if (users[touser].down_compression && compressed) {
|
if (users[touser].down_compression && compressed) {
|
||||||
user_send_data(touser, dns_fds, data, len, 1);
|
user_send_data(touser, data, len, 1);
|
||||||
} else {
|
} else {
|
||||||
user_send_data(touser, dns_fds, rawdata, rawlen, 0);
|
user_send_data(touser, rawdata, rawlen, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -879,7 +836,7 @@ handle_raw_login(uint8_t *packet, size_t len, struct query *q, int fd, int useri
|
|||||||
DEBUG(1, "RX-raw: login, len %lu, from user %d", len, userid);
|
DEBUG(1, "RX-raw: login, len %lu, from user %d", len, userid);
|
||||||
|
|
||||||
/* User sends hash of seed + 1 */
|
/* User sends hash of seed + 1 */
|
||||||
login_calculate(myhash, 16, password, users[userid].seed + 1);
|
login_calculate(myhash, 16, server.password, users[userid].seed + 1);
|
||||||
if (memcmp(packet, myhash, 16) == 0) {
|
if (memcmp(packet, myhash, 16) == 0) {
|
||||||
/* Update time info for user */
|
/* Update time info for user */
|
||||||
users[userid].last_pkt = time(NULL);
|
users[userid].last_pkt = time(NULL);
|
||||||
@ -890,7 +847,7 @@ handle_raw_login(uint8_t *packet, size_t len, struct query *q, int fd, int useri
|
|||||||
|
|
||||||
/* Correct hash, reply with hash of seed - 1 */
|
/* Correct hash, reply with hash of seed - 1 */
|
||||||
user_set_conn_type(userid, CONN_RAW_UDP);
|
user_set_conn_type(userid, CONN_RAW_UDP);
|
||||||
login_calculate(myhash, 16, password, users[userid].seed - 1);
|
login_calculate(myhash, 16, server.password, users[userid].seed - 1);
|
||||||
send_raw(fd, (uint8_t *)myhash, 16, userid, RAW_HDR_CMD_LOGIN, &q->from, q->fromlen);
|
send_raw(fd, (uint8_t *)myhash, 16, userid, RAW_HDR_CMD_LOGIN, &q->from, q->fromlen);
|
||||||
|
|
||||||
users[userid].authenticated_raw = 1;
|
users[userid].authenticated_raw = 1;
|
||||||
@ -898,7 +855,7 @@ handle_raw_login(uint8_t *packet, size_t len, struct query *q, int fd, int useri
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
handle_raw_data(uint8_t *packet, size_t len, struct query *q, struct dnsfd *dns_fds, int tun_fd, int userid)
|
handle_raw_data(uint8_t *packet, size_t len, struct query *q, int userid)
|
||||||
{
|
{
|
||||||
if (check_authenticated_user_and_ip(userid, q) != 0) {
|
if (check_authenticated_user_and_ip(userid, q) != 0) {
|
||||||
return;
|
return;
|
||||||
@ -912,7 +869,7 @@ handle_raw_data(uint8_t *packet, size_t len, struct query *q, struct dnsfd *dns_
|
|||||||
|
|
||||||
DEBUG(3, "RX-raw: full pkt raw, length %lu, from user %d", len, userid);
|
DEBUG(3, "RX-raw: full pkt raw, length %lu, from user %d", len, userid);
|
||||||
|
|
||||||
handle_full_packet(tun_fd, dns_fds, userid, packet, len, 1);
|
handle_full_packet(userid, packet, len, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -933,7 +890,7 @@ handle_raw_ping(struct query *q, int dns_fd, int userid)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
raw_decode(uint8_t *packet, size_t len, struct query *q, int dns_fd, struct dnsfd *dns_fds, int tun_fd)
|
raw_decode(uint8_t *packet, size_t len, struct query *q, int dns_fd)
|
||||||
{
|
{
|
||||||
int raw_user;
|
int raw_user;
|
||||||
uint8_t raw_cmd;
|
uint8_t raw_cmd;
|
||||||
@ -959,7 +916,7 @@ raw_decode(uint8_t *packet, size_t len, struct query *q, int dns_fd, struct dnsf
|
|||||||
break;
|
break;
|
||||||
case RAW_HDR_CMD_DATA:
|
case RAW_HDR_CMD_DATA:
|
||||||
/* Data packet */
|
/* Data packet */
|
||||||
handle_raw_data(packet, len, q, dns_fds, tun_fd, raw_user);
|
handle_raw_data(packet, len, q, raw_user);
|
||||||
break;
|
break;
|
||||||
case RAW_HDR_CMD_PING:
|
case RAW_HDR_CMD_PING:
|
||||||
/* Keepalive packet */
|
/* Keepalive packet */
|
||||||
@ -973,8 +930,7 @@ raw_decode(uint8_t *packet, size_t len, struct query *q, int dns_fd, struct dnsf
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
read_dns(int fd, struct dnsfd *dns_fds, int tun_fd, struct query *q)
|
read_dns(int fd, struct query *q)
|
||||||
/* FIXME: dns_fds and tun_fd are because of raw_decode() below */
|
|
||||||
{
|
{
|
||||||
struct sockaddr_storage from;
|
struct sockaddr_storage from;
|
||||||
socklen_t addrlen;
|
socklen_t addrlen;
|
||||||
@ -1010,7 +966,7 @@ read_dns(int fd, struct dnsfd *dns_fds, int tun_fd, struct query *q)
|
|||||||
gettimeofday(&q->time_recv, NULL);
|
gettimeofday(&q->time_recv, NULL);
|
||||||
|
|
||||||
/* TODO do not handle raw packets here! */
|
/* TODO do not handle raw packets here! */
|
||||||
if (raw_decode(packet, r, q, fd, dns_fds, tun_fd)) {
|
if (raw_decode(packet, r, q, fd)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (dns_decode(NULL, 0, q, QR_QUERY, (char *)packet, r) < 0) {
|
if (dns_decode(NULL, 0, q, QR_QUERY, (char *)packet, r) < 0) {
|
||||||
@ -1173,7 +1129,7 @@ write_dns(int fd, struct query *q, char *data, size_t datalen, char downenc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
handle_null_request(int tun_fd, int dns_fd, struct dnsfd *dns_fds, struct query *q, int domain_len)
|
handle_null_request(int dns_fd, struct query *q, int domain_len)
|
||||||
/* Handles a NULL DNS request. See doc/proto_XXXXXXXX.txt for details on iodine protocol. */
|
/* Handles a NULL DNS request. See doc/proto_XXXXXXXX.txt for details on iodine protocol. */
|
||||||
{
|
{
|
||||||
struct in_addr tempip;
|
struct in_addr tempip;
|
||||||
@ -1269,20 +1225,20 @@ handle_null_request(int tun_fd, int dns_fd, struct dnsfd *dns_fds, struct query
|
|||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
users[userid].last_pkt = time(NULL);
|
users[userid].last_pkt = time(NULL);
|
||||||
login_calculate(logindata, 16, password, users[userid].seed);
|
login_calculate(logindata, 16, server.password, users[userid].seed);
|
||||||
|
|
||||||
if (read >= 18 && (memcmp(logindata, unpacked + 1, 16) == 0)) {
|
if (read >= 18 && (memcmp(logindata, unpacked + 1, 16) == 0)) {
|
||||||
/* Store login ok */
|
/* Store login ok */
|
||||||
users[userid].authenticated = 1;
|
users[userid].authenticated = 1;
|
||||||
|
|
||||||
/* Send ip/mtu/netmask info */
|
/* Send ip/mtu/netmask info */
|
||||||
tempip.s_addr = my_ip;
|
tempip.s_addr = server.my_ip;
|
||||||
tmp[0] = strdup(inet_ntoa(tempip));
|
tmp[0] = strdup(inet_ntoa(tempip));
|
||||||
tempip.s_addr = users[userid].tun_ip;
|
tempip.s_addr = users[userid].tun_ip;
|
||||||
tmp[1] = strdup(inet_ntoa(tempip));
|
tmp[1] = strdup(inet_ntoa(tempip));
|
||||||
|
|
||||||
read = snprintf((char *)out, sizeof(out), "%s-%s-%d-%d",
|
read = snprintf((char *)out, sizeof(out), "%s-%s-%d-%d",
|
||||||
tmp[0], tmp[1], my_mtu, netmask);
|
tmp[0], tmp[1], server.mtu, server.netmask);
|
||||||
|
|
||||||
write_dns(dns_fd, q, (char *)out, read, users[userid].downenc);
|
write_dns(dns_fd, q, (char *)out, read, users[userid].downenc);
|
||||||
syslog(LOG_NOTICE, "accepted password from user #%d, given IP %s", userid, tmp[1]);
|
syslog(LOG_NOTICE, "accepted password from user #%d, given IP %s", userid, tmp[1]);
|
||||||
@ -1308,9 +1264,9 @@ handle_null_request(int tun_fd, int dns_fd, struct dnsfd *dns_fds, struct query
|
|||||||
|
|
||||||
reply[0] = 'I';
|
reply[0] = 'I';
|
||||||
if (q->from.ss_family == AF_INET) {
|
if (q->from.ss_family == AF_INET) {
|
||||||
if (ns_ip != INADDR_ANY) {
|
if (server.ns_ip != INADDR_ANY) {
|
||||||
/* If set, use assigned external ip (-n option) */
|
/* If set, use assigned external ip (-n option) */
|
||||||
memcpy(&reply[1], &ns_ip, sizeof(ns_ip));
|
memcpy(&reply[1], &server.ns_ip, sizeof(server.ns_ip));
|
||||||
} else {
|
} else {
|
||||||
/* otherwise return destination ip from packet */
|
/* otherwise return destination ip from packet */
|
||||||
struct sockaddr_in *addr = (struct sockaddr_in *) &q->destination;
|
struct sockaddr_in *addr = (struct sockaddr_in *) &q->destination;
|
||||||
@ -1647,11 +1603,11 @@ handle_null_request(int tun_fd, int dns_fd, struct dnsfd *dns_fds, struct query
|
|||||||
users[userid].outgoing->windowsize, dn_winsize, users[userid].incoming->windowsize, up_winsize);
|
users[userid].outgoing->windowsize, dn_winsize, users[userid].incoming->windowsize, up_winsize);
|
||||||
users[userid].outgoing->windowsize = dn_winsize;
|
users[userid].outgoing->windowsize = dn_winsize;
|
||||||
users[userid].incoming->windowsize = up_winsize;
|
users[userid].incoming->windowsize = up_winsize;
|
||||||
send_data_or_ping(dns_fds, userid, q, 1, 1);
|
send_data_or_ping(userid, q, 1, 1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
user_process_incoming_data(tun_fd, dns_fds, userid, dn_ack);
|
user_process_incoming_data(userid, dn_ack);
|
||||||
|
|
||||||
/* if respond flag not set, query waits in qmem and is used later */
|
/* if respond flag not set, query waits in qmem and is used later */
|
||||||
} else if (isxdigit(in[0])) { /* Upstream data packet */
|
} else if (isxdigit(in[0])) { /* Upstream data packet */
|
||||||
@ -1712,7 +1668,7 @@ handle_null_request(int tun_fd, int dns_fd, struct dnsfd *dns_fds, struct query
|
|||||||
window_process_incoming_fragment(users[userid].incoming, &f);
|
window_process_incoming_fragment(users[userid].incoming, &f);
|
||||||
users[userid].next_upstream_ack = f.seqID;
|
users[userid].next_upstream_ack = f.seqID;
|
||||||
|
|
||||||
user_process_incoming_data(tun_fd, dns_fds, userid, f.ack_other);
|
user_process_incoming_data(userid, f.ack_other);
|
||||||
|
|
||||||
/* Nothing to do. ACK for this fragment is sent later in qmem_max_wait,
|
/* Nothing to do. ACK for this fragment is sent later in qmem_max_wait,
|
||||||
* using an old query. This is left in qmem until needed/times out */
|
* using an old query. This is left in qmem until needed/times out */
|
||||||
@ -1727,14 +1683,14 @@ handle_ns_request(int dns_fd, struct query *q)
|
|||||||
char buf[64*1024];
|
char buf[64*1024];
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
if (ns_ip != INADDR_ANY) {
|
if (server.ns_ip != INADDR_ANY) {
|
||||||
/* If ns_ip set, overwrite destination addr with it.
|
/* If ns_ip set, overwrite destination addr with it.
|
||||||
* Destination addr will be sent as additional record (A, IN) */
|
* Destination addr will be sent as additional record (A, IN) */
|
||||||
struct sockaddr_in *addr = (struct sockaddr_in *) &q->destination;
|
struct sockaddr_in *addr = (struct sockaddr_in *) &q->destination;
|
||||||
memcpy(&addr->sin_addr, &ns_ip, sizeof(ns_ip));
|
memcpy(&addr->sin_addr, &server.ns_ip, sizeof(server.ns_ip));
|
||||||
}
|
}
|
||||||
|
|
||||||
len = dns_encode_ns_response(buf, sizeof(buf), q, topdomain);
|
len = dns_encode_ns_response(buf, sizeof(buf), q, server.topdomain);
|
||||||
if (len < 1) {
|
if (len < 1) {
|
||||||
warnx("dns_encode_ns_response doesn't fit");
|
warnx("dns_encode_ns_response doesn't fit");
|
||||||
return;
|
return;
|
||||||
@ -1759,11 +1715,11 @@ handle_a_request(int dns_fd, struct query *q, int fakeip)
|
|||||||
struct sockaddr_in *addr = (struct sockaddr_in *) &q->destination;
|
struct sockaddr_in *addr = (struct sockaddr_in *) &q->destination;
|
||||||
memcpy(&addr->sin_addr, &ip, sizeof(ip));
|
memcpy(&addr->sin_addr, &ip, sizeof(ip));
|
||||||
|
|
||||||
} else if (ns_ip != INADDR_ANY) {
|
} else if (server.ns_ip != INADDR_ANY) {
|
||||||
/* If ns_ip set, overwrite destination addr with it.
|
/* If ns_ip set, overwrite destination addr with it.
|
||||||
* Destination addr will be sent as additional record (A, IN) */
|
* Destination addr will be sent as additional record (A, IN) */
|
||||||
struct sockaddr_in *addr = (struct sockaddr_in *) &q->destination;
|
struct sockaddr_in *addr = (struct sockaddr_in *) &q->destination;
|
||||||
memcpy(&addr->sin_addr, &ns_ip, sizeof(ns_ip));
|
memcpy(&addr->sin_addr, &server.ns_ip, sizeof(server.ns_ip));
|
||||||
}
|
}
|
||||||
|
|
||||||
len = dns_encode_a_response(buf, sizeof(buf), q);
|
len = dns_encode_a_response(buf, sizeof(buf), q);
|
||||||
|
63
src/server.h
63
src/server.h
@ -40,7 +40,7 @@
|
|||||||
|
|
||||||
/* Max number of incoming queries to hold at one time (recommended to be same as windowsize)
|
/* Max number of incoming queries to hold at one time (recommended to be same as windowsize)
|
||||||
* Memory = USERS * (sizeof(struct query_buffer) + sizeof(query) * QMEM_LEN) */
|
* Memory = USERS * (sizeof(struct query_buffer) + sizeof(query) * QMEM_LEN) */
|
||||||
#define QMEM_LEN 24
|
#define QMEM_LEN 32
|
||||||
|
|
||||||
#define USE_DNSCACHE
|
#define USE_DNSCACHE
|
||||||
/* QMEM entries contain additional space for DNS responses.
|
/* QMEM entries contain additional space for DNS responses.
|
||||||
@ -57,6 +57,8 @@
|
|||||||
|
|
||||||
#define PASSWORD_ENV_VAR "IODINED_PASS"
|
#define PASSWORD_ENV_VAR "IODINED_PASS"
|
||||||
|
|
||||||
|
#define INSTANCE server
|
||||||
|
|
||||||
#if defined IP_RECVDSTADDR
|
#if defined IP_RECVDSTADDR
|
||||||
# define DSTADDR_SOCKOPT IP_RECVDSTADDR
|
# define DSTADDR_SOCKOPT IP_RECVDSTADDR
|
||||||
# define dstaddr(x) ((struct in_addr *) CMSG_DATA(x))
|
# define dstaddr(x) ((struct in_addr *) CMSG_DATA(x))
|
||||||
@ -82,6 +84,38 @@ struct dnsfd {
|
|||||||
int v6fd;
|
int v6fd;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct server_instance {
|
||||||
|
/* Global server variables */
|
||||||
|
int running;
|
||||||
|
char *topdomain;
|
||||||
|
char password[33];
|
||||||
|
int check_ip;
|
||||||
|
int my_mtu;
|
||||||
|
in_addr_t my_ip;
|
||||||
|
int netmask;
|
||||||
|
in_addr_t ns_ip;
|
||||||
|
int bind_port;
|
||||||
|
int debug;
|
||||||
|
|
||||||
|
int addrfamily;
|
||||||
|
struct dnsfd dns_fds;
|
||||||
|
int tun_fd;
|
||||||
|
int port;
|
||||||
|
int mtu;
|
||||||
|
int max_idle_time;
|
||||||
|
struct sockaddr_storage dns4addr;
|
||||||
|
int dns4addr_len;
|
||||||
|
struct sockaddr_storage dns6addr;
|
||||||
|
int dns6addr_len;
|
||||||
|
|
||||||
|
/* settings for forwarding normal DNS to
|
||||||
|
* local real DNS server */
|
||||||
|
int bind_fd;
|
||||||
|
int bind_enable;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct server_instance server;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
VERSION_ACK,
|
VERSION_ACK,
|
||||||
VERSION_NACK,
|
VERSION_NACK,
|
||||||
@ -110,34 +144,17 @@ struct qmem_buffer {
|
|||||||
size_t num_pending; /* number of pending queries */
|
size_t num_pending; /* number of pending queries */
|
||||||
};
|
};
|
||||||
|
|
||||||
extern char *topdomain;
|
|
||||||
extern char password[33];
|
|
||||||
extern struct encoder *b32;
|
|
||||||
extern struct encoder *b64;
|
|
||||||
extern struct encoder *b64u;
|
|
||||||
extern struct encoder *b128;
|
|
||||||
|
|
||||||
extern int check_ip;
|
|
||||||
extern int my_mtu;
|
|
||||||
extern in_addr_t my_ip;
|
|
||||||
extern int netmask;
|
|
||||||
|
|
||||||
extern in_addr_t ns_ip;
|
|
||||||
|
|
||||||
extern int bind_port;
|
|
||||||
extern int debug;
|
|
||||||
|
|
||||||
void server_init();
|
void server_init();
|
||||||
void server_stop();
|
void server_stop();
|
||||||
int server_tunnel(int tun_fd, struct dnsfd *dns_fds, int bind_fd, int max_idle_time);
|
int server_tunnel();
|
||||||
|
|
||||||
int read_dns(int fd, struct dnsfd *dns_fds, int tun_fd, struct query *q);
|
int read_dns(int fd, struct query *q);
|
||||||
void write_dns(int fd, struct query *q, char *data, size_t datalen, char downenc);
|
void write_dns(int fd, struct query *q, char *data, size_t datalen, char downenc);
|
||||||
void handle_full_packet(int tun_fd, struct dnsfd *dns_fds, int userid, uint8_t *data, size_t len, int);
|
void handle_full_packet(int userid, uint8_t *data, size_t len, int);
|
||||||
void handle_null_request(int tun_fd, int dns_fd, struct dnsfd *dns_fds, struct query *q, int domain_len);
|
void handle_null_request(int dns_fd, struct query *q, int domain_len);
|
||||||
void handle_ns_request(int dns_fd, struct query *q);
|
void handle_ns_request(int dns_fd, struct query *q);
|
||||||
void handle_a_request(int dns_fd, struct query *q, int fakeip);
|
void handle_a_request(int dns_fd, struct query *q, int fakeip);
|
||||||
|
|
||||||
void send_data_or_ping(struct dnsfd *, int, struct query *, int, int);
|
void send_data_or_ping(int, struct query *, int, int);
|
||||||
|
|
||||||
#endif /* __SERVER_H__ */
|
#endif /* __SERVER_H__ */
|
||||||
|
@ -78,7 +78,7 @@ init_users(in_addr_t my_ip, int netbits)
|
|||||||
snprintf(newip, sizeof(newip), "0.0.0.%d", i + skip + 1);
|
snprintf(newip, sizeof(newip), "0.0.0.%d", i + skip + 1);
|
||||||
ip = ipstart.s_addr + inet_addr(newip);
|
ip = ipstart.s_addr + inet_addr(newip);
|
||||||
}
|
}
|
||||||
if (debug >= 2) {
|
if (server.debug >= 2) {
|
||||||
struct in_addr IP;
|
struct in_addr IP;
|
||||||
IP.s_addr = ip;
|
IP.s_addr = ip;
|
||||||
DEBUG(2, "User %d: IP %s", i, inet_ntoa(IP));
|
DEBUG(2, "User %d: IP %s", i, inet_ntoa(IP));
|
||||||
@ -201,7 +201,7 @@ check_user_and_ip(int userid, struct query *q)
|
|||||||
if (!user_active(userid)) return 1;
|
if (!user_active(userid)) return 1;
|
||||||
|
|
||||||
/* return early if IP checking is disabled */
|
/* return early if IP checking is disabled */
|
||||||
if (!check_ip) {
|
if (!server.check_ip) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user