mirror of
https://github.com/yarrick/iodine.git
synced 2024-11-28 20:45:12 +00:00
A little bit of refactoring - separated iodined.c into separate files
Fixed up client side compile issues Removed old packet handling code - TODO: use sliding window buffer instead
This commit is contained in:
parent
83f70608fc
commit
844abefcf8
@ -1,7 +1,7 @@
|
|||||||
COMMONOBJS = tun.o dns.o read.o encoding.o login.o base32.o base64.o base64u.o base128.o md5.o window.o common.o
|
COMMONOBJS = tun.o dns.o read.o encoding.o login.o base32.o base64.o base64u.o base128.o md5.o window.o common.o
|
||||||
CLIENTOBJS = iodine.o client.o util.o
|
CLIENTOBJS = iodine.o client.o util.o
|
||||||
CLIENT = ../bin/iodine
|
CLIENT = ../bin/iodine
|
||||||
SERVEROBJS = iodined.o user.o fw_query.o
|
SERVEROBJS = iodined.o user.o fw_query.o server.o
|
||||||
SERVER = ../bin/iodined
|
SERVER = ../bin/iodined
|
||||||
|
|
||||||
OS = `echo $(TARGETOS) | tr "a-z" "A-Z"`
|
OS = `echo $(TARGETOS) | tr "a-z" "A-Z"`
|
||||||
|
104
src/client.c
104
src/client.c
@ -1,6 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
|
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
|
||||||
* 2006-2009 Bjorn Andersson <flex@kryo.se>
|
* 2006-2009 Bjorn Andersson <flex@kryo.se>,
|
||||||
|
* 2015 Frekk van Blagh <frekk@frekkworks.com>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and/or distribute this software for any
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
@ -132,7 +133,7 @@ client_init()
|
|||||||
// TODO: user-set window size (command line option)
|
// TODO: user-set window size (command line option)
|
||||||
outbuf = window_buffer_init(100, 10, hostname_maxlen, WINDOW_SENDING);
|
outbuf = window_buffer_init(100, 10, hostname_maxlen, WINDOW_SENDING);
|
||||||
/* Incoming buffer max fragsize doesn't matter */
|
/* Incoming buffer max fragsize doesn't matter */
|
||||||
inbuf = window_buffer_init(100, 10, 1200, WINDOW_RECVING);
|
inbuf = window_buffer_init(128, 10, MAX_FRAGSIZE, WINDOW_RECVING);
|
||||||
|
|
||||||
next_downstream_ack = -1;
|
next_downstream_ack = -1;
|
||||||
current_nameserver = 0;
|
current_nameserver = 0;
|
||||||
@ -362,13 +363,33 @@ is_sending()
|
|||||||
return (outbuf->numitems > 0);
|
return (outbuf->numitems > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
send_ping(int fd, int ping_response) // TODO: setup window sync stuff in ping
|
||||||
|
{
|
||||||
|
if (conn == CONN_DNS_NULL) {
|
||||||
|
char data[4];
|
||||||
|
|
||||||
|
data[0] = userid;
|
||||||
|
data[1] = inbuf->start_seq_id & 0xff;
|
||||||
|
data[2] = outbuf->start_seq_id & 0xff;
|
||||||
|
data[3] = outbuf->windowsize & 0xff;
|
||||||
|
data[4] = inbuf->windowsize & 0xff;
|
||||||
|
data[5] = ping_response & 1;
|
||||||
|
data[6] = (rand_seed >> 8) & 0xff;
|
||||||
|
data[7] = (rand_seed >> 0) & 0xff;
|
||||||
|
rand_seed++;
|
||||||
|
|
||||||
|
send_packet(fd, 'p', data, sizeof(data));
|
||||||
|
} else {
|
||||||
|
send_raw(fd, NULL, 0, userid, RAW_HDR_CMD_PING);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
send_next_frag(int fd)
|
send_next_frag(int fd)
|
||||||
/* Sends next available fragment of data from the outgoing window buffer */
|
/* Sends next available fragment of data from the outgoing window buffer */
|
||||||
{
|
{
|
||||||
static uint8_t buf[MAX_FRAGSIZE];
|
static uint8_t buf[MAX_FRAGSIZE];
|
||||||
size_t len;
|
|
||||||
int code;
|
int code;
|
||||||
static int datacmc = 0;
|
static int datacmc = 0;
|
||||||
static char *datacmcchars = "abcdefghijklmnopqrstuvwxyz0123456789";
|
static char *datacmcchars = "abcdefghijklmnopqrstuvwxyz0123456789";
|
||||||
@ -381,13 +402,13 @@ send_next_frag(int fd)
|
|||||||
if (is_sending()) {
|
if (is_sending()) {
|
||||||
/* There is stuff to send but we're out of sync, so send a ping
|
/* There is stuff to send but we're out of sync, so send a ping
|
||||||
* to get things back in order and keep the packets flowing */
|
* to get things back in order and keep the packets flowing */
|
||||||
send_ping(fd);
|
send_ping(fd, 1);
|
||||||
}
|
}
|
||||||
return; /* nothing to send - why was this called? */
|
return; /* nothing to send - why was this called? */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Note: must be same, or smaller than send_fragsize_probe() */
|
/* Note: must be same, or smaller than send_fragsize_probe() */
|
||||||
len = build_hostname(buf, sizeof(buf), f->data, f->len, topdomain, dataenc, hostname_maxlen);
|
build_hostname((char *)buf, sizeof(buf), (char *)f->data, f->len, topdomain, dataenc, hostname_maxlen);
|
||||||
|
|
||||||
/* Build upstream data header (see doc/proto_xxxxxxxx.txt) */
|
/* Build upstream data header (see doc/proto_xxxxxxxx.txt) */
|
||||||
|
|
||||||
@ -411,29 +432,7 @@ send_next_frag(int fd)
|
|||||||
if (datacmc >= 36)
|
if (datacmc >= 36)
|
||||||
datacmc = 0;
|
datacmc = 0;
|
||||||
|
|
||||||
send_query(fd, buf);
|
send_query(fd, (char *)buf);
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
send_ping(int fd, int ping_response) // TODO: setup window sync stuff in ping
|
|
||||||
{
|
|
||||||
if (conn == CONN_DNS_NULL) {
|
|
||||||
char data[4];
|
|
||||||
|
|
||||||
data[0] = userid;
|
|
||||||
data[1] = inbuf->start_seq_id & 0xff;
|
|
||||||
data[2] = outbuf->start_seq_id & 0xff;
|
|
||||||
data[3] = outbuf->windowsize & 0xff;
|
|
||||||
data[4] = inbuf->windowsize & 0xff;
|
|
||||||
data[5] = ping_response & 1;
|
|
||||||
data[6] = (rand_seed >> 8) & 0xff;
|
|
||||||
data[7] = (rand_seed >> 0) & 0xff;
|
|
||||||
rand_seed++;
|
|
||||||
|
|
||||||
send_packet(fd, 'p', data, sizeof(data));
|
|
||||||
} else {
|
|
||||||
send_raw(fd, NULL, 0, userid, RAW_HDR_CMD_PING);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -574,7 +573,7 @@ dns_namedec(char *outdata, int outdatalen, char *buf, int buflen)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
read_dns_withq(int dns_fd, int tun_fd, uint8_t *buf, int buflen, struct query *q)
|
read_dns_withq(int dns_fd, int tun_fd, char *buf, int buflen, struct query *q)
|
||||||
/* Returns -1 on receive error or decode error, including DNS error replies.
|
/* Returns -1 on receive error or decode error, including DNS error replies.
|
||||||
Returns 0 on replies that could be correct but are useless, and are not
|
Returns 0 on replies that could be correct but are useless, and are not
|
||||||
DNS error replies.
|
DNS error replies.
|
||||||
@ -671,7 +670,7 @@ read_dns_withq(int dns_fd, int tun_fd, uint8_t *buf, int buflen, struct query *q
|
|||||||
r -= RAW_HDR_LEN;
|
r -= RAW_HDR_LEN;
|
||||||
datalen = sizeof(buf);
|
datalen = sizeof(buf);
|
||||||
if (uncompress((uint8_t*)buf, &datalen, (uint8_t*) &data[RAW_HDR_LEN], r) == Z_OK) {
|
if (uncompress((uint8_t*)buf, &datalen, (uint8_t*) &data[RAW_HDR_LEN], r) == Z_OK) {
|
||||||
write_tun(tun_fd, buf, datalen);
|
write_tun(tun_fd, (uint8_t*)buf, datalen);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* don't process any further */
|
/* don't process any further */
|
||||||
@ -766,15 +765,27 @@ static int
|
|||||||
parse_data(uint8_t *data, size_t len, fragment *f)
|
parse_data(uint8_t *data, size_t len, fragment *f)
|
||||||
{
|
{
|
||||||
memset(f, 0, sizeof(fragment));
|
memset(f, 0, sizeof(fragment));
|
||||||
f->seqID = data[0];
|
int ping = (data[3] >> 5) & 1;
|
||||||
f->start = data[3] & 1;
|
if (!ping) {
|
||||||
f->end = (data[3] >> 1) & 1;
|
f->seqID = data[0];
|
||||||
f->is_nack = (data[3] >> 2) & 1;
|
f->start = data[3] & 1;
|
||||||
f->ack_other = (data[3] >> 3) & 1 ? data[1] : -1;
|
f->end = (data[3] >> 1) & 1;
|
||||||
f->compressed = (data[3] >> 4) & 1;
|
f->is_nack = (data[3] >> 2) & 1;
|
||||||
f->len = len - 3;
|
f->ack_other = (data[3] >> 3) & 1 ? data[1] : -1;
|
||||||
memcpy(f->data, data + 3, MIN(f->len, sizeof(f->data)));
|
f->compressed = (data[3] >> 4) & 1;
|
||||||
return (data[3] >> 5) & 1; /* return ping flag (if corresponding query was a ping) */
|
f->len = len - 3;
|
||||||
|
memcpy(f->data, data + 3, MIN(f->len, sizeof(f->data)));
|
||||||
|
} else { /* Handle ping stuff */
|
||||||
|
if (len != 5) return 1; /* invalid packet - continue */
|
||||||
|
static unsigned in_start_seq, out_start_seq, in_wsize, out_wsize;
|
||||||
|
out_start_seq = data[0];
|
||||||
|
in_start_seq = data[1];
|
||||||
|
in_wsize = data[3];
|
||||||
|
out_wsize = data[4];
|
||||||
|
warnx("Pingy thingy received.");
|
||||||
|
// TODO: handle pings
|
||||||
|
}
|
||||||
|
return ping; /* return ping flag (if corresponding query was a ping) */
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -825,7 +836,7 @@ tunnel_dns(int tun_fd, int dns_fd)
|
|||||||
memset(&q, 0, sizeof(q));
|
memset(&q, 0, sizeof(q));
|
||||||
memset(buf, 0, sizeof(buf));
|
memset(buf, 0, sizeof(buf));
|
||||||
memset(cbuf, 0, sizeof(cbuf));
|
memset(cbuf, 0, sizeof(cbuf));
|
||||||
read = read_dns_withq(dns_fd, tun_fd, cbuf, sizeof(cbuf), &q);
|
read = read_dns_withq(dns_fd, tun_fd, (char *)cbuf, sizeof(cbuf), &q);
|
||||||
|
|
||||||
if (conn != CONN_DNS_NULL)
|
if (conn != CONN_DNS_NULL)
|
||||||
return 1; /* everything already done */
|
return 1; /* everything already done */
|
||||||
@ -895,9 +906,9 @@ tunnel_dns(int tun_fd, int dns_fd)
|
|||||||
/* Decode the downstream data header and fragment-ify ready for processing */
|
/* Decode the downstream data header and fragment-ify ready for processing */
|
||||||
res = parse_data(cbuf, read, &f);
|
res = parse_data(cbuf, read, &f);
|
||||||
|
|
||||||
/* if this response was a reverse ping/response to a ping: do something different? */
|
/* if this response was a reverse ping/response to a ping, we need to do something */
|
||||||
if (res) {
|
if (res) {
|
||||||
// TODO: handle pings to resync window
|
goto skip_recv;
|
||||||
}
|
}
|
||||||
|
|
||||||
window_ack(outbuf, f.ack_other);
|
window_ack(outbuf, f.ack_other);
|
||||||
@ -954,6 +965,7 @@ tunnel_dns(int tun_fd, int dns_fd)
|
|||||||
send_something_now = 1;
|
send_something_now = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
skip_recv:
|
||||||
/* Move window along after doing all data processing */
|
/* Move window along after doing all data processing */
|
||||||
window_tick(inbuf);
|
window_tick(inbuf);
|
||||||
|
|
||||||
@ -968,7 +980,7 @@ tunnel_dns(int tun_fd, int dns_fd)
|
|||||||
|
|
||||||
/* Send ping if we didn't send anything yet */
|
/* Send ping if we didn't send anything yet */
|
||||||
if (send_something_now) {
|
if (send_something_now) {
|
||||||
send_ping(dns_fd);
|
send_ping(dns_fd, 0);
|
||||||
send_ping_soon = 0;
|
send_ping_soon = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1031,10 +1043,10 @@ client_tunnel(int tun_fd, int dns_fd)
|
|||||||
send_next_frag(dns_fd);
|
send_next_frag(dns_fd);
|
||||||
} else {
|
} else {
|
||||||
outbuf->resends = 0;
|
outbuf->resends = 0;
|
||||||
send_ping(dns_fd);
|
send_ping(dns_fd, 1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
send_ping(dns_fd);
|
send_ping(dns_fd, 0);
|
||||||
}
|
}
|
||||||
send_ping_soon = 0;
|
send_ping_soon = 0;
|
||||||
|
|
||||||
@ -2324,7 +2336,7 @@ client_handshake(int dns_fd, int raw_mode, int autodetect_frag_size, int fragsiz
|
|||||||
fragsize = handshake_autoprobe_fragsize(dns_fd);
|
fragsize = handshake_autoprobe_fragsize(dns_fd);
|
||||||
if (fragsize > MAX_FRAGSIZE) {
|
if (fragsize > MAX_FRAGSIZE) {
|
||||||
/* This is very unlikely except perhaps over LAN */
|
/* This is very unlikely except perhaps over LAN */
|
||||||
fprintf(stderr, "Can transfer fragsize of %d, however iodine has been compiled with MAX_FRAGSIZE = %d. To fully utilize this connection, please recompile iodine/iodined.");
|
fprintf(stderr, "Can transfer fragsize of %d, however iodine has been compiled with MAX_FRAGSIZE = %d. To fully utilize this connection, please recompile iodine/iodined.", fragsize, MAX_FRAGSIZE);
|
||||||
fragsize = MAX_FRAGSIZE;
|
fragsize = MAX_FRAGSIZE;
|
||||||
}
|
}
|
||||||
if (!fragsize) {
|
if (!fragsize) {
|
||||||
|
@ -22,13 +22,13 @@
|
|||||||
int
|
int
|
||||||
build_hostname(char *buf, size_t buflen,
|
build_hostname(char *buf, size_t buflen,
|
||||||
const char *data, const size_t datalen,
|
const char *data, const size_t datalen,
|
||||||
const char *topdomain, struct encoder *encoder, int maxlen)
|
const char *topdomain, struct encoder *encoder, size_t maxlen)
|
||||||
{
|
{
|
||||||
size_t space;
|
size_t space;
|
||||||
char *b;
|
char *b;
|
||||||
|
|
||||||
space = MIN((size_t)maxlen, buflen) - strlen(topdomain) - 8;
|
space = MIN(maxlen, buflen) - strlen(topdomain) - DOWNSTREAM_HDR + 3;
|
||||||
/* 8 = 5 max header length + 1 dot before topdomain + 2 safety */
|
/* max header length + 1 dot before topdomain + 2 safety */
|
||||||
|
|
||||||
if (!encoder->places_dots())
|
if (!encoder->places_dots())
|
||||||
space -= (space / 57); /* space for dots */
|
space -= (space / 57); /* space for dots */
|
||||||
|
@ -35,7 +35,7 @@ struct encoder {
|
|||||||
int (*blocksize_encoded)(void);
|
int (*blocksize_encoded)(void);
|
||||||
};
|
};
|
||||||
|
|
||||||
int build_hostname(char *, size_t, const char *, const size_t, const char *, struct encoder *, int);
|
int build_hostname(char *, size_t, const char *, const size_t, const char *, struct encoder *, size_t);
|
||||||
int unpack_data(char *, size_t, char *, size_t, struct encoder *);
|
int unpack_data(char *, size_t, char *, size_t, struct encoder *);
|
||||||
int inline_dotify(char *, size_t);
|
int inline_dotify(char *, size_t);
|
||||||
int inline_undotify(char *, size_t);
|
int inline_undotify(char *, size_t);
|
||||||
|
2166
src/iodined.c
2166
src/iodined.c
File diff suppressed because it is too large
Load Diff
1877
src/server.c
Normal file
1877
src/server.c
Normal file
File diff suppressed because it is too large
Load Diff
111
src/server.h
Normal file
111
src/server.h
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2006-2015 Erik Ekman <yarrick@kryo.se>,
|
||||||
|
* 2006-2009 Bjorn Andersson <flex@kryo.se>,
|
||||||
|
* 2015 Frekk van Blagh <frekk@frekkworks.com>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __SERVER_H__
|
||||||
|
#define __SERVER_H__
|
||||||
|
|
||||||
|
#ifdef WINDOWS32
|
||||||
|
#include "windows.h"
|
||||||
|
#include <winsock2.h>
|
||||||
|
#else
|
||||||
|
#include <arpa/nameser.h>
|
||||||
|
#ifdef DARWIN
|
||||||
|
#define BIND_8_COMPAT
|
||||||
|
#include <arpa/nameser_compat.h>
|
||||||
|
#endif
|
||||||
|
#define _XPG4_2
|
||||||
|
#include <netinet/in_systm.h>
|
||||||
|
#include <netinet/ip.h>
|
||||||
|
#include <grp.h>
|
||||||
|
#include <sys/uio.h>
|
||||||
|
#include <pwd.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <syslog.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define DNSCACHE_LEN 10
|
||||||
|
/* Undefine to disable. Should be less than 18; also see comments in iodined.c */
|
||||||
|
|
||||||
|
#define QMEMPING_LEN 30
|
||||||
|
/* Max advisable: 64k/2 = 32000. Total mem usage: QMEMPING_LEN * USERS * 6 bytes */
|
||||||
|
|
||||||
|
#define QMEMDATA_LEN 15
|
||||||
|
/* Max advisable: 36/2 = 18. Total mem usage: QMEMDATA_LEN * USERS * 6 bytes */
|
||||||
|
|
||||||
|
#define PASSWORD_ENV_VAR "IODINED_PASS"
|
||||||
|
|
||||||
|
#if defined IP_RECVDSTADDR
|
||||||
|
# define DSTADDR_SOCKOPT IP_RECVDSTADDR
|
||||||
|
# define dstaddr(x) ((struct in_addr *) CMSG_DATA(x))
|
||||||
|
#elif defined IP_PKTINFO
|
||||||
|
# define DSTADDR_SOCKOPT IP_PKTINFO
|
||||||
|
# define dstaddr(x) (&(((struct in_pktinfo *)(CMSG_DATA(x)))->ipi_addr))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef IPV6_RECVPKTINFO
|
||||||
|
#define IPV6_RECVPKTINFO IPV6_PKTINFO
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(BSD) && !defined(__GLIBC__)
|
||||||
|
static char *__progname;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Struct with IPv4 and IPv6 file descriptors.
|
||||||
|
* Need to be passed on down to tunneling code since we can get a
|
||||||
|
* packet on one fd meant for a user on the other.
|
||||||
|
*/
|
||||||
|
struct dnsfd {
|
||||||
|
int v4fd;
|
||||||
|
int v6fd;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
VERSION_ACK,
|
||||||
|
VERSION_NACK,
|
||||||
|
VERSION_FULL
|
||||||
|
} version_ack_t;
|
||||||
|
|
||||||
|
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_stop();
|
||||||
|
int server_tunnel(int tun_fd, struct dnsfd *dns_fds, int bind_fd, int max_idle_time);
|
||||||
|
|
||||||
|
int read_dns(int fd, struct dnsfd *dns_fds, int tun_fd, struct query *q);
|
||||||
|
void write_dns(int fd, struct query *q, char *data, int datalen, char downenc);
|
||||||
|
void handle_full_packet(int tun_fd, struct dnsfd *dns_fds, int userid, uint8_t *data, size_t len);
|
||||||
|
void handle_null_request(int tun_fd, int dns_fd, struct dnsfd *dns_fds, struct query *q, int domain_len);
|
||||||
|
void handle_ns_request(int dns_fd, struct query *q);
|
||||||
|
void handle_a_request(int dns_fd, struct query *q, int fakeip);
|
||||||
|
|
||||||
|
#endif /* __SERVER_H__ */
|
@ -504,7 +504,7 @@ read_tun(int tun_fd, char *buf, size_t len)
|
|||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
int
|
int
|
||||||
write_tun(int tun_fd, char *data, size_t len)
|
write_tun(int tun_fd, uint8_t *data, size_t len)
|
||||||
{
|
{
|
||||||
#if defined (FREEBSD) || defined (NETBSD)
|
#if defined (FREEBSD) || defined (NETBSD)
|
||||||
/* FreeBSD/NetBSD has no header */
|
/* FreeBSD/NetBSD has no header */
|
||||||
@ -545,7 +545,7 @@ write_tun(int tun_fd, char *data, size_t len)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ssize_t
|
ssize_t
|
||||||
read_tun(int tun_fd, char *buf, size_t len)
|
read_tun(int tun_fd, uint8_t *buf, size_t len)
|
||||||
{
|
{
|
||||||
#if defined (FREEBSD) || defined (NETBSD)
|
#if defined (FREEBSD) || defined (NETBSD)
|
||||||
/* FreeBSD/NetBSD has no header */
|
/* FreeBSD/NetBSD has no header */
|
||||||
|
@ -20,8 +20,8 @@
|
|||||||
|
|
||||||
int open_tun(const char *);
|
int open_tun(const char *);
|
||||||
void close_tun(int);
|
void close_tun(int);
|
||||||
int write_tun(int, char *, size_t);
|
int write_tun(int, uint8_t *, size_t);
|
||||||
ssize_t read_tun(int, char *, size_t);
|
ssize_t read_tun(int, uint8_t *, size_t);
|
||||||
int tun_setip(const char *, const char *, int);
|
int tun_setip(const char *, const char *, int);
|
||||||
int tun_setmtu(const unsigned);
|
int tun_setmtu(const unsigned);
|
||||||
|
|
||||||
|
152
src/user.c
152
src/user.c
@ -1,6 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
|
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
|
||||||
* 2006-2009 Bjorn Andersson <flex@kryo.se>
|
* 2006-2009 Bjorn Andersson <flex@kryo.se>,
|
||||||
|
* 2015 Frekk van Blagh <frekk@frekkworks.com>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and/or distribute this software for any
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
@ -33,9 +34,12 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "encoding.h"
|
#include "encoding.h"
|
||||||
#include "user.h"
|
#include "user.h"
|
||||||
|
#include "window.h"
|
||||||
|
|
||||||
struct tun_user *users;
|
struct tun_user *users;
|
||||||
unsigned usercount;
|
unsigned usercount;
|
||||||
|
int created_users;
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
init_users(in_addr_t my_ip, int netbits)
|
init_users(in_addr_t my_ip, int netbits)
|
||||||
@ -60,6 +64,7 @@ init_users(in_addr_t my_ip, int netbits)
|
|||||||
maxusers = (1 << (32-netbits)) - 3; /* 3: Net addr, broadcast addr, iodined addr */
|
maxusers = (1 << (32-netbits)) - 3; /* 3: Net addr, broadcast addr, iodined addr */
|
||||||
usercount = MIN(maxusers, USERS);
|
usercount = MIN(maxusers, USERS);
|
||||||
|
|
||||||
|
if (users) free(users);
|
||||||
users = calloc(usercount, sizeof(struct tun_user));
|
users = calloc(usercount, sizeof(struct tun_user));
|
||||||
for (i = 0; i < usercount; i++) {
|
for (i = 0; i < usercount; i++) {
|
||||||
in_addr_t ip;
|
in_addr_t ip;
|
||||||
@ -74,11 +79,7 @@ init_users(in_addr_t my_ip, int netbits)
|
|||||||
}
|
}
|
||||||
users[i].tun_ip = ip;
|
users[i].tun_ip = ip;
|
||||||
net.s_addr = ip;
|
net.s_addr = ip;
|
||||||
users[i].disabled = 0;
|
/* Rest is reset on login ('V' packet) or already 0 */
|
||||||
users[i].authenticated = 0;
|
|
||||||
users[i].authenticated_raw = 0;
|
|
||||||
users[i].active = 0;
|
|
||||||
/* Rest is reset on login ('V' packet) */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return usercount;
|
return usercount;
|
||||||
@ -95,75 +96,55 @@ users_get_first_ip()
|
|||||||
int
|
int
|
||||||
find_user_by_ip(uint32_t ip)
|
find_user_by_ip(uint32_t ip)
|
||||||
{
|
{
|
||||||
int ret;
|
for (int i = 0; i < usercount; i++) {
|
||||||
int i;
|
if (user_active(i) && users[i].authenticated && ip == users[i].tun_ip) {
|
||||||
|
return i;
|
||||||
ret = -1;
|
|
||||||
for (i = 0; i < usercount; i++) {
|
|
||||||
if (users[i].active &&
|
|
||||||
users[i].authenticated &&
|
|
||||||
!users[i].disabled &&
|
|
||||||
users[i].last_pkt + 60 > time(NULL) &&
|
|
||||||
ip == users[i].tun_ip) {
|
|
||||||
ret = i;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
user_sending(int user)
|
||||||
|
{
|
||||||
|
return users[user].outgoing->numitems > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
user_active(int i)
|
||||||
|
{
|
||||||
|
return users[i].active && !users[i].disabled && users[i].last_pkt + 60 > time(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
all_users_waiting_to_send()
|
all_users_waiting_to_send()
|
||||||
/* If this returns true, then reading from tun device is blocked.
|
/* If this returns true, then reading from tun device is blocked.
|
||||||
So only return true when all clients have at least one packet in
|
So only return true when all clients have at least one fragment in
|
||||||
the outpacket-queue, so that sending back-to-back is possible
|
the outgoing buffer, so that sending back-to-back is possible
|
||||||
without going through another select loop.
|
without going through another select loop.
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
time_t now;
|
for (int i = 0; i < usercount; i++)
|
||||||
int ret;
|
if (!(user_active(i) && user_sending(i))) return 0;
|
||||||
int i;
|
return 1;
|
||||||
|
|
||||||
ret = 1;
|
|
||||||
now = time(NULL);
|
|
||||||
for (i = 0; i < usercount; i++) {
|
|
||||||
if (users[i].active && !users[i].disabled &&
|
|
||||||
users[i].last_pkt + 60 > now &&
|
|
||||||
((users[i].conn == CONN_RAW_UDP) ||
|
|
||||||
((users[i].conn == CONN_DNS_NULL)
|
|
||||||
#ifdef OUTPACKETQ_LEN
|
|
||||||
&& users[i].outpacketq_filled < 1
|
|
||||||
#else
|
|
||||||
&& users[i].outpacket.len == 0
|
|
||||||
#endif
|
|
||||||
))) {
|
|
||||||
|
|
||||||
ret = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
find_available_user()
|
find_available_user()
|
||||||
{
|
{
|
||||||
int ret = -1;
|
for (int u = 0; u < usercount; u++) {
|
||||||
int i;
|
|
||||||
for (i = 0; i < usercount; i++) {
|
|
||||||
/* Not used at all or not used in one minute */
|
/* Not used at all or not used in one minute */
|
||||||
if ((!users[i].active || users[i].last_pkt + 60 < time(NULL)) && !users[i].disabled) {
|
if (!user_active(u)) {
|
||||||
users[i].active = 1;
|
/* reset all stats */
|
||||||
users[i].authenticated = 0;
|
memset(&users[u], 0, sizeof(users[u]));
|
||||||
users[i].authenticated_raw = 0;
|
users[u].active = 1;
|
||||||
users[i].last_pkt = time(NULL);
|
users[u].last_pkt = time(NULL);
|
||||||
users[i].fragsize = 4096;
|
users[u].fragsize = MAX_FRAGSIZE;
|
||||||
users[i].conn = CONN_DNS_NULL;
|
users[u].conn = CONN_DNS_NULL;
|
||||||
ret = i;
|
return u;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -187,3 +168,60 @@ user_set_conn_type(int userid, enum connection c)
|
|||||||
users[userid].conn = c;
|
users[userid].conn = c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This will not check that user has passed login challenge */
|
||||||
|
int
|
||||||
|
check_user_and_ip(int userid, struct query *q)
|
||||||
|
{
|
||||||
|
/* Note: duplicate in handle_raw_login() except IP-address check */
|
||||||
|
|
||||||
|
if (userid < 0 || userid >= created_users ) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (!users[userid].active || users[userid].disabled) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (users[userid].last_pkt + 60 < time(NULL)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* return early if IP checking is disabled */
|
||||||
|
if (!check_ip) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (q->from.ss_family != users[userid].host.ss_family) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/* Check IPv4 */
|
||||||
|
if (q->from.ss_family == AF_INET) {
|
||||||
|
struct sockaddr_in *expected, *received;
|
||||||
|
|
||||||
|
expected = (struct sockaddr_in *) &(users[userid].host);
|
||||||
|
received = (struct sockaddr_in *) &(q->from);
|
||||||
|
return memcmp(&(expected->sin_addr), &(received->sin_addr), sizeof(struct in_addr));
|
||||||
|
}
|
||||||
|
/* Check IPv6 */
|
||||||
|
if (q->from.ss_family == AF_INET6) {
|
||||||
|
struct sockaddr_in6 *expected, *received;
|
||||||
|
|
||||||
|
expected = (struct sockaddr_in6 *) &(users[userid].host);
|
||||||
|
received = (struct sockaddr_in6 *) &(q->from);
|
||||||
|
return memcmp(&(expected->sin6_addr), &(received->sin6_addr), sizeof(struct in6_addr));
|
||||||
|
}
|
||||||
|
/* Unknown address family */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This checks that user has passed normal (non-raw) login challenge */
|
||||||
|
int
|
||||||
|
check_authenticated_user_and_ip(int userid, struct query *q)
|
||||||
|
{
|
||||||
|
int res = check_user_and_ip(userid, q);
|
||||||
|
if (res)
|
||||||
|
return res;
|
||||||
|
|
||||||
|
if (!users[userid].authenticated)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
41
src/user.h
41
src/user.h
@ -1,6 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
|
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
|
||||||
* 2006-2009 Bjorn Andersson <flex@kryo.se>
|
* 2006-2009 Bjorn Andersson <flex@kryo.se>,
|
||||||
|
* 2015 Frekk van Blagh <frekk@frekkworks.com>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and/or distribute this software for any
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
@ -18,22 +19,11 @@
|
|||||||
#ifndef __USER_H__
|
#ifndef __USER_H__
|
||||||
#define __USER_H__
|
#define __USER_H__
|
||||||
|
|
||||||
|
#include "window.h"
|
||||||
|
#include "server.h"
|
||||||
|
|
||||||
#define USERS 16
|
#define USERS 16
|
||||||
|
|
||||||
#define OUTPACKETQ_LEN 4 /* Note: 16 users * 1 packet = 1MB */
|
|
||||||
/* Undefine to have no queue for packets coming in from tun device, which may
|
|
||||||
lead to massive dropping in multi-user situations with high traffic. */
|
|
||||||
|
|
||||||
#define DNSCACHE_LEN 4
|
|
||||||
/* Undefine to disable. Should be less than 18; also see comments in iodined.c */
|
|
||||||
|
|
||||||
|
|
||||||
#define QMEMPING_LEN 30
|
|
||||||
/* Max advisable: 64k/2 = 32000. Total mem usage: QMEMPING_LEN * USERS * 6 bytes */
|
|
||||||
|
|
||||||
#define QMEMDATA_LEN 15
|
|
||||||
/* Max advisable: 36/2 = 18. Total mem usage: QMEMDATA_LEN * USERS * 6 bytes */
|
|
||||||
|
|
||||||
struct tun_user {
|
struct tun_user {
|
||||||
char id;
|
char id;
|
||||||
int active;
|
int active;
|
||||||
@ -48,13 +38,11 @@ struct tun_user {
|
|||||||
struct query q;
|
struct query q;
|
||||||
struct query q_sendrealsoon;
|
struct query q_sendrealsoon;
|
||||||
int q_sendrealsoon_new;
|
int q_sendrealsoon_new;
|
||||||
struct packet inpacket;
|
struct frag_buffer *incoming;
|
||||||
struct packet outpacket;
|
struct frag_buffer *outgoing;
|
||||||
int outfragresent;
|
int next_upstream_ack;
|
||||||
struct encoder *encoder;
|
struct encoder *encoder;
|
||||||
char downenc;
|
char downenc;
|
||||||
int out_acked_seqno;
|
|
||||||
int out_acked_fragment;
|
|
||||||
int fragsize;
|
int fragsize;
|
||||||
enum connection conn;
|
enum connection conn;
|
||||||
int lazy;
|
int lazy;
|
||||||
@ -64,11 +52,6 @@ struct tun_user {
|
|||||||
unsigned char qmemdata_cmc[QMEMDATA_LEN * 4];
|
unsigned char qmemdata_cmc[QMEMDATA_LEN * 4];
|
||||||
unsigned short qmemdata_type[QMEMDATA_LEN];
|
unsigned short qmemdata_type[QMEMDATA_LEN];
|
||||||
int qmemdata_lastfilled;
|
int qmemdata_lastfilled;
|
||||||
#ifdef OUTPACKETQ_LEN
|
|
||||||
struct packet outpacketq[OUTPACKETQ_LEN];
|
|
||||||
int outpacketq_nexttouse;
|
|
||||||
int outpacketq_filled;
|
|
||||||
#endif
|
|
||||||
#ifdef DNSCACHE_LEN
|
#ifdef DNSCACHE_LEN
|
||||||
struct query dnscache_q[DNSCACHE_LEN];
|
struct query dnscache_q[DNSCACHE_LEN];
|
||||||
char dnscache_answer[DNSCACHE_LEN][4096];
|
char dnscache_answer[DNSCACHE_LEN][4096];
|
||||||
@ -78,11 +61,17 @@ struct tun_user {
|
|||||||
};
|
};
|
||||||
|
|
||||||
extern struct tun_user *users;
|
extern struct tun_user *users;
|
||||||
|
extern int created_users;
|
||||||
|
|
||||||
|
int user_sending(int user);
|
||||||
|
int all_users_waiting_to_send();
|
||||||
|
int user_active(int i);
|
||||||
|
int check_authenticated_user_and_ip(int userid, struct query *q);
|
||||||
|
int check_user_and_ip(int userid, struct query *q);
|
||||||
|
|
||||||
int init_users(in_addr_t, int);
|
int init_users(in_addr_t, int);
|
||||||
const char* users_get_first_ip();
|
const char* users_get_first_ip();
|
||||||
int find_user_by_ip(uint32_t);
|
int find_user_by_ip(uint32_t);
|
||||||
int all_users_waiting_to_send();
|
|
||||||
int find_available_user();
|
int find_available_user();
|
||||||
void user_switch_codec(int userid, struct encoder *enc);
|
void user_switch_codec(int userid, struct encoder *enc);
|
||||||
void user_set_conn_type(int userid, enum connection c);
|
void user_set_conn_type(int userid, enum connection c);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2015 Frekk van Blagh
|
* Copyright (c) 2015 Frekk van Blagh <frekk@frekkworks.com>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and/or distribute this software for any
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2015 Frekk van Blagh
|
* Copyright (c) 2015 Frekk van Blagh <frekk@frekkworks.com>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and/or distribute this software for any
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
@ -18,7 +18,7 @@
|
|||||||
#define __WINDOW_H__
|
#define __WINDOW_H__
|
||||||
|
|
||||||
#define MAX_SEQ_ID 256
|
#define MAX_SEQ_ID 256
|
||||||
#define MAX_FRAGSIZE 2048
|
#define MAX_FRAGSIZE 4096
|
||||||
#define ACK_TIMEOUT 5
|
#define ACK_TIMEOUT 5
|
||||||
|
|
||||||
#define WINDOW_SENDING 1
|
#define WINDOW_SENDING 1
|
||||||
@ -95,7 +95,7 @@ fragment *window_get_next_sending_fragment(struct frag_buffer *w, int other_ack)
|
|||||||
int window_get_next_ack(struct frag_buffer *w);
|
int window_get_next_ack(struct frag_buffer *w);
|
||||||
|
|
||||||
/* Sets the fragment with seqid to be ACK'd (SEND) */
|
/* Sets the fragment with seqid to be ACK'd (SEND) */
|
||||||
void window_ack(struct frag_buffer *w, unsigned seqid);
|
void window_ack(struct frag_buffer *w, int seqid);
|
||||||
|
|
||||||
/* To be called after all other processing has been done
|
/* To be called after all other processing has been done
|
||||||
* when anything happens (moves window etc) (SEND/RECV) */
|
* when anything happens (moves window etc) (SEND/RECV) */
|
||||||
|
Loading…
Reference in New Issue
Block a user