summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Changelog13
-rw-r--r--Makefile22
-rw-r--r--README284
-rw-r--r--activefor.h23
-rw-r--r--afclient.c1246
-rw-r--r--afserver.c365
-rw-r--r--buflist.c69
-rw-r--r--buflist.h35
-rw-r--r--docs/en/README284
-rw-r--r--exmodule.c66
-rw-r--r--file.c280
-rw-r--r--network.c150
-rw-r--r--network.h6
13 files changed, 1974 insertions, 869 deletions
diff --git a/Changelog b/Changelog
index 4cb70d8..2b3e214 100644
--- a/Changelog
+++ b/Changelog
@@ -1,6 +1,17 @@
+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
+
09.01.2004 (v0.5.3):
- Added: client password identification (weak)
- - Added: sigint intercepting and server closing
+ - Added: sigint interception and server closing
- Modified: communication between server and client
- Added: 'nossl' and 'nozlib' modes
- Added: zlib support
diff --git a/Makefile b/Makefile
index 5e4463f..f6064d5 100644
--- a/Makefile
+++ b/Makefile
@@ -5,20 +5,18 @@ security=server.rsa client.rsa cacert.pem
all: compi $(programs) ok1 secure
-afserver: afserver.c network.o file.o stats.o
- $(CC) $(CFLAGS) -lssl -lz afserver.c network.o file.o stats.o -o afserver
+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
-afclient: afclient.c network.o stats.o
- $(CC) $(CFLAGS) -lssl -lz afclient.c network.o stats.o -o afclient
+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
-network.o: network.c network.h
- $(CC) $(CFLAGS) -c network.c
+%.o: %.c %.h
+ $(CC) $(CFLAGS) -c $*.c
-file.o: file.c file.h
- $(CC) $(CFLAGS) -c file.c
-
-stats.o: stats.c stats.h
- $(CC) $(CFLAGS) -c stats.c
+exmodule: exmodule.c
+ $(CC) -fPIC $(CFLAGS) -c $@.c
+ $(CC) $(CFLAGS) -shared -o $@ $@.o
secure: crea $(security) ok2
@@ -47,4 +45,4 @@ ok2:
.PHONY: clean
clean:
- rm -rf a.out *~ *.o $(programs) $(security)
+ rm -rf a.out *~ *.o $(programs) $(security) exmodule
diff --git a/README b/README
index fb52e60..e9ded51 100644
--- a/README
+++ b/README
@@ -1,4 +1,4 @@
-AF - Active Port Forwarder v0.5.3 - README
+AF - Active Port Forwarder v0.5.4 - README
Copyright (C) 2003,2004 jeremian - <jeremian [at] poczta.fm>
===================
@@ -7,85 +7,287 @@ 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
- Access Control System) bypassing research field and to the computer and
+ 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.
================================================================================
+=======
+SUMMARY
+=======
-Active port forwarder is a software for secure port forwarding.
-It uses ssl for increasing security of communication between server and client.
+INTRO
-Af is dedicated for people, who don't have external ip number and want to
+1. INSTALLATION
+ 1.1 Instructions
+ 1.2 Required libs
+ 1.3 Tested platforms
+2. USAGE
+ 2.1 afserver
+ 2.2 afclient
+3. EXAMPLES
+ 3.1 tcp mode
+ 3.2 reverse udp mode
+4. BUGS/PROBLEMS
+
+NOTES
+
+THANKS
+
+================================================================================
+
+=====
+INTRO
+=====
+
+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
make some services available across the net.
-Moreover, zlib is used to compress transfered data.
+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.
+
+================================================================================
+
+===============
+1. INSTALLATION
+===============
+
+ 1.1 Instructions
+ ----------------
+
+1. Download the compressed sources from http://www.gray-world.net/pr_af.shtml
+2. Unpack them with tar zxvf
+3. Type "make".
+4. If something goes wrong - mail the author or post a message on
+ http://gray-world.net/board/
+
+ 1.2 Required libs
+ -----------------
+
+1. openssl - http://www.openssl.org/
+2. zlib - http://www.gzip.org/zlib/
+
+ 1.3 Tested platforms
+ --------------------
+
+1. Linux:
+ Gentoo, Slackware, Mandrake - built without any problems
+2. Freebsd:
+ 4.4, 4.9 - have to use patch from project homepage
+3. Windows:
+ win32 - cygwin version is available on the project homepage
+
+================================================================================
+
+========
+2. USAGE
+========
+
+ 2.1 afserver
+ ------------
+
+ 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)
+ -u, --users - the amount of users allowed to use this server
+ (default: 5)
+ -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)
+ -f, --cfgfile - the name of the file with the configuration for the
+ active forwarder (server)
+ -p, --proto - type of server (tcp|udp) - for which protocol it will be
+ operating (default: tcp)
+ -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
+ (use several times for greater effect)
+ --nossl - ssl is not used for transferring 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
-EXAMPLE 1:
+ 2.2 afclient
+ ------------
-The use of it is extremely simple. Let's suppose we want to create http server on
-our computer and we are behind masquerade or firewall:
+ Options:
+ -h, --help - prints this help
+ -n, --servername - where the second part of the active
+ port forwarder is running (required)
+ -m, --manageport - manage port number - server must be
+ listening on it (default: 50126)
+ -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)
+ -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)
+ -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
+ (use several times for greater effect)
+ --pass - set the password used for client identification
+ (default: no password)
+ -4, --ipv4 - use ipv4 only
+ -6, --ipv6 - use ipv6 only
+ -l, --load - load a module for packets filtering
+
+================================================================================
+
+===========
+3. EXAMPLES
+===========
+
+ 3.1 tcp mode
+ ------------
+
+ local network |FireWall| Internet
+ ||
+ || User 1
+ || /(tcp)
+ AF Client <---Encrypted/Compressed channel---> AF Server
+ / || | \(tcp)
+ /(tcp) || (tcp)| User 2
+ / || \
+ Http server || User 3
+ ||
-1) We have to find some machine on the net with external ip and shell account.
-2) Use make to compile everything on that machine. (you can freely remove afclient
- and client.rsa files)
+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:
-3) You can edit config file or just type from the console: (to use config type -f <cfgfile>)
- $ ./afserver
+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
+ afclient and client.rsa files)
+
+3) You can edit the config file or just type from the console (to use the config
+ 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 there is
- appropriate registration in /etc/hosts)
+ - 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
- server will be for maximum 5 users
- server will forward tcp packets
- there will be no logging and no verbose messages
- there will be no password identification
+ - ip protocol family will be unspecified
-4) We use make on our machine (we can delete everything apart afclient and client.rsa)
+4) We use "make" on our machine (we can delete everything apart from afclient
+ and client.rsa)
5) We are typing from the console:
- $ ./afclient -n <name of the server> -p 80
- Where <name of the server> is a string like : 'bastion.univ.gda.pl' or '153.19.7.200'
+ $ ./afclient -n <name of the server> -p 80
+ Where <name of the server> is a string like : 'bastion.univ.gda.pl' or
+ '153.19.7.200'
+
+6) We can now enter with a web-browser to: <name of the server>:50127 and we
+ will enter to our computer in the fact.
+
+ 3.2 reverse udp mode
+ --------------------
-6) We can now enter with webbrowser to : <name of the server>:50127 and we will enter to our
- computer in the fact.
+ local network |FireWall| Internet
+ || (udp)
+ || User 1-------AF Client
+ || /(tcp)
+ AF Client <---Encrypted/Compressed channel---> AF Server
+ / || |
+ /(udp) || (tcp)|
+ / || /
+ Game server || AF Client-------User 2
+ || (udp)
-EXAMPLE 2:
-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):
+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: -t 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
- Where <name of the server> is a name (or ip) of a host where our server is running.
+ Where <name of the server> is a name (or ip) of a host where our server is
+ running.
+
+6) Connecting to our game is more complicated. The user must use afclient to do
+ this. He has to specify the server he is connecting to and the port, which
+ his program will be listening on:
+ $ ./afclient -U -d <hostname> -p <portnum> -n <name of the server> \
+ -m <server port>
+ Where <hostname> is the name of the user machine (who wants to connect to our
+ game). <portnum> is the port he will be connecting to. <name of the server>
+ is the name of the host where our server is running. <server port> is the
+ port on which the server is listening for users. In order to connect to our
+ game, the user has to connect to <hostname>:<portnum>.
+
+================================================================================
+
+================
+4. BUGS/PROBLEMS
+================
+
+There are no known/open bugs at the moment.
+
+================================================================================
+
+=====
+NOTES
+=====
+
+Active port forwarder is still under development, so please sent any comments,
+bugs notices and suggestions about it to <jeremian [at] poczta.fm>
+
+If you have some problems or want to share your opinions with others, feel free
+to post a message at http://gray-world.net/board/
+
+================================================================================
-6) Connecting to our game is more complicated. User must use afclient to do this.
- He has to specify server he is connecting to and port which his program will be listening on:
- $ ./afclient -U -d <hostname> -p <portnum> -n <name of the server> -m <server port>
- Where <hostname> is name of user machine (who wants to connect to our game). <portnum>
- is a port he will be connecting to. <name of the server> is a name of a host where our server
- is running. <server port> is a port on which server is listening for users.
- In order to connect to our game, user have to connect to <hostname>:<portnum>.
+======
+THANKS
+======
+ Big thanks to the GW Team:
-Active port forwarder is still under development, so please sent me any comments, bugs notices
-and suggestions about it to jeremian@poczta.fm
+ to Alex <alex [at] gray-world.net>
+ and Simon <scastro [at] entreelibre.com> for testing AF and a lot of advices.
+ Thanks to Ilia Perevezentsev <iliaper [at] mail.ru> who read and corrected the
+README file.
-And thanks for using this software!
+ And thanks for using this software!
LICENSE
-------
- Active Port Forwarder is distributed under the terms of the GNU General Public License
- v2.0 and is copyright (c) 2003 jeremian <jeremian [at] poczta.fm>.
- See the file COPYING for details.
+ 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 aa08149..4c819c0 100644
--- a/activefor.h
+++ b/activefor.h
@@ -22,26 +22,32 @@
#define _JS_ACTIVEFOR_H
#include "network.h"
+#include "buflist.h"
#define AF_S_CONCLOSED 1
#define AF_S_CONOPEN 2
#define AF_S_MESSAGE 3
#define AF_S_CLOSING 4
#define AF_S_LOGIN 8
+#define AF_S_DONT_SEND 9
+#define AF_S_CAN_SEND 10
+#define AF_S_CANT_OPEN 12
#define S_STATE_CLEAR 0
#define S_STATE_CLOSING 5
#define S_STATE_OPENING 6
#define S_STATE_OPEN 7
+#define S_STATE_STOPPED 11
-#define AF_VER(info) info" v0.5.3"
+#define AF_VER(info) info" v0.5.4"
#define TYPE_TCP 1
#define TYPE_UDP 3
#define TYPE_SSL 4
#define TYPE_ZLIB 8
+#define TYPE_IPV4 16
+#define TYPE_IPV6 32
#define TYPE_COMP 0x4000
-#define TYPE_NOTCOMP (~TYPE_COMP)
#define TYPE_SET_ZERO(type) (type=0)
#define TYPE_IS_SET(type) (type&1)
@@ -55,12 +61,25 @@
#define TYPE_SET_ZLIB(type) (type|=TYPE_ZLIB)
#define TYPE_UNSET_ZLIB(type) (type&=(~TYPE_ZLIB))
#define TYPE_IS_ZLIB(type) (type&TYPE_ZLIB)
+
+#define TYPE_SET_IPV4(type) (type|=TYPE_IPV4)
+#define TYPE_UNSET_IPV4(type) (type&=(~TYPE_IPV4))
+#define TYPE_IS_IPV4(type) (type&TYPE_IPV4)
+#define TYPE_SET_IPV6(type) (type|=TYPE_IPV6)
+#define TYPE_UNSET_IPV6(type) (type&=(~TYPE_IPV6))
+#define TYPE_IS_IPV6(type) (type&TYPE_IPV6)
+#define TYPE_SET_UNSPEC(type) (type&=(~(TYPE_IPV4|TYPE_IPV6)))
+#define TYPE_IS_UNSPEC(type) (!(type&(TYPE_IPV4|TYPE_IPV6)))
+
#define TYPE_SET_COMP(type) (type|=TYPE_COMP)
#define TYPE_IS_COMP(type) (type&TYPE_COMP)
typedef struct {
char state;
int connfd;
+ char namebuf[128];
+ char portbuf[7];
+ blnodeT* head;
} ConnectuserT;
#endif
diff --git a/afclient.c b/afclient.c
index 6deee54..0eed4f3 100644
--- a/afclient.c
+++ b/afclient.c
@@ -29,6 +29,8 @@
#include <linux/sockios.h>
#include <signal.h>
#include <string.h>
+#include <fcntl.h>
+#include <dlfcn.h>
#include <getopt.h>
@@ -36,557 +38,791 @@ static void usage(char* info);
static void sig_int(int);
static struct option long_options[] = {
- {"help", 0, 0, 'h'},
- {"udpmode", 0, 0, 'u'},
- {"reverseudp", 0, 0, 'U'},
- {"servername", 1, 0, 'n'},
- {"manageport", 1, 0, 'm'},
- {"hostname", 1, 0, 'd'},
- {"portnum", 1, 0, 'p'},
- {"verbose", 0, 0, 'v'},
- {"keyfile", 1, 0, 'k'},
- {"heavylog", 1, 0, 'O'},
- {"lightlog", 1, 0, 'o'},
- {"pass", 1, 0, 301},
- {0, 0, 0, 0}
+ {"help", 0, 0, 'h'},
+ {"udpmode", 0, 0, 'u'},
+ {"reverseudp", 0, 0, 'U'},
+ {"servername", 1, 0, 'n'},
+ {"manageport", 1, 0, 'm'},
+ {"hostname", 1, 0, 'd'},
+ {"portnum", 1, 0, 'p'},
+ {"verbose", 0, 0, 'v'},
+ {"keyfile", 1, 0, 'k'},
+ {"heavylog", 1, 0, 'O'},
+ {"lightlog", 1, 0, 'o'},
+ {"pass", 1, 0, 301},
+ {"ipv4", 0, 0, '4'},
+ {"ipv6", 0, 0, '6'},
+ {"load", 1, 0, 'l'},
+ {0, 0, 0, 0}
};
int
main(int argc, char **argv)
{
- int i, n, numofcon, length, buflength, notsent, temp2; /* !!! */
- ConnectuserT* contable = NULL;
- clifd master;
- unsigned char buff[9000];
- char hostname[100];
- struct timeval tv;
- int maxfdp1, usernum, usercon, merror;
- socklen_t len, addrlen;
- struct sockaddr* cliaddr;
- fd_set rset, allset;
- char verbose = 0;
- char logging = 0;
- char* name = NULL;
- char* manage = NULL;
- char* desnam = NULL;
- char* despor = NULL;
- char* keys = NULL;
- char* logfname = NULL;
- unsigned char pass[4];
- char udp = 0;
- char reverse = 0;
- char type;
+ int i, n, numofcon, length, buflength, notsent, temp2;
+ ConnectuserT* contable = NULL;
+ clifd master;
+ unsigned char buff[9000];
+ char hostname[100];
+ struct timeval tv;
+ int maxfdp1, usernum, usercon, merror;
+ socklen_t len, addrlen;
+ struct sockaddr* cliaddr;
+ fd_set rset, allset, wset, tmpset;
+ char verbose = 0;
+ char logging = 0;
+ char* name = NULL;
+ char* manage = NULL;
+ char* desnam = NULL;
+ char* despor = NULL;
+ char* keys = NULL;
+ char* logfname = NULL;
+ char ipfam = 0;
+ unsigned char pass[4] = {1, 2, 3, 4};
+ char udp = 0;
+ 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};
- SSL_METHOD* method;
- SSL_CTX* ctx;
+ SSL_METHOD* method;
+ SSL_CTX* ctx;
+
+ sigfillset(&(act.sa_mask));
+ act.sa_flags = 0;
+
+ act.sa_handler = SIG_IGN;
+ sigaction(SIGPIPE, &act, NULL);
+ act.sa_handler = sig_int;
+ sigaction(SIGINT, &act, NULL);
- signal(SIGPIPE, SIG_IGN);
- signal(SIGINT, sig_int);
+ while ((n = getopt_long(argc, argv, "huUn:m:d:p:vk:O:o:46l:", long_options, 0)) != -1) {
+ switch (n) {
+ case 'h': {
+ usage(AF_VER("Active port forwarder (client)"));
+ break;
+ }
+ case 'n': {
+ name = optarg;
+ break;
+ }
+ case 'm': {
+ manage = optarg;
+ break;
+ }
+ case 'd': {
+ desnam = optarg;
+ break;
+ }
+ case 'p': {
+ despor = optarg;
+ break;
+ }
+ case 'v': {
+ ++verbose;
+ break;
+ }
+ case 'u': {
+ udp = 1;
+ break;
+ }
+ case 'U': {
+ reverse = 1;
+ break;
+ }
+ case 'k': {
+ keys = optarg;
+ break;
+ }
+ case 'O': {
+ logfname = optarg;
+ logging = 3;
+ break;
+ }
+ case 'o': {
+ logfname = optarg;
+ logging = 1;
+ break;
+ }
+ case 301: {
+ 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;
+ }
+ else {
+ ipfam = 4;
+ }
+ break;
+ }
+ case '6': {
+ if (ipfam != 0) {
+ ipfam = -1;
+ }
+ else {
+ ipfam = 6;
+ }
+ break;
+ }
+ case 'l': {
+ module.name = optarg;
+ break;
+ }
+ case '?': {
+ usage("");
+ break;
+ }
+ }
+ }
- while ((n = getopt_long(argc, argv, "huUn:m:d:p:vk:O:o:", long_options, 0)) != -1) {
- switch (n) {
- case 'h': {
- usage(AF_VER("Active port forwarder (client)"));
- break;
- }
- case 'n': {
- name = optarg;
- break;
- }
- case 'm': {
- manage = optarg;
- break;
- }
- case 'd': {
- desnam = optarg;
- break;
- }
- case 'p': {
- despor = optarg;
- break;
- }
- case 'v': {
- ++verbose;
- break;
- }
- case 'u': {
- udp = 1;
- break;
- }
- case 'U': {
- reverse = 1;
- break;
- }
- case 'k': {
- keys = optarg;
- break;
- }
- case 'O': {
- logfname = optarg;
- logging = 2;
- break;
- }
- case 'o': {
- logfname = optarg;
- logging = 1;
- break;
- }
- case 301: {
- n = strlen(optarg);
- memset(pass, 0, 4);
- for (i = 0; i < n; ++i) {
- pass[i%4] += optarg[i];
- }
- break;
- }
- case '?': {
- usage("");
- break;
- }
- }
- }
+ if (optind < argc) {
+ usage("Unrecognized non-option elements");
+ }
- if (optind < argc) {
- usage("Unrecognized non-option elements");
- }
+ if (name == NULL) {
+ usage("Name of the server is required");
+ }
+ if (manage == NULL) {
+ manage = "50126";
+ if (reverse)
+ usage("Port on the server is required in reverse mode");
+ }
+ if (desnam == NULL) {
+ gethostname(hostname, 100);
+ desnam = hostname;
+ }
+ 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) {
+ printf("Loading a module %s failed!\n", module.name);
+ exit(1);
+ }
+ module.loaded = 1;
+ }
- if (name == NULL) {
- usage("Name of the server is required");
- }
- if (manage == NULL) {
- manage = "50126";
- if (reverse)
- usage("Port on the server is required in reverse mode");
- }
- if (desnam == NULL) {
- gethostname(hostname, 100);
- desnam = hostname;
- }
- if (despor == NULL) {
- usage("Destination port number is required");
- }
- if (keys == NULL) {
- keys = "client.rsa";
- }
+ TYPE_SET_SSL(type);
+ TYPE_SET_ZLIB(type);
- type = 0;
- TYPE_SET_SSL(type);
- TYPE_SET_ZLIB(type);
+ if (ipfam == -1) {
+ printf("Conflicting types of ip protocol family... exiting\n");
+ exit(1);
+ }
+ else if (ipfam == 4) {
+ TYPE_SET_IPV4(type);
+ }
+ else if (ipfam == 6) {
+ TYPE_SET_IPV6(type);
+ }
- master.commfd = ip_connect(name, manage, "tcp");
+ ipfam = 0x01;
+ if (TYPE_IS_IPV4(type)) {
+ ipfam |= 0x02;
+ }
+ else if (TYPE_IS_IPV6(type)) {
+ ipfam |= 0x04;
+ }
+ if (ip_connect(&(master.commfd), name, manage, ipfam)) {
+ printf("tcp_connect_%s error for %s, %s\n",
+ (ipfam & 0x02)?"ipv4":(ipfam & 0x04)?"ipv6":"unspec", name, manage);
+ exit(1);
+ }
- if (!reverse) {
- SSL_library_init();
- method = SSLv3_client_method();
- ctx = SSL_CTX_new(method);
- if (SSL_CTX_set_cipher_list(ctx, "ALL:@STRENGTH") == 0) {
- 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);
- }
- master.ssl = SSL_new(ctx);
- if (SSL_set_fd(master.ssl, master.commfd) != 1) {
- printf("Problem with initializing ssl... exiting\n");
- exit(1);
- }
- if (verbose>1)
- printf("Trying SSL_connect\n");
- if ((n = SSL_connect(master.ssl)) == 1) {
- if (verbose) {
- printf("SSL_connect successfull\n");
- }
- }
- else {
- printf("SSL_connect has failed (%d)... exiting\n", n);
- exit(1);
- }
+ if (!reverse) {
+ SSL_library_init();
+ method = SSLv3_client_method();
+ ctx = SSL_CTX_new(method);
+ if (SSL_CTX_set_cipher_list(ctx, "ALL:@STRENGTH") == 0) {
+ 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);
+ }
+ master.ssl = SSL_new(ctx);
+ if (SSL_set_fd(master.ssl, master.commfd) != 1) {
+ printf("Problem with initializing ssl... exiting\n");
+ exit(1);
+ }
+ if (verbose>1)
+ printf("Trying SSL_connect\n");
+ if ((n = SSL_connect(master.ssl)) == 1) {
+ if (verbose) {
+ printf("SSL_connect successfull\n");
+ }
+ }
+ else {
+ printf("SSL_connect has failed (%d)... exiting\n", n);
+ exit(1);
+ }
-
- buff[0] = AF_S_LOGIN;
- buff[1] = pass[0];
- buff[2] = pass[1];
- buff[3] = pass[2];
- buff[4] = pass[3];
- send_message(type, master, buff, 5);
- buff[0] = 0;
- get_message(type, master, buff, -5);
-
- if ( buff[0] == 0 ) {
- printf("Wrong password\n");
- exit(1);
- }
- if ( buff[0] != AF_S_LOGIN ) {
- printf("Incompatible server type or server full\n");
- exit(1);
- }
+ buff[0] = AF_S_LOGIN;
+ buff[1] = pass[0];
+ buff[2] = pass[1];
+ buff[3] = pass[2];
+ buff[4] = pass[3];
+ send_message(type, master, buff, 5);
+ buff[0] = 0;
+ get_message(type, master, buff, -5);
- type = buff[3];
- usernum = buff[1];
- usernum = usernum << 8;
- usernum += buff[2];
+ if ( buff[0] == 0 ) {
+ printf("Wrong password\n");
+ exit(1);
+ }
+ if ( buff[0] != AF_S_LOGIN ) {
+ printf("Incompatible server type or server full\n");
+ exit(1);
+ }
- } /* !reverse */
- else {
- usernum = 1;
- master.ssl = NULL;
- }
+ type = buff[3];
+ usernum = buff[1];
+ usernum = usernum << 8;
+ usernum += buff[2];
+ } /* !reverse */
+ else {
+ usernum = 1;
+ master.ssl = NULL;
+ }
- contable = calloc( usernum, sizeof(ConnectuserT));
- if (contable == NULL) {
- printf("Calloc error - unable to succesfully comunicate with server\n");
- exit(1);
- }
+ contable = calloc( usernum, sizeof(ConnectuserT));
+ if (contable == NULL) {
+ printf("Calloc error - unable to succesfully comunicate with server\n");
+ exit(1);
+ }
- len = 4;
- if (getsockopt(master.commfd, SOL_SOCKET, SO_SNDBUF, &buflength, &len) == -1) {
- printf("Can't get socket send buffor size - exiting...\n");
- exit(1);
- }
+ len = 4;
+ if (getsockopt(master.commfd, SOL_SOCKET, SO_SNDBUF, &buflength, &len) == -1) {
+ printf("Can't get socket send buffer size - exiting...\n");
+ exit(1);
+ }
- if (loginit(verbose, logging, logfname)) {
- printf("Can't open file to log to... exiting\n");
- exit(1);
- }
+ if (loginit(verbose, logging, logfname)) {
+ printf("Can't open file to log to... exiting\n");
+ exit(1);
+ }
- if (!verbose)
- daemon(0, 0);
+ if (!verbose)
+ daemon(0, 0);
- FD_ZERO(&allset);
+ FD_ZERO(&allset);
+ FD_ZERO(&wset);
- FD_SET(master.commfd, &allset);
- maxfdp1 = master.commfd + 1;
+ FD_SET(master.commfd, &allset);
+ maxfdp1 = master.commfd + 1;
- if (reverse) {
- contable[0].connfd=ip_listen(desnam, despor, &addrlen, "udp");
- cliaddr = malloc(addrlen);
- maxfdp1 = (maxfdp1>contable[0].connfd+1) ? maxfdp1 : contable[0].connfd+1;
- FD_SET(contable[0].connfd, &allset);
- aflog(1, "CLIENT STARTED mode: udp reverse");
- for ( ; ; ) {
- len = 4;
- if (getsockopt(master.commfd, SOL_SOCKET, SO_SNDBUF, &temp2, &len) != -1) {
- if (temp2 != buflength) {
- buflength = temp2;
- aflog(2, "Send buffor size changed...");
- }
- }
- len = addrlen;
- rset = allset;
- aflog(2, ">select");
- select(maxfdp1, &rset, NULL, NULL, NULL);
- aflog(2, " >>after select...");
- if (FD_ISSET(contable[0].connfd, &rset)) {
- n = recvfrom(contable[0].connfd, &buff[5], 8091, 0, cliaddr, &len);
+ /* UDP REVERSE MODE */
+
+ if (reverse) {
+ ipfam = 0;
+ if (TYPE_IS_IPV4(type)) {
+ ipfam |= 0x02;
+ }
+ else if (TYPE_IS_IPV6(type)) {
+ ipfam |= 0x04;
+ }
+ if (ip_listen(&(contable[0].connfd), desnam, despor, &addrlen, ipfam)) {
+ printf("udp_listen_%s error for %s, %s\n",
+ (ipfam & 0x02)?"ipv4":(ipfam & 0x04)?"ipv6":"unspec", desnam, despor);
+ exit(1);
+ }
+ cliaddr = malloc(addrlen);
+ maxfdp1 = (maxfdp1>contable[0].connfd+1) ? maxfdp1 : contable[0].connfd+1;
+ FD_SET(contable[0].connfd, &allset);
+ aflog(1, "CLIENT STARTED mode: udp reverse");
+ for ( ; ; ) {
+ len = 4;
+ if (getsockopt(master.commfd, SOL_SOCKET, SO_SNDBUF, &temp2, &len) != -1) {
+ if (temp2 != buflength) {
+ buflength = temp2;
+ aflog(2, "Send buffer size changed...");
+ }
+ }
+ len = addrlen;
+ rset = allset;
+ aflog(3, ">select");
+ select(maxfdp1, &rset, NULL, NULL, NULL);
+ aflog(3, " >>after select...");
+
+ if (FD_ISSET(contable[0].connfd, &rset)) { /* FD_ISSET CONTABLE[0].CONNFD RSET*/
+ n = recvfrom(contable[0].connfd, &buff[5], 8091, 0, cliaddr, &len);
#ifdef SIOCOUTQ
- if (ioctl(master.commfd, SIOCOUTQ, &notsent)) {
- aflog(0, "ioctl error -> exiting...");
- exit(1);
- }
- if (buflength <= notsent + n + 5) { /* when we can't do this */
- aflog(2, "drop: size:%d, buf:%d, w:%d/%d",
- n, buflength, notsent, buflength);
+ if (ioctl(master.commfd, SIOCOUTQ, &notsent)) {
+ aflog(0, "ioctl error -> exiting...");
+ exit(1);
+ }
+ if (buflength <= notsent + n + 5) { /* when we can't do this */
+ aflog(2, "drop: size:%d, buf:%d, w:%d/%d", n, buflength, notsent, buflength);
#else
- if (ioctl(master.commfd, TIOCOUTQ, &notsent)) {
- aflog(0, "ioctl error -> exiting...");
- exit(1);
- }
- if (notsent <= n + 5) { /* when we can't do this */
- aflog(2, "drop: size:%d, buf:%d, w:%d/%d",
- n, buflength, buflength - notsent, buflength);
+ if (ioctl(master.commfd, TIOCOUTQ, &notsent)) {
+ aflog(0, "ioctl error -> exiting...");
+ exit(1);
+ }
+ if (notsent <= n + 5) { /* when we can't do this */
+ aflog(2, "drop: size:%d, buf:%d, w:%d/%d", n, buflength, buflength - notsent, buflength);
#endif
- }
- else {
- if (n > 0) {
- aflog(2, "Sending %d bytes to service (w:%d/%d)",
- n,
+ }
+ else {
+ if (n > 0) {
+ aflog(2, "Sending %d bytes to service (w:%d/%d)", n,
#ifdef SIOCOUTQ
- notsent
+ notsent
#else
- buflength - notsent
+ buflength - notsent
#endif
- , buflength);
- buff[0] = AF_S_MESSAGE;
- buff[1] = AF_S_LOGIN;
- buff[2] = AF_S_MESSAGE;
- buff[3] = n >> 8;
- buff[4] = n;
- writen(master.commfd, buff, n + 5);
- }
- }
- }
- if (FD_ISSET(master.commfd, &rset)) {
- n = readn(master.commfd, buff, 5);
- if (n == 5) {
- if ((buff[0] != AF_S_MESSAGE) || (buff[1] != AF_S_LOGIN)
- || (buff[2] != AF_S_MESSAGE)) {
- aflog(0, "Incompatible server type (not udp?) or data corruption -> exiting...");
- exit(1);
- }
- length = buff[3];
- length = length << 8;
- length += buff[4]; /* this is length of message */
- n = readn(master.commfd, buff, length);
- }
- else {
- n = 0;
- }
- if (n == 0) { /* server quits -> we do the same... */
- gettimeofday(&tv, 0);
- aflog(0, "premature quit of the server -> exiting...");
- exit(1);
- }
- aflog(2, "Sending %d bytes to user", n);
- sendto(contable[0].connfd, buff, n, 0, cliaddr, addrlen);
- }
- }
- exit(0); /* we shouldn't get here */
- }
+ , buflength);
+ buff[0] = AF_S_MESSAGE;
+ buff[1] = AF_S_LOGIN;
+ buff[2] = AF_S_MESSAGE;
+ buff[3] = n >> 8;
+ buff[4] = n;
+ writen(master.commfd, buff, n + 5);
+ }
+ }
+ } /* - FD_ISSET CONTABLE[0].CONNFD RSET */
+ if (FD_ISSET(master.commfd, &rset)) { /* FD_ISSET MASTER.COMMFD RSET */
+ n = readn(master.commfd, buff, 5);
+ if (n == 5) {
+ if ((buff[0] != AF_S_MESSAGE) || (buff[1] != AF_S_LOGIN) || (buff[2] != AF_S_MESSAGE)) {
+ aflog(0, "Incompatible server type (not udp?) or data corruption -> exiting...");
+ exit(1);
+ }
+ length = buff[3];
+ length = length << 8;
+ length += buff[4]; /* this is length of message */
+ n = readn(master.commfd, buff, length);
+ }
+ else {
+ n = 0;
+ }
+ if (n == 0) { /* server quits -> we do the same... */
+ gettimeofday(&tv, 0);
+ aflog(0, "premature quit of the server -> exiting...");
+ exit(1);
+ }
+ aflog(2, "Sending %d bytes to user", n);
+ sendto(contable[0].connfd, buff, n, 0, cliaddr, addrlen);
+ } /* - FD_ISSET MASTER.COMMFD RSET */
+ }
+ exit(0); /* we shouldn't get here */
+ }
+
+ /* NORMAL MODE */
- aflog(1, "CLIENT STARTED mode: %s", (udp)?"udp":"tcp");
- 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(1, "CLIENT STARTED mode: %s", (udp)?"udp":"tcp");
+ 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) {
+ aflog(1, "LOADED MODULE: %s INFO: %s", module.name, module.info());
+ }
- for ( ; ; ) {
- rset = allset;
- aflog(2, ">select");
- select(maxfdp1, &rset, NULL, NULL, NULL);
- aflog(2, " >>after select...");
+ for ( ; ; ) {
+ rset = allset;
+ tmpset = wset;
+ aflog(3, ">select");
+ select(maxfdp1, &rset, &tmpset, NULL, NULL);
+ aflog(3, " >>after select...");
- for (i = 0; i < usernum; ++i) {
- if (contable[i].state == S_STATE_OPEN)
- if (FD_ISSET(contable[i].connfd, &rset)) {
- aflog(2, " user[%d]: FD_ISSET", i);
- n = read(contable[i].connfd, &buff[5], 8091);
- if (n == -1) {
- aflog(0, " error (%d): while reading from service", n);
- n = 0;
- }
+ for (i = 0; i < usernum; ++i) {
+ if ((contable[i].state == S_STATE_OPEN)||(contable[i].state == S_STATE_STOPPED)) {
+ if (FD_ISSET(contable[i].connfd, &rset)) { /* FD_ISSET CONTABLE[i].CONNFD RSET */
+ aflog(3, " user[%d]: FD_ISSET", i);
+ n = read(contable[i].connfd, &buff[5], 8091);
+ if (n == -1) {
+ aflog(0, " error (%d): while reading from service", n);
+ n = 0;
+ }
#ifdef SIOCOUTQ
- if (ioctl(master.commfd, SIOCOUTQ, &notsent)) {
- aflog(0, "ioctl error -> exiting...");
- exit(1);
- }
- if (udp) {
- len = 4;
- if (getsockopt(master.commfd, SOL_SOCKET, SO_SNDBUF, &temp2, &len) != -1) {
- if (temp2 != buflength) {
- buflength = temp2;
- aflog(2, "Send buffor size changed...");
- }
- }
- if (buflength <= notsent + n + 5) { /* when we can't send this */
- aflog(2, " user[%d]: DROP size:%d, buf:%d, w:%d/%d",
- i, n+5, buflength, notsent, buflength);
+ if (ioctl(master.commfd, SIOCOUTQ, &notsent)) {
+ aflog(0, "ioctl error -> exiting...");
+ exit(1);
+ }
+ if (udp) {
+ len = 4;
+ if (getsockopt(master.commfd, SOL_SOCKET, SO_SNDBUF, &temp2, &len) != -1) {
+ if (temp2 != buflength) {
+ buflength = temp2;
+ aflog(2, "Send buffer size changed...");
+ }
+ }
+ if (buflength <= notsent + n + 5) { /* when we can't send this */
+ aflog(2, " user[%d]: DROP size:%d, buf:%d, w:%d/%d", i, n+5, buflength, notsent, buflength);
#else
- if (ioctl(master.commfd, TIOCOUTQ, &notsent)) {
- aflog(0, "ioctl error -> exiting...");
- exit(1);
- }
- if (udp) {
- len = 4;
- if (getsockopt(master.commfd, SOL_SOCKET, SO_SNDBUF, &temp2, &len) != -1) {
- if (temp2 != buflength) {
- buflength = temp2;
- aflog(2, "Send buffor size changed...");
- }
- }
- if (notsent <= n + 5) { /* when we can't send this */
- aflog(2, " user[%d]: DROP size:%d, buf:%d, w:%d/%d",
- i, n+5, buflength, buflength-notsent, buflength);
+ if (ioctl(master.commfd, TIOCOUTQ, &notsent)) {
+ aflog(0, "ioctl error -> exiting...");
+ exit(1);
+ }
+ if (udp) {
+ len = 4;
+ if (getsockopt(master.commfd, SOL_SOCKET, SO_SNDBUF, &temp2, &len) != -1) {
+ if (temp2 != buflength) {
+ buflength = temp2;
+ aflog(2, "Send buffer size changed...");
+ }
+ }
+ if (notsent <= n + 5) { /* when we can't send this */
+ aflog(2, " user[%d]: DROP size:%d, buf:%d, w:%d/%d",
+ i, n+5, buflength, buflength-notsent, buflength);
#endif
- continue; /* drop this packet */
- }
- }
- if (n) {
- 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 */
- aflog(2, " user[%d]: TO msglen: %d [%d/%d]",
- i, n,
+ continue; /* drop this packet */
+ }
+ }
+ if (n) {
+ 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 */
+ aflog(2, " user[%d]: TO msglen: %d [%d/%d]", i, n,
#ifdef SIOCOUTQ
- notsent
+ notsent
#else
- buflength - notsent
+ buflength - notsent
#endif
- , buflength);
- send_message(type, master, buff, n+5);
- }
- else if (!udp) {
- close(contable[i].connfd);
- FD_CLR(contable[i].connfd, &allset);
- contable[i].state = S_STATE_CLOSING;
- 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 (FD_ISSET(master.commfd, &rset)) {
- aflog(2, " masterfd: FD_ISSET");
- n = get_message(type, master, buff, 5);
- if (n != 5) {
- aflog(2, " FATAL ERROR! (%d)", n);
- if (n == -1) {
- if (TYPE_IS_SSL(type)) {
- merror = SSL_get_error(master.ssl, n);
- switch (merror) {
- case SSL_ERROR_NONE : {
- aflog(2, "FE: none");
- break;
- }
- case SSL_ERROR_ZERO_RETURN : {
- aflog(2, "FE: zero");
- break;
- }
- case SSL_ERROR_WANT_READ : {
- aflog(2, "FE: w_read");
- break;
- }
- case SSL_ERROR_WANT_WRITE : {
- aflog(2, "FE: w_write");
- break;
- }
- case SSL_ERROR_WANT_CONNECT : {
- aflog(2, "FE: w_connect");
- break;
- }
- case SSL_ERROR_WANT_X509_LOOKUP : {
- aflog(2, "FE: w_x509_lookup");
- break;
- }
- case SSL_ERROR_SYSCALL : {
- aflog(2, "FE: syscall");
- break;
- }
- case SSL_ERROR_SSL : {
- SSL_load_error_strings();
- aflog(2, "FE: ssl:%s",
- ERR_error_string(ERR_get_error(), (char*) buff));
- break;
- }
- }
- continue; /* what happened? */
- }
- }
- if (n != 0)
- exit(1);
- }
- if (n == 0) { /* server quits -> we do the same... */
- aflog(0, " SERVER: premature quit -> exiting...");
- exit(1);
- }
- 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<=usernum)) {
- usercon--;
- if (contable[numofcon].state == S_STATE_CLOSING) {
- contable[numofcon].state = S_STATE_CLEAR;
- }
- else if (contable[numofcon].state==S_STATE_OPEN) {
- close(contable[numofcon].connfd);
- FD_CLR(contable[numofcon].connfd, &allset);
- contable[numofcon].state = S_STATE_CLEAR;
- 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(type, master, buff, 5);
- }
- }
- break;
- }
- case AF_S_CONOPEN : {
- if ((numofcon>=0) && (numofcon<=usernum)) {
- usercon++;
- if (contable[numofcon].state == S_STATE_CLEAR) {
- if (udp) {
- contable[numofcon].connfd=ip_connect(desnam,despor,"udp");
- }
- else {
- contable[numofcon].connfd=ip_connect(desnam,despor,"tcp");
- }
- FD_SET(contable[numofcon].connfd, &allset);
- maxfdp1 = (maxfdp1 > (contable[numofcon].connfd+1)) ? maxfdp1 : (contable[numofcon].connfd+1);
- buff[0] = AF_S_CONOPEN; /* closing connection */
- buff[1] = numofcon >> 8; /* high bits of user number */
- buff[2] = numofcon; /* low bits of user number */
- send_message(type, master, buff, 5);
- contable[numofcon].state = S_STATE_OPEN;
- }
- }
- break;
- }
- case AF_S_MESSAGE : {
- aflog(2, " user[%d]: FROM msglen: %d", numofcon, length);
- n = get_message(type, master, buff, length);
- if ((numofcon>=0) && (numofcon<=usernum)) {
- if (contable[numofcon].state == S_STATE_OPEN) {
- aflog(2, " user[%d]: FROM msglen: %d SENT", numofcon, n);
- if (writen(contable[numofcon].connfd, buff, n)==-1) {
- aflog(0, "Sending msg failed!");
- }
- }
- }
- break;
- }
- case AF_S_CLOSING : { /* server shut down -> exiting... */
- aflog(0, " SERVER: CLOSED -> exiting... cg: %ld bytes", getcg());
- exit(1);
- break;
- }
- default : { /* unrecognized type of message -> exiting... */
- aflog(0, " SERVER: unrecognized message -> exiting... cg: %ld bytes", getcg());
- exit(1);
- break;
- }
- }
- }
- }
+ , buflength);
+ send_message(type, master, buff, n+5);
+ }
+ else if (!udp) {
+ aflog(2, " user[%d]: CLOSING", 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);
+ }
+ } /* - FD_ISSET CONTABLE[i].CONNFD RSET */
+ }
+ }
+ for (i = 0; i < usernum; ++i) {
+ if (contable[i].state == S_STATE_STOPPED) {
+ if (FD_ISSET(contable[i].connfd, &tmpset)) { /* FD_ISSET CONTABLE[i].CONNFD TMPSET */
+ aflog(3, " user[%d]: FD_ISSET - WRITE", i);
+ n = contable[i].head->msglen - contable[i].head->actptr;
+ temp2 = write(contable[i].connfd, &(contable[i].head->buff[contable[i].head->actptr]), n);
+ if ((temp2 > 0) && (temp2 != n)) {
+ contable[i].head->actptr+=temp2;
+ }
+ else if ((temp2 == -1) && (errno == EAGAIN)) {
+ aflog(3, " user[%d]: Couldn't write?", i);
+ }
+ else if (temp2 == -1) {
+ close(contable[i].connfd);
+ FD_CLR(contable[i].connfd, &allset);
+ FD_CLR(contable[i].connfd, &wset);
+ contable[i].state = S_STATE_CLOSING;
+ 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);
+ }
+ else {
+ deleteblnode(&contable[i].head);
+ if (contable[i].head == NULL) {
+ contable[i].state = S_STATE_OPEN;
+ FD_CLR(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, " FROM user[%d]: BUFFERING MESSAGE ENDED", i);
+ send_message(type, master, buff, 5);
+ }
+ }
+ } /* - FD_ISSET CONTABLE[i].CONNFD TMPSET */
+ }
+ }
+ if (FD_ISSET(master.commfd, &rset)) { /* FD_ISSET MASTER.COMMFD RSET */
+ aflog(3, " masterfd: FD_ISSET");
+ n = get_message(type, master, buff, 5);
+ if (n != 5) {
+ aflog(2, " FATAL ERROR! (%d)", n);
+ if (n == -1) {
+ if (TYPE_IS_SSL(type)) {
+ merror = SSL_get_error(master.ssl, n);
+ switch (merror) {
+ case SSL_ERROR_NONE : {
+ aflog(2, "FE: none");
+ break;
+ }
+ case SSL_ERROR_ZERO_RETURN : {
+ aflog(2, "FE: zero");
+ break;
+ }
+ case SSL_ERROR_WANT_READ : {
+ aflog(2, "FE: w_read");
+ break;
+ }
+ case SSL_ERROR_WANT_WRITE : {
+ aflog(2, "FE: w_write");
+ break;
+ }
+ case SSL_ERROR_WANT_CONNECT : {
+ aflog(2, "FE: w_connect");
+ break;
+ }
+ case SSL_ERROR_WANT_X509_LOOKUP : {
+ aflog(2, "FE: w_x509_lookup");
+ break;
+ }
+ case SSL_ERROR_SYSCALL : {
+ aflog(2, "FE: syscall");
+ break;
+ }
+ case SSL_ERROR_SSL : {
+ SSL_load_error_strings();
+ aflog(2, "FE: ssl:%s",
+ ERR_error_string(ERR_get_error(), (char*) buff));
+ break;
+ }
+ }
+ continue; /* what happened? */
+ }
+ }
+ if (n != 0)
+ exit(1);
+ }
+ if (n == 0) { /* server quits -> we do the same... */
+ aflog(0, " SERVER: premature quit -> exiting...");
+ exit(1);
+ }
+ 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<=usernum)) {
+ usercon--;
+ if (contable[numofcon].state == S_STATE_CLOSING) {
+ contable[numofcon].state = S_STATE_CLEAR;
+ aflog(2, " user[%d]: CLOSED", numofcon);
+ }
+ else if ((contable[numofcon].state==S_STATE_OPEN) || (contable[numofcon].state==S_STATE_STOPPED)){
+ aflog(2, " user[%d]: CLOSED", numofcon);
+ close(contable[numofcon].connfd);
+ FD_CLR(contable[numofcon].connfd, &allset);
+ FD_CLR(contable[numofcon].connfd, &wset);
+ contable[numofcon].state = S_STATE_CLEAR;
+ 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 */
+ send_message(type, master, buff, 5);
+ }
+ }
+ break;
+ }
+ case AF_S_CONOPEN : {
+ if ((numofcon>=0) && (numofcon<=usernum)) {
+ usercon++;
+ if (contable[numofcon].state == S_STATE_CLEAR) {
+ n = get_message(type, master, buff, length);
+ memcpy(contable[numofcon].namebuf, buff, 128);
+ memcpy(contable[numofcon].portbuf,&buff[128],7);
+ 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)) {
+ 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 */
+ buff[2] = numofcon; /* low bits of user number */
+ send_message(type, master, buff, 5);
+ usercon--;
+ continue;
+ }
+ if (udp) {
+ ipfam = 0;
+ }
+ else {
+ ipfam = 0x01;
+ }
+ if (TYPE_IS_IPV4(type)) {
+ ipfam |= 0x02;
+ }
+ else if (TYPE_IS_IPV6(type)) {
+ ipfam |= 0x04;
+ }
+ if (ip_connect(&(contable[numofcon].connfd), desnam, despor, ipfam)) {
+ aflog(2, " CAN'T OPEN - DROPPING", numofcon);
+ buff[0] = AF_S_CANT_OPEN; /* not opening connection */
+ buff[1] = numofcon >> 8; /* high bits of user number */
+ buff[2] = numofcon; /* low bits of user number */
+ send_message(type, master, buff, 5);
+ usercon--;
+ continue;
+ }
+ temp2 = fcntl(contable[numofcon].connfd, F_GETFL, 0);
+ fcntl(contable[numofcon].connfd, F_SETFL, temp2 | O_NONBLOCK);
+ FD_SET(contable[numofcon].connfd, &allset);
+ maxfdp1 = (maxfdp1 > (contable[numofcon].connfd+1)) ? maxfdp1 : (contable[numofcon].connfd+1);
+ buff[0] = AF_S_CONOPEN; /* opening connection */
+ buff[1] = numofcon >> 8; /* high bits of user number */
+ buff[2] = numofcon; /* low bits of user number */
+ send_message(type, master, buff, 5);
+ contable[numofcon].state = S_STATE_OPEN;
+ }
+ }
+ break;
+ }
+ case AF_S_MESSAGE : {
+ aflog(2, " user[%d]: FROM msglen: %d", numofcon, length);
+ 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: {
+ aflog(3, " user[%d]: PACKET IGNORED BY MODULE", numofcon);
+ continue;
+ break;
+ }
+ case 2: {
+ aflog(2, " user[%d]: DROPPED BY MODULE", numofcon);
+ close(contable[numofcon].connfd);
+ 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 */
+ send_message(type, master, buff, 5);
+ break;
+ }
+ }
+ }
+ aflog(2, " user[%d]: FROM msglen: %d SENT", numofcon, n);
+ temp2 = write(contable[numofcon].connfd, buff, n);
+ if ((temp2 > 0) && (temp2 != n)) {
+ insertblnode(&(contable[numofcon].head), temp2, n, buff);
+ contable[numofcon].state = S_STATE_STOPPED;
+ FD_SET(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, " FROM user[%d]: BUFFERING MESSAGE STARTED", numofcon);
+ send_message(type, master, buff, 5);
+ }
+ else if ((temp2 == -1) && (errno == EAGAIN)) {
+ insertblnode(&(contable[numofcon].head), 0, n, buff);
+ contable[numofcon].state = S_STATE_STOPPED;
+ FD_SET(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, " FROM user[%d]: BUFFERING MESSAGE STARTED", numofcon);
+ send_message(type, master, buff, 5);
+ }
+ else if (temp2 == -1) {
+ close(contable[numofcon].connfd);
+ FD_CLR(contable[numofcon].connfd, &allset);
+ FD_CLR(contable[numofcon].connfd, &wset);
+ contable[numofcon].state = S_STATE_CLOSING;
+ 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(type, master, buff, 5);
+ }
+ }
+ else if (contable[numofcon].state == S_STATE_STOPPED) {
+ aflog(3, " FROM user[%d]: BUFFERING MESSAGE", numofcon);
+ insertblnode(&(contable[numofcon].head), 0, n, buff);
+ }
+ }
+ break;
+ }
+ case AF_S_CLOSING : { /* server shut down -> exiting... */
+ aflog(0, " SERVER: CLOSED -> exiting... cg: %ld bytes", getcg());
+ exit(1);
+ break;
+ }
+ case AF_S_DONT_SEND: {
+ FD_CLR(contable[numofcon].connfd, &allset);
+ break;
+ }
+ case AF_S_CAN_SEND: {
+ FD_SET(contable[numofcon].connfd, &allset);
+ break;
+ }
+ default : { /* unrecognized type of message -> exiting... */
+ aflog(0, " SERVER: unrecognized message -> exiting... cg: %ld bytes", getcg());
+ exit(1);
+ break;
+ }
+ }
+ } /* - FD_ISSET MASTER.COMMFD RSET */
+ }
}
static void
usage(char* info)
{
- printf("\n%s\n\n", info);
- printf(" Options:\n");
- printf(" -h, --help - prints this help\n");
- printf(" -n, --servername - where the second part of the active\n");
- printf(" port forwarder is running (required)\n");
- printf(" -m, --manageport - the manage port number - server must\n");
- printf(" listening on it (default: 50126)\n");
- printf(" -d, --hostname - name of this host/remote host - the final\n");
- printf(" destination of the packets (default: name\n");
- printf(" returned by hostname function)\n");
- printf(" -p, --portnum - port we are forwarding connection to (required)\n");
- printf(" -k, --keyfile - name of the file with RSA key (default: client.rsa)\n");
- printf(" -u, --udpmode - udp mode - client will use udp protocol to\n");
- printf(" communicate with hostname\n");
- printf(" -U, --reverseudp - reverse udp forwarding. Udp packets will be forwarded\n");
- printf(" from hostname:portnum (-p) to server name:portnum (-m)\n");
- 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 into\n");
- printf(" the daemon mode (use twice for greater effect)\n");
- printf(" --pass - set the password used for client identification\n");
- printf(" (default: no password)\n\n");
- exit(0);
+ printf("\n%s\n\n", info);
+ printf(" Options:\n");
+ printf(" -h, --help - prints this help\n");
+ printf(" -n, --servername - where the second part of the active\n");
+ printf(" port forwarder is running (required)\n");
+ printf(" -m, --manageport - manage port number - server must be\n");
+ printf(" listening on it (default: 50126)\n");
+ printf(" -d, --hostname - the name of this host/remote host - the final\n");
+ 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(" -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");
+ printf(" from hostname:portnum (-p) to the server name:portnum\n");
+ printf(" (-m)\n");
+ 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(" --pass - set the password used for client identification\n");
+ 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");
+
+ exit(0);
}
static void
sig_int(int signo)
{
- aflog(1, "CLIENT CLOSED cg: %ld bytes", getcg());
- exit(0);
+ aflog(1, "CLIENT CLOSED cg: %ld bytes", getcg());
+ exit(0);
}
diff --git a/afserver.c b/afserver.c
index d5d655b..86fb85e 100644
--- a/afserver.c
+++ b/afserver.c
@@ -50,6 +50,8 @@ static struct option long_options[] = {
{"nossl", 0, 0, 301},
{"nozlib", 0, 0, 302},
{"pass", 1, 0, 303},
+ {"ipv4", 0, 0, '4'},
+ {"ipv6", 0, 0, '6'},
{0, 0, 0, 0}
};
@@ -58,12 +60,12 @@ static ConfigurationT config;
int
main(int argc, char **argv)
{
- int i, j, n, flags;
+ int i, j, n, flags, sent;
socklen_t len;
unsigned char buff[9000];
char hostname[100];
int maxfdp1;
- fd_set rset, allset;
+ fd_set rset, allset, wset, tmpset;
int manconnecting, numofcon, length;
char* name = NULL;
char* listen = NULL;
@@ -72,17 +74,24 @@ main(int argc, char **argv)
char* filenam = NULL;
char* type = NULL;
char* znak;
- unsigned char pass[4];
+ unsigned char pass[4] = {1, 2, 3, 4};
char verbose = 0;
char mode = 0;
+ char ipfam = 0;
RealmT* pointer = NULL;
+ struct sigaction act;
SSL_METHOD* method;
SSL_CTX* ctx;
- signal(SIGPIPE, SIG_IGN);
- signal(SIGINT, sig_int);
-
+ sigfillset(&(act.sa_mask));
+ act.sa_flags = 0;
+
+ act.sa_handler = SIG_IGN;
+ sigaction(SIGPIPE, &act, NULL);
+ act.sa_handler = sig_int;
+ sigaction(SIGINT, &act, NULL);
+
TYPE_SET_SSL(mode);
TYPE_SET_ZLIB(mode);
@@ -93,7 +102,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:", long_options, 0)) != -1) {
+ while ((n = getopt_long(argc, argv, "hn:l:m:vu:c:k:f:p:o:O:46", long_options, 0)) != -1) {
switch (n) {
case 'h': {
usage(AF_VER("Active port forwarder (server)"));
@@ -161,7 +170,24 @@ main(int argc, char **argv)
}
break;
}
-
+ case '4': {
+ if (ipfam != 0) {
+ ipfam = -1;
+ }
+ else {
+ ipfam = 4;
+ }
+ break;
+ }
+ case '6': {
+ if (ipfam != 0) {
+ ipfam = -1;
+ }
+ else {
+ ipfam = 6;
+ }
+ break;
+ }
case '?': {
usage("");
break;
@@ -224,6 +250,16 @@ main(int argc, char **argv)
else {
TYPE_SET_ZERO(config.realmtable[0].type);
}
+ if (ipfam == -1) {
+ printf("Conflicting types of ip protocol family... exiting\n");
+ exit(1);
+ }
+ else if (ipfam == 4) {
+ TYPE_SET_IPV4(config.realmtable[0].type);
+ }
+ else if (ipfam == 6) {
+ TYPE_SET_IPV6(config.realmtable[0].type);
+ }
config.realmtable[0].type |= mode;
}
@@ -251,14 +287,16 @@ main(int argc, char **argv)
}
FD_ZERO(&allset);
+ FD_ZERO(&wset);
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)) {
- printf("Missing some of configurable variables... exiting\n");
- printf("%d) %s, %s, %s, %s\n", i, config.realmtable[i].hostname,
+ printf("Missing some of the configurable variables...\n");
+ printf("\nRealm: %d\nhostname: %s\nlistenport: %s\nmanageport: %s\nusers: %s\n",
+ i, config.realmtable[i].hostname,
config.realmtable[i].lisportnum,
config.realmtable[i].manportnum,
config.realmtable[i].users);
@@ -282,11 +320,27 @@ main(int argc, char **argv)
printf("Calloc error - try define smaller amount of users\n");
exit(1);
}
-
- config.realmtable[i].listenfd = ip_listen(config.realmtable[i].hostname,
- config.realmtable[i].lisportnum, (&(config.realmtable[i].addrlen)), "tcp");
- config.realmtable[i].managefd = ip_listen(config.realmtable[i].hostname,
- config.realmtable[i].manportnum, (&(config.realmtable[i].addrlen)), "tcp");
+ ipfam = 0x01;
+ if (TYPE_IS_IPV4(config.realmtable[i].type)) {
+ ipfam |= 0x02;
+ }
+ else if (TYPE_IS_IPV6(config.realmtable[i].type)) {
+ ipfam |= 0x04;
+ }
+ if (ip_listen(&(config.realmtable[i].listenfd), config.realmtable[i].hostname,
+ config.realmtable[i].lisportnum, (&(config.realmtable[i].addrlen)), ipfam)) {
+ printf("tcp_listen_%s error for %s, %s\n",
+ (ipfam & 0x02)?"ipv4":(ipfam & 0x04)?"ipv6":"unspec",
+ config.realmtable[i].hostname, config.realmtable[i].lisportnum);
+ exit(1);
+ }
+ if (ip_listen(&(config.realmtable[i].managefd), config.realmtable[i].hostname,
+ config.realmtable[i].manportnum, (&(config.realmtable[i].addrlen)), ipfam)) {
+ printf("tcp_listen_%s error for %s, %s\n",
+ (ipfam & 0x02)?"ipv4":(ipfam & 0x04)?"ipv6":"unspec",
+ config.realmtable[i].hostname, config.realmtable[i].manportnum);
+ exit(1);
+ }
config.realmtable[i].cliaddr = malloc(config.realmtable[i].addrlen);
config.realmtable[i].cliconn.ssl = SSL_new(ctx);
@@ -296,7 +350,9 @@ main(int argc, char **argv)
}
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;
@@ -315,7 +371,8 @@ main(int argc, char **argv)
for ( ; ; ) {
rset = allset;
- aflog(2, ">select, maxfdp1: %d", maxfdp1);
+ tmpset = wset;
+ 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) {
@@ -323,10 +380,9 @@ main(int argc, char **argv)
break; /* so i points to first good realm */
}
}
- if (select(maxfdp1, &rset, NULL, NULL, (&(config.realmtable[i].tv))) == 0) {
+ 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);
- FD_CLR(config.realmtable[i].listenfd, &allset);
FD_SET(config.realmtable[i].managefd, &allset);
config.realmtable[i].ready = 0;
manconnecting--;
@@ -334,16 +390,17 @@ main(int argc, char **argv)
}
}
else {
- select(maxfdp1, &rset, NULL, NULL, NULL);
+ select(maxfdp1, &rset, &tmpset, NULL, NULL);
}
- aflog(2, " >>after select...");
+ aflog(3, " >>after select...");
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)
+ if ((pointer->contable[i].state == S_STATE_OPEN) ||
+ (pointer->contable[i].state == S_STATE_STOPPED))
if (FD_ISSET(pointer->contable[i].connfd, &rset)) {
- aflog(2, " realm[%d]: user[%d]: FD_ISSET", j, i);
+ 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)
@@ -364,9 +421,13 @@ main(int argc, char **argv)
}
else {
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 */
@@ -398,9 +459,13 @@ main(int argc, char **argv)
if (n == 0) {
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 */
@@ -410,31 +475,88 @@ main(int argc, char **argv)
}
}
}
- if (pointer->ready == 3)
+ /* ------------------------------------ */
+ 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 (FD_ISSET(pointer->listenfd, &rset)) {
- aflog(2, " realm[%d]: listenfd: FD_ISSET", j);
len = pointer->addrlen;
+ sent = accept(pointer->listenfd, pointer->cliaddr, &len);
+ 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) {
+ 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 =
- accept(pointer->listenfd, pointer->cliaddr, &len);
+ 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));
- if (pointer->usercon == pointer->usernum)
- FD_CLR(pointer->listenfd, &allset);
+ 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 */
- send_message(pointer->type, pointer->cliconn, buff, 5);
+ 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)
+ 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) {
@@ -496,7 +618,7 @@ main(int argc, char **argv)
}
continue; /* in the case this is not our client */
}
- aflog(2, " realm[%d]: commfd: FD_ISSET", j);
+ aflog(3, " realm[%d]: commfd: FD_ISSET", j);
if (pointer->ready == 2) {
n = get_message(pointer->type | TYPE_SSL, pointer->cliconn, buff, -5);
}
@@ -517,7 +639,6 @@ main(int argc, char **argv)
if (n==0) {
close(pointer->cliconn.commfd);
FD_CLR(pointer->cliconn.commfd, &allset);
- FD_CLR(pointer->listenfd, &allset);
FD_SET(pointer->managefd, &allset);
maxfdp1 = (maxfdp1 > (pointer->managefd+1)) ? maxfdp1 : (pointer->managefd+1);
if (pointer->ready == 3) {
@@ -525,6 +646,7 @@ main(int argc, char **argv)
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);
}
}
@@ -547,19 +669,21 @@ main(int argc, char **argv)
(numofcon<=(pointer->usernum)) &&
((pointer->ready)==3)) {
(pointer->usercon)--;
- if (pointer->usercon == pointer->usernum-1)
- FD_SET(pointer->listenfd, &allset);
if (pointer->contable[numofcon].state ==
S_STATE_CLOSING) {
pointer->contable[numofcon].state =
S_STATE_CLEAR;
}
- else if (pointer->contable[numofcon].state ==
- S_STATE_OPEN) {
+ 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 */
@@ -569,7 +693,6 @@ main(int argc, char **argv)
else {
close (pointer->cliconn.commfd);
FD_CLR(pointer->cliconn.commfd, &allset);
- FD_CLR(pointer->listenfd, &allset);
FD_SET(pointer->managefd, &allset);
if (pointer->ready == 2)
manconnecting--;
@@ -595,7 +718,6 @@ main(int argc, char **argv)
else {
close (pointer->cliconn.commfd);
FD_CLR(pointer->cliconn.commfd, &allset);
- FD_CLR(pointer->listenfd, &allset);
FD_SET(pointer->managefd, &allset);
if (pointer->ready == 2)
manconnecting--;
@@ -604,11 +726,38 @@ main(int argc, char **argv)
}
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;
+ }
+
+
+
case AF_S_MESSAGE : {
if ((pointer->ready) != 3) {
close (pointer->cliconn.commfd);
FD_CLR(pointer->cliconn.commfd, &allset);
- FD_CLR(pointer->listenfd, &allset);
FD_SET(pointer->managefd, &allset);
manconnecting--;
SSL_clear(pointer->cliconn.ssl);
@@ -629,10 +778,94 @@ main(int argc, char **argv)
if (TYPE_IS_UDP(pointer->type)) { /* udp */
buff[1] = AF_S_LOGIN;
buff[2] = AF_S_MESSAGE;
- writen(pointer->contable[numofcon].connfd, buff, n+5);
+ 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 {
- writen(pointer->contable[numofcon].connfd, buff, n);
+ insertblnode(&(pointer->contable[numofcon].head), 0, n, buff);
}
}
}
@@ -649,14 +882,12 @@ main(int argc, char **argv)
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);
- FD_SET(pointer->listenfd, &allset);
manconnecting--;
}
else {
aflog(1, " realm[%d]: Wrong password - CLOSING", j);
close (pointer->cliconn.commfd);
FD_CLR(pointer->cliconn.commfd, &allset);
- FD_CLR(pointer->listenfd, &allset);
FD_SET(pointer->managefd, &allset);
if (pointer->ready == 2)
manconnecting--;
@@ -665,11 +896,19 @@ main(int argc, char **argv)
}
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_CLR(pointer->listenfd, &allset);
FD_SET(pointer->managefd, &allset);
if (pointer->ready == 2)
manconnecting--;
@@ -678,6 +917,7 @@ main(int argc, char **argv)
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);
}
}
@@ -689,14 +929,14 @@ main(int argc, char **argv)
}
if (FD_ISSET(pointer->managefd, &rset)) {
- aflog(2, " realm[%d]: managefd: FD_ISSET", j);
+ 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));
+ 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);
@@ -717,28 +957,31 @@ usage(char* info)
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 - the listening port number - users connect\n");
+ printf(" -l, --listenport - listening port number - users connect\n");
printf(" to it (default: 50127)\n");
- printf(" -m, --manageport - the manage port number - second part of active\n");
+ printf(" -m, --manageport - manage port number - second part of the active\n");
printf(" port forwarder connects to it (default: 50126)\n");
- printf(" -u, --users - amount of users allowed to use this server\n");
+ printf(" -u, --users - the amount of users allowed to use this server\n");
printf(" (default: 5)\n");
- printf(" -c, --cerfile - name of the file with certificate (default: cacert.pem)\n");
- printf(" -k, --keyfile - name of the file with RSA key (default: server.rsa)\n");
- printf(" -f, --cfgfile - name of the file with configuration for active\n");
- printf(" forwarder (server)\n");
- printf(" -p, --proto - type of the server (tcp|udp) - for which protocol it\n");
- printf(" would be (default: tcp)\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");
+ printf(" -f, --cfgfile - the name of the file with the configuration for the\n");
+ printf(" active forwarder (server)\n");
+ printf(" -p, --proto - type of server (tcp|udp) - for which protocol it will be\n");
+ printf(" operating (default: tcp)\n");
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 into\n");
- printf(" the daemon mode (use twice for greater effect)\n");
+ printf(" -v, --verbose - to be verbose - program won't enter the daemon mode\n");
+ printf(" (use several times for greater effect)\n");
printf(" --nossl - ssl is not used for transfering data (but it's still\n");
- printf(" used to establish connection) (default: ssl is used)\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\n");
+ printf(" (default: no password)\n");
+ printf(" -4, --ipv4 - use ipv4 only\n");
+ printf(" -6, --ipv6 - use ipv6 only\n\n");
exit(0);
}
diff --git a/buflist.c b/buflist.c
new file mode 100644
index 0000000..b128249
--- /dev/null
+++ b/buflist.c
@@ -0,0 +1,69 @@
+/*
+ * 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 <stdlib.h>
+#include <string.h>
+
+#include "buflist.h"
+
+int
+insertblnode(blnodeT** headRef, int actptr, int msglen, unsigned char* buff)
+{
+ blnodeT* newnode, *lastnode;
+ lastnode = newnode = *headRef;
+ while (newnode) {
+ lastnode = newnode;
+ newnode = newnode->next;
+ }
+ 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);
+ if (lastnode)
+ lastnode->next = newnode;
+ else
+ *headRef = newnode;
+ return 0;
+}
+
+int
+deleteblnode(blnodeT** headRef)
+{
+ blnodeT* node = *headRef;
+ if (*headRef == NULL)
+ return 1;
+ *headRef = node->next;
+ free(node->buff);
+ free(node);
+ return 0;
+}
+
+int
+freebuflist(blnodeT** headRef)
+{
+ while (*headRef) {
+ deleteblnode(headRef);
+ }
+ return 0;
+}
diff --git a/buflist.h b/buflist.h
new file mode 100644
index 0000000..c4baeae
--- /dev/null
+++ b/buflist.h
@@ -0,0 +1,35 @@
+/*
+ * 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_BUFLIST_H
+#define _JS_BUFLIST_H
+
+typedef struct blnode {
+ int actptr;
+ int msglen;
+ unsigned char* buff;
+ struct blnode* next;
+} blnodeT;
+
+int insertblnode(blnodeT** headRef, int actptr, int msglen, unsigned char* buff);
+int deleteblnode(blnodeT** headRef);
+int freebuflist(blnodeT** headRef);
+
+#endif
diff --git a/docs/en/README b/docs/en/README
index fb52e60..e9ded51 100644
--- a/docs/en/README
+++ b/docs/en/README
@@ -1,4 +1,4 @@
-AF - Active Port Forwarder v0.5.3 - README
+AF - Active Port Forwarder v0.5.4 - README
Copyright (C) 2003,2004 jeremian - <jeremian [at] poczta.fm>
===================
@@ -7,85 +7,287 @@ 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
- Access Control System) bypassing research field and to the computer and
+ 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.
================================================================================
+=======
+SUMMARY
+=======
-Active port forwarder is a software for secure port forwarding.
-It uses ssl for increasing security of communication between server and client.
+INTRO
-Af is dedicated for people, who don't have external ip number and want to
+1. INSTALLATION
+ 1.1 Instructions
+ 1.2 Required libs
+ 1.3 Tested platforms
+2. USAGE
+ 2.1 afserver
+ 2.2 afclient
+3. EXAMPLES
+ 3.1 tcp mode
+ 3.2 reverse udp mode
+4. BUGS/PROBLEMS
+
+NOTES
+
+THANKS
+
+================================================================================
+
+=====
+INTRO
+=====
+
+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
make some services available across the net.
-Moreover, zlib is used to compress transfered data.
+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.
+
+================================================================================
+
+===============
+1. INSTALLATION
+===============
+
+ 1.1 Instructions
+ ----------------
+
+1. Download the compressed sources from http://www.gray-world.net/pr_af.shtml
+2. Unpack them with tar zxvf
+3. Type "make".
+4. If something goes wrong - mail the author or post a message on
+ http://gray-world.net/board/
+
+ 1.2 Required libs
+ -----------------
+
+1. openssl - http://www.openssl.org/
+2. zlib - http://www.gzip.org/zlib/
+
+ 1.3 Tested platforms
+ --------------------
+
+1. Linux:
+ Gentoo, Slackware, Mandrake - built without any problems
+2. Freebsd:
+ 4.4, 4.9 - have to use patch from project homepage
+3. Windows:
+ win32 - cygwin version is available on the project homepage
+
+================================================================================
+
+========
+2. USAGE
+========
+
+ 2.1 afserver
+ ------------
+
+ 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)
+ -u, --users - the amount of users allowed to use this server
+ (default: 5)
+ -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)
+ -f, --cfgfile - the name of the file with the configuration for the
+ active forwarder (server)
+ -p, --proto - type of server (tcp|udp) - for which protocol it will be
+ operating (default: tcp)
+ -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
+ (use several times for greater effect)
+ --nossl - ssl is not used for transferring 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
-EXAMPLE 1:
+ 2.2 afclient
+ ------------
-The use of it is extremely simple. Let's suppose we want to create http server on
-our computer and we are behind masquerade or firewall:
+ Options:
+ -h, --help - prints this help
+ -n, --servername - where the second part of the active
+ port forwarder is running (required)
+ -m, --manageport - manage port number - server must be
+ listening on it (default: 50126)
+ -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)
+ -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)
+ -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
+ (use several times for greater effect)
+ --pass - set the password used for client identification
+ (default: no password)
+ -4, --ipv4 - use ipv4 only
+ -6, --ipv6 - use ipv6 only
+ -l, --load - load a module for packets filtering
+
+================================================================================
+
+===========
+3. EXAMPLES
+===========
+
+ 3.1 tcp mode
+ ------------
+
+ local network |FireWall| Internet
+ ||
+ || User 1
+ || /(tcp)
+ AF Client <---Encrypted/Compressed channel---> AF Server
+ / || | \(tcp)
+ /(tcp) || (tcp)| User 2
+ / || \
+ Http server || User 3
+ ||
-1) We have to find some machine on the net with external ip and shell account.
-2) Use make to compile everything on that machine. (you can freely remove afclient
- and client.rsa files)
+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:
-3) You can edit config file or just type from the console: (to use config type -f <cfgfile>)
- $ ./afserver
+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
+ afclient and client.rsa files)
+
+3) You can edit the config file or just type from the console (to use the config
+ 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 there is
- appropriate registration in /etc/hosts)
+ - 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
- server will be for maximum 5 users
- server will forward tcp packets
- there will be no logging and no verbose messages
- there will be no password identification
+ - ip protocol family will be unspecified
-4) We use make on our machine (we can delete everything apart afclient and client.rsa)
+4) We use "make" on our machine (we can delete everything apart from afclient
+ and client.rsa)
5) We are typing from the console:
- $ ./afclient -n <name of the server> -p 80
- Where <name of the server> is a string like : 'bastion.univ.gda.pl' or '153.19.7.200'
+ $ ./afclient -n <name of the server> -p 80
+ Where <name of the server> is a string like : 'bastion.univ.gda.pl' or
+ '153.19.7.200'
+
+6) We can now enter with a web-browser to: <name of the server>:50127 and we
+ will enter to our computer in the fact.
+
+ 3.2 reverse udp mode
+ --------------------
-6) We can now enter with webbrowser to : <name of the server>:50127 and we will enter to our
- computer in the fact.
+ local network |FireWall| Internet
+ || (udp)
+ || User 1-------AF Client
+ || /(tcp)
+ AF Client <---Encrypted/Compressed channel---> AF Server
+ / || |
+ /(udp) || (tcp)|
+ / || /
+ Game server || AF Client-------User 2
+ || (udp)
-EXAMPLE 2:
-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):
+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: -t 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
- Where <name of the server> is a name (or ip) of a host where our server is running.
+ Where <name of the server> is a name (or ip) of a host where our server is
+ running.
+
+6) Connecting to our game is more complicated. The user must use afclient to do
+ this. He has to specify the server he is connecting to and the port, which
+ his program will be listening on:
+ $ ./afclient -U -d <hostname> -p <portnum> -n <name of the server> \
+ -m <server port>
+ Where <hostname> is the name of the user machine (who wants to connect to our
+ game). <portnum> is the port he will be connecting to. <name of the server>
+ is the name of the host where our server is running. <server port> is the
+ port on which the server is listening for users. In order to connect to our
+ game, the user has to connect to <hostname>:<portnum>.
+
+================================================================================
+
+================
+4. BUGS/PROBLEMS
+================
+
+There are no known/open bugs at the moment.
+
+================================================================================
+
+=====
+NOTES
+=====
+
+Active port forwarder is still under development, so please sent any comments,
+bugs notices and suggestions about it to <jeremian [at] poczta.fm>
+
+If you have some problems or want to share your opinions with others, feel free
+to post a message at http://gray-world.net/board/
+
+================================================================================
-6) Connecting to our game is more complicated. User must use afclient to do this.
- He has to specify server he is connecting to and port which his program will be listening on:
- $ ./afclient -U -d <hostname> -p <portnum> -n <name of the server> -m <server port>
- Where <hostname> is name of user machine (who wants to connect to our game). <portnum>
- is a port he will be connecting to. <name of the server> is a name of a host where our server
- is running. <server port> is a port on which server is listening for users.
- In order to connect to our game, user have to connect to <hostname>:<portnum>.
+======
+THANKS
+======
+ Big thanks to the GW Team:
-Active port forwarder is still under development, so please sent me any comments, bugs notices
-and suggestions about it to jeremian@poczta.fm
+ to Alex <alex [at] gray-world.net>
+ and Simon <scastro [at] entreelibre.com> for testing AF and a lot of advices.
+ Thanks to Ilia Perevezentsev <iliaper [at] mail.ru> who read and corrected the
+README file.
-And thanks for using this software!
+ And thanks for using this software!
LICENSE
-------
- Active Port Forwarder is distributed under the terms of the GNU General Public License
- v2.0 and is copyright (c) 2003 jeremian <jeremian [at] poczta.fm>.
- See the file COPYING for details.
+ 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
new file mode 100644
index 0000000..133609c
--- /dev/null
+++ b/exmodule.c
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ *
+ */
+
+/* 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.
+ */
+
+/* info
+ * return values:
+ * info about module
+ */
+
+char*
+info(void)
+{
+ return "An example module";
+}
+
+/* allow
+ * return values:
+ * 0 - allow to connect
+ * !=0 - drop the connection
+ */
+
+int
+allow(char* host, char* port)
+{
+ return 0; /* allow to connect */
+}
+
+/* filter
+ * return values:
+ * 0 - allow to transfer
+ * 1 - drop the packet
+ * 2 - drop the connection
+ */
+
+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 */
+}
diff --git a/file.c b/file.c
index c1b994e..d3712ea 100644
--- a/file.c
+++ b/file.c
@@ -28,150 +28,160 @@
ConfigurationT
parsefile(char* name, int* status)
{
- static ConfigurationT cfg;
- FILE* file = NULL;
- int state, i, n;
- char buff[256];
- char helpbuf1[256];
- char helpbuf2[256];
+ static ConfigurationT cfg;
+ FILE* file = NULL;
+ int state, i, n;
+ char buff[256];
+ char helpbuf1[256];
+ char helpbuf2[256];
- *status = 1;
+ *status = 1;
- memset(buff, 0, 256);
+ memset(buff, 0, 256);
- cfg.certif = NULL;
- cfg.keys = NULL;
- cfg.size = 0;
- cfg.realmtable = NULL;
- cfg.logging = 0;
- cfg.logfnam = NULL;
+ cfg.certif = NULL;
+ cfg.keys = NULL;
+ cfg.size = 0;
+ cfg.realmtable = NULL;
+ cfg.logging = 0;
+ cfg.logfnam = NULL;
- state = F_UNKNOWN;
+ state = F_UNKNOWN;
- file = fopen(name, "r");
- if (file == NULL) {
- return cfg;
- }
+ file = fopen(name, "r");
+ if (file == NULL) {
+ return cfg;
+ }
- while (fgets(buff, 256, file) != NULL) {
- helpbuf1[0] = 0;
- sscanf(buff, "%s", helpbuf1);
- if (strcmp(helpbuf1, "newrealm")==0) {
- ++cfg.size;
- }
- }
- rewind(file);
+ while (fgets(buff, 256, file) != NULL) {
+ helpbuf1[0] = 0;
+ sscanf(buff, "%s", helpbuf1);
+ if (strcmp(helpbuf1, "newrealm")==0) {
+ ++cfg.size;
+ }
+ }
+ rewind(file);
- cfg.realmtable = calloc(cfg.size, sizeof(RealmT));
- cfg.size = 0;
- *status = 0;
+ cfg.realmtable = calloc(cfg.size, sizeof(RealmT));
+ cfg.size = 0;
+ *status = 0;
- while (fgets(buff, 256, file) != NULL) {
- (*status)++;
- state = sscanf(buff, "%s %s", helpbuf1, helpbuf2);
- if (helpbuf1[0] == '#') {
- memset(buff, 0, 256);
- continue;
- }
- if (state == 1) {
- if (strcmp(helpbuf1, "newrealm")==0) {
- ++cfg.size;
- TYPE_SET_SSL(cfg.realmtable[cfg.size-1].type);
- TYPE_SET_ZLIB(cfg.realmtable[cfg.size-1].type);
- }
- else if (cfg.size == 0) {
- return cfg;
- }
- else if (strcmp(helpbuf1, "nossl")==0) {
- TYPE_UNSET_SSL(cfg.realmtable[cfg.size-1].type);
- }
- else if (strcmp(helpbuf1, "nozlib")==0) {
- TYPE_UNSET_ZLIB(cfg.realmtable[cfg.size-1].type);
- }
- else {
- return cfg;
- }
- }
- else if (state == 2) {
- if (strcmp(helpbuf1, "certificate")==0) {
- cfg.certif = calloc(strlen(helpbuf2)+1, sizeof(char));
- strcpy(cfg.certif, helpbuf2);
- }
- else if (strcmp(helpbuf1, "key")==0) {
- cfg.keys = calloc(strlen(helpbuf2)+1, sizeof(char));
- strcpy(cfg.keys, helpbuf2);
- }
- else if (strcmp(helpbuf1, "heavylog")==0) {
- if (cfg.logging)
- return cfg;
- cfg.logging = 2;
- cfg.logfnam = calloc(strlen(helpbuf2)+1,
- sizeof(char));
- strcpy(cfg.logfnam, helpbuf2);
-
- }
- else if (strcmp(helpbuf1, "lightlog")==0) {
- if (cfg.logging) {
- return cfg;
- }
- cfg.logging = 1;
- cfg.logfnam = calloc(strlen(helpbuf2)+1,
- sizeof(char));
- strcpy(cfg.logfnam, helpbuf2);
- }
- else if (cfg.size == 0) {
- return cfg;
- }
- else if (strcmp(helpbuf1, "hostname")==0) {
- cfg.realmtable[cfg.size-1].hostname = calloc(strlen(helpbuf2)+1,
- sizeof(char));
- strcpy(cfg.realmtable[cfg.size-1].hostname, helpbuf2);
- }
- else if (strcmp(helpbuf1, "listen")==0) {
- cfg.realmtable[cfg.size-1].lisportnum = calloc(strlen(helpbuf2)+1,
- sizeof(char));
- strcpy(cfg.realmtable[cfg.size-1].lisportnum, helpbuf2);
- }
- else if (strcmp(helpbuf1, "pass")==0) {
- n = strlen(helpbuf2);
- for (i = 0; i < n; ++i) {
- cfg.realmtable[cfg.size-1].pass[i%4] += helpbuf2[i];
- }
- }
- else if (strcmp(helpbuf1, "manage")==0) {
- cfg.realmtable[cfg.size-1].manportnum = calloc(strlen(helpbuf2)+1,
- sizeof(char));
- strcpy(cfg.realmtable[cfg.size-1].manportnum, helpbuf2);
- }
- else if (strcmp(helpbuf1, "users")==0) {
- cfg.realmtable[cfg.size-1].users = calloc(strlen(helpbuf2)+1,
- sizeof(char));
- strcpy(cfg.realmtable[cfg.size-1].users, helpbuf2);
- }
- else if (strcmp(helpbuf1, "proto")==0) {
- if (TYPE_IS_SET(cfg.realmtable[cfg.size-1].type)) {
- return cfg;
- }
- if (strcmp(helpbuf2, "tcp")==0) {
- TYPE_SET_TCP(cfg.realmtable[cfg.size-1].type);
- }
- else if (strcmp(helpbuf2, "udp")==0) {
- TYPE_SET_UDP(cfg.realmtable[cfg.size-1].type);
- }
- else {
- return cfg;
- }
- }
- else {
- return cfg;
- }
- }
- memset(buff, 0, 256);
- }
+ while (fgets(buff, 256, file) != NULL) {
+ (*status)++;
+ state = sscanf(buff, "%s %s", helpbuf1, helpbuf2);
+ if (helpbuf1[0] == '#') {
+ memset(buff, 0, 256);
+ continue;
+ }
+ if (state == 1) {
+ if (strcmp(helpbuf1, "newrealm")==0) {
+ ++cfg.size;
+ TYPE_SET_SSL(cfg.realmtable[cfg.size-1].type);
+ TYPE_SET_ZLIB(cfg.realmtable[cfg.size-1].type);
+ }
+ else if (cfg.size == 0) {
+ return cfg;
+ }
+ else if (strcmp(helpbuf1, "nossl")==0) {
+ TYPE_UNSET_SSL(cfg.realmtable[cfg.size-1].type);
+ }
+ else if (strcmp(helpbuf1, "nozlib")==0) {
+ TYPE_UNSET_ZLIB(cfg.realmtable[cfg.size-1].type);
+ }
+ else if (strcmp(helpbuf1, "ipv4")==0) {
+ if (TYPE_IS_UNSPEC(cfg.realmtable[cfg.size-1].type)) {
+ TYPE_SET_IPV4(cfg.realmtable[cfg.size-1].type);
+ }
+ else {
+ return cfg;
+ }
+ }
+ else if (strcmp(helpbuf1, "ipv6")==0) {
+ if (TYPE_IS_UNSPEC(cfg.realmtable[cfg.size-1].type)) {
+ TYPE_SET_IPV6(cfg.realmtable[cfg.size-1].type);
+ }
+ else {
+ return cfg;
+ }
+ }
+ else {
+ return cfg;
+ }
+ }
+ else if (state == 2) {
+ if (strcmp(helpbuf1, "certificate")==0) {
+ cfg.certif = calloc(strlen(helpbuf2)+1, sizeof(char));
+ strcpy(cfg.certif, helpbuf2);
+ }
+ else if (strcmp(helpbuf1, "key")==0) {
+ cfg.keys = calloc(strlen(helpbuf2)+1, sizeof(char));
+ strcpy(cfg.keys, helpbuf2);
+ }
+ else if (strcmp(helpbuf1, "heavylog")==0) {
+ if (cfg.logging) {
+ return cfg;
+ }
+ cfg.logging = 3;
+ cfg.logfnam = calloc(strlen(helpbuf2)+1, sizeof(char));
+ strcpy(cfg.logfnam, helpbuf2);
+ }
+ else if (strcmp(helpbuf1, "lightlog")==0) {
+ if (cfg.logging) {
+ return cfg;
+ }
+ cfg.logging = 1;
+ cfg.logfnam = calloc(strlen(helpbuf2)+1, sizeof(char));
+ strcpy(cfg.logfnam, helpbuf2);
+ }
+ else if (cfg.size == 0) {
+ return cfg;
+ }
+ else if (strcmp(helpbuf1, "hostname")==0) {
+ cfg.realmtable[cfg.size-1].hostname = calloc(strlen(helpbuf2)+1, sizeof(char));
+ strcpy(cfg.realmtable[cfg.size-1].hostname, helpbuf2);
+ }
+ else if (strcmp(helpbuf1, "listen")==0) {
+ cfg.realmtable[cfg.size-1].lisportnum = calloc(strlen(helpbuf2)+1, sizeof(char));
+ strcpy(cfg.realmtable[cfg.size-1].lisportnum, helpbuf2);
+ }
+ else if (strcmp(helpbuf1, "pass")==0) {
+ n = strlen(helpbuf2);
+ for (i = 0; i < n; ++i) {
+ cfg.realmtable[cfg.size-1].pass[i%4] += helpbuf2[i];
+ }
+ }
+ else if (strcmp(helpbuf1, "manage")==0) {
+ cfg.realmtable[cfg.size-1].manportnum = calloc(strlen(helpbuf2)+1, sizeof(char));
+ strcpy(cfg.realmtable[cfg.size-1].manportnum, helpbuf2);
+ }
+ else if (strcmp(helpbuf1, "users")==0) {
+ cfg.realmtable[cfg.size-1].users = calloc(strlen(helpbuf2)+1, sizeof(char));
+ strcpy(cfg.realmtable[cfg.size-1].users, helpbuf2);
+ }
+ else if (strcmp(helpbuf1, "proto")==0) {
+ if (TYPE_IS_SET(cfg.realmtable[cfg.size-1].type)) {
+ return cfg;
+ }
+ if (strcmp(helpbuf2, "tcp")==0) {
+ TYPE_SET_TCP(cfg.realmtable[cfg.size-1].type);
+ }
+ else if (strcmp(helpbuf2, "udp")==0) {
+ TYPE_SET_UDP(cfg.realmtable[cfg.size-1].type);
+ }
+ else {
+ return cfg;
+ }
+ }
+ else {
+ return cfg;
+ }
+ }
+ memset(buff, 0, 256);
+ }
- fclose(file);
+ fclose(file);
- *status = 0;
- return cfg;
+ *status = 0;
+ return cfg;
}
diff --git a/network.c b/network.c
index 1487aba..01fe513 100644
--- a/network.c
+++ b/network.c
@@ -23,156 +23,176 @@
#include "stats.h"
#include <string.h>
#include <errno.h>
-#include <signal.h>
#include <zlib.h>
-static void
-sig_alrm(int signo)
-{
- return;
-}
-
int
-ip_listen(const char *host, const char *serv, socklen_t *addrlenp, const char *type)
+ip_listen(int* sockfd, const char *host, const char *serv, socklen_t *addrlenp, const char type)
{
- int listenfd, n, typ;
+ int n;
const int on = 1;
struct addrinfo hints, *res, *ressave;
- if (strcmp(type, "udp") == 0)
- typ = 0; /* this is udp_listen */
- else
- typ = 1; /* default: tcp_listen */
-
bzero(&hints, sizeof(struct addrinfo));
hints.ai_flags = AI_PASSIVE;
- hints.ai_family = AF_UNSPEC;
+ if (type & 0x02) {
+ hints.ai_family = AF_INET;
+ }
+ else if (type & 0x04) {
+ hints.ai_family = AF_INET6;
+ }
+ else {
+ hints.ai_family = AF_UNSPEC;
+ }
- if (typ)
+ if (type & 0x01) {
hints.ai_socktype = SOCK_STREAM;
- else
+ }
+ else {
hints.ai_socktype = SOCK_DGRAM;
+ }
if ( (n = getaddrinfo(host, serv, &hints, &res)) != 0) {
- printf("%s_listen error for %s, %s: %s\n",
- (typ)?"tcp":"udp", host, serv, gai_strerror(n));
- exit(1);
+ return n;
}
ressave = res;
do {
- listenfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
- if (listenfd < 0)
+ (*sockfd) = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
+ if ((*sockfd) < 0) {
continue; /* error, try next one */
+ }
- if (typ) /* tcp_listen */
- setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
- if (bind(listenfd, res->ai_addr, res->ai_addrlen) == 0)
+ if (type & 0x01) { /* tcp_listen */
+ setsockopt((*sockfd), SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
+ }
+ if (bind((*sockfd), res->ai_addr, res->ai_addrlen) == 0) {
break; /* success */
+ }
- close(listenfd); /* bind error, close and try next one */
+ close((*sockfd)); /* bind error, close and try next one */
} while ( (res = res->ai_next) != NULL);
if (res == NULL) { /* errno from final socket() or bind() */
- printf("%s_listen error for %s, %s\n", (typ)?"tcp":"udp", host, serv);
- exit(1);
+ return 1;
}
- if (typ) /* tcp_listen */
- listen(listenfd, 1);
+ if (type & 0x01) { /* tcp_listen */
+ listen((*sockfd), 1);
+ }
- if (addrlenp)
+ if (addrlenp) {
*addrlenp = res->ai_addrlen; /* return size of protocol address */
+ }
freeaddrinfo(ressave);
- return(listenfd);
+ return(0);
}
int
-ip_connect(const char *host, const char *serv, const char* type)
+ip_connect(int* sockfd, const char *host, const char *serv, const char type)
{
- int sockfd, n, typ;
+ int n;
struct addrinfo hints, *res, *ressave;
- if (strcmp(type, "udp") == 0)
- typ = 0; /* this is udp_listen */
- else
- typ = 1; /* default: tcp_listen */
-
bzero(&hints, sizeof(struct addrinfo));
- hints.ai_family = AF_UNSPEC;
- if (typ)
+ if (type & 0x02) {
+ hints.ai_family = AF_INET;
+ }
+ else if (type & 0x04) {
+ hints.ai_family = AF_INET6;
+ }
+ else {
+ hints.ai_family = AF_UNSPEC;
+ }
+ if (type & 0x01) {
hints.ai_socktype = SOCK_STREAM;
- else
+ }
+ else {
hints.ai_socktype = SOCK_DGRAM;
+ }
if ( (n = getaddrinfo(host, serv, &hints, &res)) != 0) {
- printf("%s_connect error for %s, %s: %s\n",
- (typ)?"tcp":"udp", host, serv, gai_strerror(n));
- exit(1);
+ return n;
}
ressave = res;
do {
- sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
- if (sockfd < 0)
+ (*sockfd) = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
+ if ((*sockfd) < 0) {
continue; /* ignore this one */
+ }
- if (connect(sockfd, res->ai_addr, res->ai_addrlen) == 0)
+ if (connect((*sockfd), res->ai_addr, res->ai_addrlen) == 0) {
break; /* success */
+ }
- close(sockfd); /* ignore this one */
+ close((*sockfd)); /* ignore this one */
} while ( (res = res->ai_next) != NULL);
if (res == NULL) { /* errno set from final connect() */
- printf("%s_connect error for %s, %s\n", (typ)?"tcp":"udp", host, serv);
- exit(1);
+ return 1;
}
freeaddrinfo(ressave);
- return(sockfd);
+ return(0);
}
char *
-sock_ntop(const struct sockaddr *sa, socklen_t salen)
+sock_ntop(const struct sockaddr *sa, socklen_t salen, char* namebuf, char* portbuf)
{
char portstr[7];
static char str[128]; /* Unix domain is largest */
- switch (sa->sa_family) {
+ switch (sa->sa_family) {
case AF_INET: {
struct sockaddr_in *sin = (struct sockaddr_in *) sa;
- if (inet_ntop(AF_INET, &sin->sin_addr, str, sizeof(str)) == NULL)
+ if (inet_ntop(AF_INET, &sin->sin_addr, str, sizeof(str)) == NULL) {
return(NULL);
+ }
+ if (namebuf) {
+ if (inet_ntop(AF_INET, &sin->sin_addr, namebuf, 128) == NULL) {
+ return(NULL);
+ }
+ }
if (ntohs(sin->sin_port) != 0) {
snprintf(portstr, sizeof(portstr), ".%d", ntohs(sin->sin_port));
+ if (portbuf) {
+ snprintf(portbuf, 7, "%d", ntohs(sin->sin_port));
+ }
strcat(str, portstr);
}
return(str);
}
-
-#ifdef IPV6
+#ifdef AF_INET6
case AF_INET6: {
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sa;
- if (inet_ntop(AF_INET6, &sin6->sin6_addr, str, sizeof(str)) == NULL)
+ if (inet_ntop(AF_INET6, &sin6->sin6_addr, str, sizeof(str)) == NULL) {
return(NULL);
+ }
+ if (namebuf) {
+ if (inet_ntop(AF_INET6, &sin6->sin6_addr, namebuf, 128) == NULL) {
+ return(NULL);
+ }
+ }
if (ntohs(sin6->sin6_port) != 0) {
snprintf(portstr, sizeof(portstr), ".%d", ntohs(sin6->sin6_port));
+ if (portbuf) {
+ snprintf(portbuf, 7, "%d", ntohs(sin6->sin6_port));
+ }
strcat(str, portstr);
}
return(str);
}
#endif
-
- default:
- snprintf(str, sizeof(str), "sock_ntop: unknown AF_xxx: %d, len %d",
- sa->sa_family, salen);
+ default: {
+ snprintf(str, sizeof(str), "sock_ntop: unknown AF_xxx: %d, len %d", sa->sa_family, salen);
return(str);
}
+ }
return (NULL);
}
@@ -182,10 +202,7 @@ SSL_writen(SSL* fd, unsigned char* buf, int amount)
int sent, n;
sent = 0;
while (sent < amount) {
- signal(SIGALRM, sig_alrm);
- alarm(5);
n = SSL_write(fd, buf+sent, amount - sent);
- alarm(0);
if (n != -1) {
sent += n;
}
@@ -223,10 +240,7 @@ writen(int fd, unsigned char* buf, int amount)
int sent, n;
sent = 0;
while (sent < amount) {
- signal(SIGALRM, sig_alrm);
- alarm(5);
n = write(fd, buf+sent, amount - sent);
- alarm(0);
if (n != -1) {
sent += n;
}
diff --git a/network.h b/network.h
index 2dff6e0..1ce2ccb 100644
--- a/network.h
+++ b/network.h
@@ -39,9 +39,9 @@ typedef struct {
SSL* ssl;
} clifd;
-int ip_listen(const char *host, const char *serv, socklen_t *addrlenp, const char *type); /* socket, bind, listen... */
-int ip_connect(const char *host, const char *serv, const char *type); /* socket, connect... */
-char* sock_ntop(const struct sockaddr* sa, socklen_t salen); /* return the hostname of connected user */
+int ip_listen(int* sockfd, const char *host, const char *serv, socklen_t *addrlenp, const char type); /* socket, bind, listen... */
+int ip_connect(int* sockfd, const char *host, const char *serv, const char type); /* socket, connect... */
+char* sock_ntop(const struct sockaddr* sa, socklen_t salen, char* namebuf, char* portbuf); /* return the IP of connected user */
int send_message(char type, clifd fd, unsigned char* buf, int amount);
int get_message(char type, clifd fd, unsigned char* buf, int amount);