summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AUTHORS7
-rw-r--r--Changelog72
-rw-r--r--Makefile12
-rw-r--r--README47
-rw-r--r--activefor.h12
-rw-r--r--afclient.c157
-rw-r--r--afserver.c1195
-rw-r--r--buflist.c15
-rw-r--r--config24
-rw-r--r--docs/ru/ru_README294
-rw-r--r--exmodule.c37
-rw-r--r--file.c16
-rw-r--r--file.h13
-rw-r--r--modules.c63
-rw-r--r--modules.h37
15 files changed, 1357 insertions, 644 deletions
diff --git a/AUTHORS b/AUTHORS
index 10c79d5..6446e90 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -1,5 +1,8 @@
Author:
- o jeremian <jeremian [at] poczta.fm>
+ o jeremian <jeremian [at] poczta.fm>
French translation:
- o Simon CASTRO <scastro [at] entreelibre.com>
+ o Simon CASTRO <scastro [at] entreelibre.com>
+
+Russian translation:
+ o Alex Dyatlov <alex [at] gray-world.net>
diff --git a/Changelog b/Changelog
index 2b3e214..af4e6af 100644
--- a/Changelog
+++ b/Changelog
@@ -1,36 +1,50 @@
+11.10.2004 (v0.5.5):
+ - Added: rsa key generation by afclient
+ - Modified: afclient is now generating keys by default
+ - Fixed: major bug in packet buffering
+ - Added: 'timeout', 'clients' and 'usrpcli' options
+ - Fixed: parsing 'users' option
+ - Modified: module management routines
+ - Added: module support for service's packet filtering
+ - Fixed: few minor bugs in closing connection routines
+ - Added: possibility to use several clients per realm
+ - Modified: there is no need for 'users', 'timeout', 'clients',
+ 'proto', 'usrpcli' and 'climode' options in config
+ file when default values are acceptable
+
26.05.2004 (v0.5.4):
- - Fixed: default password incompatibilities
- - Modified: Server listening behaviour
- - Added: Module support for client's packet filtering
- - Modified: client behaviour after unsuccessful connection
- - Fixed: printing ipv6 addresses
- - Added: IP protocol family strict choice: 'ipv4' and 'ipv6'
- - Added: flow control / packet buffering
- - Fixed: signal handling
- - Fixed: client freeze in udp reverse mode with zlib enabled
+ - Fixed: default password incompatibilities
+ - Modified: server listening behaviour
+ - Added: module support for client's packet filtering
+ - Modified: client behaviour after unsuccessful connection
+ - Fixed: printing ipv6 addresses
+ - Added: IP protocol family strict choice: 'ipv4' and 'ipv6'
+ - Added: flow control / packet buffering
+ - Fixed: signal handling
+ - Fixed: client freeze in udp reverse mode with zlib enabled
09.01.2004 (v0.5.3):
- - Added: client password identification (weak)
- - Added: sigint interception and server closing
- - Modified: communication between server and client
- - Added: 'nossl' and 'nozlib' modes
- - Added: zlib support
- - Lightly Modified: verbose mode
- - Modified/Added: help screen and long options support
-
+ - Added: client password identification (weak)
+ - Added: sigint interception and server closing
+ - Modified: communication between server and client
+ - Added: 'nossl' and 'nozlib' modes
+ - Added: zlib support
+ - Lightly Modified: verbose mode
+ - Modified/Added: help screen and long options support
+
06.12.2003 (v0.5.2):
- - Added: types of realm
- - Added: logging to a file
- - Fixed: major bug in communication between server and client
- - Fixed: deformed packets in udp protocol forwarding
-
+ - Added: types of realm
+ - Added: logging to a file
+ - Fixed: major bug in communication between server and client
+ - Fixed: deformed packets in udp protocol forwarding
+
04.12.2003 (v0.5.1):
- - Fixed: Some data transfer problems
- - Added: udp protocol tunneling/forwarding
- - Fixed: bug in parsing the config file
- - Improved: making connection between server and client
- - Lightly modified: verbose mode (added double v mode)
+ - Fixed: some data transfer problems
+ - Added: udp protocol tunneling/forwarding
+ - Fixed: bug in parsing the config file
+ - Improved: making connection between server and client
+ - Lightly modified: verbose mode (added double v mode)
23.11.2003 (v0.5):
- - This is the first release
- - There are no known major bugs
+ - This is the first release
+ - There are no known major bugs
diff --git a/Makefile b/Makefile
index f6064d5..09c9034 100644
--- a/Makefile
+++ b/Makefile
@@ -1,15 +1,17 @@
CC=gcc
CFLAGS=-pedantic -Wall -O2
programs=afserver afclient
-security=server.rsa client.rsa cacert.pem
+security=server.rsa cacert.pem
+serdepends=afserver.c network.o file.o stats.o buflist.o
+clidepends=afclient.c network.o stats.o buflist.o modules.o
all: compi $(programs) ok1 secure
-afserver: afserver.c network.o file.o stats.o buflist.o
- $(CC) $(CFLAGS) -lssl -lz afserver.c network.o file.o stats.o buflist.o -o afserver
+afserver: $(serdepends)
+ $(CC) $(CFLAGS) -lssl -lz $(serdepends) -o afserver
-afclient: afclient.c network.o stats.o buflist.o
- $(CC) $(CFLAGS) -rdynamic -lssl -lz -ldl afclient.c network.o stats.o buflist.o -o afclient
+afclient: $(clidepends)
+ $(CC) $(CFLAGS) -rdynamic -lssl -lz -ldl $(clidepends) -o afclient
%.o: %.c %.h
$(CC) $(CFLAGS) -c $*.c
diff --git a/README b/README
index e9ded51..8901699 100644
--- a/README
+++ b/README
@@ -1,4 +1,4 @@
-AF - Active Port Forwarder v0.5.4 - README
+AF - Active Port Forwarder v0.5.5 - README
Copyright (C) 2003,2004 jeremian - <jeremian [at] poczta.fm>
===================
@@ -7,10 +7,10 @@ Copyright (C) 2003,2004 jeremian - <jeremian [at] poczta.fm>
GRAY-WORLD.NET / Active Port Forwarder
==========================
- The Active Port Forwarder program is part of the Gray-World.net projects.
+ The Active Port Forwarder program is part of the Gray-World.net projects.
Our Gray-World Team presents on the http://gray-world.net website the projects
- and publications we are working on which are related to the NACS (Network
+ and publications we are working on which are related to the NACS (Network
Access Control System) bypassing research field and to the computer and
network security topics.
@@ -44,13 +44,13 @@ THANKS
INTRO
=====
-Active port forwarder is a software tool for secure port forwarding.
+Active port forwarder is a software tool for secure port forwarding.
It uses ssl to increase security of communication between a server and a client.
Originally, it was developed to forward data point to point. However, the need
for bypassing firewalls in order to connect to internally located computers
influenced the further development of the project.
-AF is dedicated for people, who don't have an external ip number and want to
+AF is dedicated for people, who don't have an external ip number and want to
make some services available across the net.
Moreover, zlib is used to compress the transferred data.
@@ -58,6 +58,8 @@ Moreover, zlib is used to compress the transferred data.
Using one, permanent data/control channel with flow control / packet buffering
provides good performance and reasonably small latency.
+Multiple clients allow to create more sophisticated tunneling scheme.
+
================================================================================
===============
@@ -99,15 +101,23 @@ provides good performance and reasonably small latency.
------------
Options:
- -h, --help - prints this help
-n, --hostname - it's used when creating listening sockets
(default: name returned by hostname function)
-l, --listenport - listening port number - users connect
to it (default: 50127)
-m, --manageport - manage port number - second part of the active
port forwarder connects to it (default: 50126)
+ -t, --timeout - the timeout value for the client's connection
+ (default: 5)
-u, --users - the amount of users allowed to use this server
(default: 5)
+ -C, --clients - the number of allowed clients to use this server
+ (default: 1)
+ -U, --usrpcli - the number of allowed users per client (default: $users)
+ -M, --climode - strategy used for connecting users with clients (default: 1)
+ Available strategies:
+ 1. fill first client before go to next
+
-c, --cerfile - the name of the file with certificate
(default: cacert.pem)
-k, --keyfile - the name of the file with RSA key (default: server.rsa)
@@ -119,15 +129,19 @@ provides good performance and reasonably small latency.
-o, --lightlog - logging some data to a logfile
-v, --verbose - to be verbose - program won't enter the daemon mode
(use several times for greater effect)
- --nossl - ssl is not used for transferring data (but it's still
+
+ --nossl - ssl is not used for transfering data (but it's still
used to establish a connection) (default: ssl is used)
--nozlib - zlib is not used for compressing data (default:
zlib is used)
--pass - set the password used for client identification
(default: no password)
+
-4, --ipv4 - use ipv4 only
-6, --ipv6 - use ipv6 only
+ -h, --help - prints this help
+
2.2 afclient
------------
@@ -140,13 +154,13 @@ provides good performance and reasonably small latency.
-d, --hostname - the name of this host/remote host - the final
destination of the packets (default: the name
returned by hostname function)
- -p, --portnum - the port we are forwarding the connection to (required)
- -k, --keyfile - the name of the file with RSA key (default: client.rsa)
+ -p, --portnum - the port we are forwarding connection to (required)
+ -k, --keyfile - the name of the file with RSA key (default: (none))
-u, --udpmode - udp mode - client will use udp protocol to
communicate with the hostname
-U, --reverseudp - reverse udp forwarding. Udp packets will be forwarded
from hostname:portnum (-p) to the server name:portnum
- (-m)
+ (-m)
-O, --heavylog - logging everything to a logfile
-o, --lightlog - logging some data to a logfile
-v, --verbose - to be verbose - program won't enter the daemon mode
@@ -155,7 +169,8 @@ provides good performance and reasonably small latency.
(default: no password)
-4, --ipv4 - use ipv4 only
-6, --ipv6 - use ipv6 only
- -l, --load - load a module for packets filtering
+ -l, --load - load a module for user's packets filtering
+ -L, --Load - load a module for service's packets filtering
================================================================================
@@ -181,7 +196,7 @@ provides good performance and reasonably small latency.
The use of it is extremely simple. Let's suppose we want to create a http server
on our computer and we are behind a masquerade or a firewall:
-1) We have to find some machine on the net with an external ip and a shell
+1) We have to find some machine on the net with an external ip and a shell
account.
2) Use "make" to compile everything on that machine. (you can freely remove the
@@ -191,7 +206,7 @@ on our computer and we are behind a masquerade or a firewall:
type -f <cfgfile>) :
$ ./afserver
This will work, if you want to use default values:
- - hostname will be taken from hostname function (it would be ideally, if
+ - hostname will be taken from hostname function (it would be ideally, if
there is appropriate registration in /etc/hosts)
- server will be listening for users on port 50127
- server will be listening for client on port 50126
@@ -230,10 +245,10 @@ on our computer and we are behind a masquerade or a firewall:
Let's see how to use af to forward udp packets. Suppose we want to create a game
server on our computer (udp port 27960 on our machine):
-1) - 4) is the same like in example 1. (but we add option: -p udp)
+1) - 4) is the same like in example 1. (but we add option: -p udp)
5) We are typing from the console:
- $ ./afclient -u -n <name of the server> -p 27960
+ $ ./afclient -u -n <name of the server> -p 27960
Where <name of the server> is a name (or ip) of a host where our server is
running.
@@ -287,7 +302,7 @@ README file.
LICENSE
-------
- Active Port Forwarder is distributed under the terms of the GNU General
+ Active Port Forwarder is distributed under the terms of the GNU General
Public License v2.0 and is copyright (c) 2003,2004 jeremian <jeremian [at]
poczta.fm>. See the file COPYING for details.
diff --git a/activefor.h b/activefor.h
index 4c819c0..18211e1 100644
--- a/activefor.h
+++ b/activefor.h
@@ -39,7 +39,7 @@
#define S_STATE_OPEN 7
#define S_STATE_STOPPED 11
-#define AF_VER(info) info" v0.5.4"
+#define AF_VER(info) info" v0.5.5"
#define TYPE_TCP 1
#define TYPE_UDP 3
@@ -79,8 +79,18 @@ typedef struct {
int connfd;
char namebuf[128];
char portbuf[7];
+ int whatcli;
blnodeT* head;
} ConnectuserT;
+typedef struct {
+ char ready;
+ clifd cliconn;
+ struct timeval tv;
+ int* users;
+ int usercon;
+ int usernum;
+} ConnectclientT;
+
#endif
diff --git a/afclient.c b/afclient.c
index 0eed4f3..61ab6b8 100644
--- a/afclient.c
+++ b/afclient.c
@@ -21,7 +21,9 @@
#include "activefor.h"
#include "network.h"
#include "stats.h"
+#include "modules.h"
+#include <openssl/rsa.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <sys/time.h>
@@ -30,12 +32,12 @@
#include <signal.h>
#include <string.h>
#include <fcntl.h>
-#include <dlfcn.h>
#include <getopt.h>
static void usage(char* info);
static void sig_int(int);
+static void callback(int, int, void*);
static struct option long_options[] = {
{"help", 0, 0, 'h'},
@@ -53,6 +55,7 @@ static struct option long_options[] = {
{"ipv4", 0, 0, '4'},
{"ipv6", 0, 0, '6'},
{"load", 1, 0, 'l'},
+ {"Load", 1, 0, 'L'},
{0, 0, 0, 0}
};
@@ -83,17 +86,11 @@ main(int argc, char **argv)
char reverse = 0;
char type = 0;
struct sigaction act;
- struct {
- char loaded;
- char* name;
- void* handle;
- char* (*info)(void);
- int (*allow)(char*, char*);
- int (*filter)(char*, unsigned char*, int*);
- } module = {0, NULL, NULL, NULL, NULL};
+ moduleT module = {0, NULL, NULL, NULL, NULL}, secmodule = {0, NULL, NULL, NULL, NULL};
SSL_METHOD* method;
SSL_CTX* ctx;
+ RSA* rsa;
sigfillset(&(act.sa_mask));
act.sa_flags = 0;
@@ -103,7 +100,7 @@ main(int argc, char **argv)
act.sa_handler = sig_int;
sigaction(SIGINT, &act, NULL);
- while ((n = getopt_long(argc, argv, "huUn:m:d:p:vk:O:o:46l:", long_options, 0)) != -1) {
+ while ((n = getopt_long(argc, argv, "huUn:m:d:p:vk:O:o:46l:L:", long_options, 0)) != -1) {
switch (n) {
case 'h': {
usage(AF_VER("Active port forwarder (client)"));
@@ -181,6 +178,10 @@ main(int argc, char **argv)
module.name = optarg;
break;
}
+ case 'L': {
+ secmodule.name = optarg;
+ break;
+ }
case '?': {
usage("");
break;
@@ -207,26 +208,16 @@ main(int argc, char **argv)
if (despor == NULL) {
usage("Destination port number is required");
}
- if (keys == NULL) {
- keys = "client.rsa";
- }
- if (module.name) {
- module.handle = dlopen(module.name, RTLD_NOW);
- if (!module.handle) {
- printf("Can't load a module: %s\n", dlerror());
- exit(1);
- }
- dlerror();
- *(void**) (&module.info) = dlsym(module.handle, "info");
- *(void**) (&module.allow) = dlsym(module.handle, "allow");
- *(void**) (&module.filter) = dlsym(module.handle, "filter");
- if (dlerror() != NULL) {
+
+ if (loadmodule(&module)) {
printf("Loading a module %s failed!\n", module.name);
exit(1);
- }
- module.loaded = 1;
}
-
+ if (loadmodule(&secmodule)) {
+ printf("Loading a module %s failed!\n", secmodule.name);
+ exit(1);
+ }
+
TYPE_SET_SSL(type);
TYPE_SET_ZLIB(type);
@@ -262,9 +253,32 @@ main(int argc, char **argv)
printf("Setting cipher list failed... exiting\n");
exit(1);
}
- if (SSL_CTX_use_RSAPrivateKey_file(ctx, keys, SSL_FILETYPE_PEM) != 1) {
- printf("Setting rsa key failed (%s)... exiting\n", keys);
- exit(1);
+ if (keys == NULL) {
+ gettimeofday(&tv, 0);
+ srand(tv.tv_sec);
+ if (verbose)
+ printf("Generating RSA key...\n");
+ if (verbose>1) {
+ rsa = RSA_generate_key(2048, 65537, callback, NULL);
+ printf("\n");
+ }
+ else {
+ rsa = RSA_generate_key(2048, 65537, NULL, NULL);
+ }
+ if (verbose) {
+ if (RSA_check_key(rsa)==1) {
+ printf(" OK!\n");
+ }
+ else {
+ printf(" FAILED\n");
+ }
+ }
+ }
+ else {
+ if (SSL_CTX_use_RSAPrivateKey_file(ctx, keys, SSL_FILETYPE_PEM) != 1) {
+ printf("Setting rsa key failed (%s)... exiting\n", keys);
+ exit(1);
+ }
}
master.ssl = SSL_new(ctx);
if (SSL_set_fd(master.ssl, master.commfd) != 1) {
@@ -313,7 +327,7 @@ main(int argc, char **argv)
contable = calloc( usernum, sizeof(ConnectuserT));
if (contable == NULL) {
- printf("Calloc error - unable to succesfully comunicate with server\n");
+ printf("Calloc error - unable to succesfully communicate with server\n");
exit(1);
}
@@ -422,7 +436,6 @@ main(int argc, char **argv)
n = 0;
}
if (n == 0) { /* server quits -> we do the same... */
- gettimeofday(&tv, 0);
aflog(0, "premature quit of the server -> exiting...");
exit(1);
}
@@ -439,9 +452,12 @@ main(int argc, char **argv)
aflog(1, "SERVER SSL: %s, ZLIB: %s, MODE: %s", (TYPE_IS_SSL(type))?"yes":"no",
(TYPE_IS_ZLIB(type))?"yes":"no", (TYPE_IS_TCP(type))?"tcp":"udp");
aflog(2, "CIPHER: %s VER: %s", SSL_get_cipher_name(master.ssl), SSL_get_cipher_version(master.ssl));
- if (module.loaded) {
+ if (ismloaded(&module)) {
aflog(1, "LOADED MODULE: %s INFO: %s", module.name, module.info());
}
+ if (ismloaded(&secmodule)) {
+ aflog(1, "LOADED MODULE (ser): %s INFO: %s", secmodule.name, secmodule.info());
+ }
for ( ; ; ) {
rset = allset;
@@ -495,6 +511,42 @@ main(int argc, char **argv)
}
}
if (n) {
+ if (ismloaded(&secmodule)) {
+ switch ((temp2 = secmodule.filter(contable[i].namebuf, &buff[5], &n))) {
+ case 1: case 4: {
+ aflog(3, " user[%d] (by ser): PACKET IGNORED BY MODULE", i);
+ if (temp2 == 4) {
+ aflog(1, "RELEASED MODULE (ser): %s INFO: %s", secmodule.name, secmodule.info());
+ releasemodule(&secmodule);
+ }
+ continue;
+ break;
+ }
+ case 2: case 5: {
+ aflog(2, " user[%d] (by ser): DROPPED BY MODULE", i);
+ close(contable[i].connfd);
+ FD_CLR(contable[i].connfd, &allset);
+ FD_CLR(contable[i].connfd, &wset);
+ contable[i].state = S_STATE_CLOSING;
+ freebuflist(&contable[i].head);
+ buff[0] = AF_S_CONCLOSED; /* closing connection */
+ buff[1] = i >> 8; /* high bits of user number */
+ buff[2] = i; /* low bits of user number */
+ send_message(type, master, buff, 5);
+ if (temp2 == 5) {
+ aflog(1, "RELEASED MODULE (ser): %s INFO: %s", secmodule.name, secmodule.info());
+ releasemodule(&secmodule);
+ }
+ continue;
+ break;
+ }
+ case 3: {
+ aflog(1, "RELEASED MODULE (ser): %s INFO: %s", secmodule.name, secmodule.info());
+ releasemodule(&secmodule);
+ break;
+ }
+ }
+ }
buff[0] = AF_S_MESSAGE; /* sending message */
buff[1] = i >> 8; /* high bits of user number */
buff[2] = i; /* low bits of user number */
@@ -654,7 +706,7 @@ main(int argc, char **argv)
aflog(2, " user[%d]: OPENING", numofcon);
aflog(1, "user[%d]: IP:%s PORT:%s", numofcon,
contable[numofcon].namebuf, contable[numofcon].portbuf);
- if (module.loaded && module.allow(contable[numofcon].namebuf, contable[numofcon].portbuf)) {
+ if (ismloaded(&module) && module.allow(contable[numofcon].namebuf, contable[numofcon].portbuf)) {
aflog(2, " IT'S NOT ALLOWED - DROPPING", numofcon);
buff[0] = AF_S_CANT_OPEN; /* not opening connection */
buff[1] = numofcon >> 8; /* high bits of user number */
@@ -702,14 +754,18 @@ main(int argc, char **argv)
n = get_message(type, master, buff, length);
if ((numofcon>=0) && (numofcon<=usernum)) {
if (contable[numofcon].state == S_STATE_OPEN) {
- if (module.loaded) {
- switch (module.filter(contable[numofcon].namebuf, buff, &n)) {
- case 1: {
+ if (ismloaded(&module)) {
+ switch ((temp2 = module.filter(contable[numofcon].namebuf, buff, &n))) {
+ case 1: case 4:{
aflog(3, " user[%d]: PACKET IGNORED BY MODULE", numofcon);
+ if (temp2 == 4) {
+ aflog(1, "RELEASED MODULE: %s INFO: %s", module.name, module.info());
+ releasemodule(&module);
+ }
continue;
break;
}
- case 2: {
+ case 2: case 5:{
aflog(2, " user[%d]: DROPPED BY MODULE", numofcon);
close(contable[numofcon].connfd);
FD_CLR(contable[numofcon].connfd, &allset);
@@ -720,6 +776,16 @@ main(int argc, char **argv)
buff[1] = numofcon >> 8; /* high bits of user number */
buff[2] = numofcon; /* low bits of user number */
send_message(type, master, buff, 5);
+ if (temp2 == 5) {
+ aflog(1, "RELEASED MODULE: %s INFO: %s", module.name, module.info());
+ releasemodule(&module);
+ }
+ continue;
+ break;
+ }
+ case 3: {
+ aflog(1, "RELEASED MODULE: %s INFO: %s", module.name, module.info());
+ releasemodule(&module);
break;
}
}
@@ -751,6 +817,7 @@ main(int argc, char **argv)
FD_CLR(contable[numofcon].connfd, &allset);
FD_CLR(contable[numofcon].connfd, &wset);
contable[numofcon].state = S_STATE_CLOSING;
+ freebuflist(&contable[numofcon].head);
buff[0] = AF_S_CONCLOSED; /* closing connection */
buff[1] = numofcon >> 8; /* high bits of user number */
buff[2] = numofcon; /* low bits of user number */
@@ -801,7 +868,7 @@ usage(char* info)
printf(" destination of the packets (default: the name\n");
printf(" returned by hostname function)\n");
printf(" -p, --portnum - the port we are forwarding connection to (required)\n");
- printf(" -k, --keyfile - the name of the file with RSA key (default: client.rsa)\n");
+ printf(" -k, --keyfile - the name of the file with RSA key (default: (none))\n");
printf(" -u, --udpmode - udp mode - client will use udp protocol to\n");
printf(" communicate with the hostname\n");
printf(" -U, --reverseudp - reverse udp forwarding. Udp packets will be forwarded\n");
@@ -815,7 +882,8 @@ usage(char* info)
printf(" (default: no password)\n");
printf(" -4, --ipv4 - use ipv4 only\n");
printf(" -6, --ipv6 - use ipv6 only\n");
- printf(" -l, --load - load a module for packets filtering\n\n");
+ printf(" -l, --load - load a module for user's packets filtering\n");
+ printf(" -L, --Load - load a module for service's packets filtering\n\n");
exit(0);
}
@@ -826,3 +894,12 @@ sig_int(int signo)
aflog(1, "CLIENT CLOSED cg: %ld bytes", getcg());
exit(0);
}
+
+void
+callback(int i, int j, void* k)
+{
+ if (k == NULL) {
+ printf("%d", i);
+ fflush(stdout);
+ }
+}
diff --git a/afserver.c b/afserver.c
index 86fb85e..369ef69 100644
--- a/afserver.c
+++ b/afserver.c
@@ -28,19 +28,29 @@
#include <fcntl.h>
#include <signal.h>
#include <string.h>
-
+#include <sys/time.h>
#include <getopt.h>
static void usage(char* info);
static void sig_int(int);
+static void remove_client(RealmT*, int, fd_set*, fd_set*, int*);
+static int find_client(RealmT*, char);
+static int eval_numofcon(RealmT*, int, int);
+static int eval_usernum(ConnectclientT*, int);
+static int find_usernum(ConnectclientT*, int);
+static void check_value(int*, char*, char*);
static struct option long_options[] = {
{"help", 0, 0, 'h'},
{"hostname", 1, 0, 'n'},
{"listenport", 1, 0, 'l'},
{"manageport", 1, 0, 'm'},
+ {"timeout", 1, 0, 't'},
{"verbose", 0, 0, 'v'},
{"users", 1, 0, 'u'},
+ {"clients", 1, 0, 'C'},
+ {"usrpcli", 1, 0, 'U'},
+ {"climode", 1, 0, 'M'},
{"cerfile", 1, 0, 'c'},
{"keyfile", 1, 0, 'k'},
{"cfgfile", 1, 0, 'f'},
@@ -60,7 +70,7 @@ static ConfigurationT config;
int
main(int argc, char **argv)
{
- int i, j, n, flags, sent;
+ int i, j=0, k, n, flags, sent;
socklen_t len;
unsigned char buff[9000];
char hostname[100];
@@ -71,9 +81,12 @@ main(int argc, char **argv)
char* listen = NULL;
char* manage = NULL;
char* amount = NULL;
+ char* clients = NULL;
+ char* usrpcli = NULL;
+ char* clim = NULL;
char* filenam = NULL;
char* type = NULL;
- char* znak;
+ char* timeout = NULL;
unsigned char pass[4] = {1, 2, 3, 4};
char verbose = 0;
char mode = 0;
@@ -102,7 +115,7 @@ main(int argc, char **argv)
config.logging = 0;
config.logfnam = NULL;
- while ((n = getopt_long(argc, argv, "hn:l:m:vu:c:k:f:p:o:O:46", long_options, 0)) != -1) {
+ while ((n = getopt_long(argc, argv, "hn:l:m:vu:c:k:f:p:o:O:46t:C:U:M:", long_options, 0)) != -1) {
switch (n) {
case 'h': {
usage(AF_VER("Active port forwarder (server)"));
@@ -120,6 +133,10 @@ main(int argc, char **argv)
manage = optarg;
break;
}
+ case 't': {
+ timeout = optarg;
+ break;
+ }
case 'v': {
++verbose;
break;
@@ -128,6 +145,18 @@ main(int argc, char **argv)
amount = optarg;
break;
}
+ case 'C': {
+ clients = optarg;
+ break;
+ }
+ case 'U': {
+ usrpcli = optarg;
+ break;
+ }
+ case 'M': {
+ clim = optarg;
+ break;
+ }
case 'c': {
config.certif = optarg;
break;
@@ -146,7 +175,7 @@ main(int argc, char **argv)
}
case 'O': {
config.logfnam = optarg;
- config.logging = 2;
+ config.logging = 3;
break;
}
case 'o': {
@@ -162,14 +191,14 @@ main(int argc, char **argv)
TYPE_UNSET_ZLIB(mode);
break;
}
- case 303: {
- n = strlen(optarg);
- memset(pass, 0, 4);
- for (i = 0; i < n; ++i) {
- pass[i%4] += optarg[i];
- }
- break;
- }
+ case 303: {
+ n = strlen(optarg);
+ memset(pass, 0, 4);
+ for (i = 0; i < n; ++i) {
+ pass[i%4] += optarg[i];
+ }
+ break;
+ }
case '4': {
if (ipfam != 0) {
ipfam = -1;
@@ -222,9 +251,21 @@ main(int argc, char **argv)
if (manage == NULL) {
manage = "50126";
}
+ if (timeout == NULL) {
+ timeout = "5";
+ }
if (amount == NULL) {
amount = "5";
}
+ if (clients == NULL) {
+ clients = "1";
+ }
+ if (usrpcli == NULL) {
+ usrpcli = amount;
+ }
+ if (clim == NULL) {
+ clim = "1";
+ }
if (config.certif == NULL) {
config.certif = "cacert.pem";
}
@@ -240,6 +281,10 @@ main(int argc, char **argv)
config.realmtable[0].lisportnum = listen;
config.realmtable[0].manportnum = manage;
config.realmtable[0].users = amount;
+ config.realmtable[0].clients = clients;
+ config.realmtable[0].timeout = timeout;
+ config.realmtable[0].usrpcli = usrpcli;
+ config.realmtable[0].clim = clim;
memcpy(config.realmtable[0].pass, pass, 4);
if (strcmp(type, "tcp") == 0) {
TYPE_SET_TCP(config.realmtable[0].type);
@@ -273,9 +318,9 @@ main(int argc, char **argv)
exit(1);
}
if (SSL_CTX_use_RSAPrivateKey_file(ctx, config.keys, SSL_FILETYPE_PEM) != 1) {
- printf("Setting rsa key failed (%s)... exiting\n", config.keys);
- exit(1);
- }
+ printf("Setting rsa key failed (%s)... exiting\n", config.keys);
+ exit(1);
+ }
if (SSL_CTX_use_certificate_file(ctx, config.certif, SSL_FILETYPE_PEM) != 1) {
printf("Setting certificate failed (%s)... exiting\n", config.certif);
exit(1);
@@ -292,34 +337,54 @@ main(int argc, char **argv)
for (i = 0; i < config.size; ++i) {
if ((config.realmtable[i].hostname == NULL) ||
(config.realmtable[i].lisportnum == NULL) ||
- (config.realmtable[i].manportnum == NULL) ||
- (config.realmtable[i].users == NULL)) {
+ (config.realmtable[i].manportnum == NULL)) {
printf("Missing some of the configurable variables...\n");
- printf("\nRealm: %d\nhostname: %s\nlistenport: %s\nmanageport: %s\nusers: %s\n",
+ printf("\nRealm: %d\nhostname: %s\nlistenport: %s\nmanageport: %s\n",
i, config.realmtable[i].hostname,
config.realmtable[i].lisportnum,
- config.realmtable[i].manportnum,
- config.realmtable[i].users);
+ config.realmtable[i].manportnum);
exit(1);
}
+ /* checking type of the realm */
if (!TYPE_IS_SET(config.realmtable[i].type)) {
- printf("Unrecognized type of the realm... exiting\n");
- exit(1);
- }
- if ((( config.realmtable[i].usernum = strtol(config.realmtable[i].users, &znak, 10)) == LONG_MAX) || (config.realmtable[i].usernum == LONG_MIN)) {
- printf("Invalid user amount - %s\n", config.realmtable[i].users);
- exit(1);
+ TYPE_SET_TCP(config.realmtable[i].type);
}
- if (((*(config.realmtable[i].users)) == '\0') || (*znak != '\0')) {
- printf("Invalid user amount - %s\n", config.realmtable[i].users);
- exit(1);
- }
-
+ /* checking users amount */
+ if (config.realmtable[i].users == NULL) {
+ config.realmtable[i].users = "5";
+ }
+ check_value(&(config.realmtable[i].usernum), config.realmtable[i].users, "Invalid users amount");
+ /* checking clients amount */
+ if (config.realmtable[i].clients == NULL) {
+ config.realmtable[i].clients = "1";
+ }
+ check_value(&(config.realmtable[i].clinum), config.realmtable[i].clients, "Invalid clients amount");
+ /* checking usrpcli value */
+ if (config.realmtable[i].usrpcli == NULL) {
+ config.realmtable[i].usrpcli = config.realmtable[i].users;
+ }
+ check_value(&(config.realmtable[i].upcnum), config.realmtable[i].usrpcli, "Invalid usrpcli value");
+ /* checking timeout value */
+ if (config.realmtable[i].timeout == NULL) {
+ config.realmtable[i].timeout = "5";
+ }
+ check_value(&(config.realmtable[i].tmout), config.realmtable[i].timeout, "Invalid timeout value");
+ /* checking climode value */
+ if (config.realmtable[i].clim == NULL) {
+ config.realmtable[i].clim = "1";
+ }
+ check_value(&(config.realmtable[i].climode), config.realmtable[i].clim, "Invalid climode value");
+ /* allocating memory*/
config.realmtable[i].contable = calloc( config.realmtable[i].usernum, sizeof(ConnectuserT));
if (config.realmtable[i].contable == NULL) {
printf("Calloc error - try define smaller amount of users\n");
exit(1);
}
+ config.realmtable[i].clitable = calloc( config.realmtable[i].clinum, sizeof(ConnectclientT));
+ if (config.realmtable[i].clitable == NULL) {
+ printf("Calloc error - try define smaller amount of clients\n");
+ exit(1);
+ }
ipfam = 0x01;
if (TYPE_IS_IPV4(config.realmtable[i].type)) {
ipfam |= 0x02;
@@ -343,21 +408,35 @@ main(int argc, char **argv)
}
config.realmtable[i].cliaddr = malloc(config.realmtable[i].addrlen);
- config.realmtable[i].cliconn.ssl = SSL_new(ctx);
- if (config.realmtable[i].cliconn.ssl == NULL) {
- printf("Creating of ssl object failed... exiting\n");
- exit(1);
- }
+ for (j=0; j<config.realmtable[i].clinum; ++j) {
+ config.realmtable[i].clitable[j].cliconn.ssl = SSL_new(ctx);
+ if (config.realmtable[i].clitable[j].cliconn.ssl == NULL) {
+ printf("Creating of ssl object failed... exiting\n");
+ exit(1);
+ }
+ }
FD_SET(config.realmtable[i].managefd, &allset);
FD_SET(config.realmtable[i].listenfd, &allset);
maxfdp1 = (maxfdp1 > (config.realmtable[i].managefd+1)) ? maxfdp1 : (config.realmtable[i].managefd+1);
maxfdp1 = (maxfdp1 > (config.realmtable[i].listenfd+1)) ? maxfdp1 : (config.realmtable[i].listenfd+1);
config.realmtable[i].usercon = 0;
- config.realmtable[i].ready = 0;
- config.realmtable[i].tv.tv_sec = 5;
- config.realmtable[i].tv.tv_usec = 0;
- }
+ config.realmtable[i].clicon = 0;
+ for (j=0; j<config.realmtable[i].clinum; ++j) {
+ config.realmtable[i].clitable[j].ready = 0;
+ config.realmtable[i].clitable[j].tv.tv_sec = config.realmtable[i].tmout;
+ config.realmtable[i].clitable[j].tv.tv_usec = 0;
+ config.realmtable[i].clitable[j].usernum = config.realmtable[i].upcnum;
+ config.realmtable[i].clitable[j].users = malloc( config.realmtable[i].clitable[j].usernum * sizeof(int));
+ if (config.realmtable[i].clitable[j].users == NULL) {
+ printf("Calloc error - try define smaller amount of usrpcli (or users)\n");
+ exit(1);
+ }
+ for (k=0; k<config.realmtable[i].clitable[j].usernum; ++k) {
+ config.realmtable[i].clitable[j].users[k] = -1;
+ }
+ }
+ }
if (loginit(verbose, config.logging, config.logfnam)) {
printf("Can't open file to log to... exiting\n");
@@ -375,18 +454,24 @@ main(int argc, char **argv)
aflog(3, ">select, maxfdp1: %d", maxfdp1);
if (manconnecting) {
/* find out, in what realm client is trying to connect */
- for (i = 0; i < config.size; ++i) {
- if ((config.realmtable[i].ready == 1) || (config.realmtable[i].ready == 2)) {
- break; /* so i points to first good realm */
- }
+ for (k = 0; k < config.size; ++k) {
+ for (j=0; j < config.realmtable[k].clinum; ++j) {
+ if ((config.realmtable[k].clitable[j].ready == 1) || (config.realmtable[k].clitable[j].ready == 2)) {
+ i = k;
+ k = config.size;
+ break; /* so i points to first good realm and j to good client */
+ }
+ }
}
- if (select(maxfdp1, &rset, &tmpset, NULL, (&(config.realmtable[i].tv))) == 0) {
- close (config.realmtable[i].cliconn.commfd);
- FD_CLR(config.realmtable[i].cliconn.commfd, &allset);
+ if (select(maxfdp1, &rset, &tmpset, NULL, (&(config.realmtable[i].clitable[j].tv))) == 0) {
+ close (config.realmtable[i].clitable[j].cliconn.commfd);
+ FD_CLR(config.realmtable[i].clitable[j].cliconn.commfd, &allset);
FD_SET(config.realmtable[i].managefd, &allset);
- config.realmtable[i].ready = 0;
+ SSL_clear(config.realmtable[i].clitable[j].cliconn.ssl);
+ config.realmtable[i].clitable[j].ready = 0;
manconnecting--;
- aflog(1, " realm[%d]: SSL_accept failed (timeout)", i);
+ config.realmtable[i].clicon--;
+ aflog(1, " realm[%d]: client[%d]: SSL_accept failed (timeout)", i, j);
}
}
else {
@@ -397,125 +482,131 @@ main(int argc, char **argv)
for (j = 0; j < config.size; ++j) {
pointer = (&(config.realmtable[j]));
for (i = 0; i <pointer->usernum; ++i) {
- if ((pointer->contable[i].state == S_STATE_OPEN) ||
- (pointer->contable[i].state == S_STATE_STOPPED))
- if (FD_ISSET(pointer->contable[i].connfd, &rset)) {
- aflog(3, " realm[%d]: user[%d]: FD_ISSET", j, i);
- if (TYPE_IS_TCP(pointer->type)) { /* forwarding tcp packets */
- n = read(pointer->contable[i].connfd, &buff[5], 8091);
- if (n == -1)
- n = 0;
- if (n) {
- aflog(2, " realm[%d]: FROM user[%d]: MESSAGE length=%d", j, i, n);
- if ((buff[5] == AF_S_MESSAGE) &&
- (buff[6] == AF_S_LOGIN) &&
- (buff[7] == AF_S_MESSAGE)) {
- aflog(2, " WARNING: got packet similiar to udp");
- }
- buff[0] = AF_S_MESSAGE; /* sending message */
- buff[1] = i >> 8; /* high bits of user number */
- buff[2] = i; /* low bits of user number */
- buff[3] = n >> 8; /* high bits of message length */
- buff[4] = n; /* low bits of message length */
- send_message(pointer->type, pointer->cliconn, buff, n+5);
- }
- else {
- aflog(1, " realm[%d]: user[%d]: CLOSED", j, i);
- aflog(2, " IP:%s PORT:%s", pointer->contable[i].namebuf,
+ if ((pointer->contable[i].state == S_STATE_OPEN) || (pointer->contable[i].state == S_STATE_STOPPED))
+ if (FD_ISSET(pointer->contable[i].connfd, &rset)) {
+ k = eval_usernum(&(pointer->clitable[pointer->contable[i].whatcli]), i);
+ aflog(3, " realm[%d]: client[%d]: user[%d]: FD_ISSET", j, pointer->contable[i].whatcli, k);
+ if (TYPE_IS_TCP(pointer->type)) { /* forwarding tcp packets */
+ n = read(pointer->contable[i].connfd, &buff[5], 8091);
+ if (n == -1) {
+ aflog(3, " realm[%d]: client[%d]: user[%d]: READ ERROR (%d)", j,
+ pointer->contable[i].whatcli, k, errno);
+ n = 0;
+ }
+ if (n) {
+ aflog(2, " realm[%d]: client[%d]: FROM user[%d]: MESSAGE length=%d", j,
+ pointer->contable[i].whatcli, k, n);
+ if ((buff[5] == AF_S_MESSAGE) && (buff[6] == AF_S_LOGIN) && (buff[7] == AF_S_MESSAGE)) {
+ aflog(2, " WARNING: got packet similiar to udp");
+ }
+ buff[0] = AF_S_MESSAGE; /* sending message */
+ buff[1] = k >> 8; /* high bits of user number */
+ buff[2] = k; /* low bits of user number */
+ buff[3] = n >> 8; /* high bits of message length */
+ buff[4] = n; /* low bits of message length */
+ send_message(pointer->type, pointer->clitable[pointer->contable[i].whatcli].cliconn, buff, n+5);
+ }
+ else {
+ aflog(1, " realm[%d]: client[%d]: user[%d]: CLOSED", j, pointer->contable[i].whatcli, k);
+ aflog(2, " IP:%s PORT:%s", pointer->contable[i].namebuf,
pointer->contable[i].portbuf);
- close(pointer->contable[i].connfd);
- FD_CLR(pointer->contable[i].connfd, &allset);
- FD_CLR(pointer->contable[i].connfd, &wset);
- pointer->contable[i].state = S_STATE_CLOSING;
- freebuflist(&pointer->contable[i].head);
- buff[0] = AF_S_CONCLOSED; /* closing connection */
- buff[1] = i >> 8; /* high bits of user number */
- buff[2] = i; /* low bits of user number */
- send_message(pointer->type, pointer->cliconn, buff, 5);
- }
- }
- else { /* when forwarding udp packets */
- n = readn(pointer->contable[i].connfd, buff, 5 );
- if (n != 5) {
- n = 0;
- }
- if (n) {
- if ((buff[0] == AF_S_MESSAGE) && (buff[1] == AF_S_LOGIN)
- && (buff[2] == AF_S_MESSAGE)) {
- length = buff[3];
- length = length << 8;
- length += buff[4]; /* this is length of message */
- if ((n = readn(pointer->contable[i].connfd, &buff[5], length)) != 0) {
- aflog(2, " realm[%d]: FROM user[%d]: MESSAGE length=%d", j, i, n);
- buff[1] = i >> 8; /* high bits of user number */
- buff[2] = i; /* low bits of user number */
- send_message(pointer->type, pointer->cliconn, buff, n+5);
- }
- }
- else {
- n = 0;
- }
- }
-
- if (n == 0) {
- aflog(1, " realm[%d]: user[%d]: CLOSED", j, i);
- aflog(2, " IP:%s PORT:%s", pointer->contable[i].namebuf,
+ close(pointer->contable[i].connfd);
+ FD_CLR(pointer->contable[i].connfd, &allset);
+ FD_CLR(pointer->contable[i].connfd, &wset);
+ pointer->contable[i].state = S_STATE_CLOSING;
+ freebuflist(&pointer->contable[i].head);
+ buff[0] = AF_S_CONCLOSED; /* closing connection */
+ buff[1] = k >> 8; /* high bits of user number */
+ buff[2] = k; /* low bits of user number */
+ send_message(pointer->type, pointer->clitable[pointer->contable[i].whatcli].cliconn, buff, 5);
+ }
+ }
+ else { /* when forwarding udp packets */
+ n = readn(pointer->contable[i].connfd, buff, 5 );
+ if (n != 5) {
+ n = 0;
+ }
+ if (n) {
+ if ((buff[0] == AF_S_MESSAGE) && (buff[1] == AF_S_LOGIN) && (buff[2] == AF_S_MESSAGE)) {
+ length = buff[3];
+ length = length << 8;
+ length += buff[4]; /* this is length of message */
+ if ((n = readn(pointer->contable[i].connfd, &buff[5], length)) != 0) {
+ aflog(2, " realm[%d]: client[%d]: FROM user[%d]: MESSAGE length=%d", j,
+ pointer->contable[i].whatcli, k, n);
+ buff[1] = k >> 8; /* high bits of user number */
+ buff[2] = k; /* low bits of user number */
+ send_message(pointer->type, pointer->clitable[pointer->contable[i].whatcli].cliconn,
+ buff, n+5);
+ }
+ }
+ else {
+ n = 0;
+ }
+ }
+
+ if (n == 0) {
+ aflog(1, " realm[%d]: client[%d]: user[%d]: CLOSED (udp mode)", j,
+ pointer->contable[i].whatcli, k);
+ aflog(2, " IP:%s PORT:%s", pointer->contable[i].namebuf,
pointer->contable[i].portbuf);
- close(pointer->contable[i].connfd);
- FD_CLR(pointer->contable[i].connfd, &allset);
- FD_CLR(pointer->contable[i].connfd, &wset);
- pointer->contable[i].state = S_STATE_CLOSING;
- freebuflist(&pointer->contable[i].head);
- buff[0] = AF_S_CONCLOSED; /* closing connection */
- buff[1] = i >> 8; /* high bits of user number */
- buff[2] = i; /* low bits of user number */
- send_message(pointer->type, pointer->cliconn, buff, 5);
- }
-
- }
- }
- }
+ close(pointer->contable[i].connfd);
+ FD_CLR(pointer->contable[i].connfd, &allset);
+ FD_CLR(pointer->contable[i].connfd, &wset);
+ pointer->contable[i].state = S_STATE_CLOSING;
+ freebuflist(&pointer->contable[i].head);
+ buff[0] = AF_S_CONCLOSED; /* closing connection */
+ buff[1] = k >> 8; /* high bits of user number */
+ buff[2] = k; /* low bits of user number */
+ send_message(pointer->type, pointer->clitable[pointer->contable[i].whatcli].cliconn, buff, 5);
+ }
+
+ }
+ }
+ }
/* ------------------------------------ */
for (i = 0; i <pointer->usernum; ++i) {
- if (pointer->contable[i].state == S_STATE_STOPPED)
- if (FD_ISSET(pointer->contable[i].connfd, &tmpset)) {
- aflog(3, " realm[%d]: user[%d]: FD_ISSET - WRITE", j, i);
- n = pointer->contable[i].head->msglen - pointer->contable[i].head->actptr;
- sent = write(pointer->contable[i].connfd,
- &(pointer->contable[i].head->buff[pointer->contable[i].head->actptr]), n);
- if ((sent > 0) && (sent != n)) {
- pointer->contable[i].head->actptr+=sent;
- }
- else if ((sent == -1) && (errno == EAGAIN)) {
- }
- else if (sent == -1) {
- aflog(1, " realm[%d]: user[%d]: CLOSED", j, i);
- aflog(2, " IP:%s PORT:%s", pointer->contable[i].namebuf,
- pointer->contable[i].portbuf);
- close(pointer->contable[i].connfd);
- FD_CLR(pointer->contable[i].connfd, &allset);
- FD_CLR(pointer->contable[i].connfd, &wset);
- pointer->contable[i].state = S_STATE_CLOSING;
- freebuflist(&pointer->contable[i].head);
- buff[0] = AF_S_CONCLOSED; /* closing connection */
- buff[1] = i >> 8; /* high bits of user number */
- buff[2] = i; /* low bits of user number */
- send_message(pointer->type, pointer->cliconn, buff, 5);
- }
- else {
- deleteblnode(&pointer->contable[i].head);
- if (pointer->contable[i].head == NULL) {
- pointer->contable[i].state = S_STATE_OPEN;
- FD_CLR(pointer->contable[i].connfd, &wset);
- buff[0] = AF_S_CAN_SEND; /* stopping transfer */
- buff[1] = i >> 8; /* high bits of user number */
- buff[2] = i; /* low bits of user number */
- aflog(3, " realm[%d]: TO user[%d]: BUFFERING MESSAGE ENDED", j, i);
- send_message(pointer->type, pointer->cliconn, buff, 5);
- }
- }
- }
- }
+ if (pointer->contable[i].state == S_STATE_STOPPED)
+ if (FD_ISSET(pointer->contable[i].connfd, &tmpset)) {
+ k = eval_usernum(&(pointer->clitable[pointer->contable[i].whatcli]), i);
+ aflog(3, " realm[%d]: client[%d]: user[%d]: FD_ISSET - WRITE", j, pointer->contable[i].whatcli,
+ k);
+ n = pointer->contable[i].head->msglen - pointer->contable[i].head->actptr;
+ sent = write(pointer->contable[i].connfd,
+ &(pointer->contable[i].head->buff[pointer->contable[i].head->actptr]), n);
+ if ((sent > 0) && (sent != n)) {
+ pointer->contable[i].head->actptr+=sent;
+ }
+ else if ((sent == -1) && (errno == EAGAIN)) {
+ }
+ else if (sent == -1) {
+ aflog(1, " realm[%d]: client[%d]: user[%d]: CLOSED", j, pointer->contable[i].whatcli, k);
+ aflog(2, " IP:%s PORT:%s", pointer->contable[i].namebuf, pointer->contable[i].portbuf);
+ close(pointer->contable[i].connfd);
+ FD_CLR(pointer->contable[i].connfd, &allset);
+ FD_CLR(pointer->contable[i].connfd, &wset);
+ pointer->contable[i].state = S_STATE_CLOSING;
+ freebuflist(&pointer->contable[i].head);
+ buff[0] = AF_S_CONCLOSED; /* closing connection */
+ buff[1] = k >> 8; /* high bits of user number */
+ buff[2] = k; /* low bits of user number */
+ send_message(pointer->type, pointer->clitable[pointer->contable[i].whatcli].cliconn, buff, 5);
+ }
+ else {
+ deleteblnode(&pointer->contable[i].head);
+ if (pointer->contable[i].head == NULL) {
+ pointer->contable[i].state = S_STATE_OPEN;
+ FD_CLR(pointer->contable[i].connfd, &wset);
+ buff[0] = AF_S_CAN_SEND; /* stopping transfer */
+ buff[1] = k >> 8; /* high bits of user number */
+ buff[2] = k; /* low bits of user number */
+ aflog(3, " realm[%d]: client[%d]: TO user[%d]: BUFFERING MESSAGE ENDED", j,
+ pointer->contable[i].whatcli, k);
+ send_message(pointer->type, pointer->clitable[pointer->contable[i].whatcli].cliconn, buff, 5);
+ }
+ }
+ }
+ }
/* ------------------------------------ */
if (FD_ISSET(pointer->listenfd, &rset)) {
len = pointer->addrlen;
@@ -523,49 +614,59 @@ main(int argc, char **argv)
flags = fcntl(sent, F_GETFL, 0);
fcntl(sent, F_SETFL, flags | O_NONBLOCK);
aflog(3, " realm[%d]: listenfd: FD_ISSET", j);
- if (pointer->ready == 3) {
+ k = find_client(pointer, pointer->climode);
+ if (pointer->clitable[k].ready == 3) {
if (pointer->usercon == pointer->usernum) {
close(sent);
- aflog(3, " realm[%d]: user limit EXCEEDED", j);
- }
- else {
- for (i = 0; i < pointer->usernum; ++i) {
- if (pointer->contable[i].state == S_STATE_CLEAR) {
- aflog(2, " realm[%d]: new user[%d]: CONNECTING", j, i);
- pointer->contable[i].connfd = sent;
- pointer->contable[i].state = S_STATE_OPENING;
- pointer->usercon++;
- aflog(1, " user IP:%s",sock_ntop(pointer->cliaddr, len,
- pointer->contable[i].namebuf, pointer->contable[i].portbuf));
- memcpy(&buff[5], pointer->contable[i].namebuf, 128);
- memcpy(&buff[133], pointer->contable[i].portbuf, 7);
- n = 135;
- buff[0] = AF_S_CONOPEN; /* opening connection */
- buff[1] = i >> 8; /* high bits of user number */
- buff[2] = i; /* low bits of user number */
- buff[3] = n >> 8; /* high bits of message length */
- buff[4] = n; /* low bits of message length */
- send_message(pointer->type, pointer->cliconn, buff, n+5);
- break;
- }
- }
- }
- }
- else {
- close(sent);
- aflog(3, " realm[%d]: client is NOT CONNECTED", j);
- }
- }
- if (pointer->ready != 0) /* Command file descriptor */
- if (FD_ISSET(pointer->cliconn.commfd, &rset)) {
- if (pointer->ready == 1) {
- if (SSL_set_fd(pointer->cliconn.ssl, pointer->cliconn.commfd) != 1) {
+ aflog(3, " realm[%d]: user limit EXCEEDED", j);
+ }
+ else if(pointer->clitable[k].usercon == pointer->clitable[k].usernum) {
+ close(sent);
+ aflog(3, " realm[%d]: client[%d]: usrpcli limit EXCEEDED", j, k);
+ }
+ else {
+ for (i = 0; i < pointer->usernum; ++i) {
+ if (pointer->contable[i].state == S_STATE_CLEAR) {
+ aflog(2, " realm[%d]: client[%d]: new user: CONNECTING", j, k);
+ pointer->contable[i].connfd = sent;
+ pointer->contable[i].state = S_STATE_OPENING;
+ pointer->contable[i].whatcli = k;
+ pointer->usercon++;
+ pointer->clitable[k].usercon++;
+ aflog(1, " user IP:%s",sock_ntop(pointer->cliaddr, len,
+ pointer->contable[i].namebuf, pointer->contable[i].portbuf));
+ memcpy(&buff[5], pointer->contable[i].namebuf, 128);
+ memcpy(&buff[133], pointer->contable[i].portbuf, 7);
+ n = 135;
+ i = find_usernum(&(pointer->clitable[k]), i);
+ buff[0] = AF_S_CONOPEN; /* opening connection */
+ buff[1] = i >> 8; /* high bits of user number */
+ buff[2] = i; /* low bits of user number */
+ buff[3] = n >> 8; /* high bits of message length */
+ buff[4] = n; /* low bits of message length */
+ send_message(pointer->type, pointer->clitable[k].cliconn, buff, n+5);
+ break;
+ }
+ }
+ }
+ }
+ else {
+ close(sent);
+ aflog(3, " realm[%d]: client[%d] is NOT CONNECTED", j, k);
+ }
+ }
+ /* ------------------------------------ */
+ for (k = 0; k < pointer->clinum; ++k)
+ if (pointer->clitable[k].ready != 0) /* Command file descriptor */
+ if (FD_ISSET(pointer->clitable[k].cliconn.commfd, &rset)) {
+ if (pointer->clitable[k].ready == 1) {
+ if (SSL_set_fd(pointer->clitable[k].cliconn.ssl, pointer->clitable[k].cliconn.commfd) != 1) {
aflog(0, "Problem with initializing ssl... exiting");
exit(1);
}
aflog(2, " realm[%d]: new client: SSL_accept", j);
- if ((n = SSL_accept(pointer->cliconn.ssl)) != 1) {
- flags = SSL_get_error(pointer->cliconn.ssl, n);
+ if ((n = SSL_accept(pointer->clitable[k].cliconn.ssl)) != 1) {
+ flags = SSL_get_error(pointer->clitable[k].cliconn.ssl, n);
switch (flags) {
case SSL_ERROR_NONE : {
aflog(2, " SSL_accept has failed(%d)...none", n);
@@ -604,349 +705,290 @@ main(int argc, char **argv)
}
if (flags == SSL_ERROR_WANT_READ)
continue;
- close (pointer->cliconn.commfd);
- FD_CLR(pointer->cliconn.commfd, &allset);
+ close (pointer->clitable[k].cliconn.commfd);
+ FD_CLR(pointer->clitable[k].cliconn.commfd, &allset);
FD_SET(pointer->managefd, &allset);
- SSL_clear(pointer->cliconn.ssl);
- pointer->ready = 0;
+ SSL_clear(pointer->clitable[k].cliconn.ssl);
+ pointer->clitable[k].ready = 0;
manconnecting--;
- aflog(1, " realm[%d]: new client: DENIED by SSL_accept", j);
+ pointer->clicon--;
+ aflog(1, " realm[%d]: new client[%d]: DENIED by SSL_accept", j, k);
}
else {
- aflog(1, " realm[%d]: new client: ACCEPTED by SSL_accept", j);
- pointer->ready = 2;
+ aflog(1, " realm[%d]: new client[%d]: ACCEPTED by SSL_accept", j, k);
+ pointer->clitable[k].ready = 2;
}
continue; /* in the case this is not our client */
}
- aflog(3, " realm[%d]: commfd: FD_ISSET", j);
- if (pointer->ready == 2) {
- n = get_message(pointer->type | TYPE_SSL, pointer->cliconn, buff, -5);
+ aflog(3, " realm[%d]: client[%d]: commfd: FD_ISSET", j, k);
+ if (pointer->clitable[k].ready == 2) {
+ n = get_message(pointer->type | TYPE_SSL, pointer->clitable[k].cliconn, buff, -5);
}
else {
- n = get_message(pointer->type, pointer->cliconn, buff, -5);
+ n = get_message(pointer->type, pointer->clitable[k].cliconn, buff, -5);
}
if (n == -1) {
if (errno == EAGAIN) {
+ aflog(4, " realm[%d]: client[%d]: commfd: EAGAIN", j, k);
continue;
}
else {
+ aflog(4, " realm[%d]: client[%d]: commfd: ERROR: %d", j, k, errno);
n = 0;
}
}
else if (n != 5) {
n = 0;
}
- if (n==0) {
- close(pointer->cliconn.commfd);
- FD_CLR(pointer->cliconn.commfd, &allset);
- FD_SET(pointer->managefd, &allset);
- maxfdp1 = (maxfdp1 > (pointer->managefd+1)) ? maxfdp1 : (pointer->managefd+1);
- if (pointer->ready == 3) {
- for (i = 0; i < pointer->usernum; ++i) {
- if (pointer->contable[i].state != S_STATE_CLEAR) {
- pointer->contable[i].state = S_STATE_CLEAR;
- FD_CLR(pointer->contable[i].connfd, &allset);
- FD_CLR(pointer->contable[i].connfd, &wset);
- close(pointer->contable[i].connfd);
- }
- }
- }
- pointer->usercon = 0;
- SSL_clear(pointer->cliconn.ssl);
- pointer->ready = 0;
- aflog(1, " realm[%d]: commfd: CLOSED", j);
+ if (n==0) {
+ remove_client(pointer, k, &allset, &wset, &manconnecting);
+ aflog(1, " realm[%d]: client[%d]: commfd: CLOSED", j, k);
continue;
}
- numofcon = buff[1];
- numofcon = numofcon << 8;
- numofcon += buff[2]; /* this is id of user */
- length = buff[3];
- length = length << 8;
- length += buff[4]; /* this is length of message */
+
+ numofcon = buff[1];
+ numofcon = numofcon << 8;
+ numofcon += buff[2]; /* this is id of user */
+ length = buff[3];
+ length = length << 8;
+ length += buff[4]; /* this is length of message */
+
switch (buff[0]) {
case AF_S_CONCLOSED : {
- if ((numofcon>=0) &&
- (numofcon<=(pointer->usernum)) &&
- ((pointer->ready)==3)) {
- (pointer->usercon)--;
- if (pointer->contable[numofcon].state ==
- S_STATE_CLOSING) {
- pointer->contable[numofcon].state =
- S_STATE_CLEAR;
- }
- else if ((pointer->contable[numofcon].state == S_STATE_OPEN) ||
- (pointer->contable[numofcon].state == S_STATE_STOPPED)) {
- aflog(1, " realm[%d]: user[%d]: KICKED", j, numofcon);
- aflog(2, " IP:%s PORT:%s", pointer->contable[numofcon].namebuf,
- pointer->contable[numofcon].portbuf);
- close(pointer->contable[numofcon].connfd);
- FD_CLR(pointer->contable[numofcon].connfd, &allset);
- FD_CLR(pointer->contable[numofcon].connfd, &wset);
- pointer->contable[numofcon].state = S_STATE_CLEAR;
- freebuflist(&pointer->contable[numofcon].head);
- buff[0] = AF_S_CONCLOSED; /* closing connection */
- buff[1] = numofcon >> 8; /* high bits of user number */
- buff[2] = numofcon; /* low bits of user number */
- send_message(pointer->type, pointer->cliconn, buff, 5);
- }
- }
- else {
- close (pointer->cliconn.commfd);
- FD_CLR(pointer->cliconn.commfd, &allset);
- FD_SET(pointer->managefd, &allset);
- if (pointer->ready == 2)
- manconnecting--;
- SSL_clear(pointer->cliconn.ssl);
- pointer->ready = 0;
- }
- break;
- }
+ n = numofcon;
+ numofcon = eval_numofcon(pointer, k, numofcon);
+ if ((numofcon>=0) && (numofcon<(pointer->usernum)) && ((pointer->clitable[k].ready)==3)) {
+ pointer->usercon--;
+ pointer->clitable[k].usercon--;
+ pointer->clitable[k].users[n] = -1;
+ if (pointer->contable[numofcon].state == S_STATE_CLOSING) {
+ pointer->contable[numofcon].state = S_STATE_CLEAR;
+ }
+ else if ((pointer->contable[numofcon].state == S_STATE_OPEN) ||
+ (pointer->contable[numofcon].state == S_STATE_STOPPED)) {
+ aflog(1, " realm[%d]: user[%d]: KICKED", j, numofcon);
+ aflog(2, " IP:%s PORT:%s", pointer->contable[numofcon].namebuf,
+ pointer->contable[numofcon].portbuf);
+ close(pointer->contable[numofcon].connfd);
+ FD_CLR(pointer->contable[numofcon].connfd, &allset);
+ FD_CLR(pointer->contable[numofcon].connfd, &wset);
+ pointer->contable[numofcon].state = S_STATE_CLEAR;
+ freebuflist(&pointer->contable[numofcon].head);
+ buff[0] = AF_S_CONCLOSED; /* closing connection */
+ buff[1] = numofcon >> 8; /* high bits of user number */
+ buff[2] = numofcon; /* low bits of user number */
+ send_message(pointer->type, pointer->clitable[k].cliconn, buff, 5);
+ }
+ }
+ else {
+ remove_client(pointer, k, &allset, &wset, &manconnecting);
+ }
+ break;
+ }
case AF_S_CONOPEN : {
- if ((numofcon>=0) &&
- (numofcon<=(pointer->usernum)) &&
- ((pointer->ready)==3)) {
- if (pointer->contable[numofcon].state ==
- S_STATE_OPENING) {
- aflog(2, " realm[%d]: user[%d]: NEW", j, numofcon);
- FD_SET(pointer->contable[numofcon].connfd, &allset);
- maxfdp1 = (maxfdp1 > (pointer->contable[numofcon].connfd+1)) ?
- maxfdp1 : (pointer->contable[numofcon].connfd+1);
- pointer->contable[numofcon].state =
- S_STATE_OPEN;
- }
- }
- else {
- close (pointer->cliconn.commfd);
- FD_CLR(pointer->cliconn.commfd, &allset);
- FD_SET(pointer->managefd, &allset);
- if (pointer->ready == 2)
- manconnecting--;
- SSL_clear(pointer->cliconn.ssl);
- pointer->ready = 0;
- }
- break;
- }
-
+ numofcon = eval_numofcon(pointer, k, numofcon);
+ if ((numofcon>=0) && (numofcon<(pointer->usernum)) && ((pointer->clitable[k].ready)==3)) {
+ if (pointer->contable[numofcon].state == S_STATE_OPENING) {
+ aflog(2, " realm[%d]: user[%d]: NEW", j, numofcon);
+ FD_SET(pointer->contable[numofcon].connfd, &allset);
+ maxfdp1 = (maxfdp1 > (pointer->contable[numofcon].connfd+1)) ?
+ maxfdp1 : (pointer->contable[numofcon].connfd+1);
+ pointer->contable[numofcon].state = S_STATE_OPEN;
+ }
+ }
+ else {
+ remove_client(pointer, k, &allset, &wset, &manconnecting);
+ }
+ break;
+ }
case AF_S_CANT_OPEN : {
- if ((numofcon>=0) &&
- (numofcon<=(pointer->usernum)) &&
- ((pointer->ready)==3)) {
- if (pointer->contable[numofcon].state ==
- S_STATE_OPENING) {
- aflog(2, " realm[%d]: user[%d]: DROPPED",j, numofcon);
- (pointer->usercon)--;
- close(pointer->contable[numofcon].connfd);
- pointer->contable[numofcon].state =
- S_STATE_CLEAR;
- }
- }
- else {
- close (pointer->cliconn.commfd);
- FD_CLR(pointer->cliconn.commfd, &allset);
- FD_SET(pointer->managefd, &allset);
- if (pointer->ready == 2)
- manconnecting--;
- SSL_clear(pointer->cliconn.ssl);
- pointer->ready = 0;
- }
- break;
- }
-
-
-
+ n = numofcon;
+ numofcon = eval_numofcon(pointer, k, numofcon);
+ if ((numofcon>=0) && (numofcon<(pointer->usernum)) && ((pointer->clitable[k].ready)==3)) {
+ if (pointer->contable[numofcon].state == S_STATE_OPENING) {
+ aflog(2, " realm[%d]: user[%d]: DROPPED", j, numofcon);
+ pointer->usercon--;
+ pointer->clitable[k].usercon--;
+ pointer->clitable[k].users[n] = -1;
+ close(pointer->contable[numofcon].connfd);
+ pointer->contable[numofcon].state = S_STATE_CLEAR;
+ }
+ }
+ else {
+ remove_client(pointer, k, &allset, &wset, &manconnecting);
+ }
+ break;
+ }
case AF_S_MESSAGE : {
- if ((pointer->ready) != 3) {
- close (pointer->cliconn.commfd);
- FD_CLR(pointer->cliconn.commfd, &allset);
- FD_SET(pointer->managefd, &allset);
- manconnecting--;
- SSL_clear(pointer->cliconn.ssl);
- pointer->ready = 0;
+ if ((pointer->clitable[k].ready) != 3) {
+ remove_client(pointer, k, &allset, &wset, &manconnecting);
break;
- }
- if (TYPE_IS_UDP(pointer->type)) { /* udp */
- n = get_message(pointer->type, pointer->cliconn, &buff[5], length);
- }
- else {
- n = get_message(pointer->type, pointer->cliconn, buff, length);
- }
- if ((numofcon>=0) &&
- (numofcon<=(pointer->usernum))) {
- if (pointer->contable[numofcon].state ==
- S_STATE_OPEN) {
- aflog(2, " realm[%d]: TO user[%d]: MESSAGE length=%d", j, numofcon, n);
- if (TYPE_IS_UDP(pointer->type)) { /* udp */
- buff[1] = AF_S_LOGIN;
- buff[2] = AF_S_MESSAGE;
- buff[3] = n >> 8; /* high bits of message length */
- buff[4] = n; /* low bits of message length */
- sent = write(pointer->contable[numofcon].connfd, buff, n+5);
- if ((sent > 0) && (sent != n)) {
- insertblnode(&(pointer->contable[numofcon].head), sent, n, buff);
- pointer->contable[numofcon].state = S_STATE_STOPPED;
- FD_SET(pointer->contable[numofcon].connfd, &wset);
- buff[0] = AF_S_DONT_SEND; /* stopping transfer */
- buff[1] = numofcon >> 8; /* high bits of user number */
- buff[2] = numofcon; /* low bits of user number */
- aflog(3, " realm[%d]: TO user[%d]: BUFFERING MESSAGE STARTED", j, numofcon);
- send_message(pointer->type, pointer->cliconn, buff, 5);
- }
- else if ((sent == -1) && (errno == EAGAIN)) {
- insertblnode(&(pointer->contable[numofcon].head), 0, n, buff);
- pointer->contable[numofcon].state = S_STATE_STOPPED;
- FD_SET(pointer->contable[numofcon].connfd, &wset);
- buff[0] = AF_S_DONT_SEND; /* stopping transfer */
- buff[1] = numofcon >> 8; /* high bits of user number */
- buff[2] = numofcon; /* low bits of user number */
- aflog(3, " realm[%d]: TO user[%d]: BUFFERING MESSAGE STARTED", j, numofcon);
- send_message(pointer->type, pointer->cliconn, buff, 5);
- }
- else if (sent == -1) {
- aflog(1, " realm[%d]: user[%d]: CLOSED", j, numofcon);
- aflog(2, " IP:%s PORT:%s", pointer->contable[numofcon].namebuf,
- pointer->contable[numofcon].portbuf);
- close(pointer->contable[numofcon].connfd);
- FD_CLR(pointer->contable[numofcon].connfd, &allset);
- FD_CLR(pointer->contable[numofcon].connfd, &wset);
- pointer->contable[numofcon].state = S_STATE_CLOSING;
- freebuflist(&pointer->contable[numofcon].head);
- buff[0] = AF_S_CONCLOSED; /* closing connection */
- buff[1] = numofcon >> 8; /* high bits of user number */
- buff[2] = numofcon; /* low bits of user number */
- send_message(pointer->type, pointer->cliconn, buff, 5);
- }
- }
- else { /* tcp */
- sent = write(pointer->contable[numofcon].connfd, buff, n);
- if ((sent > 0) && (sent != n)) {
- insertblnode(&(pointer->contable[numofcon].head), sent, n, buff);
- pointer->contable[numofcon].state = S_STATE_STOPPED;
- FD_SET(pointer->contable[numofcon].connfd, &wset);
- buff[0] = AF_S_DONT_SEND; /* stopping transfer */
- buff[1] = numofcon >> 8; /* high bits of user number */
- buff[2] = numofcon; /* low bits of user number */
- aflog(3, " realm[%d]: TO user[%d]: BUFFERING MESSAGE STARTED", j, numofcon);
- send_message(pointer->type, pointer->cliconn, buff, 5);
- }
- else if ((sent == -1) && (errno == EAGAIN)) {
- insertblnode(&(pointer->contable[numofcon].head), 0, n, buff);
- pointer->contable[numofcon].state = S_STATE_STOPPED;
- FD_SET(pointer->contable[numofcon].connfd, &wset);
- buff[0] = AF_S_DONT_SEND; /* stopping transfer */
- buff[1] = numofcon >> 8; /* high bits of user number */
- buff[2] = numofcon; /* low bits of user number */
- aflog(3, " realm[%d]: TO user[%d]: BUFFERING MESSAGE STARTED", j, numofcon);
- send_message(pointer->type, pointer->cliconn, buff, 5);
- }
- else if (sent == -1) {
- aflog(1, " realm[%d]: user[%d]: CLOSED", j, numofcon);
- aflog(2, " IP:%s PORT:%s", pointer->contable[numofcon].namebuf,
- pointer->contable[numofcon].portbuf);
- close(pointer->contable[numofcon].connfd);
- FD_CLR(pointer->contable[numofcon].connfd, &allset);
- FD_CLR(pointer->contable[numofcon].connfd, &wset);
- pointer->contable[numofcon].state = S_STATE_CLOSING;
- freebuflist(&pointer->contable[numofcon].head);
- buff[0] = AF_S_CONCLOSED; /* closing connection */
- buff[1] = numofcon >> 8; /* high bits of user number */
- buff[2] = numofcon; /* low bits of user number */
- send_message(pointer->type, pointer->cliconn, buff, 5);
- }
- }
- }
- else if (pointer->contable[numofcon].state ==
- S_STATE_STOPPED) {
- aflog(3, " realm[%d]: TO user[%d]: BUFFERING MESSAGE", j, numofcon);
- if (TYPE_IS_UDP(pointer->type)) { /* udp */
- buff[1] = AF_S_LOGIN;
- buff[2] = AF_S_MESSAGE;
- buff[3] = n >> 8; /* high bits of message length */
- buff[4] = n; /* low bits of message length */
- insertblnode(&(pointer->contable[numofcon].head), 0, n+5, buff);
- }
- else {
- insertblnode(&(pointer->contable[numofcon].head), 0, n, buff);
- }
- }
- }
- break;
- }
+ }
+ if (TYPE_IS_UDP(pointer->type)) { /* udp */
+ n = get_message(pointer->type, pointer->clitable[k].cliconn, &buff[5], length);
+ }
+ else {
+ n = get_message(pointer->type, pointer->clitable[k].cliconn, buff, length);
+ }
+ numofcon = eval_numofcon(pointer, k, numofcon);
+ if ((numofcon>=0) && (numofcon<(pointer->usernum))) {
+ if (pointer->contable[numofcon].state == S_STATE_OPEN) {
+ aflog(2, " realm[%d]: TO user[%d]: MESSAGE length=%d", j, numofcon, n);
+ if (TYPE_IS_UDP(pointer->type)) { /* udp */
+ buff[1] = AF_S_LOGIN;
+ buff[2] = AF_S_MESSAGE;
+ buff[3] = n >> 8; /* high bits of message length */
+ buff[4] = n; /* low bits of message length */
+ sent = write(pointer->contable[numofcon].connfd, buff, n+5);
+ if ((sent > 0) && (sent != n)) {
+ insertblnode(&(pointer->contable[numofcon].head), sent, n, buff);
+ pointer->contable[numofcon].state = S_STATE_STOPPED;
+ FD_SET(pointer->contable[numofcon].connfd, &wset);
+ buff[0] = AF_S_DONT_SEND; /* stopping transfer */
+ buff[1] = numofcon >> 8; /* high bits of user number */
+ buff[2] = numofcon; /* low bits of user number */
+ aflog(3, " realm[%d]: TO user[%d]: BUFFERING MESSAGE STARTED (%d/%d)", j, numofcon,
+ sent, n);
+ send_message(pointer->type, pointer->clitable[k].cliconn, buff, 5);
+ }
+ else if ((sent == -1) && (errno == EAGAIN)) {
+ insertblnode(&(pointer->contable[numofcon].head), 0, n, buff);
+ pointer->contable[numofcon].state = S_STATE_STOPPED;
+ FD_SET(pointer->contable[numofcon].connfd, &wset);
+ buff[0] = AF_S_DONT_SEND; /* stopping transfer */
+ buff[1] = numofcon >> 8; /* high bits of user number */
+ buff[2] = numofcon; /* low bits of user number */
+ aflog(3, " realm[%d]: TO user[%d]: BUFFERING MESSAGE STARTED (%d/%d)", j, numofcon,
+ sent, n);
+ send_message(pointer->type, pointer->clitable[k].cliconn, buff, 5);
+ }
+ else if (sent == -1) {
+ aflog(1, " realm[%d]: user[%d]: CLOSED (write-udp)", j, numofcon);
+ aflog(2, " IP:%s PORT:%s", pointer->contable[numofcon].namebuf,
+ pointer->contable[numofcon].portbuf);
+ close(pointer->contable[numofcon].connfd);
+ FD_CLR(pointer->contable[numofcon].connfd, &allset);
+ FD_CLR(pointer->contable[numofcon].connfd, &wset);
+ pointer->contable[numofcon].state = S_STATE_CLOSING;
+ freebuflist(&pointer->contable[numofcon].head);
+ buff[0] = AF_S_CONCLOSED; /* closing connection */
+ buff[1] = numofcon >> 8; /* high bits of user number */
+ buff[2] = numofcon; /* low bits of user number */
+ send_message(pointer->type, pointer->clitable[k].cliconn, buff, 5);
+ }
+ }
+ else { /* tcp */
+ sent = write(pointer->contable[numofcon].connfd, buff, n);
+ if ((sent > 0) && (sent != n)) {
+ insertblnode(&(pointer->contable[numofcon].head), sent, n, buff);
+ pointer->contable[numofcon].state = S_STATE_STOPPED;
+ FD_SET(pointer->contable[numofcon].connfd, &wset);
+ buff[0] = AF_S_DONT_SEND; /* stopping transfer */
+ buff[1] = numofcon >> 8; /* high bits of user number */
+ buff[2] = numofcon; /* low bits of user number */
+ aflog(3, " realm[%d]: TO user[%d]: BUFFERING MESSAGE STARTED (%d/%d)", j, numofcon,
+ sent, n);
+ send_message(pointer->type, pointer->clitable[k].cliconn, buff, 5);
+ }
+ else if ((sent == -1) && (errno == EAGAIN)) {
+ insertblnode(&(pointer->contable[numofcon].head), 0, n, buff);
+ pointer->contable[numofcon].state = S_STATE_STOPPED;
+ FD_SET(pointer->contable[numofcon].connfd, &wset);
+ buff[0] = AF_S_DONT_SEND; /* stopping transfer */
+ buff[1] = numofcon >> 8; /* high bits of user number */
+ buff[2] = numofcon; /* low bits of user number */
+ aflog(3, " realm[%d]: TO user[%d]: BUFFERING MESSAGE STARTED (%d/%d)", j, numofcon,
+ sent, n);
+ send_message(pointer->type, pointer->clitable[k].cliconn, buff, 5);
+ }
+ else if (sent == -1) {
+ aflog(1, " realm[%d]: user[%d]: CLOSED (write-tcp)", j, numofcon);
+ aflog(2, " IP:%s PORT:%s", pointer->contable[numofcon].namebuf,
+ pointer->contable[numofcon].portbuf);
+ close(pointer->contable[numofcon].connfd);
+ FD_CLR(pointer->contable[numofcon].connfd, &allset);
+ FD_CLR(pointer->contable[numofcon].connfd, &wset);
+ pointer->contable[numofcon].state = S_STATE_CLOSING;
+ freebuflist(&pointer->contable[numofcon].head);
+ buff[0] = AF_S_CONCLOSED; /* closing connection */
+ buff[1] = numofcon >> 8; /* high bits of user number */
+ buff[2] = numofcon; /* low bits of user number */
+ send_message(pointer->type, pointer->clitable[k].cliconn, buff, 5);
+ }
+ }
+ }
+ else if (pointer->contable[numofcon].state == S_STATE_STOPPED) {
+ aflog(3, " realm[%d]: TO user[%d]: BUFFERING MESSAGE (%d)", j, numofcon, n);
+ if (TYPE_IS_UDP(pointer->type)) { /* udp */
+ buff[1] = AF_S_LOGIN;
+ buff[2] = AF_S_MESSAGE;
+ buff[3] = n >> 8; /* high bits of message length */
+ buff[4] = n; /* low bits of message length */
+ insertblnode(&(pointer->contable[numofcon].head), 0, n+5, buff);
+ }
+ else {
+ insertblnode(&(pointer->contable[numofcon].head), 0, n, buff);
+ }
+ }
+ }
+ break;
+ }
case AF_S_LOGIN : {
- if ((pointer->ready == 2)&&
- (numofcon==(pointer->pass[0]*256+pointer->pass[1]))&&
- (length==(pointer->pass[2]*256+pointer->pass[3]))) {
- pointer->ready = 3;
- aflog(1, " realm[%d]: pass ok - ACCESS GRANTED", j);
- buff[0] = AF_S_LOGIN; /* sending message */
- buff[1] = pointer->usernum >> 8;/* high bits of user number */
- buff[2] = pointer->usernum; /* low bits of user number */
- buff[3] = pointer->type; /* type of connection */
- send_message(pointer->type | TYPE_SSL, pointer->cliconn, buff, 5);
- manconnecting--;
- }
- else {
- aflog(1, " realm[%d]: Wrong password - CLOSING", j);
- close (pointer->cliconn.commfd);
- FD_CLR(pointer->cliconn.commfd, &allset);
- FD_SET(pointer->managefd, &allset);
- if (pointer->ready == 2)
- manconnecting--;
- SSL_clear(pointer->cliconn.ssl);
- pointer->ready = 0;
- }
- break;
- }
- case AF_S_DONT_SEND: {
- FD_CLR(pointer->contable[numofcon].connfd, &allset);
- break;
- }
- case AF_S_CAN_SEND: {
- FD_SET(pointer->contable[numofcon].connfd, &allset);
- break;
- }
-
+ if ((pointer->clitable[k].ready == 2) && (numofcon==(pointer->pass[0]*256+pointer->pass[1])) &&
+ (length==(pointer->pass[2]*256+pointer->pass[3]))) {
+ pointer->clitable[k].ready = 3;
+ aflog(1, " realm[%d]: pass ok - ACCESS GRANTED", j);
+ buff[0] = AF_S_LOGIN; /* sending message */
+ buff[1] = pointer->clitable[k].usernum >> 8;/* high bits of user number */
+ buff[2] = pointer->clitable[k].usernum; /* low bits of user number */
+ buff[3] = pointer->type; /* type of connection */
+ send_message(pointer->type | TYPE_SSL, pointer->clitable[k].cliconn, buff, 5);
+ manconnecting--;
+ }
+ else {
+ aflog(1, " realm[%d]: Wrong password - CLOSING", j);
+ remove_client(pointer, k, &allset, &wset, &manconnecting);
+ }
+ break;
+ }
+ case AF_S_DONT_SEND: {
+ FD_CLR(pointer->contable[numofcon].connfd, &allset);
+ break;
+ }
+ case AF_S_CAN_SEND: {
+ FD_SET(pointer->contable[numofcon].connfd, &allset);
+ break;
+ }
default : {
- aflog(1, " realm[%d]: Unrecognized message - CLOSING", j);
- close (pointer->cliconn.commfd);
- FD_CLR(pointer->cliconn.commfd, &allset);
- FD_SET(pointer->managefd, &allset);
- if (pointer->ready == 2)
- manconnecting--;
- if (pointer->ready == 3) {
- for (i = 0; i < pointer->usernum; ++i) {
- if (pointer->contable[i].state != S_STATE_CLEAR) {
- pointer->contable[i].state = S_STATE_CLEAR;
- FD_CLR(pointer->contable[i].connfd, &allset);
- FD_CLR(pointer->contable[i].connfd, &wset);
- close(pointer->contable[i].connfd);
- }
- }
- }
- SSL_clear(pointer->cliconn.ssl);
- pointer->ready = 0;
- }
- }
- }
-
- if (FD_ISSET(pointer->managefd, &rset)) {
- aflog(3, " realm[%d]: managefd: FD_ISSET", j);
- len = pointer->addrlen;
- if (!(pointer->ready)) {
- aflog(2, " realm[%d]: new client: CONNECTING", j);
- pointer->cliconn.commfd = accept(pointer->managefd, pointer->cliaddr, &len);
- flags = fcntl(pointer->cliconn.commfd, F_GETFL, 0);
- fcntl(pointer->cliconn.commfd, F_SETFL, flags | O_NONBLOCK);
- aflog(1, " realm[%d]: Client IP:%s", j, sock_ntop(pointer->cliaddr, len, NULL, NULL));
- FD_SET(pointer->cliconn.commfd, &allset);
- maxfdp1 = (maxfdp1 > (pointer->cliconn.commfd+1)) ? maxfdp1 : (pointer->cliconn.commfd+1);
- FD_CLR(pointer->managefd, &allset);
- pointer->tv.tv_sec = 5;
- manconnecting++;
- pointer->ready = 1;
- }
- }
- } /* realms loop */
- }
+ aflog(1, " realm[%d]: Unrecognized message - CLOSING", j);
+ remove_client(pointer, k, &allset, &wset, &manconnecting);
+ }
+ }
+ }
+ if (FD_ISSET(pointer->managefd, &rset)) {
+ aflog(3, " realm[%d]: managefd: FD_ISSET", j);
+ len = pointer->addrlen;
+ for (k = 0; k < pointer->clinum; ++k)
+ if (!(pointer->clitable[k].ready)) {
+ aflog(2, " realm[%d]: new client[%d]: CONNECTING", j, k);
+ pointer->clitable[k].cliconn.commfd = accept(pointer->managefd, pointer->cliaddr, &len);
+ flags = fcntl(pointer->clitable[k].cliconn.commfd, F_GETFL, 0);
+ fcntl(pointer->clitable[k].cliconn.commfd, F_SETFL, flags | O_NONBLOCK);
+ aflog(1, " realm[%d]: Client[%d] IP:%s", j, k, sock_ntop(pointer->cliaddr, len, NULL, NULL));
+ FD_SET(pointer->clitable[k].cliconn.commfd, &allset);
+ maxfdp1 = (maxfdp1 > (pointer->clitable[k].cliconn.commfd+1)) ?
+ maxfdp1 : (pointer->clitable[k].cliconn.commfd+1);
+ pointer->clicon++;
+ if (pointer->clicon == pointer->clinum)
+ FD_CLR(pointer->managefd, &allset);
+ pointer->clitable[k].tv.tv_sec = pointer->tmout;
+ manconnecting++;
+ pointer->clitable[k].ready = 1;
+ break;
+ }
+ }
+ } /* realms loop */
+ }
}
static void
@@ -954,15 +996,22 @@ usage(char* info)
{
printf("\n%s\n\n", info);
printf(" Options:\n");
- printf(" -h, --help - prints this help\n");
printf(" -n, --hostname - it's used when creating listening sockets\n");
printf(" (default: name returned by hostname function)\n");
printf(" -l, --listenport - listening port number - users connect\n");
printf(" to it (default: 50127)\n");
printf(" -m, --manageport - manage port number - second part of the active\n");
printf(" port forwarder connects to it (default: 50126)\n");
+ printf(" -t, --timeout - the timeout value for the client's connection\n");
+ printf(" (default: 5)\n");
printf(" -u, --users - the amount of users allowed to use this server\n");
printf(" (default: 5)\n");
+ printf(" -C, --clients - the number of allowed clients to use this server\n");
+ printf(" (default: 1)\n");
+ printf(" -U, --usrpcli - the number of allowed users per client (default: $users)\n");
+ printf(" -M, --climode - strategy used for connecting users with clients (default: 1)\n");
+ printf(" Available strategies:\n");
+ printf(" 1. fill first client before go to next\n\n");
printf(" -c, --cerfile - the name of the file with certificate\n");
printf(" (default: cacert.pem)\n");
printf(" -k, --keyfile - the name of the file with RSA key (default: server.rsa)\n");
@@ -973,28 +1022,136 @@ usage(char* info)
printf(" -O, --heavylog - logging everything to a logfile\n");
printf(" -o, --lightlog - logging some data to a logfile\n");
printf(" -v, --verbose - to be verbose - program won't enter the daemon mode\n");
- printf(" (use several times for greater effect)\n");
+ printf(" (use several times for greater effect)\n\n");
printf(" --nossl - ssl is not used for transfering data (but it's still\n");
printf(" used to establish a connection) (default: ssl is used)\n");
printf(" --nozlib - zlib is not used for compressing data (default:\n");
printf(" zlib is used)\n");
printf(" --pass - set the password used for client identification\n");
- printf(" (default: no password)\n");
+ printf(" (default: no password)\n\n");
printf(" -4, --ipv4 - use ipv4 only\n");
printf(" -6, --ipv6 - use ipv6 only\n\n");
+ printf(" -h, --help - prints this help\n\n");
exit(0);
}
static void
sig_int(int signo)
{
- int j;
+ int i, j;
unsigned char buff[5];
for (j = 0; j < config.size; ++j) {
buff[0] = AF_S_CLOSING; /* closing */
- send_message(config.realmtable[j].type, config.realmtable[j].cliconn, buff, 5);
+ for (i = 0; i < config.realmtable[j].clinum; ++i) {
+ if (config.realmtable[j].clitable[i].ready == 3) {
+ send_message(config.realmtable[j].type, config.realmtable[j].clitable[i].cliconn, buff, 5);
+ }
+ }
}
aflog(1, "SERVER CLOSED cg: %ld bytes", getcg());
exit(0);
}
+static void
+remove_client(RealmT* ptr, int client, fd_set* set, fd_set* wset, int* con)
+{
+ int i;
+ if (ptr->clitable[client].ready == 3) {
+ for (i = 0; i < ptr->usernum; ++i) {
+ if (ptr->contable[i].whatcli == client) {
+ if (ptr->contable[i].state != S_STATE_CLEAR) {
+ ptr->contable[i].state = S_STATE_CLEAR;
+ FD_CLR(ptr->contable[i].connfd, set);
+ FD_CLR(ptr->contable[i].connfd, wset);
+ close(ptr->contable[i].connfd);
+ ptr->usercon--;
+ }
+ }
+ }
+ }
+ ptr->clitable[client].usercon = 0;
+ close(ptr->clitable[client].cliconn.commfd);
+ FD_CLR(ptr->clitable[client].cliconn.commfd, set);
+ FD_SET(ptr->managefd, set);
+ if (ptr->clitable[client].ready == 2)
+ (*con)--;
+ SSL_clear(ptr->clitable[client].cliconn.ssl);
+ ptr->clitable[client].ready = 0;
+ ptr->clicon--;
+}
+
+static int
+find_client(RealmT* ptr, char mode)
+{
+ int i;
+ switch(mode) {
+ case 1: { /* fill first client before go to next */
+ for (i = 0; i < ptr->clinum; ++i) {
+ if (ptr->clitable[i].ready == 3) {
+ if (ptr->clitable[i].usercon < ptr->clitable[i].usernum) {
+ return i;
+ }
+ }
+ }
+ break;
+ }
+ default: {
+ return 0;
+ }
+ }
+ return 0;
+}
+
+static int
+eval_numofcon(RealmT* ptr, int client, int numofcon)
+{
+ if ((numofcon >= 0) && (numofcon < ptr->clitable[client].usernum)) {
+ numofcon = ptr->clitable[client].users[numofcon];
+ }
+ else {
+ numofcon = -1;
+ }
+ return numofcon;
+}
+
+static int
+eval_usernum(ConnectclientT* ptr, int usernum)
+{
+ int i;
+ for (i = 0; i < ptr->usernum; ++i) {
+ if (ptr->users[i] == usernum)
+ return i;
+ }
+ return -1;
+}
+
+static int
+find_usernum(ConnectclientT* ptr, int usernum)
+{
+ int i;
+ for (i = 0; i < ptr->usernum; ++i) {
+ if (ptr->users[i] == -1) {
+ ptr->users[i] = usernum;
+ return i;
+ }
+ }
+ return -1;
+}
+
+static void
+check_value(int* where, char* what, char* info)
+{
+ char* znak;
+ if ((( (*where) = strtol(what, &znak, 10)) == LONG_MAX) || ((*where) == LONG_MIN)) {
+ printf("%s: %s\n", info, what);
+ exit(1);
+ }
+ if (((*what) == '\0') || (*znak != '\0')) {
+ printf("%s: %s\n", info, what);
+ exit(1);
+ }
+ if ((*where) <= 0) {
+ printf("%s: %d\n", info, *where);
+ exit(1);
+ }
+}
diff --git a/buflist.c b/buflist.c
index b128249..d25a0ea 100644
--- a/buflist.c
+++ b/buflist.c
@@ -26,20 +26,20 @@
int
insertblnode(blnodeT** headRef, int actptr, int msglen, unsigned char* buff)
{
- blnodeT* newnode, *lastnode;
+ blnodeT* newnode, *lastnode;
lastnode = newnode = *headRef;
while (newnode) {
lastnode = newnode;
newnode = newnode->next;
}
- newnode = calloc(1, sizeof(blnodeT));
- newnode->next = NULL;
+ newnode = calloc(1, sizeof(blnodeT));
+ newnode->next = NULL;
newnode->actptr = 0;
newnode->msglen = msglen - actptr;
newnode->buff = calloc(1, newnode->msglen);
if (newnode->buff == NULL)
return 1;
- strncpy(newnode->buff, buff, newnode->msglen);
+ strncpy(newnode->buff, buff+actptr, newnode->msglen);
if (lastnode)
lastnode->next = newnode;
else
@@ -53,9 +53,10 @@ deleteblnode(blnodeT** headRef)
blnodeT* node = *headRef;
if (*headRef == NULL)
return 1;
- *headRef = node->next;
- free(node->buff);
- free(node);
+ *headRef = node->next;
+ if (node->buff != NULL)
+ free(node->buff);
+ free(node);
return 0;
}
diff --git a/config b/config
index 8230abc..8d82f1d 100644
--- a/config
+++ b/config
@@ -23,18 +23,20 @@ newrealm
#options values
-hostname <yourhostname> #this is a name of the server (it's using it for choosing interface)
-listen 50127 #portnumber on which server is listening for users
-manage 50126 #portnumber on which server is listening for afclient
-users 5 #amount of users we are allowing to connect
-proto tcp #type of the realm (which protocol it will forward (tcp|udp)
-#pass mypassword #this is a password used for client identification
+hostname <yourhostname> #this is a name of the server (it's using it for choosing interface)
+listen 50127 #portnumber on which server is listening for users
+manage 50126 #portnumber on which server is listening for afclient
+#users 5 #amount of users we are allowing to connect (>0) (default: 5)
+#timeout 5 #timeout value for the client's connection (>0) (default: 5)
+#clients 1 #number of allowed clients for this realm (>0) (default: 1)
+#usrpcli $users #allowed users per client for this realm (>0) (default: $users)
+#climode 1 #strategy used for connecting users with clients (1) (default: 1)
+#proto tcp #type of the realm (which protocol it will forward (tcp|udp) (default: tcp)
+#pass mypassword #this is a password used for client identification
# and now the second realm
newrealm
-hostname <yourhostname>
-listen 50125
-manage 50124
-users 5
-proto tcp
+hostname <yourhostname>
+listen 50125
+manage 50124
diff --git a/docs/ru/ru_README b/docs/ru/ru_README
new file mode 100644
index 0000000..4e825f7
--- /dev/null
+++ b/docs/ru/ru_README
@@ -0,0 +1,294 @@
+AF - Active Port Forwarder v0.5.4 - README
+Copyright (C) 2003,2004 jeremian - &lt;jeremian [at] poczta.fm&gt;
+===================
+
+================================================================================
+
+GRAY-WORLD.NET / Active Port Forwarder
+==========================
+
+ Программа Active Port Forwarder является частью проекта Gray-World.net.
+
+ Наша команда Gray-World представляет на сайте http://gray-world.net проекты и
+ публикации, над которыми мы работаем, относящиеся к области исследования
+ NACS (Систем Контроля Сетевого Доступа), а также к теме компьютерной и
+ сетевой безопасности.
+
+================================================================================
+
+==========
+СОДЕРЖАНИЕ
+==========
+
+ОПИСАНИЕ
+
+1. УСТАНОВКА
+ 1.1 Инструкции
+ 1.2 Необходимые библиотеки
+ 1.3 Тестовые платформы
+2. ИСПОЛЬЗОВАНИЕ
+ 2.1 afserver
+ 2.2 afclient
+3. ПРИМЕРЫ
+ 3.1 tcp-режим
+ 3.2 обратный udp-режим
+4. ИЗВЕСТНЫЕ ОШИБКИ/ПРОБЛЕМЫ
+
+ЗАМЕЧАНИЯ
+
+БЛАГОДАРНОСТИ
+
+================================================================================
+
+========
+ОПИСАНИЕ
+========
+
+Active port forwarder это программный инструмент для безопасного тунелирования
+данных. Он использует SSL для защиты соединения между клиентом и сервером.
+Изначально, программа была разработана для простой пересылки данных от точки к
+точке. Однако необходимость обхода брандмауэра с целью сделать компьютеры
+локальной сети доступными извне, повлияла на дальнейшее развитие проекта.
+
+AF предназначен для людей, не имеющих внешнего IP адреса и которые хотят сделать
+некоторые локальные сервисы доступными в сети.
+
+В программе использована библиотека zlib для сжатия передаваемых данных.
+
+Использование единого канала для передачи данных и команд управления в сочетании
+с буферизацией пересылаемых пакетов обеспечивает хорошую производительность и
+малое время отклика системы.
+
+Для запуска afserver не требуется привилегий root, также он не использует
+thread-ы или другие процессы.
+
+================================================================================
+
+============
+1. УСТАНОВКА
+============
+
+ 1.1 Инструкции
+ --------------
+
+1. Загрузите упакованный исходный код с http://www.gray-world.net/pr_af.shtml
+2. Распакуйте - tar zxvf
+3. Выполните команду "make".
+4. Если что-то пошло не так - напишите письмо автору или оставьте сообщение на
+ http://gray-world.net/board/
+
+ 1.2 Необходимые библиотеки
+ --------------------------
+
+1. openssl - http://www.openssl.org/
+2. zlib - http://www.gzip.org/zlib/
+
+ 1.3 Тестовые платформы
+ ----------------------
+
+1. Linux:
+ Gentoo, Slackware, Mandrake - было собрано без каких-либо проблем
+2. Freebsd:
+ 4.4, 4.9 - Необходим patch с домашней страницы проекта
+3. Windows:
+ win32 - Версия с cygwin доступна на домашней странице проекта
+
+================================================================================
+
+================
+2. ИСПОЛЬЗОВАНИЕ
+================
+
+ 2.1 afserver
+ ------------
+
+ Параметры:
+ -h, --help - печатает эту справку
+ -n, --hostname - используется при создании "слушающих" сокетов
+ (по умолчанию: имя возвращаемое функцией hostname)
+ -l, --listenport - порт сервера - пользователи соединяются
+ с ним (по умолчанию: 50127)
+ -m, --manageport - порт для управления - другая часть active
+ port forwarder соединяется с ним (по умолчанию: 50126)
+ -u, --users - количество пользователей, использующих сервер
+ (по умолчанию: 5)
+ -c, --cerfile - имя файла с сертификатом
+ (по умолчанию: cacert.pem)
+ -k, --keyfile - имя файла с ключом RSA (по умолчанию: server.rsa)
+ -f, --cfgfile - имя файла с конфигурацией для active forwarder (сервер)
+ -p, --proto - тип сервера (tcp|udp) - с каким протоколом он будет
+ работать (по умолчанию: tcp)
+ -O, --heavylog - писать все сообщения в logfile
+ -o, --lightlog - писать некоторые сообщения в logfile
+ -v, --verbose - вывод сообщений в консоль - програма не будет работать
+ как daemon.
+ --nossl - протокол ssl не будет использован для передачи данных (но
+ будет использован для установки соединений) (по умолчанию:
+ ssl используется всегда)
+ --nozlib - zlib не будет использоваться для сжатия данных
+ (по умолчанию: zlib используется)
+ --pass - задать пароль для идентификации клиента
+ (по умолчанию: нет пароля)
+ -4, --ipv4 - использовать только ipv4
+ -6, --ipv6 - использовать только ipv6
+
+ 2.2 afclient
+ ------------
+
+ Options:
+ -h, --help - печатает эту справку
+ -n, --servername - где работает вторая часть active port
+ forwarder (необходимо)
+ -m, --manageport - порт для управления - сервер соединяется с ним
+ (по умолчанию: 50126)
+ -d, --hostname - имя локального/удаленного сервера - данные будут тунелированы
+ на него (по умолчанию: имя возвращаемое фунцией hostname)
+ -p, --portnum - порт на который будут тунелированы данные (необходимо)
+ -k, --keyfile - имя файла с ключом RSA (по умолчанию: client.rsa)
+ -u, --udpmode - udp-режим - клиент будет использовать udp протокол для
+ коммуникации с hostname
+ -U, --reverseudp - обратный udp-режим. Udp пакеты будут перенаправляться
+ с hostname:portnum (-p) на сервер name:portnum (-m)
+ -O, --heavylog - писать все сообщения в logfile
+ -o, --lightlog - писать некоторые сообщения в logfile
+ -v, --verbose - вывод сообщений в консоль - програма не будет работать
+ как daemon.
+ --pass - задать пароль для идентификации клиента
+ (по умолчанию: нет пароля)
+ -4, --ipv4 - использовать только ipv4
+ -6, --ipv6 - использовать только ipv6
+ -l, --load - загрузить модуль для фильтрации пакетов
+
+================================================================================
+
+==========
+3. ПРИМЕРЫ
+==========
+
+ 3.1 tcp-режим
+ -------------
+
+ local network |FireWall| Internet
+ ||
+ || User 1
+ || /(tcp)
+ AF Client &lt;---Encrypted/Compressed channel---&gt; AF Server
+ / || | \(tcp)
+ /(tcp) || (tcp)| User 2
+ / || \
+ Http server || User 3
+ ||
+
+
+Использование этого режима черезвычано простое. Давайте предположим, что мы
+хотим создат http сервер на нашем компьютере, находящемся в локальной сети за
+брандмауэром:
+
+1) Мы должны найти машину с внешним IP адресом и доступом к shell.
+
+2) Использовать "make" чтобы скомпилировать AF на ней. (вы можете спокойно
+ удалять файлы afclient и client.rsa)
+
+3) Вы можете отредактировать конфигурационный файл или передать программе все
+ параметры из консоли (для использования файла наберите -f <cfgfile>) :
+ $ ./afserver
+ Это будет работать, если вы хотите использовать настройки по умолчанию:
+ - hostname будет взят из функции hostname (это работает замечательно, если
+ есть соответствующая запись в /etc/hosts)
+ - сервер будет ждать пользователей на порту 50127
+ - сервер будет ждать клиента на порту 50126
+ - сервер будет обслуживать макимум 5 пользователей
+ - сервер будет перенаправлять tcp соединения
+ - отладочных сообщений не будет
+ - идентификаций по паролю не будет
+ - версия протокола ip не будет задана
+
+4) Мы используем "make" на нашей машине (можно удалить все кроме afclient и
+ client.rsa)
+
+5) Набираем в консоли:
+ $ ./afclient -n <имя сервера> -p 80
+ Где <имя сервера> строка типа: 'bastion.univ.gda.pl' или '153.19.7.200'
+
+6) Теперь в браузере мы можем набрать: <имя сервера>:50127 и попадем на наш
+ компьютер.
+
+ 3.2 обратный udp-режим
+ ----------------------
+
+ local network |FireWall| Internet
+ || (udp)
+ || User 1-------AF Client
+ || /(tcp)
+ AF Client &lt;---Encrypted/Compressed channel---&gt; AF Server
+ / || |
+ /(udp) || (tcp)|
+ / || /
+ Game server || AF Client-------User 2
+ || (udp)
+
+
+Давайте теперь посмотрим как мы можем использовать af для перенаправления udp
+пакетов. Предположим, что мы хотим создать игровой сервер на нашем компьютере
+(udp порт 27960):
+
+1) - 4) тоже самое, что и в первом примере. (но добавляем параметр: -p udp)
+
+5) Набираем в консоли:
+ $ ./afclient -u -n <имя сервера> -p 27960
+ Где <имя сервера> это имя (или ip) компютера где работает наш сервер.
+
+6) Процесс соединения с игровым сервером более сложный. Пользователь должен
+ запустить fclient чтобы сделать это. Он должен указать сервер с которым он
+ будет соединяться и порт, на котором его программа будет слушать:
+ $ ./afclient -U -d <hostname> -p <порт> -n <имя сервера> \
+ -m <порт сервера>
+
+ Где <hostname> имя машины пользователя (который соединяется с игровым
+ сервером), <порт> - локальный порт, <имя сервера> - имя сервера, <порт
+ сервера> - порт на котором сервер ждет пользователей.Теперь, чтобы попасть на
+ игровой сервер, пользователь должен соединятся с <hostname>:<порт>.
+
+================================================================================
+
+============================
+4. ИЗВЕСТНЫЕ ОШИБКИ/ПРОБЛЕМЫ
+============================
+
+На данный момент, нет никаких известных проблем.
+
+================================================================================
+
+=========
+ЗАМЕЧАНИЯ
+=========
+
+Active port forwarder находится в разработке, так что пожалуйста, присылайте
+свои комментарии, замечания об ошибках и предложения на jeremian [at] poczta.fm
+
+Если у вас есть какие-либо проблемы с использованием программы или вы хотите
+поделиться своим мнением о ней, пожалйста оставляйте свои сообщения на:
+http://gray-world.net/board/
+
+================================================================================
+
+=============
+БЛАГОДАРНОСТИ
+=============
+
+ Большое спасибо команде GW:
+
+ Alex <alex [at] gray-world.net>
+ и Simon <scastro [at] entreelibre.com> за тестирование AF и множество советов.
+
+ Спасибо Ilia Perevezentsev <iliaper [at] mail.ru> за корректировку английской
+ версии этого файла.
+
+ И спасибо за использование AF!
+
+ЛИЦЕНЗИЯ
+--------
+
+ Active Port Forwarder is distributed under the terms of the GNU General
+ Public License v2.0 and is copyright (c) 2003,2004 jeremian <jeremian [at]
+ poczta.fm>. See the file COPYING for details.
diff --git a/exmodule.c b/exmodule.c
index 133609c..09141c4 100644
--- a/exmodule.c
+++ b/exmodule.c
@@ -18,10 +18,8 @@
*
*/
-/* This example module put IP of the connected user into a body of the message */
-#include <string.h>
-/* There is no required headers for module to work.
- * We just need string.h for memcpy and strlen functions.
+/* This example module scan the message for specified string and perform
+ * appropriate action
*/
/* info
@@ -32,7 +30,7 @@
char*
info(void)
{
- return "An example module";
+ return "Module tester v0.1";
}
/* allow
@@ -52,15 +50,32 @@ allow(char* host, char* port)
* 0 - allow to transfer
* 1 - drop the packet
* 2 - drop the connection
+ * 3 - release the module
+ * 4 - drop the packet and release the module
+ * 5 - drop the connection and release the module
*/
int
filter(char* host, unsigned char* message, int* length)
{
- int n;
- n = strlen(host);
- message[*length] = '|';
- memcpy(&message[*length+1], host, n);
- *length += n+1;
- return 0; /* allow to transfer */
+ int i;
+ for (i = 0; i < *length; ++i) {
+ if ((message[i] == 'M') && (message[i+1] == '1')) {
+ return 1; /* ignored */
+ }
+ if ((message[i] == 'M') && (message[i+1] == '2')) {
+ return 2; /* dropped */
+ }
+ if ((message[i] == 'M') && (message[i+1] == '3')) {
+ return 3; /* release */
+ }
+ if ((message[i] == 'M') && (message[i+1] == '4')) {
+ return 4; /* ignored + release */
+ }
+ if ((message[i] == 'M') && (message[i+1] == '5')) {
+ return 5; /* dropped + release */
+ }
+ }
+ return 0; /* allow to transfer */
+
}
diff --git a/file.c b/file.c
index d3712ea..59ff7ba 100644
--- a/file.c
+++ b/file.c
@@ -158,6 +158,22 @@ parsefile(char* name, int* status)
cfg.realmtable[cfg.size-1].users = calloc(strlen(helpbuf2)+1, sizeof(char));
strcpy(cfg.realmtable[cfg.size-1].users, helpbuf2);
}
+ else if (strcmp(helpbuf1, "timeout")==0) {
+ cfg.realmtable[cfg.size-1].timeout = calloc(strlen(helpbuf2)+1, sizeof(char));
+ strcpy(cfg.realmtable[cfg.size-1].timeout, helpbuf2);
+ }
+ else if (strcmp(helpbuf1, "clients")==0) {
+ cfg.realmtable[cfg.size-1].clients = calloc(strlen(helpbuf2)+1, sizeof(char));
+ strcpy(cfg.realmtable[cfg.size-1].clients, helpbuf2);
+ }
+ else if (strcmp(helpbuf1, "usrpcli")==0) {
+ cfg.realmtable[cfg.size-1].usrpcli = calloc(strlen(helpbuf2)+1, sizeof(char));
+ strcpy(cfg.realmtable[cfg.size-1].usrpcli, helpbuf2);
+ }
+ else if (strcmp(helpbuf1, "climode")==0) {
+ cfg.realmtable[cfg.size-1].clim = calloc(strlen(helpbuf2)+1, sizeof(char));
+ strcpy(cfg.realmtable[cfg.size-1].clim, helpbuf2);
+ }
else if (strcmp(helpbuf1, "proto")==0) {
if (TYPE_IS_SET(cfg.realmtable[cfg.size-1].type)) {
return cfg;
diff --git a/file.h b/file.h
index c0e752b..9132caa 100644
--- a/file.h
+++ b/file.h
@@ -36,17 +36,24 @@ typedef struct {
char* lisportnum;
char* manportnum;
char* users;
+ char* clients;
+ char* usrpcli;
+ char* clim;
+ char* timeout;
unsigned char pass[4];
int usercon;
int usernum;
+ int clicon;
+ int clinum;
+ int upcnum;
+ int tmout;
int listenfd;
int managefd;
- char ready;
+ int climode;
char type;
socklen_t addrlen;
struct sockaddr* cliaddr;
- struct timeval tv;
- clifd cliconn;
+ ConnectclientT* clitable;
ConnectuserT* contable;
} RealmT;
diff --git a/modules.c b/modules.c
new file mode 100644
index 0000000..75c2a08
--- /dev/null
+++ b/modules.c
@@ -0,0 +1,63 @@
+/*
+ * active port forwarder - software for secure forwarding
+ * Copyright (C) 2003,2004 jeremian <jeremian [at] poczta.fm>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "modules.h"
+
+#include <stdlib.h>
+#include <dlfcn.h>
+
+int
+loadmodule(moduleT* module)
+{
+ if (module->name) {
+ module->handle = dlopen(module->name, RTLD_NOW);
+ if (!module->handle) {
+ return 1;
+ }
+ dlerror();
+ *(void**) (&module->info) = dlsym(module->handle, "info");
+ *(void**) (&module->allow) = dlsym(module->handle, "allow");
+ *(void**) (&module->filter) = dlsym(module->handle, "filter");
+ if (dlerror() != NULL) {
+ return 2;
+ }
+ module->loaded = 1;
+ }
+ return 0;
+}
+
+int
+releasemodule(moduleT* module)
+{
+ if (ismloaded(module)) {
+ module->loaded = 0;
+ module->info = NULL;
+ module->allow = NULL;
+ module->filter = NULL;
+ return dlclose(module->handle);
+ }
+ return 0;
+}
+
+int
+ismloaded(moduleT* module)
+{
+ return module->loaded;
+}
diff --git a/modules.h b/modules.h
new file mode 100644
index 0000000..7527114
--- /dev/null
+++ b/modules.h
@@ -0,0 +1,37 @@
+/*
+ * active port forwarder - software for secure forwarding
+ * Copyright (C) 2003,2004 jeremian <jeremian [at] poczta.fm>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef _JS_MODULES_H
+#define _JS_MODULES_H
+
+typedef struct {
+ char loaded;
+ char* name;
+ void* handle;
+ char* (*info)(void);
+ int (*allow)(char*, char*);
+ int (*filter)(char*, unsigned char*, int*);
+} moduleT;
+
+int loadmodule(moduleT* module);
+int releasemodule(moduleT* module);
+int ismloaded(moduleT* module);
+
+#endif