提交 3866752e 编写于 作者: G Geoff Thorpe

- New INSTALL document describing different ways to build "tunala" and

  possible problems.
- New file breakage.c handles (so far) missing functions.
- Get rid of some signed/unsigned/const warnings thanks to solaris-cc
- Add autoconf/automake input files, and helper scripts to populate missing
  (but auto-generated) files.

This change adds a configure.in and Makefile.am to build everything using
autoconf, automake, and libtool - and adds "gunk" scripts to generate the
various files those things need (and clean then up again after). This means
that "autogunk.sh" needs to be run first on a system with the autotools,
but the resulting directory should be "configure"able and compilable on
systems without those tools.
上级 3e3dac9f
There are two ways to build this code;
(1) Manually
(2) Using all-singing all-dancing (all-confusing) autotools, ie. autoconf,
automake, libtool, and their little friends (autoheader, etc).
=================
Building Manually
=================
There is a basic "Makefile" in this directory that gets moved out of the way and
ignored when building with autoconf et al. This Makefile is suitable for
building tunala on Linux using gcc. Any other platform probably requires some
tweaking. Here are the various bits you might need to do if you want to build
this way and the default Makefile isn't sufficient;
* Compiler: Edit the "CC" definition in Makefile
* Headers, features: tunala.h controls what happens in the non-autoconf world.
It, by default, assumes the system has *everything* (except autoconf's
"config.h") so if a target system is missing something it must define the
appropriate "NO_***" symbols in CFLAGS. These include;
- NO_HAVE_UNISTD_H, NO_HAVE_FCNTL_H, NO_HAVE_LIMITS_H
Indicates the compiling system doesn't have (or need) these header files.
- NO_HAVE_STRSTR, NO_HAVE_STRTOUL
Indicates the compiling system doesn't have these functions. Replacements
are compiled and used in breakage.c
- NO_HAVE_SELECT, NO_HAVE_SOCKET
Pointless symbols - these indicate select() and/or socket() are missing in
which case the program won't compile anyway.
If you want to specify any of these, add them with "-D" prefixed to each in
the CFLAGS definition in Makefile.
* Compilation flags: edit DEBUG_FLAGS and/or CFLAGS directly to control the
flags passed to the compiler. This can also be used to change the degree of
optimisation.
* Linker flags: some systems (eg. Solaris) require extra linker flags such as;
-ldl, -lsocket, -lnsl, etc. If unsure, bring up the man page for whichever
function is "undefined" when the linker fails - that usually indicates what
you need to add. Make changes to the LINK_FLAGS symbol.
* Linker command: if a different linker syntax or even a different program is
required to link, edit the linker line directly in the "tunala:" target
definition - it currently assumes the "CC" (compiler) program is used to link.
======================
Building Automagically
======================
Automagic building is handled courtesy of autoconf, automake, and libtool. There
is in fact two steps required to build, and only the first has to be done on a
system with these tools installed (and if I was prepared to bloat out the CVS
repository, I could store these extra files, but I'm not).
First step: "autogunk.sh"
-------------------------
The "./autogunk.sh" script will call all the necessary autotool commands to
create missing files and run automake and autoconf. The result is that a
"./configure" script should be generated and a "Makefile.in" generated from the
supplied "Makefile.am". NB: This script also moves the "manual" Makefile (see
above) out of the way and calls it "Makefile.plain" - the "ungunk" script
reverses this to leave the directory it was previously.
Once "ungunk" has been run, the resulting directory should be able to build on
other systems without autoconf, automake, or libtool. Which is what the second
step describes;
Second step: "./configure"
--------------------------
The second step is to run the generated "./configure" script to create a
config.h header for your system and to generate a "Makefile" (generated from
"Makefile.in") tweaked to compile on your system. This is the standard sort of
thing you see in GNU packages, for example, and the standard tricks also work.
Eg. to override "configure"'s choice of compiler, set the CC environment
variable prior to running configure, eg.
CC=gcc ./configure
would cause "gcc" to be used even if there is an otherwise preferable (to
autoconf) native compiler on your system.
*IMPORTANT* It's highly recommended to pass "--disable-shared" to the configure
script. Otherwise, libtool may elect to build most of the code as a
shared-library, hide various bits of it in dotted directories and generating
wrapper scripts in place of the linked binary. The autotool stuff, when "make
install" is run (which you probably won't want to do for this dinky little
thing) will unravel all that mess and either install a small executable +
shared-lib or will install a linked executable. Passing the above flag ensures
this is all done statically even if the platform supports building and using
shared-libraries. Ie;
./configure --disable-shared
After this run "make" and it should build the "tunala" executable.
Notes
-----
- Some versions of autoconf (or automake?) generate a Makefile syntax that gives
trouble to some "make" programs on some systems (eg. OpenBSD). If this
happens, either build 'Manually' (see above) or use "gmake" instead of "make".
I don't like this either but like even less the idea of sifting into all the
script magic crud that's involved.
- On a solaris system I tried, the "configure" script specified some broken
compiler flags in the resulting Makefile that don't even get echoed to
stdout/err when the error happens (evil!). If this happens, go into the
generated Makefile, find the two affected targets ("%.o:" and "%.lo"), and
remove the offending hidden option in the $(COMPILE) line all the sludge after
the two first lines of script (ie. after the "echo" and the "COMPILE" lines).
NB: This will probably only function if "--disable-shared" was used, otherwise
who knows what would result ...
......@@ -11,14 +11,14 @@ RM=rm -f
CC=gcc
DEBUG_FLAGS=-g -ggdb3 -Wall -Wshadow
INCLUDE_FLAGS=-I$(SSL_INCLUDEDIR)
CFLAGS=$(DEBUG_FLAGS) $(INCLUDE_FLAGS)
CFLAGS=$(DEBUG_FLAGS) $(INCLUDE_FLAGS) -DNO_CONFIG_H
COMPILE=$(CC) $(CFLAGS) -c
# Edit, particularly the "-ldl" if not building with "dlfcn" support
LINK_FLAGS=-L$(SSL_LIBDIR) -lssl -lcrypto -ldl
SRCS=buffer.c cb.c ip.c sm.c tunala.c
OBJS=buffer.o cb.o ip.o sm.o tunala.o
SRCS=buffer.c cb.c ip.c sm.c tunala.c breakage.c
OBJS=buffer.o cb.o ip.o sm.o tunala.o breakage.o
TARGETS=tunala
......
# Our includes come from the OpenSSL build-tree we're in
INCLUDES = -I$(top_builddir)/../../include
lib_LTLIBRARIES = libtunala.la
libtunala_la_SOURCES = buffer.c cb.c ip.c sm.c breakage.c
bin_PROGRAMS = tunala
tunala_SOURCES = tunala.c
tunala_LDADD = libtunala.la -L$(top_builddir)/../.. -lssl -lcrypto
......@@ -188,20 +188,16 @@ flags inside the Makefile. Likewise, if you want to tweak the building, it's
best to try and do so in the makefile (eg. removing the debug flags and adding
optimisation flags).
Secondly, this code so far has only ever been built and run on Linux - network
specifics are more than likely to create little glitches on other unixen,
particularly Solaris in my experience. If you're not on Linux, please read the
code wherever compilation flares up and try to make the necessary changes -
usually the man-page associated with the relevant function is enough (eg. all
that AF_INET/PF_INET stuff, subtlely different parameters to various
IPv4-related functions like socket(), bind(), fcntl(), etc).
Secondly, this code has mostly only been tested on Linux. However, some
autoconf/etc support has been added and the code has been compiled on openbsd
and solaris using that.
Thirdly, if you are Win32, you probably need to do some *major* rewriting of
ip.c to stand a hope in hell. Good luck, and please mail me the diff if you do
this, otherwise I will take a look at another time. It can certainly be done,
but it's very non-POSIXy.
Type make.
See the INSTALL document for details on building.
Now, if you don't have an executable "tunala" compiled, go back to "First,...".
Rinse and repeat.
......@@ -217,8 +213,10 @@ In another console, type;
-cert A-server.pem -server 1 -out_totals -v_peer -v_strict
Now if you open another console and "telnet localhost 8080", you should be
tunneled through to the telnet service on your local machine. Feel free to
experiment :-)
tunneled through to the telnet service on your local machine (if it's running -
you could change it to port "22" and tunnel ssh instead if you so desired). When
you logout of the telnet session, the tunnel should cleanly shutdown and show
you some traffic stats in both consoles. Feel free to experiment. :-)
Notes:
......
#!/bin/sh
# This script tries to follow the "GNU way" w.r.t. the autobits.
# This does of course generate a number of irritating files.
# Try to get over it (I am getting there myself).
# This should generate any missing crud, and then run autoconf which should turn
# configure.in into a "./configure" script and "Makefile.am" into a
# "Makefile.in". Then running "./configure" should turn "Makefile.in" into
# "Makefile" and should generate the config.h containing your systems various
# settings. I know ... what a hassle ...
# Also, sometimes these autobits things generate bizarre output (looking like
# errors). So I direct everything "elsewhere" ...
(aclocal
autoheader
libtoolize --copy --force
automake --foreign --add-missing --copy
autoconf) 1> /dev/null 2>&1
# Move the "no-autotools" Makefile out of the way
if test ! -f Makefile.plain; then
mv Makefile Makefile.plain
fi
#!/bin/sh
# This script tries to clean up as much as is possible from whatever diabolical
# mess has been left in the directory thanks to autoconf, automake, and their
# friends.
if test -f Makefile; then
make distclean
rm -f Makefile
fi
if test -f Makefile.plain; then
mv Makefile.plain Makefile
fi
rm -f aclocal.m4 config.* configure install-sh \
missing mkinstalldirs stamp-h.* Makefile.in \
ltconfig ltmain.sh
#include "tunala.h"
int int_strtoul(const char *str, unsigned long *val)
{
#ifdef HAVE_STRTOUL
char *tmp;
unsigned long ret = strtoul(str, &tmp, 10);
if((str == tmp) || (*tmp != '\0'))
/* The value didn't parse cleanly */
return 0;
if(ret == ULONG_MAX)
/* We hit a limit */
return 0;
*val = ret;
return 1;
#else
char buf[2];
unsigned long ret = 0;
buf[1] = '\0';
if(str == '\0')
/* An empty string ... */
return 0;
while(*str != '\0') {
/* We have to multiply 'ret' by 10 before absorbing the next
* digit. If this will overflow, catch it now. */
if(ret && (((ULONG_MAX + 10) / ret) < 10))
return 0;
ret *= 10;
if(!isdigit(*str))
return 0;
buf[0] = *str;
ret += atoi(buf);
str++;
}
*val = ret;
return 1;
#endif
}
#ifndef HAVE_STRSTR
char *int_strstr(const char *haystack, const char *needle)
{
const char *sub_haystack = haystack, *sub_needle = needle;
unsigned int offset = 0;
if(!needle)
return haystack;
if(!haystack)
return NULL;
while((*sub_haystack != '\0') && (*sub_needle != '\0')) {
if(sub_haystack[offset] == sub_needle) {
/* sub_haystack is still a candidate */
offset++;
sub_needle++;
} else {
/* sub_haystack is no longer a possibility */
sub_haystack++;
offset = 0;
sub_needle = needle;
}
}
if(*sub_haystack == '\0')
/* Found nothing */
return NULL;
return sub_haystack;
}
#endif
dnl Process this file with autoconf to produce a configure script.
AC_INIT(tunala.c)
AM_CONFIG_HEADER(config.h)
AM_INIT_AUTOMAKE(tunala, 0.0.1-dev)
dnl Checks for programs.
AC_PROG_CC
AC_PROG_LIBTOOL
AM_PROG_LIBTOOL
dnl Checks for libraries.
AC_CHECK_LIB(dl, dlopen)
AC_CHECK_LIB(socket, socket)
AC_CHECK_LIB(nsl, gethostbyname)
dnl Checks for header files.
AC_HEADER_STDC
AC_CHECK_HEADERS(fcntl.h limits.h unistd.h)
dnl Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
dnl Checks for library functions.
AC_CHECK_FUNCS(strstr strtoul)
AC_CHECK_FUNCS(select socket)
AC_CHECK_FUNCS(dlopen)
AC_OUTPUT(Makefile)
......@@ -18,7 +18,7 @@ int ip_initialise(void)
return 1;
}
int ip_create_listener_split(const unsigned char *ip, unsigned short port)
int ip_create_listener_split(const char *ip, unsigned short port)
{
struct sockaddr_in in_addr;
int fd = -1;
......@@ -36,7 +36,7 @@ int ip_create_listener_split(const unsigned char *ip, unsigned short port)
memcpy(&in_addr.sin_addr.s_addr, ip, 4);
in_addr.sin_port = htons(port);
/* Bind to the required port/address/interface */
if(bind(fd, &in_addr, sizeof(struct sockaddr_in)) != 0)
if(bind(fd, (struct sockaddr *)&in_addr, sizeof(struct sockaddr_in)) != 0)
goto err;
/* Start "listening" */
if(listen(fd, IP_LISTENER_BACKLOG) != 0)
......@@ -48,7 +48,7 @@ err:
return -1;
}
int ip_create_connection_split(const unsigned char *ip, unsigned short port)
int ip_create_connection_split(const char *ip, unsigned short port)
{
struct sockaddr_in in_addr;
int flags, fd = -1;
......@@ -65,7 +65,8 @@ int ip_create_connection_split(const unsigned char *ip, unsigned short port)
memcpy(&in_addr.sin_addr.s_addr, ip, 4);
in_addr.sin_port = htons(port);
/* Start a connect (non-blocking, in all likelihood) */
if((connect(fd, &in_addr, sizeof(struct sockaddr_in)) != 0) &&
if((connect(fd, (struct sockaddr *)&in_addr,
sizeof(struct sockaddr_in)) != 0) &&
(errno != EINPROGRESS))
goto err;
return fd;
......@@ -75,17 +76,16 @@ err:
return -1;
}
static unsigned char all_local_ip[] = {0x00,0x00,0x00,0x00};
static char all_local_ip[] = {0x00,0x00,0x00,0x00};
int ip_parse_address(const char *address, unsigned char **parsed_ip,
int ip_parse_address(const char *address, const char **parsed_ip,
unsigned short *parsed_port, int accept_all_ip)
{
char buf[256];
struct hostent *lookup;
unsigned long port;
char *temp;
const char *ptr = strstr(address, ":");
unsigned char *ip = all_local_ip;
const char *ip = all_local_ip;
if(!ptr) {
/* We assume we're listening on all local interfaces and have
......@@ -110,8 +110,7 @@ int ip_parse_address(const char *address, unsigned char **parsed_ip,
determine_port:
if(strlen(ptr) < 1)
return 0;
port = strtoul(ptr, &temp, 10);
if((temp == ptr) || (*temp != '\0') || (port > 65535))
if(!int_strtoul(ptr, &port) || (port > 65535))
return 0;
*parsed_ip = ip;
*parsed_port = (unsigned short)port;
......@@ -120,7 +119,7 @@ determine_port:
int ip_create_listener(const char *address)
{
unsigned char *ip;
const char *ip;
unsigned short port;
if(!ip_parse_address(address, &ip, &port, 1))
......@@ -130,7 +129,7 @@ int ip_create_listener(const char *address)
int ip_create_connection(const char *address)
{
unsigned char *ip;
const char *ip;
unsigned short port;
if(!ip_parse_address(address, &ip, &port, 0))
......
......@@ -80,7 +80,7 @@ static int selector_select(tunala_selector_t *selector);
* which case *newfd is populated. */
static int selector_get_listener(tunala_selector_t *selector, int fd, int *newfd);
static int tunala_world_new_item(tunala_world_t *world, int fd,
const unsigned char *ip, unsigned short port, int flipped);
const char *ip, unsigned short port, int flipped);
static void tunala_world_del_item(tunala_world_t *world, unsigned int idx);
static int tunala_item_io(tunala_selector_t *selector, tunala_item_t *item);
......@@ -219,9 +219,7 @@ static int err_str1(const char *fmt, const char *str1)
static int parse_max_tunnels(const char *s, unsigned int *maxtunnels)
{
unsigned long l;
char *temp;
l = strtoul(s, &temp, 10);
if((temp == s) || (*temp != '\0') || (l < 1) || (l > 1024)) {
if(!int_strtoul(s, &l) || (l < 1) || (l > 1024)) {
fprintf(stderr, "Error, '%s' is an invalid value for "
"maxtunnels\n", s);
return 0;
......@@ -233,9 +231,7 @@ static int parse_max_tunnels(const char *s, unsigned int *maxtunnels)
static int parse_server_mode(const char *s, int *servermode)
{
unsigned long l;
char *temp;
l = strtoul(s, &temp, 10);
if((temp == s) || (*temp != '\0') || (l > 1)) {
if(!int_strtoul(s, &l) || (l > 1)) {
fprintf(stderr, "Error, '%s' is an invalid value for the "
"server mode\n", s);
return 0;
......@@ -258,9 +254,7 @@ static int parse_dh_special(const char *s, const char **dh_special)
static int parse_verify_level(const char *s, unsigned int *verify_level)
{
unsigned long l;
char *temp;
l = strtoul(s, &temp, 10);
if((temp == s) || (*temp != '\0') || (l > 3)) {
if(!int_strtoul(s, &l) || (l > 3)) {
fprintf(stderr, "Error, '%s' is an invalid value for "
"out_verify\n", s);
return 0;
......@@ -272,9 +266,7 @@ static int parse_verify_level(const char *s, unsigned int *verify_level)
static int parse_verify_depth(const char *s, unsigned int *verify_depth)
{
unsigned long l;
char *temp;
l = strtoul(s, &temp, 10);
if((temp == s) || (*temp != '\0') || (l < 1) || (l > 50)) {
if(!int_strtoul(s, &l) || (l < 1) || (l > 50)) {
fprintf(stderr, "Error, '%s' is an invalid value for "
"verify_depth\n", s);
return 0;
......@@ -299,7 +291,7 @@ int main(int argc, char *argv[])
int newfd;
tunala_world_t world;
tunala_item_t *t_item;
unsigned char *proxy_ip;
const char *proxy_ip;
unsigned short proxy_port;
/* Overridables */
const char *proxyhost = def_proxyhost;
......@@ -527,7 +519,7 @@ main_loop:
switch(selector_select(&world.selector)) {
case -1:
fprintf(stderr, "selector_select returned a badness error.\n");
abort();
goto shouldnt_happen;
case 0:
fprintf(stderr, "Warn, selector_select returned 0 - signal??\n");
goto main_loop;
......@@ -589,6 +581,7 @@ skip_totals:
}
goto main_loop;
/* Should never get here */
shouldnt_happen:
abort();
return 1;
}
......@@ -736,6 +729,7 @@ static SSL_CTX *initialise_ssl_ctx(int server_mode, const char *engine_id,
if(meth == NULL)
goto err;
if(engine_id) {
ENGINE_load_builtin_engines();
if((e = ENGINE_by_id(engine_id)) == NULL) {
fprintf(stderr, "Error obtaining '%s' engine, openssl "
"errors follow\n", engine_id);
......@@ -935,7 +929,7 @@ static int tunala_world_make_room(tunala_world_t *world)
}
static int tunala_world_new_item(tunala_world_t *world, int fd,
const unsigned char *ip, unsigned short port, int flipped)
const char *ip, unsigned short port, int flipped)
{
tunala_item_t *item;
int newfd;
......
......@@ -17,13 +17,57 @@
#ifndef _TUNALA_H
#define _TUNALA_H
/* pull in autoconf fluff */
#ifndef NO_CONFIG_H
#include "config.h"
#else
/* We don't have autoconf, we have to set all of these unless a tweaked Makefile
* tells us not to ... */
/* headers */
#ifndef NO_HAVE_SELECT
#define HAVE_SELECT
#endif
#ifndef NO_HAVE_SOCKET
#define HAVE_SOCKET
#endif
#ifndef NO_HAVE_UNISTD_H
#define HAVE_UNISTD_H
#endif
#ifndef NO_HAVE_FCNTL_H
#define HAVE_FCNTL_H
#endif
#ifndef NO_HAVE_LIMITS_H
#define HAVE_LIMITS_H
#endif
/* features */
#ifndef NO_HAVE_STRSTR
#define HAVE_STRSTR
#endif
#ifndef NO_HAVE_STRTOUL
#define HAVE_STRTOUL
#endif
#endif
#if !defined(HAVE_SELECT) || !defined(HAVE_SOCKET)
#error "can't build without some network basics like select() and socket()"
#endif
#include <stdlib.h>
#ifndef NO_SYSTEM_H
#include <string.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif
#include <netdb.h>
#include <signal.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#endif /* !defined(NO_SYSTEM_H) */
......@@ -143,20 +187,28 @@ int ip_initialise(void);
/* ip is the 4-byte ip address (eg. 127.0.0.1 is {0x7F,0x00,0x00,0x01}), port is
* the port to listen on (host byte order), and the return value is the
* file-descriptor or -1 on error. */
int ip_create_listener_split(const unsigned char *ip, unsigned short port);
int ip_create_listener_split(const char *ip, unsigned short port);
/* Same semantics as above. */
int ip_create_connection_split(const unsigned char *ip, unsigned short port);
int ip_create_connection_split(const char *ip, unsigned short port);
/* Converts a string into the ip/port before calling the above */
int ip_create_listener(const char *address);
int ip_create_connection(const char *address);
/* Just does a string conversion on its own. NB: If accept_all_ip is non-zero,
* then the address string could be just a port. Ie. it's suitable for a
* listening address but not a connecting address. */
int ip_parse_address(const char *address, unsigned char **parsed_ip,
int ip_parse_address(const char *address, const char **parsed_ip,
unsigned short *port, int accept_all_ip);
/* Accepts an incoming connection through the listener. Assumes selects and
* what-not have deemed it an appropriate thing to do. */
int ip_accept_connection(int listen_fd);
#endif /* !defined(NO_IP) */
/* These functions wrap up things that can be portability hassles. */
int int_strtoul(const char *str, unsigned long *val);
#ifdef HAVE_STRSTR
#define int_strstr strstr
#else
char *int_strstr(const char *haystack, const char *needle);
#endif
#endif /* !defined(_TUNALA_H) */
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册