mirror of
https://github.com/yarrick/iodine.git
synced 2024-11-25 02:55:15 +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
|
||||
CLIENTOBJS = iodine.o client.o util.o
|
||||
CLIENT = ../bin/iodine
|
||||
SERVEROBJS = iodined.o user.o fw_query.o
|
||||
SERVEROBJS = iodined.o user.o fw_query.o server.o
|
||||
SERVER = ../bin/iodined
|
||||
|
||||
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>,
|
||||
* 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
|
||||
* 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)
|
||||
outbuf = window_buffer_init(100, 10, hostname_maxlen, WINDOW_SENDING);
|
||||
/* 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;
|
||||
current_nameserver = 0;
|
||||
@ -362,13 +363,33 @@ is_sending()
|
||||
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
|
||||
send_next_frag(int fd)
|
||||
/* Sends next available fragment of data from the outgoing window buffer */
|
||||
{
|
||||
static uint8_t buf[MAX_FRAGSIZE];
|
||||
size_t len;
|
||||
int code;
|
||||
static int datacmc = 0;
|
||||
static char *datacmcchars = "abcdefghijklmnopqrstuvwxyz0123456789";
|
||||
@ -381,13 +402,13 @@ send_next_frag(int fd)
|
||||
if (is_sending()) {
|
||||
/* 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 */
|
||||
send_ping(fd);
|
||||
send_ping(fd, 1);
|
||||
}
|
||||
return; /* nothing to send - why was this called? */
|
||||
}
|
||||
|
||||
/* 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) */
|
||||
|
||||
@ -411,29 +432,7 @@ send_next_frag(int fd)
|
||||
if (datacmc >= 36)
|
||||
datacmc = 0;
|
||||
|
||||
send_query(fd, 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);
|
||||
}
|
||||
send_query(fd, (char *)buf);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -574,7 +573,7 @@ dns_namedec(char *outdata, int outdatalen, char *buf, int buflen)
|
||||
}
|
||||
|
||||
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 0 on replies that could be correct but are useless, and are not
|
||||
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;
|
||||
datalen = sizeof(buf);
|
||||
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 */
|
||||
@ -766,15 +765,27 @@ static int
|
||||
parse_data(uint8_t *data, size_t len, fragment *f)
|
||||
{
|
||||
memset(f, 0, sizeof(fragment));
|
||||
f->seqID = data[0];
|
||||
f->start = data[3] & 1;
|
||||
f->end = (data[3] >> 1) & 1;
|
||||
f->is_nack = (data[3] >> 2) & 1;
|
||||
f->ack_other = (data[3] >> 3) & 1 ? data[1] : -1;
|
||||
f->compressed = (data[3] >> 4) & 1;
|
||||
f->len = len - 3;
|
||||
memcpy(f->data, data + 3, MIN(f->len, sizeof(f->data)));
|
||||
return (data[3] >> 5) & 1; /* return ping flag (if corresponding query was a ping) */
|
||||
int ping = (data[3] >> 5) & 1;
|
||||
if (!ping) {
|
||||
f->seqID = data[0];
|
||||
f->start = data[3] & 1;
|
||||
f->end = (data[3] >> 1) & 1;
|
||||
f->is_nack = (data[3] >> 2) & 1;
|
||||
f->ack_other = (data[3] >> 3) & 1 ? data[1] : -1;
|
||||
f->compressed = (data[3] >> 4) & 1;
|
||||
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
|
||||
@ -825,7 +836,7 @@ tunnel_dns(int tun_fd, int dns_fd)
|
||||
memset(&q, 0, sizeof(q));
|
||||
memset(buf, 0, sizeof(buf));
|
||||
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)
|
||||
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 */
|
||||
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) {
|
||||
// TODO: handle pings to resync window
|
||||
goto skip_recv;
|
||||
}
|
||||
|
||||
window_ack(outbuf, f.ack_other);
|
||||
@ -954,6 +965,7 @@ tunnel_dns(int tun_fd, int dns_fd)
|
||||
send_something_now = 1;
|
||||
}
|
||||
|
||||
skip_recv:
|
||||
/* Move window along after doing all data processing */
|
||||
window_tick(inbuf);
|
||||
|
||||
@ -968,7 +980,7 @@ tunnel_dns(int tun_fd, int dns_fd)
|
||||
|
||||
/* Send ping if we didn't send anything yet */
|
||||
if (send_something_now) {
|
||||
send_ping(dns_fd);
|
||||
send_ping(dns_fd, 0);
|
||||
send_ping_soon = 0;
|
||||
}
|
||||
|
||||
@ -1031,10 +1043,10 @@ client_tunnel(int tun_fd, int dns_fd)
|
||||
send_next_frag(dns_fd);
|
||||
} else {
|
||||
outbuf->resends = 0;
|
||||
send_ping(dns_fd);
|
||||
send_ping(dns_fd, 1);
|
||||
}
|
||||
} else {
|
||||
send_ping(dns_fd);
|
||||
send_ping(dns_fd, 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);
|
||||
if (fragsize > MAX_FRAGSIZE) {
|
||||
/* 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;
|
||||
}
|
||||
if (!fragsize) {
|
||||
|
@ -22,13 +22,13 @@
|
||||
int
|
||||
build_hostname(char *buf, size_t buflen,
|
||||
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;
|
||||
char *b;
|
||||
|
||||
space = MIN((size_t)maxlen, buflen) - strlen(topdomain) - 8;
|
||||
/* 8 = 5 max header length + 1 dot before topdomain + 2 safety */
|
||||
space = MIN(maxlen, buflen) - strlen(topdomain) - DOWNSTREAM_HDR + 3;
|
||||
/* max header length + 1 dot before topdomain + 2 safety */
|
||||
|
||||
if (!encoder->places_dots())
|
||||
space -= (space / 57); /* space for dots */
|
||||
|
@ -35,7 +35,7 @@ struct encoder {
|
||||
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 inline_dotify(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
|
||||
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)
|
||||
/* FreeBSD/NetBSD has no header */
|
||||
@ -545,7 +545,7 @@ write_tun(int tun_fd, char *data, size_t len)
|
||||
}
|
||||
|
||||
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)
|
||||
/* FreeBSD/NetBSD has no header */
|
||||
|
@ -20,8 +20,8 @@
|
||||
|
||||
int open_tun(const char *);
|
||||
void close_tun(int);
|
||||
int write_tun(int, char *, size_t);
|
||||
ssize_t read_tun(int, char *, size_t);
|
||||
int write_tun(int, uint8_t *, size_t);
|
||||
ssize_t read_tun(int, uint8_t *, size_t);
|
||||
int tun_setip(const char *, const char *, int);
|
||||
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>,
|
||||
* 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
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
@ -33,9 +34,12 @@
|
||||
#include "common.h"
|
||||
#include "encoding.h"
|
||||
#include "user.h"
|
||||
#include "window.h"
|
||||
|
||||
struct tun_user *users;
|
||||
unsigned usercount;
|
||||
int created_users;
|
||||
|
||||
|
||||
int
|
||||
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 */
|
||||
usercount = MIN(maxusers, USERS);
|
||||
|
||||
if (users) free(users);
|
||||
users = calloc(usercount, sizeof(struct tun_user));
|
||||
for (i = 0; i < usercount; i++) {
|
||||
in_addr_t ip;
|
||||
@ -74,11 +79,7 @@ init_users(in_addr_t my_ip, int netbits)
|
||||
}
|
||||
users[i].tun_ip = ip;
|
||||
net.s_addr = ip;
|
||||
users[i].disabled = 0;
|
||||
users[i].authenticated = 0;
|
||||
users[i].authenticated_raw = 0;
|
||||
users[i].active = 0;
|
||||
/* Rest is reset on login ('V' packet) */
|
||||
/* Rest is reset on login ('V' packet) or already 0 */
|
||||
}
|
||||
|
||||
return usercount;
|
||||
@ -95,75 +96,55 @@ users_get_first_ip()
|
||||
int
|
||||
find_user_by_ip(uint32_t ip)
|
||||
{
|
||||
int ret;
|
||||
int 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;
|
||||
for (int i = 0; i < usercount; i++) {
|
||||
if (user_active(i) && users[i].authenticated && ip == users[i].tun_ip) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
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
|
||||
all_users_waiting_to_send()
|
||||
/* If this returns true, then reading from tun device is blocked.
|
||||
So only return true when all clients have at least one packet in
|
||||
the outpacket-queue, so that sending back-to-back is possible
|
||||
So only return true when all clients have at least one fragment in
|
||||
the outgoing buffer, so that sending back-to-back is possible
|
||||
without going through another select loop.
|
||||
*/
|
||||
{
|
||||
time_t now;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
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;
|
||||
for (int i = 0; i < usercount; i++)
|
||||
if (!(user_active(i) && user_sending(i))) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
find_available_user()
|
||||
{
|
||||
int ret = -1;
|
||||
int i;
|
||||
for (i = 0; i < usercount; i++) {
|
||||
for (int u = 0; u < usercount; u++) {
|
||||
/* Not used at all or not used in one minute */
|
||||
if ((!users[i].active || users[i].last_pkt + 60 < time(NULL)) && !users[i].disabled) {
|
||||
users[i].active = 1;
|
||||
users[i].authenticated = 0;
|
||||
users[i].authenticated_raw = 0;
|
||||
users[i].last_pkt = time(NULL);
|
||||
users[i].fragsize = 4096;
|
||||
users[i].conn = CONN_DNS_NULL;
|
||||
ret = i;
|
||||
break;
|
||||
if (!user_active(u)) {
|
||||
/* reset all stats */
|
||||
memset(&users[u], 0, sizeof(users[u]));
|
||||
users[u].active = 1;
|
||||
users[u].last_pkt = time(NULL);
|
||||
users[u].fragsize = MAX_FRAGSIZE;
|
||||
users[u].conn = CONN_DNS_NULL;
|
||||
return u;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void
|
||||
@ -187,3 +168,60 @@ user_set_conn_type(int userid, enum connection 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>,
|
||||
* 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
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
@ -18,22 +19,11 @@
|
||||
#ifndef __USER_H__
|
||||
#define __USER_H__
|
||||
|
||||
#include "window.h"
|
||||
#include "server.h"
|
||||
|
||||
#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 {
|
||||
char id;
|
||||
int active;
|
||||
@ -48,13 +38,11 @@ struct tun_user {
|
||||
struct query q;
|
||||
struct query q_sendrealsoon;
|
||||
int q_sendrealsoon_new;
|
||||
struct packet inpacket;
|
||||
struct packet outpacket;
|
||||
int outfragresent;
|
||||
struct frag_buffer *incoming;
|
||||
struct frag_buffer *outgoing;
|
||||
int next_upstream_ack;
|
||||
struct encoder *encoder;
|
||||
char downenc;
|
||||
int out_acked_seqno;
|
||||
int out_acked_fragment;
|
||||
int fragsize;
|
||||
enum connection conn;
|
||||
int lazy;
|
||||
@ -64,11 +52,6 @@ struct tun_user {
|
||||
unsigned char qmemdata_cmc[QMEMDATA_LEN * 4];
|
||||
unsigned short qmemdata_type[QMEMDATA_LEN];
|
||||
int qmemdata_lastfilled;
|
||||
#ifdef OUTPACKETQ_LEN
|
||||
struct packet outpacketq[OUTPACKETQ_LEN];
|
||||
int outpacketq_nexttouse;
|
||||
int outpacketq_filled;
|
||||
#endif
|
||||
#ifdef DNSCACHE_LEN
|
||||
struct query dnscache_q[DNSCACHE_LEN];
|
||||
char dnscache_answer[DNSCACHE_LEN][4096];
|
||||
@ -78,11 +61,17 @@ struct tun_user {
|
||||
};
|
||||
|
||||
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);
|
||||
const char* users_get_first_ip();
|
||||
int find_user_by_ip(uint32_t);
|
||||
int all_users_waiting_to_send();
|
||||
int find_available_user();
|
||||
void user_switch_codec(int userid, struct encoder *enc);
|
||||
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
|
||||
* 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
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
@ -18,7 +18,7 @@
|
||||
#define __WINDOW_H__
|
||||
|
||||
#define MAX_SEQ_ID 256
|
||||
#define MAX_FRAGSIZE 2048
|
||||
#define MAX_FRAGSIZE 4096
|
||||
#define ACK_TIMEOUT 5
|
||||
|
||||
#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);
|
||||
|
||||
/* 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
|
||||
* when anything happens (moves window etc) (SEND/RECV) */
|
||||
|
Loading…
Reference in New Issue
Block a user