httptunnel-3.3/0000755000175000017500000000000007246172756010524 5ustar httptunnel-3.3/acinclude.m40000644000175000017500000000171507001660311012673 0ustar dnl HTTPTUNNEL_TYPE_SOCKLEN_T dnl Check for the existance of type socklen_t. AC_DEFUN(HTTPTUNNEL_TYPE_SOCKLEN_T, [AC_CACHE_CHECK([for socklen_t], ac_cv_httptunnel_type_socklen_t, [ AC_TRY_COMPILE( [#include #include ], [socklen_t len = 42; return 0;], ac_cv_httptunnel_type_socklen_t=yes, ac_cv_httptunnel_type_socklen_t=no) ]) if test $ac_cv_httptunnel_type_socklen_t != yes; then AC_DEFINE(socklen_t, int) fi ]) dnl HTTPTUNNEL_DEFINE_INADDR_NONE dnl Check for the existance of define INADDR_NONE AC_DEFUN(HTTPTUNNEL_DEFINE_INADDR_NONE, [AC_CACHE_CHECK([whether INADDR_NONE is defined], ac_cv_httptunnel_define_inaddr_none, [ AC_TRY_COMPILE( [#include #include ], [return INADDR_NONE;], ac_cv_httptunnel_define_inaddr_none=yes, ac_cv_httptunnel_define_inaddr_none=no) ]) if test $ac_cv_httptunnel_define_inaddr_none != yes; then AC_DEFINE(INADDR_NONE, 0xffffffff) fi ]) httptunnel-3.3/config.h.in0000644000175000017500000000445107126740721012541 0ustar /* config.h.in. Generated automatically from configure.in by autoheader. */ /* Define to empty if the keyword does not work. */ #undef const /* Define if you don't have vprintf but do have _doprnt. */ #undef HAVE_DOPRNT /* Define if you have the vprintf function. */ #undef HAVE_VPRINTF /* Define as __inline if that's what the C compiler calls it. */ #undef inline /* Define as the return type of signal handlers (int or void). */ #undef RETSIGTYPE /* Define to `unsigned' if doesn't define. */ #undef size_t /* Define if you have the ANSI C header files. */ #undef STDC_HEADERS /* Enable debugging mode. */ #undef DEBUG_MODE /* The number of bytes in a char. */ #undef SIZEOF_CHAR /* The number of bytes in a int. */ #undef SIZEOF_INT /* The number of bytes in a long. */ #undef SIZEOF_LONG /* The number of bytes in a long long. */ #undef SIZEOF_LONG_LONG /* The number of bytes in a short. */ #undef SIZEOF_SHORT /* Define if you have the daemon function. */ #undef HAVE_DAEMON /* Define if you have the endprotoent function. */ #undef HAVE_ENDPROTOENT /* Define if you have the poll function. */ #undef HAVE_POLL /* Define if you have the select function. */ #undef HAVE_SELECT /* Define if you have the socket function. */ #undef HAVE_SOCKET /* Define if you have the strdup function. */ #undef HAVE_STRDUP /* Define if you have the strerror function. */ #undef HAVE_STRERROR /* Define if you have the syslog function. */ #undef HAVE_SYSLOG /* Define if you have the vsnprintf function. */ #undef HAVE_VSNPRINTF /* Define if you have the vsyslog function. */ #undef HAVE_VSYSLOG /* Define if you have the header file. */ #undef HAVE_FCNTL_H /* Define if you have the header file. */ #undef HAVE_SYS_POLL_H /* Define if you have the header file. */ #undef HAVE_SYSLOG_H /* Define if you have the header file. */ #undef HAVE_UNISTD_H /* Define if you have the nsl library (-lnsl). */ #undef HAVE_LIBNSL /* Define if you have the socket library (-lsocket). */ #undef HAVE_LIBSOCKET /* Name of package */ #undef PACKAGE /* Version number of package */ #undef VERSION /* Define to 'int' if doesn't define. */ #undef socklen_t /* Define to 0xffffffff if doesn't define. */ #undef INADDR_NONE httptunnel-3.3/Makefile.am0000644000175000017500000000117307126737715012561 0ustar ## Copyright (C) 1999 Lars Brinkhoff SUBDIRS = port bin_PROGRAMS = htc hts man_MANS = hts.1 htc.1 if SRCDIR CPPFLAGS += -I$(VPATH)/port else CPPFLAGS += -Iport endif htc_SOURCES = htc.c common.c tunnel.c http.c base64.c htc_LDADD = -Lport -lport hts_SOURCES = hts.c common.c tunnel.c http.c hts_LDADD = -Lport -lport noinst_HEADERS = common.h tunnel.h http.h base64.h EXTRA_DIST = TODO HACKING DISCLAIMER doc/rfc1945.txt doc/rfc2068.txt \ FAQ doc/rfc2045.txt hts.1 htc.1 debian/changelog debian/control \ debian/copyright debian/dirs debian/docs debian/rules \ debian/prerm debian/postinst httptunnel-3.3/htc.10000644000175000017500000000344506760512045011357 0ustar .TH HTC 1 .SH NAME htc \- httptunnel client .SH SYNOPSIS .B htc .I "[options] host[:port]" .SH "DESCRIPTION" This manual page briefly documents the .B htc command. .PP .B htc sets up a httptunnel connection to PORT at HOST (default port is 8888). When a connection is made, I/O is redirected from the source specified by the --device or --forward-port switch to the tunnel. .SH OPTIONS The program follows the usual GNU command line syntax, with long options starting with two dashes (`-'). A summary of options are included below. .TP .B \-h, \-\-help Show summary of options. .TP .B \-c, \-\-content-length BYTES use HTTP PUT requests of BYTES size (k, M, and G postfixes recognized) .TP .B \-d, \-\-device DEVICE use DEVICE for input and output .TP .B \-F, \-\-forward\-port PORT use TCP port PORT for input and output .TP .B \-k, \-\-keep\-alive SECONDS send keepalive bytes every SECONDS seconds (default is 5) .TP .B \-M, \-\-max\-connection\-age SEC maximum time a connection will stay open is SEC seconds (default is 300) .TP .B \-S, \-\-strict\-content\-length always write Content-Length bytes in requests .TP .B \-A, \-\-proxy\-authorization USER:PASSWORD proxy authorization .TP .B \-\-proxy\-authorization\-file FILE proxy authorization file .TP .B \-B, \-\-proxy\-buffer\-size BYTES assume a proxy buffer size of BYTES bytes (k, M, and G postfixes recognized) .TP .B \-P, \-\-proxy HOSTNAME[:PORT] use a HTTP proxy (default port is 8080) .TP .B \-T, \-\-timeout TIME timeout, in milliseconds, before sending padding to a buffering proxy .TP .B \-U, \-\-user-agent STRING specify User-Agent value in HTTP requests .TP .B \-V, \-\-version output version information and exit .SH AUTHOR This manual page was contributed by Teemu Hukkanen , and was originally written for the Debian GNU/Linux system. httptunnel-3.3/base64.c0000644000175000017500000000321406754751553011755 0ustar /* base64.c Copyright (C) 1999 Lars Brinkhoff. See COPYING for terms and conditions. */ #include #include #include "config.h" #include "base64.h" #include "common.h" static int encode[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' }; /* Base64-encode LENGTH bytes of DATA in *CODE, which will be a newly malloced area. *CODE will be a null-terminated string. Return -1 on failure, or number of bytes of base64 code on success. */ ssize_t encode_base64 (const void *data, size_t length, char **code) { const unsigned char *s, *end; unsigned char *buf; unsigned int x; ssize_t n; int i, j; if (length == 0) return 0; end = (char *)data + length - 3; buf = malloc (4 * ((length + 2) / 3) + 1); if (buf == NULL) return -1; n = 0; for (s = data; s < end;) { x = *s++ << 24; x |= *s++ << 16; x |= *s++ << 8; *buf++ = encode[x >> 26]; x <<= 6; *buf++ = encode[x >> 26]; x <<= 6; *buf++ = encode[x >> 26]; x <<= 6; *buf++ = encode[x >> 26]; n += 4; } end += 3; x = 0; for (i = 0; s < end; i++) x |= *s++ << (24 - 8 * i); for (j = 0; j < 4; j++) { if (8 * i >= 6 * j) { *buf++ = encode [x >> 26]; x <<= 6; n++; } else { *buf++ = '='; n++; } } *buf = 0; *code = buf - n; return n; } httptunnel-3.3/configure0000755000175000017500000023642407246172547012444 0ustar #! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated automatically using autoconf version 2.13 # Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. # Defaults: ac_help= ac_default_prefix=/usr/local # Any additions from configure.in: ac_help="$ac_help --enable-debug enable debugging" # Initialize some variables set by options. # The variables have the same names as the options, with # dashes changed to underlines. build=NONE cache_file=./config.cache exec_prefix=NONE host=NONE no_create= nonopt=NONE no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= target=NONE verbose= x_includes=NONE x_libraries=NONE bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datadir='${prefix}/share' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' libdir='${exec_prefix}/lib' includedir='${prefix}/include' oldincludedir='/usr/include' infodir='${prefix}/info' mandir='${prefix}/man' # Initialize some other variables. subdirs= MFLAGS= MAKEFLAGS= SHELL=${CONFIG_SHELL-/bin/sh} # Maximum number of lines to put in a shell here document. ac_max_here_lines=12 ac_prev= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval "$ac_prev=\$ac_option" ac_prev= continue fi case "$ac_option" in -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; *) ac_optarg= ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case "$ac_option" in -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir="$ac_optarg" ;; -build | --build | --buil | --bui | --bu) ac_prev=build ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build="$ac_optarg" ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file="$ac_optarg" ;; -datadir | --datadir | --datadi | --datad | --data | --dat | --da) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ | --da=*) datadir="$ac_optarg" ;; -disable-* | --disable-*) ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` # Reject names that are not valid shell variable names. if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } fi ac_feature=`echo $ac_feature| sed 's/-/_/g'` eval "enable_${ac_feature}=no" ;; -enable-* | --enable-*) ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'` # Reject names that are not valid shell variable names. if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } fi ac_feature=`echo $ac_feature| sed 's/-/_/g'` case "$ac_option" in *=*) ;; *) ac_optarg=yes ;; esac eval "enable_${ac_feature}='$ac_optarg'" ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix="$ac_optarg" ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he) # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat << EOF Usage: configure [options] [host] Options: [defaults in brackets after descriptions] Configuration: --cache-file=FILE cache test results in FILE --help print this message --no-create do not create output files --quiet, --silent do not print \`checking...' messages --version print the version of autoconf that created configure Directory and file names: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [same as prefix] --bindir=DIR user executables in DIR [EPREFIX/bin] --sbindir=DIR system admin executables in DIR [EPREFIX/sbin] --libexecdir=DIR program executables in DIR [EPREFIX/libexec] --datadir=DIR read-only architecture-independent data in DIR [PREFIX/share] --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data in DIR [PREFIX/com] --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var] --libdir=DIR object code libraries in DIR [EPREFIX/lib] --includedir=DIR C header files in DIR [PREFIX/include] --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include] --infodir=DIR info documentation in DIR [PREFIX/info] --mandir=DIR man documentation in DIR [PREFIX/man] --srcdir=DIR find the sources in DIR [configure dir or ..] --program-prefix=PREFIX prepend PREFIX to installed program names --program-suffix=SUFFIX append SUFFIX to installed program names --program-transform-name=PROGRAM run sed PROGRAM on installed program names EOF cat << EOF Host type: --build=BUILD configure for building on BUILD [BUILD=HOST] --host=HOST configure for HOST [guessed] --target=TARGET configure for TARGET [TARGET=HOST] Features and packages: --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --x-includes=DIR X include files are in DIR --x-libraries=DIR X library files are in DIR EOF if test -n "$ac_help"; then echo "--enable and --with options recognized:$ac_help" fi exit 0 ;; -host | --host | --hos | --ho) ac_prev=host ;; -host=* | --host=* | --hos=* | --ho=*) host="$ac_optarg" ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir="$ac_optarg" ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir="$ac_optarg" ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir="$ac_optarg" ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir="$ac_optarg" ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst \ | --locals | --local | --loca | --loc | --lo) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* \ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) localstatedir="$ac_optarg" ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir="$ac_optarg" ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir="$ac_optarg" ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix="$ac_optarg" ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix="$ac_optarg" ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix="$ac_optarg" ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name="$ac_optarg" ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir="$ac_optarg" ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir="$ac_optarg" ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site="$ac_optarg" ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir="$ac_optarg" ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir="$ac_optarg" ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target="$ac_optarg" ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers) echo "configure generated by autoconf version 2.13" exit 0 ;; -with-* | --with-*) ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'` # Reject names that are not valid shell variable names. if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } fi ac_package=`echo $ac_package| sed 's/-/_/g'` case "$ac_option" in *=*) ;; *) ac_optarg=yes ;; esac eval "with_${ac_package}='$ac_optarg'" ;; -without-* | --without-*) ac_package=`echo $ac_option|sed -e 's/-*without-//'` # Reject names that are not valid shell variable names. if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } fi ac_package=`echo $ac_package| sed 's/-/_/g'` eval "with_${ac_package}=no" ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes="$ac_optarg" ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries="$ac_optarg" ;; -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; } ;; *) if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then echo "configure: warning: $ac_option: invalid host type" 1>&2 fi if test "x$nonopt" != xNONE; then { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } fi nonopt="$ac_option" ;; esac done if test -n "$ac_prev"; then { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; } fi trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 # File descriptor usage: # 0 standard input # 1 file creation # 2 errors and warnings # 3 some systems may open it to /dev/tty # 4 used on the Kubota Titan # 6 checking for... messages and results # 5 compiler messages saved in config.log if test "$silent" = yes; then exec 6>/dev/null else exec 6>&1 fi exec 5>./config.log echo "\ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. " 1>&5 # Strip out --no-create and --no-recursion so they do not pile up. # Also quote any args containing shell metacharacters. ac_configure_args= for ac_arg do case "$ac_arg" in -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c) ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;; *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) ac_configure_args="$ac_configure_args '$ac_arg'" ;; *) ac_configure_args="$ac_configure_args $ac_arg" ;; esac done # NLS nuisances. # Only set these to C if already set. These must not be set unconditionally # because not all systems understand e.g. LANG=C (notably SCO). # Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'! # Non-C LC_CTYPE values break the ctype check. if test "${LANG+set}" = set; then LANG=C; export LANG; fi if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -rf conftest* confdefs.h # AIX cpp loses on an empty file, so make sure it contains at least a newline. echo > confdefs.h # A filename unique to this package, relative to the directory that # configure is in, which we can look for to find out if srcdir is correct. ac_unique_file=tunnel.c # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then its parent. ac_prog=$0 ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'` test "x$ac_confdir" = "x$ac_prog" && ac_confdir=. srcdir=$ac_confdir if test ! -r $srcdir/$ac_unique_file; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r $srcdir/$ac_unique_file; then if test "$ac_srcdir_defaulted" = yes; then { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; } else { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; } fi fi srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'` # Prefer explicitly selected file to automatically selected ones. if test -z "$CONFIG_SITE"; then if test "x$prefix" != xNONE; then CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" else CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" fi fi for ac_site_file in $CONFIG_SITE; do if test -r "$ac_site_file"; then echo "loading site script $ac_site_file" . "$ac_site_file" fi done if test -r "$cache_file"; then echo "loading cache $cache_file" . $cache_file else echo "creating cache $cache_file" > $cache_file fi ac_ext=c # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. ac_cpp='$CPP $CPPFLAGS' ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' cross_compiling=$ac_cv_prog_cc_cross ac_exeext= ac_objext=o if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then ac_n= ac_c=' ' ac_t=' ' else ac_n=-n ac_c= ac_t= fi else ac_n= ac_c='\c' ac_t= fi ac_aux_dir= for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do if test -f $ac_dir/install-sh; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install-sh -c" break elif test -f $ac_dir/install.sh; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install.sh -c" break fi done if test -z "$ac_aux_dir"; then { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; } fi ac_config_guess=$ac_aux_dir/config.guess ac_config_sub=$ac_aux_dir/config.sub ac_configure=$ac_aux_dir/configure # This should be Cygnus configure. # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install # SunOS /usr/etc/install # IRIX /sbin/install # AIX /bin/install # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # ./install, which can be erroneously created by make from ./install.sh. echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 echo "configure:558: checking for a BSD compatible install" >&5 if test -z "$INSTALL"; then if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":" for ac_dir in $PATH; do # Account for people who put trailing slashes in PATH elements. case "$ac_dir/" in /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. # Don't use installbsd from OSF since it installs stuff as root # by default. for ac_prog in ginstall scoinst install; do if test -f $ac_dir/$ac_prog; then if test $ac_prog = install && grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : else ac_cv_path_install="$ac_dir/$ac_prog -c" break 2 fi fi done ;; esac done IFS="$ac_save_IFS" fi if test "${ac_cv_path_install+set}" = set; then INSTALL="$ac_cv_path_install" else # As a last resort, use the slow shell script. We don't cache a # path for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the path is relative. INSTALL="$ac_install_sh" fi fi echo "$ac_t""$INSTALL" 1>&6 # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' echo $ac_n "checking whether build environment is sane""... $ac_c" 1>&6 echo "configure:611: checking whether build environment is sane" >&5 # Just in case sleep 1 echo timestamp > conftestfile # Do `set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null` if test "$*" = "X"; then # -L didn't work. set X `ls -t $srcdir/configure conftestfile` fi if test "$*" != "X $srcdir/configure conftestfile" \ && test "$*" != "X conftestfile $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". { echo "configure: error: ls -t appears to fail. Make sure there is not a broken alias in your environment" 1>&2; exit 1; } fi test "$2" = conftestfile ) then # Ok. : else { echo "configure: error: newly created file is older than distributed files! Check your system clock" 1>&2; exit 1; } fi rm -f conftest* echo "$ac_t""yes" 1>&6 if test "$program_transform_name" = s,x,x,; then program_transform_name= else # Double any \ or $. echo might interpret backslashes. cat <<\EOF_SED > conftestsed s,\\,\\\\,g; s,\$,$$,g EOF_SED program_transform_name="`echo $program_transform_name|sed -f conftestsed`" rm -f conftestsed fi test "$program_prefix" != NONE && program_transform_name="s,^,${program_prefix},; $program_transform_name" # Use a double $ so make ignores it. test "$program_suffix" != NONE && program_transform_name="s,\$\$,${program_suffix},; $program_transform_name" # sed with no file args requires a program. test "$program_transform_name" = "" && program_transform_name="s,x,x," echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6 echo "configure:668: checking whether ${MAKE-make} sets \${MAKE}" >&5 set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftestmake <<\EOF all: @echo 'ac_maketemp="${MAKE}"' EOF # GNU make sometimes prints "make[1]: Entering...", which would confuse us. eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=` if test -n "$ac_maketemp"; then eval ac_cv_prog_make_${ac_make}_set=yes else eval ac_cv_prog_make_${ac_make}_set=no fi rm -f conftestmake fi if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then echo "$ac_t""yes" 1>&6 SET_MAKE= else echo "$ac_t""no" 1>&6 SET_MAKE="MAKE=${MAKE-make}" fi PACKAGE=httptunnel VERSION=3.3 if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then { echo "configure: error: source directory already configured; run "make distclean" there first" 1>&2; exit 1; } fi cat >> confdefs.h <> confdefs.h <&6 echo "configure:714: checking for working aclocal" >&5 # Run test in a subshell; some versions of sh will print an error if # an executable is not found, even if stderr is redirected. # Redirect stdin to placate older versions of autoconf. Sigh. if (aclocal --version) < /dev/null > /dev/null 2>&1; then ACLOCAL=aclocal echo "$ac_t""found" 1>&6 else ACLOCAL="$missing_dir/missing aclocal" echo "$ac_t""missing" 1>&6 fi echo $ac_n "checking for working autoconf""... $ac_c" 1>&6 echo "configure:727: checking for working autoconf" >&5 # Run test in a subshell; some versions of sh will print an error if # an executable is not found, even if stderr is redirected. # Redirect stdin to placate older versions of autoconf. Sigh. if (autoconf --version) < /dev/null > /dev/null 2>&1; then AUTOCONF=autoconf echo "$ac_t""found" 1>&6 else AUTOCONF="$missing_dir/missing autoconf" echo "$ac_t""missing" 1>&6 fi echo $ac_n "checking for working automake""... $ac_c" 1>&6 echo "configure:740: checking for working automake" >&5 # Run test in a subshell; some versions of sh will print an error if # an executable is not found, even if stderr is redirected. # Redirect stdin to placate older versions of autoconf. Sigh. if (automake --version) < /dev/null > /dev/null 2>&1; then AUTOMAKE=automake echo "$ac_t""found" 1>&6 else AUTOMAKE="$missing_dir/missing automake" echo "$ac_t""missing" 1>&6 fi echo $ac_n "checking for working autoheader""... $ac_c" 1>&6 echo "configure:753: checking for working autoheader" >&5 # Run test in a subshell; some versions of sh will print an error if # an executable is not found, even if stderr is redirected. # Redirect stdin to placate older versions of autoconf. Sigh. if (autoheader --version) < /dev/null > /dev/null 2>&1; then AUTOHEADER=autoheader echo "$ac_t""found" 1>&6 else AUTOHEADER="$missing_dir/missing autoheader" echo "$ac_t""missing" 1>&6 fi echo $ac_n "checking for working makeinfo""... $ac_c" 1>&6 echo "configure:766: checking for working makeinfo" >&5 # Run test in a subshell; some versions of sh will print an error if # an executable is not found, even if stderr is redirected. # Redirect stdin to placate older versions of autoconf. Sigh. if (makeinfo --version) < /dev/null > /dev/null 2>&1; then MAKEINFO=makeinfo echo "$ac_t""found" 1>&6 else MAKEINFO="$missing_dir/missing makeinfo" echo "$ac_t""missing" 1>&6 fi if test "x$srcdir" != x.; then SRCDIR_TRUE= SRCDIR_FALSE='#' else SRCDIR_TRUE='#' SRCDIR_FALSE= fi # Check whether --enable-debug or --disable-debug was given. if test "${enable_debug+set}" = set; then enableval="$enable_debug" cat >> confdefs.h <<\EOF #define DEBUG_MODE 1 EOF fi if test "x$CFLAGS" = x; then if test "x$enable_debug" != x; then CFLAGS="-g -Wall -Wstrict-prototypes -Wmissing-prototypes -Wpointer-arith" else CFLAGS="-O2 -Wall -fomit-frame-pointer" fi fi for ac_prog in mawk gawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 echo "configure:816: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_AWK'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test -n "$AWK"; then ac_cv_prog_AWK="$AWK" # Let the user override the test. else IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" ac_dummy="$PATH" for ac_dir in $ac_dummy; do test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/$ac_word; then ac_cv_prog_AWK="$ac_prog" break fi done IFS="$ac_save_ifs" fi fi AWK="$ac_cv_prog_AWK" if test -n "$AWK"; then echo "$ac_t""$AWK" 1>&6 else echo "$ac_t""no" 1>&6 fi test -n "$AWK" && break done # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 echo "configure:848: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" ac_dummy="$PATH" for ac_dir in $ac_dummy; do test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/$ac_word; then ac_cv_prog_CC="gcc" break fi done IFS="$ac_save_ifs" fi fi CC="$ac_cv_prog_CC" if test -n "$CC"; then echo "$ac_t""$CC" 1>&6 else echo "$ac_t""no" 1>&6 fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 echo "configure:878: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" ac_prog_rejected=no ac_dummy="$PATH" for ac_dir in $ac_dummy; do test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/$ac_word; then if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" break fi done IFS="$ac_save_ifs" if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# -gt 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift set dummy "$ac_dir/$ac_word" "$@" shift ac_cv_prog_CC="$@" fi fi fi fi CC="$ac_cv_prog_CC" if test -n "$CC"; then echo "$ac_t""$CC" 1>&6 else echo "$ac_t""no" 1>&6 fi if test -z "$CC"; then case "`uname -s`" in *win32* | *WIN32*) # Extract the first word of "cl", so it can be a program name with args. set dummy cl; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 echo "configure:929: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" ac_dummy="$PATH" for ac_dir in $ac_dummy; do test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/$ac_word; then ac_cv_prog_CC="cl" break fi done IFS="$ac_save_ifs" fi fi CC="$ac_cv_prog_CC" if test -n "$CC"; then echo "$ac_t""$CC" 1>&6 else echo "$ac_t""no" 1>&6 fi ;; esac fi test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; } fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 echo "configure:961: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 ac_ext=c # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. ac_cpp='$CPP $CPPFLAGS' ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' cross_compiling=$ac_cv_prog_cc_cross cat > conftest.$ac_ext << EOF #line 972 "configure" #include "confdefs.h" main(){return(0);} EOF if { (eval echo configure:977: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then ac_cv_prog_cc_works=yes # If we can't run a trivial program, we are probably using a cross compiler. if (./conftest; exit) 2>/dev/null; then ac_cv_prog_cc_cross=no else ac_cv_prog_cc_cross=yes fi else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 ac_cv_prog_cc_works=no fi rm -fr conftest* ac_ext=c # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. ac_cpp='$CPP $CPPFLAGS' ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' cross_compiling=$ac_cv_prog_cc_cross echo "$ac_t""$ac_cv_prog_cc_works" 1>&6 if test $ac_cv_prog_cc_works = no; then { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 echo "configure:1003: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 cross_compiling=$ac_cv_prog_cc_cross echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 echo "configure:1008: checking whether we are using GNU C" >&5 if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.c <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then ac_cv_prog_gcc=yes else ac_cv_prog_gcc=no fi fi echo "$ac_t""$ac_cv_prog_gcc" 1>&6 if test $ac_cv_prog_gcc = yes; then GCC=yes else GCC= fi ac_test_CFLAGS="${CFLAGS+set}" ac_save_CFLAGS="$CFLAGS" CFLAGS= echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 echo "configure:1036: checking whether ${CC-cc} accepts -g" >&5 if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else echo 'void f(){}' > conftest.c if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then ac_cv_prog_cc_g=yes else ac_cv_prog_cc_g=no fi rm -f conftest* fi echo "$ac_t""$ac_cv_prog_cc_g" 1>&6 if test "$ac_test_CFLAGS" = set; then CFLAGS="$ac_save_CFLAGS" elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi if test "$program_transform_name" = s,x,x,; then program_transform_name= else # Double any \ or $. echo might interpret backslashes. cat <<\EOF_SED > conftestsed s,\\,\\\\,g; s,\$,$$,g EOF_SED program_transform_name="`echo $program_transform_name|sed -f conftestsed`" rm -f conftestsed fi test "$program_prefix" != NONE && program_transform_name="s,^,${program_prefix},; $program_transform_name" # Use a double $ so make ignores it. test "$program_suffix" != NONE && program_transform_name="s,\$\$,${program_suffix},; $program_transform_name" # sed with no file args requires a program. test "$program_transform_name" = "" && program_transform_name="s,x,x," # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install # SunOS /usr/etc/install # IRIX /sbin/install # AIX /bin/install # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # ./install, which can be erroneously created by make from ./install.sh. echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 echo "configure:1098: checking for a BSD compatible install" >&5 if test -z "$INSTALL"; then if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":" for ac_dir in $PATH; do # Account for people who put trailing slashes in PATH elements. case "$ac_dir/" in /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. # Don't use installbsd from OSF since it installs stuff as root # by default. for ac_prog in ginstall scoinst install; do if test -f $ac_dir/$ac_prog; then if test $ac_prog = install && grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : else ac_cv_path_install="$ac_dir/$ac_prog -c" break 2 fi fi done ;; esac done IFS="$ac_save_IFS" fi if test "${ac_cv_path_install+set}" = set; then INSTALL="$ac_cv_path_install" else # As a last resort, use the slow shell script. We don't cache a # path for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the path is relative. INSTALL="$ac_install_sh" fi fi echo "$ac_t""$INSTALL" 1>&6 # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' echo $ac_n "checking whether ln -s works""... $ac_c" 1>&6 echo "configure:1151: checking whether ln -s works" >&5 if eval "test \"`echo '$''{'ac_cv_prog_LN_S'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else rm -f conftestdata if ln -s X conftestdata 2>/dev/null then rm -f conftestdata ac_cv_prog_LN_S="ln -s" else ac_cv_prog_LN_S=ln fi fi LN_S="$ac_cv_prog_LN_S" if test "$ac_cv_prog_LN_S" = "ln -s"; then echo "$ac_t""yes" 1>&6 else echo "$ac_t""no" 1>&6 fi # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 echo "configure:1174: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" ac_dummy="$PATH" for ac_dir in $ac_dummy; do test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/$ac_word; then ac_cv_prog_RANLIB="ranlib" break fi done IFS="$ac_save_ifs" test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":" fi fi RANLIB="$ac_cv_prog_RANLIB" if test -n "$RANLIB"; then echo "$ac_t""$RANLIB" 1>&6 else echo "$ac_t""no" 1>&6 fi echo $ac_n "checking for gethostent""... $ac_c" 1>&6 echo "configure:1203: checking for gethostent" >&5 if eval "test \"`echo '$''{'ac_cv_func_gethostent'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char gethostent(); int main() { /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_gethostent) || defined (__stub___gethostent) choke me #else gethostent(); #endif ; return 0; } EOF if { (eval echo configure:1231: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_gethostent=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_func_gethostent=no" fi rm -f conftest* fi if eval "test \"`echo '$ac_cv_func_'gethostent`\" = yes"; then echo "$ac_t""yes" 1>&6 : else echo "$ac_t""no" 1>&6 echo $ac_n "checking for gethostent in -lnsl""... $ac_c" 1>&6 echo "configure:1249: checking for gethostent in -lnsl" >&5 ac_lib_var=`echo nsl'_'gethostent | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-lnsl $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=no" fi rm -f conftest* LIBS="$ac_save_LIBS" fi if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then echo "$ac_t""yes" 1>&6 ac_tr_lib=HAVE_LIB`echo nsl | sed -e 's/^a-zA-Z0-9_/_/g' \ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'` cat >> confdefs.h <&6 fi fi echo $ac_n "checking for setsockopt""... $ac_c" 1>&6 echo "configure:1298: checking for setsockopt" >&5 if eval "test \"`echo '$''{'ac_cv_func_setsockopt'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char setsockopt(); int main() { /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_setsockopt) || defined (__stub___setsockopt) choke me #else setsockopt(); #endif ; return 0; } EOF if { (eval echo configure:1326: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_setsockopt=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_func_setsockopt=no" fi rm -f conftest* fi if eval "test \"`echo '$ac_cv_func_'setsockopt`\" = yes"; then echo "$ac_t""yes" 1>&6 : else echo "$ac_t""no" 1>&6 echo $ac_n "checking for setsockopt in -lsocket""... $ac_c" 1>&6 echo "configure:1344: checking for setsockopt in -lsocket" >&5 ac_lib_var=`echo socket'_'setsockopt | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-lsocket $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=no" fi rm -f conftest* LIBS="$ac_save_LIBS" fi if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then echo "$ac_t""yes" 1>&6 ac_tr_lib=HAVE_LIB`echo socket | sed -e 's/^a-zA-Z0-9_/_/g' \ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'` cat >> confdefs.h <&6 fi fi echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 echo "configure:1394: checking how to run the C preprocessor" >&5 # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else # This must be in double quotes, not single quotes, because CPP may get # substituted into the Makefile and "${CC-cc}" will confuse make. CPP="${CC-cc} -E" # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" { (eval echo configure:1415: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : else echo "$ac_err" >&5 echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* CPP="${CC-cc} -E -traditional-cpp" cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" { (eval echo configure:1432: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : else echo "$ac_err" >&5 echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* CPP="${CC-cc} -nologo -E" cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" { (eval echo configure:1449: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : else echo "$ac_err" >&5 echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* CPP=/lib/cpp fi rm -f conftest* fi rm -f conftest* fi rm -f conftest* ac_cv_prog_CPP="$CPP" fi CPP="$ac_cv_prog_CPP" else ac_cv_prog_CPP="$CPP" fi echo "$ac_t""$CPP" 1>&6 echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6 echo "configure:1474: checking for ANSI C header files" >&5 if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include #include #include EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" { (eval echo configure:1487: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* ac_cv_header_stdc=yes else echo "$ac_err" >&5 echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* ac_cv_header_stdc=no fi rm -f conftest* if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat > conftest.$ac_ext < EOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | egrep "memchr" >/dev/null 2>&1; then : else rm -rf conftest* ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat > conftest.$ac_ext < EOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | egrep "free" >/dev/null 2>&1; then : else rm -rf conftest* ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : else cat > conftest.$ac_ext < #define ISLOWER(c) ('a' <= (c) && (c) <= 'z') #define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); exit (0); } EOF if { (eval echo configure:1554: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then : else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -fr conftest* ac_cv_header_stdc=no fi rm -fr conftest* fi fi fi echo "$ac_t""$ac_cv_header_stdc" 1>&6 if test $ac_cv_header_stdc = yes; then cat >> confdefs.h <<\EOF #define STDC_HEADERS 1 EOF fi for ac_hdr in fcntl.h syslog.h unistd.h sys/poll.h do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 echo "configure:1581: checking for $ac_hdr" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" { (eval echo configure:1591: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* eval "ac_cv_header_$ac_safe=yes" else echo "$ac_err" >&5 echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_header_$ac_safe=no" fi rm -f conftest* fi if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then echo "$ac_t""yes" 1>&6 ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` cat >> confdefs.h <&6 fi done echo $ac_n "checking for working const""... $ac_c" 1>&6 echo "configure:1619: checking for working const" >&5 if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <j = 5; } { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ const int foo = 10; } ; return 0; } EOF if { (eval echo configure:1673: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_const=yes else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* ac_cv_c_const=no fi rm -f conftest* fi echo "$ac_t""$ac_cv_c_const" 1>&6 if test $ac_cv_c_const = no; then cat >> confdefs.h <<\EOF #define const EOF fi echo $ac_n "checking for inline""... $ac_c" 1>&6 echo "configure:1694: checking for inline" >&5 if eval "test \"`echo '$''{'ac_cv_c_inline'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_cv_c_inline=no for ac_kw in inline __inline__ __inline; do cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_inline=$ac_kw; break else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 fi rm -f conftest* done fi echo "$ac_t""$ac_cv_c_inline" 1>&6 case "$ac_cv_c_inline" in inline | yes) ;; no) cat >> confdefs.h <<\EOF #define inline EOF ;; *) cat >> confdefs.h <&6 echo "configure:1734: checking for size_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #if STDC_HEADERS #include #include #endif EOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | egrep "(^|[^a-zA-Z_0-9])size_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then rm -rf conftest* ac_cv_type_size_t=yes else rm -rf conftest* ac_cv_type_size_t=no fi rm -f conftest* fi echo "$ac_t""$ac_cv_type_size_t" 1>&6 if test $ac_cv_type_size_t = no; then cat >> confdefs.h <<\EOF #define size_t unsigned EOF fi ##AC_CHECK_TYPE(socklen_t, unsigned) # doesn't search echo $ac_n "checking for socklen_t""... $ac_c" 1>&6 echo "configure:1768: checking for socklen_t" >&5 if eval "test \"`echo '$''{'ac_cv_httptunnel_type_socklen_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include int main() { socklen_t len = 42; return 0; ; return 0; } EOF if { (eval echo configure:1782: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_httptunnel_type_socklen_t=yes else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* ac_cv_httptunnel_type_socklen_t=no fi rm -f conftest* fi echo "$ac_t""$ac_cv_httptunnel_type_socklen_t" 1>&6 if test $ac_cv_httptunnel_type_socklen_t != yes; then cat >> confdefs.h <<\EOF #define socklen_t int EOF fi echo $ac_n "checking whether INADDR_NONE is defined""... $ac_c" 1>&6 echo "configure:1804: checking whether INADDR_NONE is defined" >&5 if eval "test \"`echo '$''{'ac_cv_httptunnel_define_inaddr_none'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include int main() { return INADDR_NONE; ; return 0; } EOF if { (eval echo configure:1818: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_httptunnel_define_inaddr_none=yes else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* ac_cv_httptunnel_define_inaddr_none=no fi rm -f conftest* fi echo "$ac_t""$ac_cv_httptunnel_define_inaddr_none" 1>&6 if test $ac_cv_httptunnel_define_inaddr_none != yes; then cat >> confdefs.h <<\EOF #define INADDR_NONE 0xffffffff EOF fi echo $ac_n "checking size of char""... $ac_c" 1>&6 echo "configure:1840: checking size of char" >&5 if eval "test \"`echo '$''{'ac_cv_sizeof_char'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then ac_cv_sizeof_char=1 else cat > conftest.$ac_ext < main() { FILE *f=fopen("conftestval", "w"); if (!f) exit(1); fprintf(f, "%d\n", sizeof(char)); exit(0); } EOF if { (eval echo configure:1859: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_sizeof_char=`cat conftestval` else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -fr conftest* ac_cv_sizeof_char=0 fi rm -fr conftest* fi fi echo "$ac_t""$ac_cv_sizeof_char" 1>&6 cat >> confdefs.h <&6 echo "configure:1879: checking size of short" >&5 if eval "test \"`echo '$''{'ac_cv_sizeof_short'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then ac_cv_sizeof_short=2 else cat > conftest.$ac_ext < main() { FILE *f=fopen("conftestval", "w"); if (!f) exit(1); fprintf(f, "%d\n", sizeof(short)); exit(0); } EOF if { (eval echo configure:1898: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_sizeof_short=`cat conftestval` else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -fr conftest* ac_cv_sizeof_short=0 fi rm -fr conftest* fi fi echo "$ac_t""$ac_cv_sizeof_short" 1>&6 cat >> confdefs.h <&6 echo "configure:1918: checking size of int" >&5 if eval "test \"`echo '$''{'ac_cv_sizeof_int'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then ac_cv_sizeof_int=4 else cat > conftest.$ac_ext < main() { FILE *f=fopen("conftestval", "w"); if (!f) exit(1); fprintf(f, "%d\n", sizeof(int)); exit(0); } EOF if { (eval echo configure:1937: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_sizeof_int=`cat conftestval` else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -fr conftest* ac_cv_sizeof_int=0 fi rm -fr conftest* fi fi echo "$ac_t""$ac_cv_sizeof_int" 1>&6 cat >> confdefs.h <&6 echo "configure:1957: checking size of long" >&5 if eval "test \"`echo '$''{'ac_cv_sizeof_long'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then ac_cv_sizeof_long=4 else cat > conftest.$ac_ext < main() { FILE *f=fopen("conftestval", "w"); if (!f) exit(1); fprintf(f, "%d\n", sizeof(long)); exit(0); } EOF if { (eval echo configure:1976: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_sizeof_long=`cat conftestval` else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -fr conftest* ac_cv_sizeof_long=0 fi rm -fr conftest* fi fi echo "$ac_t""$ac_cv_sizeof_long" 1>&6 cat >> confdefs.h <&6 echo "configure:1996: checking size of long long" >&5 if eval "test \"`echo '$''{'ac_cv_sizeof_long_long'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then ac_cv_sizeof_long_long=8 else cat > conftest.$ac_ext < main() { FILE *f=fopen("conftestval", "w"); if (!f) exit(1); fprintf(f, "%d\n", sizeof(long long)); exit(0); } EOF if { (eval echo configure:2015: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_sizeof_long_long=`cat conftestval` else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -fr conftest* ac_cv_sizeof_long_long=0 fi rm -fr conftest* fi fi echo "$ac_t""$ac_cv_sizeof_long_long" 1>&6 cat >> confdefs.h <&6 echo "configure:2036: checking for 8-bit clean memcmp" >&5 if eval "test \"`echo '$''{'ac_cv_func_memcmp_clean'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then ac_cv_func_memcmp_clean=no else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_func_memcmp_clean=yes else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -fr conftest* ac_cv_func_memcmp_clean=no fi rm -fr conftest* fi fi echo "$ac_t""$ac_cv_func_memcmp_clean" 1>&6 test $ac_cv_func_memcmp_clean = no && LIBOBJS="$LIBOBJS memcmp.${ac_objext}" echo $ac_n "checking return type of signal handlers""... $ac_c" 1>&6 echo "configure:2072: checking return type of signal handlers" >&5 if eval "test \"`echo '$''{'ac_cv_type_signal'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include #ifdef signal #undef signal #endif #ifdef __cplusplus extern "C" void (*signal (int, void (*)(int)))(int); #else void (*signal ()) (); #endif int main() { int i; ; return 0; } EOF if { (eval echo configure:2094: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_type_signal=void else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* ac_cv_type_signal=int fi rm -f conftest* fi echo "$ac_t""$ac_cv_type_signal" 1>&6 cat >> confdefs.h <&6 echo "configure:2113: checking for vprintf" >&5 if eval "test \"`echo '$''{'ac_cv_func_vprintf'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char vprintf(); int main() { /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_vprintf) || defined (__stub___vprintf) choke me #else vprintf(); #endif ; return 0; } EOF if { (eval echo configure:2141: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_vprintf=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_func_vprintf=no" fi rm -f conftest* fi if eval "test \"`echo '$ac_cv_func_'vprintf`\" = yes"; then echo "$ac_t""yes" 1>&6 cat >> confdefs.h <<\EOF #define HAVE_VPRINTF 1 EOF else echo "$ac_t""no" 1>&6 fi if test "$ac_cv_func_vprintf" != yes; then echo $ac_n "checking for _doprnt""... $ac_c" 1>&6 echo "configure:2165: checking for _doprnt" >&5 if eval "test \"`echo '$''{'ac_cv_func__doprnt'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char _doprnt(); int main() { /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub__doprnt) || defined (__stub____doprnt) choke me #else _doprnt(); #endif ; return 0; } EOF if { (eval echo configure:2193: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func__doprnt=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_func__doprnt=no" fi rm -f conftest* fi if eval "test \"`echo '$ac_cv_func_'_doprnt`\" = yes"; then echo "$ac_t""yes" 1>&6 cat >> confdefs.h <<\EOF #define HAVE_DOPRNT 1 EOF else echo "$ac_t""no" 1>&6 fi fi for ac_func in socket strdup strerror daemon vsyslog do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 echo "configure:2220: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char $ac_func(); int main() { /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_$ac_func) || defined (__stub___$ac_func) choke me #else $ac_func(); #endif ; return 0; } EOF if { (eval echo configure:2248: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_func_$ac_func=no" fi rm -f conftest* fi if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then echo "$ac_t""yes" 1>&6 ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` cat >> confdefs.h <&6 fi done for ac_func in poll select endprotoent vsnprintf syslog do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 echo "configure:2275: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char $ac_func(); int main() { /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_$ac_func) || defined (__stub___$ac_func) choke me #else $ac_func(); #endif ; return 0; } EOF if { (eval echo configure:2303: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_func_$ac_func=no" fi rm -f conftest* fi if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then echo "$ac_t""yes" 1>&6 ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` cat >> confdefs.h <&6 fi done trap '' 1 2 15 cat > confcache <<\EOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs. It is not useful on other systems. # If it contains results you don't want to keep, you may remove or edit it. # # By default, configure uses ./config.cache as the cache file, # creating it if it does not exist already. You can give configure # the --cache-file=FILE option to use a different cache file; that is # what configure does when it calls configure scripts in # subdirectories, so they share the cache. # Giving --cache-file=/dev/null disables caching, for debugging configure. # config.status only pays attention to the cache file if you give it the # --recheck option to rerun configure. # EOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, don't put newlines in cache variables' values. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. (set) 2>&1 | case `(ac_space=' '; set | grep ac_space) 2>&1` in *ac_space=\ *) # `set' does not quote correctly, so add quotes (double-quote substitution # turns \\\\ into \\, and sed turns \\ into \). sed -n \ -e "s/'/'\\\\''/g" \ -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" ;; *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' ;; esac >> confcache if cmp -s $cache_file confcache; then : else if test -w $cache_file; then echo "updating cache $cache_file" cat confcache > $cache_file else echo "not updating unwritable cache $cache_file" fi fi rm -f confcache trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' # Any assignment to VPATH causes Sun make to only execute # the first set of double-colon rules, so remove it if not needed. # If there is a colon in the path, we need to keep it. if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d' fi trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15 DEFS=-DHAVE_CONFIG_H # Without the "./", some shells look in PATH for config.status. : ${CONFIG_STATUS=./config.status} echo creating $CONFIG_STATUS rm -f $CONFIG_STATUS cat > $CONFIG_STATUS </dev/null | sed 1q`: # # $0 $ac_configure_args # # Compiler output produced by configure, useful for debugging # configure, is in ./config.log if it exists. ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]" for ac_option do case "\$ac_option" in -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion" exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;; -version | --version | --versio | --versi | --vers | --ver | --ve | --v) echo "$CONFIG_STATUS generated by autoconf version 2.13" exit 0 ;; -help | --help | --hel | --he | --h) echo "\$ac_cs_usage"; exit 0 ;; *) echo "\$ac_cs_usage"; exit 1 ;; esac done ac_given_srcdir=$srcdir ac_given_INSTALL="$INSTALL" trap 'rm -fr `echo "Makefile port/Makefile port/sys/Makefile config.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 EOF cat >> $CONFIG_STATUS < conftest.subs <<\\CEOF $ac_vpsub $extrasub s%@SHELL@%$SHELL%g s%@CFLAGS@%$CFLAGS%g s%@CPPFLAGS@%$CPPFLAGS%g s%@CXXFLAGS@%$CXXFLAGS%g s%@FFLAGS@%$FFLAGS%g s%@DEFS@%$DEFS%g s%@LDFLAGS@%$LDFLAGS%g s%@LIBS@%$LIBS%g s%@exec_prefix@%$exec_prefix%g s%@prefix@%$prefix%g s%@program_transform_name@%$program_transform_name%g s%@bindir@%$bindir%g s%@sbindir@%$sbindir%g s%@libexecdir@%$libexecdir%g s%@datadir@%$datadir%g s%@sysconfdir@%$sysconfdir%g s%@sharedstatedir@%$sharedstatedir%g s%@localstatedir@%$localstatedir%g s%@libdir@%$libdir%g s%@includedir@%$includedir%g s%@oldincludedir@%$oldincludedir%g s%@infodir@%$infodir%g s%@mandir@%$mandir%g s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g s%@INSTALL_DATA@%$INSTALL_DATA%g s%@PACKAGE@%$PACKAGE%g s%@VERSION@%$VERSION%g s%@ACLOCAL@%$ACLOCAL%g s%@AUTOCONF@%$AUTOCONF%g s%@AUTOMAKE@%$AUTOMAKE%g s%@AUTOHEADER@%$AUTOHEADER%g s%@MAKEINFO@%$MAKEINFO%g s%@SET_MAKE@%$SET_MAKE%g s%@SRCDIR_TRUE@%$SRCDIR_TRUE%g s%@SRCDIR_FALSE@%$SRCDIR_FALSE%g s%@AWK@%$AWK%g s%@CC@%$CC%g s%@LN_S@%$LN_S%g s%@RANLIB@%$RANLIB%g s%@CPP@%$CPP%g s%@LIBOBJS@%$LIBOBJS%g CEOF EOF cat >> $CONFIG_STATUS <<\EOF # Split the substitutions into bite-sized pieces for seds with # small command number limits, like on Digital OSF/1 and HP-UX. ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script. ac_file=1 # Number of current file. ac_beg=1 # First line for current file. ac_end=$ac_max_sed_cmds # Line after last line for current file. ac_more_lines=: ac_sed_cmds="" while $ac_more_lines; do if test $ac_beg -gt 1; then sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file else sed "${ac_end}q" conftest.subs > conftest.s$ac_file fi if test ! -s conftest.s$ac_file; then ac_more_lines=false rm -f conftest.s$ac_file else if test -z "$ac_sed_cmds"; then ac_sed_cmds="sed -f conftest.s$ac_file" else ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file" fi ac_file=`expr $ac_file + 1` ac_beg=$ac_end ac_end=`expr $ac_end + $ac_max_sed_cmds` fi done if test -z "$ac_sed_cmds"; then ac_sed_cmds=cat fi EOF cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". case "$ac_file" in *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; *) ac_file_in="${ac_file}.in" ;; esac # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories. # Remove last slash and all that follows it. Not all systems have dirname. ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then # The file is in a subdirectory. test ! -d "$ac_dir" && mkdir "$ac_dir" ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`" # A "../" for each directory in $ac_dir_suffix. ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'` else ac_dir_suffix= ac_dots= fi case "$ac_given_srcdir" in .) srcdir=. if test -z "$ac_dots"; then top_srcdir=. else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;; /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;; *) # Relative path. srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix" top_srcdir="$ac_dots$ac_given_srcdir" ;; esac case "$ac_given_INSTALL" in [/$]*) INSTALL="$ac_given_INSTALL" ;; *) INSTALL="$ac_dots$ac_given_INSTALL" ;; esac echo creating "$ac_file" rm -f "$ac_file" configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure." case "$ac_file" in *Makefile*) ac_comsub="1i\\ # $configure_input" ;; *) ac_comsub= ;; esac ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` sed -e "$ac_comsub s%@configure_input@%$configure_input%g s%@srcdir@%$srcdir%g s%@top_srcdir@%$top_srcdir%g s%@INSTALL@%$INSTALL%g " $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file fi; done rm -f conftest.s* # These sed commands are passed to sed as "A NAME B NAME C VALUE D", where # NAME is the cpp macro being defined and VALUE is the value it is being given. # # ac_d sets the value in "#define NAME VALUE" lines. ac_dA='s%^\([ ]*\)#\([ ]*define[ ][ ]*\)' ac_dB='\([ ][ ]*\)[^ ]*%\1#\2' ac_dC='\3' ac_dD='%g' # ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE". ac_uA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' ac_uB='\([ ]\)%\1#\2define\3' ac_uC=' ' ac_uD='\4%g' # ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE". ac_eA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' ac_eB='$%\1#\2define\3' ac_eC=' ' ac_eD='%g' if test "${CONFIG_HEADERS+set}" != set; then EOF cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF fi for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". case "$ac_file" in *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; *) ac_file_in="${ac_file}.in" ;; esac echo creating $ac_file rm -f conftest.frag conftest.in conftest.out ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` cat $ac_file_inputs > conftest.in EOF # Transform confdefs.h into a sed script conftest.vals that substitutes # the proper values into config.h.in to produce config.h. And first: # Protect against being on the right side of a sed subst in config.status. # Protect against being in an unquoted here document in config.status. rm -f conftest.vals cat > conftest.hdr <<\EOF s/[\\&%]/\\&/g s%[\\$`]%\\&%g s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp s%ac_d%ac_u%gp s%ac_u%ac_e%gp EOF sed -n -f conftest.hdr confdefs.h > conftest.vals rm -f conftest.hdr # This sed command replaces #undef with comments. This is necessary, for # example, in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. cat >> conftest.vals <<\EOF s%^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */% EOF # Break up conftest.vals because some shells have a limit on # the size of here documents, and old seds have small limits too. rm -f conftest.tail while : do ac_lines=`grep -c . conftest.vals` # grep -c gives empty output for an empty file on some AIX systems. if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi # Write a limited-size here document to conftest.frag. echo ' cat > conftest.frag <> $CONFIG_STATUS sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS echo 'CEOF sed -f conftest.frag conftest.in > conftest.out rm -f conftest.in mv conftest.out conftest.in ' >> $CONFIG_STATUS sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail rm -f conftest.vals mv conftest.tail conftest.vals done rm -f conftest.vals cat >> $CONFIG_STATUS <<\EOF rm -f conftest.frag conftest.h echo "/* $ac_file. Generated automatically by configure. */" > conftest.h cat conftest.in >> conftest.h rm -f conftest.in if cmp -s $ac_file conftest.h 2>/dev/null; then echo "$ac_file is unchanged" rm -f conftest.h else # Remove last slash and all that follows it. Not all systems have dirname. ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then # The file is in a subdirectory. test ! -d "$ac_dir" && mkdir "$ac_dir" fi rm -f $ac_file mv conftest.h $ac_file fi fi; done EOF cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF test -z "$CONFIG_HEADERS" || echo timestamp > stamp-h exit 0 EOF chmod +x $CONFIG_STATUS rm -fr confdefs* $ac_clean_files test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1 httptunnel-3.3/tunnel.h0000644000175000017500000000505607137270032012171 0ustar /* tunnel.h Copyright (C) 1999 Lars Brinkhoff. See COPYING for terms and conditions. */ /* This is the programming interface to the HTTP tunnel. It consists of the following functions: Tunnel *tunnel_new_client (const char *host, int host_port, const char *proxy, int proxy_port, size_t content_length); Create a new HTTP tunnel client. Tunnel *tunnel_new_server (const char *host, int port, size_t content_length); Create a new HTTP tunnel server. If LENGTH is 0, the Content-Length of the HTTP GET response will be determined automatically in some way. If HOST is not NULL, use it to bind the server socket to a specific network interface. int tunnel_connect (Tunnel *tunnel); Open the tunnel. (Client only.) int tunnel_accept (Tunnel *tunnel); Accept a tunnel connection. (Server only.) int tunnel_pollin_fd (Tunnel *tunnel); Return a file descriptor that can be used to poll for input from the tunnel. ssize_t tunnel_read (Tunnel *tunnel, void *data, size_t length); ssize_t tunnel_write (Tunnel *tunnel, void *data, size_t length); Read or write to the tunnel. Same semantics as with read() and write(). Watch out for return values less than LENGTH. int tunnel_padding (Tunnel *tunnel, size_t length); Send LENGTH pad bytes. int tunnel_maybe_pad (Tunnel *tunnel, size_t length); Pad to nearest even multiple of LENGTH. int tunnel_close (Tunnel *tunnel); Close the tunnel. void tunnel_destroy (Tunnel *tunnel); */ #ifndef TUNNEL_H #define TUNNEL_H #include "config.h" #include #define DEFAULT_CONNECTION_MAX_TIME 300 typedef struct tunnel Tunnel; extern Tunnel *tunnel_new_client (const char *host, int host_port, const char *proxy, int proxy_port, size_t content_length); extern Tunnel *tunnel_new_server (const char *host, int port, size_t content_length); extern int tunnel_connect (Tunnel *tunnel); extern int tunnel_accept (Tunnel *tunnel); extern int tunnel_pollin_fd (Tunnel *tunnel); extern ssize_t tunnel_read (Tunnel *tunnel, void *data, size_t length); extern ssize_t tunnel_write (Tunnel *tunnel, void *data, size_t length); extern ssize_t tunnel_padding (Tunnel *tunnel, size_t length); extern int tunnel_maybe_pad (Tunnel *tunnel, size_t length); extern int tunnel_setopt (Tunnel *tunnel, const char *opt, void *data); extern int tunnel_getopt (Tunnel *tunnel, const char *opt, void *data); extern int tunnel_close (Tunnel *tunnel); extern void tunnel_destroy (Tunnel *tunnel); #endif /* TUNNEL_H */ httptunnel-3.3/missing0000755000175000017500000001421306657300626012116 0ustar #! /bin/sh # Common stub for a few missing GNU programs while installing. # Copyright (C) 1996, 1997 Free Software Foundation, Inc. # Franc,ois Pinard , 1996. # 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, 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. if test $# -eq 0; then echo 1>&2 "Try \`$0 --help' for more information" exit 1 fi case "$1" in -h|--h|--he|--hel|--help) echo "\ $0 [OPTION]... PROGRAM [ARGUMENT]... Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an error status if there is no known handling for PROGRAM. Options: -h, --help display this help and exit -v, --version output version information and exit Supported PROGRAM values: aclocal touch file \`aclocal.m4' autoconf touch file \`configure' autoheader touch file \`config.h.in' automake touch all \`Makefile.in' files bison create \`y.tab.[ch]', if possible, from existing .[ch] flex create \`lex.yy.c', if possible, from existing .c lex create \`lex.yy.c', if possible, from existing .c makeinfo touch the output file yacc create \`y.tab.[ch]', if possible, from existing .[ch]" ;; -v|--v|--ve|--ver|--vers|--versi|--versio|--version) echo "missing - GNU libit 0.0" ;; -*) echo 1>&2 "$0: Unknown \`$1' option" echo 1>&2 "Try \`$0 --help' for more information" exit 1 ;; aclocal) echo 1>&2 "\ WARNING: \`$1' is missing on your system. You should only need it if you modified \`acinclude.m4' or \`configure.in'. You might want to install the \`Automake' and \`Perl' packages. Grab them from any GNU archive site." touch aclocal.m4 ;; autoconf) echo 1>&2 "\ WARNING: \`$1' is missing on your system. You should only need it if you modified \`configure.in'. You might want to install the \`Autoconf' and \`GNU m4' packages. Grab them from any GNU archive site." touch configure ;; autoheader) echo 1>&2 "\ WARNING: \`$1' is missing on your system. You should only need it if you modified \`acconfig.h' or \`configure.in'. You might want to install the \`Autoconf' and \`GNU m4' packages. Grab them from any GNU archive site." files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' configure.in` test -z "$files" && files="config.h" touch_files= for f in $files; do case "$f" in *:*) touch_files="$touch_files "`echo "$f" | sed -e 's/^[^:]*://' -e 's/:.*//'`;; *) touch_files="$touch_files $f.in";; esac done touch $touch_files ;; automake) echo 1>&2 "\ WARNING: \`$1' is missing on your system. You should only need it if you modified \`Makefile.am', \`acinclude.m4' or \`configure.in'. You might want to install the \`Automake' and \`Perl' packages. Grab them from any GNU archive site." find . -type f -name Makefile.am -print | sed 's/\.am$/.in/' | while read f; do touch "$f"; done ;; bison|yacc) echo 1>&2 "\ WARNING: \`$1' is missing on your system. You should only need it if you modified a \`.y' file. You may need the \`Bison' package in order for those modifications to take effect. You can get \`Bison' from any GNU archive site." rm -f y.tab.c y.tab.h if [ $# -ne 1 ]; then eval LASTARG="\${$#}" case "$LASTARG" in *.y) SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` if [ -f "$SRCFILE" ]; then cp "$SRCFILE" y.tab.c fi SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` if [ -f "$SRCFILE" ]; then cp "$SRCFILE" y.tab.h fi ;; esac fi if [ ! -f y.tab.h ]; then echo >y.tab.h fi if [ ! -f y.tab.c ]; then echo 'main() { return 0; }' >y.tab.c fi ;; lex|flex) echo 1>&2 "\ WARNING: \`$1' is missing on your system. You should only need it if you modified a \`.l' file. You may need the \`Flex' package in order for those modifications to take effect. You can get \`Flex' from any GNU archive site." rm -f lex.yy.c if [ $# -ne 1 ]; then eval LASTARG="\${$#}" case "$LASTARG" in *.l) SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` if [ -f "$SRCFILE" ]; then cp "$SRCFILE" lex.yy.c fi ;; esac fi if [ ! -f lex.yy.c ]; then echo 'main() { return 0; }' >lex.yy.c fi ;; makeinfo) echo 1>&2 "\ WARNING: \`$1' is missing on your system. You should only need it if you modified a \`.texi' or \`.texinfo' file, or any other file indirectly affecting the aspect of the manual. The spurious call might also be the consequence of using a buggy \`make' (AIX, DU, IRIX). You might want to install the \`Texinfo' package or the \`GNU make' package. Grab either from any GNU archive site." file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` if test -z "$file"; then file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file` fi touch $file ;; *) echo 1>&2 "\ WARNING: \`$1' is needed, and you do not seem to have it handy on your system. You might have modified some files without having the proper tools for further handling them. Check the \`README' file, it often tells you about the needed prerequirements for installing this package. You may also peek at any GNU archive site, in case some other package would contain this missing \`$1' program." exit 1 ;; esac exit 0 httptunnel-3.3/INSTALL0000644000175000017500000001722706657300626011560 0ustar Basic Installation ================== These are generic installation instructions. The `configure' shell script attempts to guess correct values for various system-dependent variables used during compilation. It uses those values to create a `Makefile' in each directory of the package. It may also create one or more `.h' files containing system-dependent definitions. Finally, it creates a shell script `config.status' that you can run in the future to recreate the current configuration, a file `config.cache' that saves the results of its tests to speed up reconfiguring, and a file `config.log' containing compiler output (useful mainly for debugging `configure'). If you need to do unusual things to compile the package, please try to figure out how `configure' could check whether to do them, and mail diffs or instructions to the address given in the `README' so they can be considered for the next release. If at some point `config.cache' contains results you don't want to keep, you may remove or edit it. The file `configure.in' is used to create `configure' by a program called `autoconf'. You only need `configure.in' if you want to change it or regenerate `configure' using a newer version of `autoconf'. The simplest way to compile this package is: 1. `cd' to the directory containing the package's source code and type `./configure' to configure the package for your system. If you're using `csh' on an old version of System V, you might need to type `sh ./configure' instead to prevent `csh' from trying to execute `configure' itself. Running `configure' takes awhile. While running, it prints some messages telling which features it is checking for. 2. Type `make' to compile the package. 3. Optionally, type `make check' to run any self-tests that come with the package. 4. Type `make install' to install the programs and any data files and documentation. 5. You can remove the program binaries and object files from the source code directory by typing `make clean'. To also remove the files that `configure' created (so you can compile the package for a different kind of computer), type `make distclean'. There is also a `make maintainer-clean' target, but that is intended mainly for the package's developers. If you use it, you may have to get all sorts of other programs in order to regenerate files that came with the distribution. Compilers and Options ===================== Some systems require unusual options for compilation or linking that the `configure' script does not know about. You can give `configure' initial values for variables by setting them in the environment. Using a Bourne-compatible shell, you can do that on the command line like this: CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure Or on systems that have the `env' program, you can do it like this: env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure Compiling For Multiple Architectures ==================================== You can compile the package for more than one kind of computer at the same time, by placing the object files for each architecture in their own directory. To do this, you must use a version of `make' that supports the `VPATH' variable, such as GNU `make'. `cd' to the directory where you want the object files and executables to go and run the `configure' script. `configure' automatically checks for the source code in the directory that `configure' is in and in `..'. If you have to use a `make' that does not supports the `VPATH' variable, you have to compile the package for one architecture at a time in the source code directory. After you have installed the package for one architecture, use `make distclean' before reconfiguring for another architecture. Installation Names ================== By default, `make install' will install the package's files in `/usr/local/bin', `/usr/local/man', etc. You can specify an installation prefix other than `/usr/local' by giving `configure' the option `--prefix=PATH'. You can specify separate installation prefixes for architecture-specific files and architecture-independent files. If you give `configure' the option `--exec-prefix=PATH', the package will use PATH as the prefix for installing programs and libraries. Documentation and other data files will still use the regular prefix. In addition, if you use an unusual directory layout you can give options like `--bindir=PATH' to specify different values for particular kinds of files. Run `configure --help' for a list of the directories you can set and what kinds of files go in them. If the package supports it, you can cause programs to be installed with an extra prefix or suffix on their names by giving `configure' the option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. Optional Features ================= Some packages pay attention to `--enable-FEATURE' options to `configure', where FEATURE indicates an optional part of the package. They may also pay attention to `--with-PACKAGE' options, where PACKAGE is something like `gnu-as' or `x' (for the X Window System). The `README' should mention any `--enable-' and `--with-' options that the package recognizes. For packages that use the X Window System, `configure' can usually find the X include and library files automatically, but if it doesn't, you can use the `configure' options `--x-includes=DIR' and `--x-libraries=DIR' to specify their locations. Specifying the System Type ========================== There may be some features `configure' can not figure out automatically, but needs to determine by the type of host the package will run on. Usually `configure' can figure that out, but if it prints a message saying it can not guess the host type, give it the `--host=TYPE' option. TYPE can either be a short name for the system type, such as `sun4', or a canonical name with three fields: CPU-COMPANY-SYSTEM See the file `config.sub' for the possible values of each field. If `config.sub' isn't included in this package, then this package doesn't need to know the host type. If you are building compiler tools for cross-compiling, you can also use the `--target=TYPE' option to select the type of system they will produce code for and the `--build=TYPE' option to select the type of system on which you are compiling the package. Sharing Defaults ================ If you want to set default values for `configure' scripts to share, you can create a site shell script called `config.site' that gives default values for variables like `CC', `cache_file', and `prefix'. `configure' looks for `PREFIX/share/config.site' if it exists, then `PREFIX/etc/config.site' if it exists. Or, you can set the `CONFIG_SITE' environment variable to the location of the site script. A warning: not all `configure' scripts look for a site script. Operation Controls ================== `configure' recognizes the following options to control how it operates. `--cache-file=FILE' Use and save the results of the tests in FILE instead of `./config.cache'. Set FILE to `/dev/null' to disable caching, for debugging `configure'. `--help' Print a summary of the options to `configure', and exit. `--quiet' `--silent' `-q' Do not print messages saying which checks are being made. To suppress all normal output, redirect it to `/dev/null' (any error messages will still be shown). `--srcdir=DIR' Look for the package's source code in directory DIR. Usually `configure' can determine that directory automatically. `--version' Print the version of Autoconf used to generate the `configure' script, and exit. `configure' also accepts some other, not widely useful, options. httptunnel-3.3/NEWS0000644000175000017500000001574507037144454011227 0ustar * Version 3.0 Summary of user-visible changes since 2.0: ** Bug fixes and improved stability. ** Long options work on all platforms. The GNU libc getopt_long() functions were copied into the httptunnel distribution and is used on systems where no long options are available in the standard libraries. ** Logging messages get a time stamp. ** httptunnel is now Debianized. ** Replaced the MANUAL file with two man pages. ** Made compatible with the Univeral TUN device driver. ** New --strict-content-length option. This option makes httptunnel obey the Content-Length field in the HTTP header. This improves compatibility with some proxies. The defalt is to be sloppy about the Content-Length field. ** New --keep-alive option. With this option, httptunnel will send keep-alive bytes, which improves stability with some proxies. The defailt is to send keep-alive bytes every five seconds. ** New --max-connection-age option. This option specifies the maximum age of any HTTP connection made by httptunnel. The default is 300 seconds. ** New --proxy-authorization option. This option is used to send a authorization string to the proxy. ** New --proxy-authorization-file option. This option works as --proxy-authorization, only it reads the string from the specified file. ** New --pid-file option. With this option, httptunnel will write its process identification number to the specified file. ** New --user-agent option. Use this option to specify a string for the User-Agent field sent in HTTP headers. This is useful for proxies that want a specific value there. * Version 2.0 Summary of user-visible changes since 1.0: ** There is a FAQ. ** There is a MANUAL which isn't. ** Port numbers have default values. ** There is a debug mode. Using --enable-debug with 'configure' will make htc and hts recognize --debug and --logfile options. ** Uses syslog. When not in debug mode, important events and unexpected errors are logged using LOG_NOTICE and LOG_ERROR, respectively. ** hts takes a --content-length option. It works like the one for htc. ** Short option for --forward-port changed from -f to -F. ** Improved portability. Works on at least some versions of GNU/Linux, Solaris, AIX, Digital UNIX, Cygwin, FreeBSD, OpenBSD. ** Improved protocol and HTTP handling. Resulting in better stability. ** Bug fixes. ** Bug reports should now go to bug-httptunnel@nocrew.org. * Version 1.103 ** Bug reporting email addres changed to bug-httptunnel@gnu.org. ** Miscellaneous cosmetic stuff. * Version 1.102 ** Emulate endprotoent() if not present. ** Changed email addresses to preferred ones. ** Handle setsockopt() errors slightly more gracefully. * Version 1.101 ** Disabled compilation of tt and rw, as they are hardly needed anymore. ** Changed internal parameters once again. Send keep-alive bytes ever 5 seconds. Maximum connection time back to 5 minutes. ** Improved logging. Write package name, package version and debug level to log. Removed one superfluous level of indentation. ** Removed a problem which caused a busy loop. This only happened when --proxy-buffer-* was active. * Version 1.100 ** Removed an attempt to printf() NULL, which caused a crash on Solaris. Thanks to Tomas Berndtsson for the fix. ** Hopefully the setsockopt() errors will be gone. ** Changed some internal parameters to satisfy really picky proxies. Increased frequency of keep-alive bytes from 1/30s to 1/10s. Decreased maximum connection time from 5 minutes to 1 minute. TODO: user interface for these parameters. * Version 1.99 ** Added plea for post cards to README. The greedy author tries to turn this otherwise perfectly free software into a vehicle for extracting post cards from innocent users. ** Fixed --enable-debug without --debug bug. ** Adjusted debugging levels. 0 now means no debugging messages, 5 is the highest level. * Version 1.98 ** Close a HTTP POST connection after 5 minutes. This is a kludge, but finally no data is lost with Squid 2. ** httptunnel is now GNU software. ** Changed the short option for --forward-port from -f to -F. Because I want to use -f for a future --file option. ** Removed some possible buffer overflows. * Version 1.97 ** Improved poll() emulation. ** Improved HTTP request and response parsing. ** hts --content-length works now. Thanks Philip! ** Try some setsockopt() settings to make connections more reliable. * Version 1.96 ** Changed compiler warnings when --enable-debug. ** Included the HTTP RFCs in the distribution. ** Emulate poll() using select() on systems without poll(). Still untested, though. ** Fixed void * arithmetic and a prototype/definition mismatch. Thanks to Larry Gensch for this patch! * Version 1.95 ** I/O byte counters. --debug 3 will show byte counters for the data sent and recieived. --debug 4 will also show byte counters for the raw protocol data sent and received. ** hts takes a --content-length switch. ** Make sure HTTP GET responses are not cached. Added "Expires: 0" (invalid HTTP, I know) and "Cache-Control: no-store, must-revalidate" to HTTP GET response header. * Version 1.94 ** Avoid a few compilation warnings. ** http.h didn't make it into the distribution. * Version 1.93 ** Parse HTTP GET responses. If the version is unknown or the status code signals an error, fail. * Version 1.92 ** Forgot to regenerate configure, Makefile, etc. * Version 1.91 ** Forgot to update NEWS before releasing 1.90. * Version 1.90 ** More robust. ** Major protocol change. Now uses the protocol for HTTP GET requests too. ** Improved error logging. ** Solaris and AIX fixes. Thanks to Andrew Gray for the patch. ** Send keep-alive bytes every 30 seconds of inactivity. * Version 1.5 ** New --logfile switch. ** Uses syslog. * Version 1.4 ** Works with Squid 2. ** Solaris fixed. And this time, they're actually tested! Thanks to Tomas Berndtsson for supplying these fixes. * Version 1.3 ** Fixes for addr_inet() and systems without getopt_long(). Thanks to sgback@nety.yeungnam.ac.kr for the bug report. * Version 1.2 ** 'configure' checks whether socklen_t is declared or not. This should make httptunnel compile on older libc's. Thanks to Tomas Almlof and J A for reporting this bug. ** Not specifying a proxy doesn't give a usage error any more. Thanks to George Bonser for reporting this bug. * Version 1.1 ** 'configure' takes a --enable-debug switch. Use it to enable debugging code. ** 'htc' and 'hts' take a --debug switch. Use it to enable debugging mode. ** Some arguments on the command line of 'hts' and 'htc' don't need to be specified with port numbers. If unspecified, a default port number is used. Use --help to see where this applies. ** Removed annoying buffering bug. So no fake --proxy-buffer-size and --proxy-buffer-timeout is needed any more. * Version 1.0 ** First public release. httptunnel-3.3/aclocal.m40000644000175000017500000001263507246172543012365 0ustar dnl aclocal.m4 generated automatically by aclocal 1.4 dnl Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl This program is distributed in the hope that it will be useful, dnl but WITHOUT ANY WARRANTY, to the extent permitted by law; without dnl even the implied warranty of MERCHANTABILITY or FITNESS FOR A dnl PARTICULAR PURPOSE. dnl HTTPTUNNEL_TYPE_SOCKLEN_T dnl Check for the existance of type socklen_t. AC_DEFUN(HTTPTUNNEL_TYPE_SOCKLEN_T, [AC_CACHE_CHECK([for socklen_t], ac_cv_httptunnel_type_socklen_t, [ AC_TRY_COMPILE( [#include #include ], [socklen_t len = 42; return 0;], ac_cv_httptunnel_type_socklen_t=yes, ac_cv_httptunnel_type_socklen_t=no) ]) if test $ac_cv_httptunnel_type_socklen_t != yes; then AC_DEFINE(socklen_t, int) fi ]) dnl HTTPTUNNEL_DEFINE_INADDR_NONE dnl Check for the existance of define INADDR_NONE AC_DEFUN(HTTPTUNNEL_DEFINE_INADDR_NONE, [AC_CACHE_CHECK([whether INADDR_NONE is defined], ac_cv_httptunnel_define_inaddr_none, [ AC_TRY_COMPILE( [#include #include ], [return INADDR_NONE;], ac_cv_httptunnel_define_inaddr_none=yes, ac_cv_httptunnel_define_inaddr_none=no) ]) if test $ac_cv_httptunnel_define_inaddr_none != yes; then AC_DEFINE(INADDR_NONE, 0xffffffff) fi ]) # Do all the work for Automake. This macro actually does too much -- # some checks are only needed if your package does certain things. # But this isn't really a big deal. # serial 1 dnl Usage: dnl AM_INIT_AUTOMAKE(package,version, [no-define]) AC_DEFUN(AM_INIT_AUTOMAKE, [AC_REQUIRE([AC_PROG_INSTALL]) PACKAGE=[$1] AC_SUBST(PACKAGE) VERSION=[$2] AC_SUBST(VERSION) dnl test to see if srcdir already configured if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) fi ifelse([$3],, AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])) AC_REQUIRE([AM_SANITY_CHECK]) AC_REQUIRE([AC_ARG_PROGRAM]) dnl FIXME This is truly gross. missing_dir=`cd $ac_aux_dir && pwd` AM_MISSING_PROG(ACLOCAL, aclocal, $missing_dir) AM_MISSING_PROG(AUTOCONF, autoconf, $missing_dir) AM_MISSING_PROG(AUTOMAKE, automake, $missing_dir) AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir) AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir) AC_REQUIRE([AC_PROG_MAKE_SET])]) # # Check to make sure that the build environment is sane. # AC_DEFUN(AM_SANITY_CHECK, [AC_MSG_CHECKING([whether build environment is sane]) # Just in case sleep 1 echo timestamp > conftestfile # Do `set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null` if test "[$]*" = "X"; then # -L didn't work. set X `ls -t $srcdir/configure conftestfile` fi if test "[$]*" != "X $srcdir/configure conftestfile" \ && test "[$]*" != "X conftestfile $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken alias in your environment]) fi test "[$]2" = conftestfile ) then # Ok. : else AC_MSG_ERROR([newly created file is older than distributed files! Check your system clock]) fi rm -f conftest* AC_MSG_RESULT(yes)]) dnl AM_MISSING_PROG(NAME, PROGRAM, DIRECTORY) dnl The program must properly implement --version. AC_DEFUN(AM_MISSING_PROG, [AC_MSG_CHECKING(for working $2) # Run test in a subshell; some versions of sh will print an error if # an executable is not found, even if stderr is redirected. # Redirect stdin to placate older versions of autoconf. Sigh. if ($2 --version) < /dev/null > /dev/null 2>&1; then $1=$2 AC_MSG_RESULT(found) else $1="$3/missing $2" AC_MSG_RESULT(missing) fi AC_SUBST($1)]) # Like AC_CONFIG_HEADER, but automatically create stamp file. AC_DEFUN(AM_CONFIG_HEADER, [AC_PREREQ([2.12]) AC_CONFIG_HEADER([$1]) dnl When config.status generates a header, we must update the stamp-h file. dnl This file resides in the same directory as the config header dnl that is generated. We must strip everything past the first ":", dnl and everything past the last "/". AC_OUTPUT_COMMANDS(changequote(<<,>>)dnl ifelse(patsubst(<<$1>>, <<[^ ]>>, <<>>), <<>>, <>CONFIG_HEADERS" || echo timestamp > patsubst(<<$1>>, <<^\([^:]*/\)?.*>>, <<\1>>)stamp-h<<>>dnl>>, <>; do case " <<$>>CONFIG_HEADERS " in *" <<$>>am_file "*<<)>> echo timestamp > `echo <<$>>am_file | sed -e 's%:.*%%' -e 's%[^/]*$%%'`stamp-h$am_indx ;; esac am_indx=`expr "<<$>>am_indx" + 1` done<<>>dnl>>) changequote([,]))]) # Define a conditional. AC_DEFUN(AM_CONDITIONAL, [AC_SUBST($1_TRUE) AC_SUBST($1_FALSE) if $2; then $1_TRUE= $1_FALSE='#' else $1_TRUE='#' $1_FALSE= fi]) httptunnel-3.3/FAQ0000644000175000017500000000630206752257207011053 0ustar Q: I'm not real sure what httptunnel can be used for exactly? A: It's a generic tool for sending data in and out through an HTTP proxy. This is not very useful in itself, so you must run another program which uses this data "tunnel". For example, you could use telnet to log in on a computer ouside the proxy. Q: httptunnel craches my SuSE 5.3 box, why? A: I don't know, but upgrading to 6.0 seems to help. Q: I'm responsible for network security in our company. My question is: are there any characteristics of the communication that may be detected at the proxy? A: Maybe. I make no guarantees. Use the source. Q: I wrote 'hts -d /dev/ptyq1' but 'cat . Ditto for AIX 3.2 and . */ #ifndef _NO_PROTO #define _NO_PROTO #endif #ifdef HAVE_CONFIG_H #include #endif #if !defined (__STDC__) || !__STDC__ /* This is a separate conditional since some stdc systems reject `defined (const)'. */ #ifndef const #define const #endif #endif #include #include /* Comment out all this code if we are using the GNU C Library, and are not actually compiling the library itself. This code is part of the GNU C Library, but also included in many other GNU distributions. Compiling and linking in this code is a waste when using the GNU C library (especially if it is a shared library). Rather than having every GNU program understand `configure --with-gnu-libc' and omit the object files, it is simpler to just do this in the source for each such file. */ #define GETOPT_INTERFACE_VERSION 2 #if !defined (_LIBC) && defined (__GLIBC__) && __GLIBC__ >= 2 #include #if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION #define ELIDE_CODE #endif #endif #ifndef ELIDE_CODE /* This needs to come after some library #include to get __GNU_LIBRARY__ defined. */ #ifdef __GNU_LIBRARY__ /* Don't include stdlib.h for non-GNU C libraries because some of them contain conflicting prototypes for getopt. */ #include #include #endif /* GNU C library. */ #ifdef VMS #include #if HAVE_STRING_H - 0 #include #endif #endif #if defined (WIN32) && !defined (__CYGWIN32__) /* It's not Unix, really. See? Capital letters. */ #include #define getpid() GetCurrentProcessId() #endif #ifndef _ /* This is for other GNU distributions with internationalized messages. When compiling libc, the _ macro is predefined. */ #ifdef HAVE_LIBINTL_H # include # define _(msgid) gettext (msgid) #else # define _(msgid) (msgid) #endif #endif /* This version of `getopt' appears to the caller like standard Unix `getopt' but it behaves differently for the user, since it allows the user to intersperse the options with the other arguments. As `getopt' works, it permutes the elements of ARGV so that, when it is done, all the options precede everything else. Thus all application programs are extended to handle flexible argument order. Setting the environment variable POSIXLY_CORRECT disables permutation. Then the behavior is completely standard. GNU application programs can use a third alternative mode in which they can distinguish the relative order of options and other arguments. */ #include "getopt.h" /* For communication from `getopt' to the caller. When `getopt' finds an option that takes an argument, the argument value is returned here. Also, when `ordering' is RETURN_IN_ORDER, each non-option ARGV-element is returned here. */ char *optarg = NULL; /* Index in ARGV of the next element to be scanned. This is used for communication to and from the caller and for communication between successive calls to `getopt'. On entry to `getopt', zero means this is the first call; initialize. When `getopt' returns -1, this is the index of the first of the non-option elements that the caller should itself scan. Otherwise, `optind' communicates from one call to the next how much of ARGV has been scanned so far. */ /* 1003.2 says this must be 1 before any call. */ int optind = 1; /* Formerly, initialization of getopt depended on optind==0, which causes problems with re-calling getopt as programs generally don't know that. */ int __getopt_initialized = 0; /* The next char to be scanned in the option-element in which the last option character we returned was found. This allows us to pick up the scan where we left off. If this is zero, or a null string, it means resume the scan by advancing to the next ARGV-element. */ static char *nextchar; /* Callers store zero here to inhibit the error message for unrecognized options. */ int opterr = 1; /* Set to an option character which was unrecognized. This must be initialized on some systems to avoid linking in the system's own getopt implementation. */ int optopt = '?'; /* Describe how to deal with options that follow non-option ARGV-elements. If the caller did not specify anything, the default is REQUIRE_ORDER if the environment variable POSIXLY_CORRECT is defined, PERMUTE otherwise. REQUIRE_ORDER means don't recognize them as options; stop option processing when the first non-option is seen. This is what Unix does. This mode of operation is selected by either setting the environment variable POSIXLY_CORRECT, or using `+' as the first character of the list of option characters. PERMUTE is the default. We permute the contents of ARGV as we scan, so that eventually all the non-options are at the end. This allows options to be given in any order, even with programs that were not written to expect this. RETURN_IN_ORDER is an option available to programs that were written to expect options and other ARGV-elements in any order and that care about the ordering of the two. We describe each non-option ARGV-element as if it were the argument of an option with character code 1. Using `-' as the first character of the list of option characters selects this mode of operation. The special argument `--' forces an end of option-scanning regardless of the value of `ordering'. In the case of RETURN_IN_ORDER, only `--' can cause `getopt' to return -1 with `optind' != ARGC. */ static enum { REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER } ordering; /* Value of POSIXLY_CORRECT environment variable. */ static char *posixly_correct; #ifdef __GNU_LIBRARY__ /* We want to avoid inclusion of string.h with non-GNU libraries because there are many ways it can cause trouble. On some systems, it contains special magic macros that don't work in GCC. */ #include #define my_index strchr #else /* Avoid depending on library functions or files whose names are inconsistent. */ char *getenv (); static char * my_index (str, chr) const char *str; int chr; { while (*str) { if (*str == chr) return (char *) str; str++; } return 0; } /* If using GCC, we can safely declare strlen this way. If not using GCC, it is ok not to declare it. */ #ifdef __GNUC__ /* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h. That was relevant to code that was here before. */ #if !defined (__STDC__) || !__STDC__ /* gcc with -traditional declares the built-in strlen to return int, and has done so at least since version 2.4.5. -- rms. */ extern int strlen (const char *); #endif /* not __STDC__ */ #endif /* __GNUC__ */ #endif /* not __GNU_LIBRARY__ */ /* Handle permutation of arguments. */ /* Describe the part of ARGV that contains non-options that have been skipped. `first_nonopt' is the index in ARGV of the first of them; `last_nonopt' is the index after the last of them. */ static int first_nonopt; static int last_nonopt; #ifdef _LIBC /* Bash 2.0 gives us an environment variable containing flags indicating ARGV elements that should not be considered arguments. */ /* Defined in getopt_init.c */ extern char *__getopt_nonoption_flags; static int nonoption_flags_max_len; static int nonoption_flags_len; static int original_argc; static char *const *original_argv; extern pid_t __libc_pid; /* Make sure the environment variable bash 2.0 puts in the environment is valid for the getopt call we must make sure that the ARGV passed to getopt is that one passed to the process. */ static void __attribute__ ((unused)) store_args_and_env (int argc, char *const *argv) { /* XXX This is no good solution. We should rather copy the args so that we can compare them later. But we must not use malloc(3). */ original_argc = argc; original_argv = argv; } text_set_element (__libc_subinit, store_args_and_env); # define SWAP_FLAGS(ch1, ch2) \ if (nonoption_flags_len > 0) \ { \ char __tmp = __getopt_nonoption_flags[ch1]; \ __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \ __getopt_nonoption_flags[ch2] = __tmp; \ } #else /* !_LIBC */ # define SWAP_FLAGS(ch1, ch2) #endif /* _LIBC */ /* Exchange two adjacent subsequences of ARGV. One subsequence is elements [first_nonopt,last_nonopt) which contains all the non-options that have been skipped so far. The other is elements [last_nonopt,optind), which contains all the options processed since those non-options were skipped. `first_nonopt' and `last_nonopt' are relocated so that they describe the new indices of the non-options in ARGV after they are moved. */ #if defined (__STDC__) && __STDC__ static void exchange (char **); #endif static void exchange (argv) char **argv; { int bottom = first_nonopt; int middle = last_nonopt; int top = optind; char *tem; /* Exchange the shorter segment with the far end of the longer segment. That puts the shorter segment into the right place. It leaves the longer segment in the right place overall, but it consists of two parts that need to be swapped next. */ #ifdef _LIBC /* First make sure the handling of the `__getopt_nonoption_flags' string can work normally. Our top argument must be in the range of the string. */ if (nonoption_flags_len > 0 && top >= nonoption_flags_max_len) { /* We must extend the array. The user plays games with us and presents new arguments. */ char *new_str = malloc (top + 1); if (new_str == NULL) nonoption_flags_len = nonoption_flags_max_len = 0; else { memcpy (new_str, __getopt_nonoption_flags, nonoption_flags_max_len); memset (&new_str[nonoption_flags_max_len], '\0', top + 1 - nonoption_flags_max_len); nonoption_flags_max_len = top + 1; __getopt_nonoption_flags = new_str; } } #endif while (top > middle && middle > bottom) { if (top - middle > middle - bottom) { /* Bottom segment is the short one. */ int len = middle - bottom; register int i; /* Swap it with the top part of the top segment. */ for (i = 0; i < len; i++) { tem = argv[bottom + i]; argv[bottom + i] = argv[top - (middle - bottom) + i]; argv[top - (middle - bottom) + i] = tem; SWAP_FLAGS (bottom + i, top - (middle - bottom) + i); } /* Exclude the moved bottom segment from further swapping. */ top -= len; } else { /* Top segment is the short one. */ int len = top - middle; register int i; /* Swap it with the bottom part of the bottom segment. */ for (i = 0; i < len; i++) { tem = argv[bottom + i]; argv[bottom + i] = argv[middle + i]; argv[middle + i] = tem; SWAP_FLAGS (bottom + i, middle + i); } /* Exclude the moved top segment from further swapping. */ bottom += len; } } /* Update records for the slots the non-options now occupy. */ first_nonopt += (optind - last_nonopt); last_nonopt = optind; } /* Initialize the internal data when the first call is made. */ #if defined (__STDC__) && __STDC__ static const char *_getopt_initialize (int, char *const *, const char *); #endif static const char * _getopt_initialize (argc, argv, optstring) int argc; char *const *argv; const char *optstring; { /* Start processing options with ARGV-element 1 (since ARGV-element 0 is the program name); the sequence of previously skipped non-option ARGV-elements is empty. */ first_nonopt = last_nonopt = optind; nextchar = NULL; posixly_correct = getenv ("POSIXLY_CORRECT"); /* Determine how to handle the ordering of options and nonoptions. */ if (optstring[0] == '-') { ordering = RETURN_IN_ORDER; ++optstring; } else if (optstring[0] == '+') { ordering = REQUIRE_ORDER; ++optstring; } else if (posixly_correct != NULL) ordering = REQUIRE_ORDER; else ordering = PERMUTE; #ifdef _LIBC if (posixly_correct == NULL && argc == original_argc && argv == original_argv) { if (nonoption_flags_max_len == 0) { if (__getopt_nonoption_flags == NULL || __getopt_nonoption_flags[0] == '\0') nonoption_flags_max_len = -1; else { const char *orig_str = __getopt_nonoption_flags; int len = nonoption_flags_max_len = strlen (orig_str); if (nonoption_flags_max_len < argc) nonoption_flags_max_len = argc; __getopt_nonoption_flags = (char *) malloc (nonoption_flags_max_len); if (__getopt_nonoption_flags == NULL) nonoption_flags_max_len = -1; else { memcpy (__getopt_nonoption_flags, orig_str, len); memset (&__getopt_nonoption_flags[len], '\0', nonoption_flags_max_len - len); } } } nonoption_flags_len = nonoption_flags_max_len; } else nonoption_flags_len = 0; #endif return optstring; } /* Scan elements of ARGV (whose length is ARGC) for option characters given in OPTSTRING. If an element of ARGV starts with '-', and is not exactly "-" or "--", then it is an option element. The characters of this element (aside from the initial '-') are option characters. If `getopt' is called repeatedly, it returns successively each of the option characters from each of the option elements. If `getopt' finds another option character, it returns that character, updating `optind' and `nextchar' so that the next call to `getopt' can resume the scan with the following option character or ARGV-element. If there are no more option characters, `getopt' returns -1. Then `optind' is the index in ARGV of the first ARGV-element that is not an option. (The ARGV-elements have been permuted so that those that are not options now come last.) OPTSTRING is a string containing the legitimate option characters. If an option character is seen that is not listed in OPTSTRING, return '?' after printing an error message. If you set `opterr' to zero, the error message is suppressed but we still return '?'. If a char in OPTSTRING is followed by a colon, that means it wants an arg, so the following text in the same ARGV-element, or the text of the following ARGV-element, is returned in `optarg'. Two colons mean an option that wants an optional arg; if there is text in the current ARGV-element, it is returned in `optarg', otherwise `optarg' is set to zero. If OPTSTRING starts with `-' or `+', it requests different methods of handling the non-option ARGV-elements. See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. Long-named options begin with `--' instead of `-'. Their names may be abbreviated as long as the abbreviation is unique or is an exact match for some defined option. If they have an argument, it follows the option name in the same ARGV-element, separated from the option name by a `=', or else the in next ARGV-element. When `getopt' finds a long-named option, it returns 0 if that option's `flag' field is nonzero, the value of the option's `val' field if the `flag' field is zero. The elements of ARGV aren't really const, because we permute them. But we pretend they're const in the prototype to be compatible with other systems. LONGOPTS is a vector of `struct option' terminated by an element containing a name which is zero. LONGIND returns the index in LONGOPT of the long-named option found. It is only valid when a long-named option has been found by the most recent call. If LONG_ONLY is nonzero, '-' as well as '--' can introduce long-named options. */ int _getopt_internal (argc, argv, optstring, longopts, longind, long_only) int argc; char *const *argv; const char *optstring; const struct option *longopts; int *longind; int long_only; { optarg = NULL; if (optind == 0 || !__getopt_initialized) { if (optind == 0) optind = 1; /* Don't scan ARGV[0], the program name. */ optstring = _getopt_initialize (argc, argv, optstring); __getopt_initialized = 1; } /* Test whether ARGV[optind] points to a non-option argument. Either it does not have option syntax, or there is an environment flag from the shell indicating it is not an option. The later information is only used when the used in the GNU libc. */ #ifdef _LIBC #define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \ || (optind < nonoption_flags_len \ && __getopt_nonoption_flags[optind] == '1')) #else #define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0') #endif if (nextchar == NULL || *nextchar == '\0') { /* Advance to the next ARGV-element. */ /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been moved back by the user (who may also have changed the arguments). */ if (last_nonopt > optind) last_nonopt = optind; if (first_nonopt > optind) first_nonopt = optind; if (ordering == PERMUTE) { /* If we have just processed some options following some non-options, exchange them so that the options come first. */ if (first_nonopt != last_nonopt && last_nonopt != optind) exchange ((char **) argv); else if (last_nonopt != optind) first_nonopt = optind; /* Skip any additional non-options and extend the range of non-options previously skipped. */ while (optind < argc && NONOPTION_P) optind++; last_nonopt = optind; } /* The special ARGV-element `--' means premature end of options. Skip it like a null option, then exchange with previous non-options as if it were an option, then skip everything else like a non-option. */ if (optind != argc && !strcmp (argv[optind], "--")) { optind++; if (first_nonopt != last_nonopt && last_nonopt != optind) exchange ((char **) argv); else if (first_nonopt == last_nonopt) first_nonopt = optind; last_nonopt = argc; optind = argc; } /* If we have done all the ARGV-elements, stop the scan and back over any non-options that we skipped and permuted. */ if (optind == argc) { /* Set the next-arg-index to point at the non-options that we previously skipped, so the caller will digest them. */ if (first_nonopt != last_nonopt) optind = first_nonopt; return -1; } /* If we have come to a non-option and did not permute it, either stop the scan or describe it to the caller and pass it by. */ if (NONOPTION_P) { if (ordering == REQUIRE_ORDER) return -1; optarg = argv[optind++]; return 1; } /* We have found another option-ARGV-element. Skip the initial punctuation. */ nextchar = (argv[optind] + 1 + (longopts != NULL && argv[optind][1] == '-')); } /* Decode the current option-ARGV-element. */ /* Check whether the ARGV-element is a long option. If long_only and the ARGV-element has the form "-f", where f is a valid short option, don't consider it an abbreviated form of a long option that starts with f. Otherwise there would be no way to give the -f short option. On the other hand, if there's a long option "fubar" and the ARGV-element is "-fu", do consider that an abbreviation of the long option, just like "--fu", and not "-f" with arg "u". This distinction seems to be the most useful approach. */ if (longopts != NULL && (argv[optind][1] == '-' || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1]))))) { char *nameend; const struct option *p; const struct option *pfound = NULL; int exact = 0; int ambig = 0; int indfound = -1; int option_index; for (nameend = nextchar; *nameend && *nameend != '='; nameend++) /* Do nothing. */ ; /* Test all long options for either exact match or abbreviated matches. */ for (p = longopts, option_index = 0; p->name; p++, option_index++) if (!strncmp (p->name, nextchar, nameend - nextchar)) { if ((unsigned int) (nameend - nextchar) == (unsigned int) strlen (p->name)) { /* Exact match found. */ pfound = p; indfound = option_index; exact = 1; break; } else if (pfound == NULL) { /* First nonexact match found. */ pfound = p; indfound = option_index; } else /* Second or later nonexact match found. */ ambig = 1; } if (ambig && !exact) { if (opterr) fprintf (stderr, _("%s: option `%s' is ambiguous\n"), argv[0], argv[optind]); nextchar += strlen (nextchar); optind++; optopt = 0; return '?'; } if (pfound != NULL) { option_index = indfound; optind++; if (*nameend) { /* Don't test has_arg with >, because some C compilers don't allow it to be used on enums. */ if (pfound->has_arg) optarg = nameend + 1; else { if (opterr) { if (argv[optind - 1][1] == '-') /* --option */ fprintf (stderr, _("%s: option `--%s' doesn't allow an argument\n"), argv[0], pfound->name); else /* +option or -option */ fprintf (stderr, _("%s: option `%c%s' doesn't allow an argument\n"), argv[0], argv[optind - 1][0], pfound->name); } nextchar += strlen (nextchar); optopt = pfound->val; return '?'; } } else if (pfound->has_arg == 1) { if (optind < argc) optarg = argv[optind++]; else { if (opterr) fprintf (stderr, _("%s: option `%s' requires an argument\n"), argv[0], argv[optind - 1]); nextchar += strlen (nextchar); optopt = pfound->val; return optstring[0] == ':' ? ':' : '?'; } } nextchar += strlen (nextchar); if (longind != NULL) *longind = option_index; if (pfound->flag) { *(pfound->flag) = pfound->val; return 0; } return pfound->val; } /* Can't find it as a long option. If this is not getopt_long_only, or the option starts with '--' or is not a valid short option, then it's an error. Otherwise interpret it as a short option. */ if (!long_only || argv[optind][1] == '-' || my_index (optstring, *nextchar) == NULL) { if (opterr) { if (argv[optind][1] == '-') /* --option */ fprintf (stderr, _("%s: unrecognized option `--%s'\n"), argv[0], nextchar); else /* +option or -option */ fprintf (stderr, _("%s: unrecognized option `%c%s'\n"), argv[0], argv[optind][0], nextchar); } nextchar = (char *) ""; optind++; optopt = 0; return '?'; } } /* Look at and handle the next short option-character. */ { char c = *nextchar++; char *temp = my_index (optstring, c); /* Increment `optind' when we start to process its last character. */ if (*nextchar == '\0') ++optind; if (temp == NULL || c == ':') { if (opterr) { if (posixly_correct) /* 1003.2 specifies the format of this message. */ fprintf (stderr, _("%s: illegal option -- %c\n"), argv[0], c); else fprintf (stderr, _("%s: invalid option -- %c\n"), argv[0], c); } optopt = c; return '?'; } /* Convenience. Treat POSIX -W foo same as long option --foo */ if (temp[0] == 'W' && temp[1] == ';') { char *nameend; const struct option *p; const struct option *pfound = NULL; int exact = 0; int ambig = 0; int indfound = 0; int option_index; /* This is an option that requires an argument. */ if (*nextchar != '\0') { optarg = nextchar; /* If we end this ARGV-element by taking the rest as an arg, we must advance to the next element now. */ optind++; } else if (optind == argc) { if (opterr) { /* 1003.2 specifies the format of this message. */ fprintf (stderr, _("%s: option requires an argument -- %c\n"), argv[0], c); } optopt = c; if (optstring[0] == ':') c = ':'; else c = '?'; return c; } else /* We already incremented `optind' once; increment it again when taking next ARGV-elt as argument. */ optarg = argv[optind++]; /* optarg is now the argument, see if it's in the table of longopts. */ for (nextchar = nameend = optarg; *nameend && *nameend != '='; nameend++) /* Do nothing. */ ; /* Test all long options for either exact match or abbreviated matches. */ for (p = longopts, option_index = 0; p->name; p++, option_index++) if (!strncmp (p->name, nextchar, nameend - nextchar)) { if ((unsigned int) (nameend - nextchar) == strlen (p->name)) { /* Exact match found. */ pfound = p; indfound = option_index; exact = 1; break; } else if (pfound == NULL) { /* First nonexact match found. */ pfound = p; indfound = option_index; } else /* Second or later nonexact match found. */ ambig = 1; } if (ambig && !exact) { if (opterr) fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"), argv[0], argv[optind]); nextchar += strlen (nextchar); optind++; return '?'; } if (pfound != NULL) { option_index = indfound; if (*nameend) { /* Don't test has_arg with >, because some C compilers don't allow it to be used on enums. */ if (pfound->has_arg) optarg = nameend + 1; else { if (opterr) fprintf (stderr, _("\ %s: option `-W %s' doesn't allow an argument\n"), argv[0], pfound->name); nextchar += strlen (nextchar); return '?'; } } else if (pfound->has_arg == 1) { if (optind < argc) optarg = argv[optind++]; else { if (opterr) fprintf (stderr, _("%s: option `%s' requires an argument\n"), argv[0], argv[optind - 1]); nextchar += strlen (nextchar); return optstring[0] == ':' ? ':' : '?'; } } nextchar += strlen (nextchar); if (longind != NULL) *longind = option_index; if (pfound->flag) { *(pfound->flag) = pfound->val; return 0; } return pfound->val; } nextchar = NULL; return 'W'; /* Let the application handle it. */ } if (temp[1] == ':') { if (temp[2] == ':') { /* This is an option that accepts an argument optionally. */ if (*nextchar != '\0') { optarg = nextchar; optind++; } else optarg = NULL; nextchar = NULL; } else { /* This is an option that requires an argument. */ if (*nextchar != '\0') { optarg = nextchar; /* If we end this ARGV-element by taking the rest as an arg, we must advance to the next element now. */ optind++; } else if (optind == argc) { if (opterr) { /* 1003.2 specifies the format of this message. */ fprintf (stderr, _("%s: option requires an argument -- %c\n"), argv[0], c); } optopt = c; if (optstring[0] == ':') c = ':'; else c = '?'; } else /* We already incremented `optind' once; increment it again when taking next ARGV-elt as argument. */ optarg = argv[optind++]; nextchar = NULL; } } return c; } } int getopt (argc, argv, optstring) int argc; char *const *argv; const char *optstring; { return _getopt_internal (argc, argv, optstring, (const struct option *) 0, (int *) 0, 0); } #endif /* Not ELIDE_CODE. */ #ifdef TEST /* Compile with -DTEST to make an executable for use in testing the above definition of `getopt'. */ int main (argc, argv) int argc; char **argv; { int c; int digit_optind = 0; while (1) { int this_option_optind = optind ? optind : 1; c = getopt (argc, argv, "abc:d:0123456789"); if (c == -1) break; switch (c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (digit_optind != 0 && digit_optind != this_option_optind) printf ("digits occur in two different argv-elements.\n"); digit_optind = this_option_optind; printf ("option %c\n", c); break; case 'a': printf ("option a\n"); break; case 'b': printf ("option b\n"); break; case 'c': printf ("option c with value `%s'\n", optarg); break; case '?': break; default: printf ("?? getopt returned character code 0%o ??\n", c); } } if (optind < argc) { printf ("non-option ARGV-elements: "); while (optind < argc) printf ("%s ", argv[optind++]); printf ("\n"); } exit (0); } #endif /* TEST */ httptunnel-3.3/port/vsyslog.c0000644000175000017500000000132506715256760013361 0ustar /* port/vsyslog.c Copyright (C) 1999 Lars Brinkhoff. See COPYING for terms and conditions. */ #include #include #include #include "config.h" #ifndef HAVE_SYSLOG void syslog (int level, const char *fmt0, ...) { #ifdef HAVE_VSYSLOG va_list ap; va_start (ap, fmt0); vsyslog (level, fmt0, ap); va_end (ap); #else /* This system has neither syslog() nor vsyslog(), so do nothing. */ /* FIXME: this function could open a file and log messages in it. */ #endif } #endif #ifndef HAVE_VSYSLOG void vsyslog (int level, const char *fmt0, va_list ap) { char buffer[512]; if (vsnprintf (buffer, sizeof buffer, fmt0, ap) > 0) syslog (level, buffer); } #endif /* HAVE_VSYSLOG */ httptunnel-3.3/port/syslog_.h0000644000175000017500000000056506715256760013344 0ustar /* port/syslog_.h Copyright (C) 1999 Lars Brinkhoff. See COPYING for terms and conditions. */ #ifndef PORT_SYSLOG_H #define PORT_SYSLOG_H #include "config.h" #include #ifdef HAVE_SYSLOG_H #include #else void syslog (int level, char *fmt0, ...); #endif #ifndef HAVE_VSYSLOG void vsyslog (int level, const char *fmt0, va_list ap); #endif #endif httptunnel-3.3/port/getopt.h0000644000175000017500000001102307126737354013156 0ustar /* Declarations for getopt. Copyright (C) 1989,90,91,92,93,94,96,97 Free Software Foundation, Inc. the C library, however. The master source lives in /gd/gnu/lib. NOTE: The canonical source of this file is maintained with the GNU C Library. Bugs can be reported to bug-glibc@prep.ai.mit.edu. 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, 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 _GETOPT_H #define _GETOPT_H 1 #ifdef __cplusplus extern "C" { #endif /* For communication from `getopt' to the caller. When `getopt' finds an option that takes an argument, the argument value is returned here. Also, when `ordering' is RETURN_IN_ORDER, each non-option ARGV-element is returned here. */ extern char *optarg; /* Index in ARGV of the next element to be scanned. This is used for communication to and from the caller and for communication between successive calls to `getopt'. On entry to `getopt', zero means this is the first call; initialize. When `getopt' returns -1, this is the index of the first of the non-option elements that the caller should itself scan. Otherwise, `optind' communicates from one call to the next how much of ARGV has been scanned so far. */ extern int optind; /* Callers store zero here to inhibit the error message `getopt' prints for unrecognized options. */ extern int opterr; /* Set to an option character which was unrecognized. */ extern int optopt; /* Describe the long-named options requested by the application. The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector of `struct option' terminated by an element containing a name which is zero. The field `has_arg' is: no_argument (or 0) if the option does not take an argument, required_argument (or 1) if the option requires an argument, optional_argument (or 2) if the option takes an optional argument. If the field `flag' is not NULL, it points to a variable that is set to the value given in the field `val' when the option is found, but left unchanged if the option is not found. To have a long-named option do something other than set an `int' to a compiled-in constant, such as set a value from `optarg', set the option's `flag' field to zero and its `val' field to a nonzero value (the equivalent single-letter option character, if there is one). For long options that have a zero `flag' field, `getopt' returns the contents of the `val' field. */ struct option { #if defined (__STDC__) && __STDC__ const char *name; #else char *name; #endif /* has_arg can't be an enum because some compilers complain about type mismatches in all the code that assumes it is an int. */ int has_arg; int *flag; int val; }; /* Names for the values of the `has_arg' field of `struct option'. */ #define no_argument 0 #define required_argument 1 #define optional_argument 2 #if defined (__STDC__) && __STDC__ #ifdef __GNU_LIBRARY__ /* Many other libraries have conflicting prototypes for getopt, with differences in the consts, in stdlib.h. To avoid compilation errors, only prototype getopt for the GNU C library. */ extern int getopt (int argc, char *const *argv, const char *shortopts); #else /* not __GNU_LIBRARY__ */ extern int getopt (); #endif /* __GNU_LIBRARY__ */ extern int getopt_long (int argc, char *const *argv, const char *shortopts, const struct option *longopts, int *longind); extern int getopt_long_only (int argc, char *const *argv, const char *shortopts, const struct option *longopts, int *longind); /* Internal only. Users should not call this directly. */ extern int _getopt_internal (int argc, char *const *argv, const char *shortopts, const struct option *longopts, int *longind, int long_only); #else /* not __STDC__ */ extern int getopt (); extern int getopt_long (); extern int getopt_long_only (); extern int _getopt_internal (); #endif /* __STDC__ */ #ifdef __cplusplus } #endif #endif /* _GETOPT_H */ httptunnel-3.3/port/unistd_.h0000644000175000017500000000041506715256760013324 0ustar /* port/unistd_.h Copyright (C) 1999 Lars Brinkhoff. See COPYING for terms and conditions. */ #ifndef PORT_UNISTD_H #define PORT_UNISTD_H #include "config.h" #ifndef HAVE_DAEMON extern int daemon (int, int); #endif #include #endif /* PORT_UNISTD_H */ httptunnel-3.3/port/daemon.c0000644000175000017500000000114206715256760013113 0ustar /* port/daemon.c Copyright (C) 1999 Lars Brinkhoff. See COPYING for terms and conditions. */ #include "config.h" #ifndef HAVE_DAEMON #include #include #include #include int daemon (int nochdir, int noclose) { if (fork () != 0) exit (0); if (!nochdir) chdir ("/"); close (0); close (1); close (2); if (noclose == 0) { open ("/dev/null", O_RDONLY); open ("/dev/null", O_WRONLY); open ("/dev/null", O_WRONLY); } /* FIXME: disassociate from controlling terminal. */ return 0; } #endif /* HAVE_DAEMON */ httptunnel-3.3/port/poll.c0000644000175000017500000000235607023131603012603 0ustar /* port/poll.c Copyright (C) 1999 Lars Brinkhoff. See COPYING for terms and conditions. */ #include "config.h" #ifndef HAVE_POLL #include #include #include #include #ifndef HAVE_SELECT #error "Must have either poll() or select()." #endif int poll (struct pollfd *p, int n, int t) { struct timeval t2, *t3; fd_set r, w, e; int i, m, ret; FD_ZERO (&r); FD_ZERO (&w); FD_ZERO (&e); m = -1; for (i = 0; i < n; i++) { if (p[i].fd < 0) continue; if (p[i].events & POLLIN) FD_SET (p[i].fd, &r); if (p[i].events & POLLOUT) FD_SET (p[i].fd, &w); FD_SET (p[i].fd, &e); /* or something */ if (p[i].fd > m) m = p[i].fd; } if (m == -1) return 0; if (t < 0) t3 = NULL; else { t2.tv_sec = t / 1000; t2.tv_usec = 1000 * (t % 1000); t3 = &t2; } ret = select (m + 1, &r, &w, &e, t3); if (ret != -1) for (i = 0; i < n; i++) { p[i].revents = 0; if (FD_ISSET (p[i].fd, &r)) p[i].revents |= POLLIN; if (FD_ISSET (p[i].fd, &w)) p[i].revents |= POLLOUT; if (FD_ISSET (p[i].fd, &e)) p[i].revents |= POLLERR; /* or something */ } return ret; } #endif /* HAVE_POLL */ httptunnel-3.3/port/endprotoent.c0000644000175000017500000000033606715256760014215 0ustar /* port/endprotoent.c Copyright (C) 1999 Lars Brinkhoff. See COPYING for terms and conditions. */ #include #include "config.h" #ifndef HAVE_ENDPROTOENT void endprotoent (void) { /* do nothing */ } #endif httptunnel-3.3/port/sys/0000755000175000017500000000000007246172761012322 5ustar httptunnel-3.3/port/sys/Makefile.am0000644000175000017500000000003107126737715014353 0ustar noinst_HEADERS = poll_.h httptunnel-3.3/port/sys/poll_.h0000644000175000017500000000077506715256760013613 0ustar /* port/sys/poll_.h Copyright (C) 1999 Lars Brinkhoff. See COPYING for terms and conditions. */ #ifndef PORT_SYS_POLL_H #define PORT_SYS_POLL_H #include "config.h" #ifdef HAVE_SYS_POLL_H # include #else #define POLLIN 0x01 #define POLLOUT 0x02 #define POLLERR 0x10 #define POLLHUP 0x20 #define POLLNVAL 0x40 struct pollfd { int fd; int events; int revents; }; extern int poll (struct pollfd *p, int n, int timeout); #endif /* !HAVE_SYS_POLL_H */ #endif /* PORT_SYS_POLL_H */ httptunnel-3.3/port/sys/Makefile.in0000644000175000017500000001200707246172761014367 0ustar # Makefile.in generated automatically by automake 1.4 from Makefile.am # Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. SHELL = @SHELL@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ prefix = @prefix@ exec_prefix = @exec_prefix@ bindir = @bindir@ sbindir = @sbindir@ libexecdir = @libexecdir@ datadir = @datadir@ sysconfdir = @sysconfdir@ sharedstatedir = @sharedstatedir@ localstatedir = @localstatedir@ libdir = @libdir@ infodir = @infodir@ mandir = @mandir@ includedir = @includedir@ oldincludedir = /usr/include DESTDIR = pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = ../.. ACLOCAL = @ACLOCAL@ AUTOCONF = @AUTOCONF@ AUTOMAKE = @AUTOMAKE@ AUTOHEADER = @AUTOHEADER@ INSTALL = @INSTALL@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS) INSTALL_DATA = @INSTALL_DATA@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ transform = @program_transform_name@ NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : AWK = @AWK@ CC = @CC@ LN_S = @LN_S@ MAKEINFO = @MAKEINFO@ PACKAGE = @PACKAGE@ RANLIB = @RANLIB@ VERSION = @VERSION@ noinst_HEADERS = poll_.h mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = ../../config.h CONFIG_CLEAN_FILES = HEADERS = $(noinst_HEADERS) DIST_COMMON = Makefile.am Makefile.in DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) TAR = tar GZIP_ENV = --best all: all-redirect .SUFFIXES: $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps port/sys/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status cd $(top_builddir) \ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status tags: TAGS ID: $(HEADERS) $(SOURCES) $(LISP) list='$(SOURCES) $(HEADERS)'; \ unique=`for i in $$list; do echo $$i; done | \ awk ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ here=`pwd` && cd $(srcdir) \ && mkid -f$$here/ID $$unique $(LISP) TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS)'; \ unique=`for i in $$list; do echo $$i; done | \ awk ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS) mostlyclean-tags: clean-tags: distclean-tags: -rm -f TAGS ID maintainer-clean-tags: distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) subdir = port/sys distdir: $(DISTFILES) @for file in $(DISTFILES); do \ d=$(srcdir); \ if test -d $$d/$$file; then \ cp -pr $$d/$$file $(distdir)/$$file; \ else \ test -f $(distdir)/$$file \ || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ || cp -p $$d/$$file $(distdir)/$$file || :; \ fi; \ done info-am: info: info-am dvi-am: dvi: dvi-am check-am: all-am check: check-am installcheck-am: installcheck: installcheck-am install-exec-am: install-exec: install-exec-am install-data-am: install-data: install-data-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am install: install-am uninstall-am: uninstall: uninstall-am all-am: Makefile $(HEADERS) all-redirect: all-am install-strip: $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install installdirs: mostlyclean-generic: clean-generic: distclean-generic: -rm -f Makefile $(CONFIG_CLEAN_FILES) -rm -f config.cache config.log stamp-h stamp-h[0-9]* maintainer-clean-generic: mostlyclean-am: mostlyclean-tags mostlyclean-generic mostlyclean: mostlyclean-am clean-am: clean-tags clean-generic mostlyclean-am clean: clean-am distclean-am: distclean-tags distclean-generic clean-am distclean: distclean-am maintainer-clean-am: maintainer-clean-tags maintainer-clean-generic \ distclean-am @echo "This command is intended for maintainers to use;" @echo "it deletes files that may require special tools to rebuild." maintainer-clean: maintainer-clean-am .PHONY: tags mostlyclean-tags distclean-tags clean-tags \ maintainer-clean-tags distdir info-am info dvi-am dvi check check-am \ installcheck-am installcheck install-exec-am install-exec \ install-data-am install-data install-am install uninstall-am uninstall \ all-redirect all-am all installdirs mostlyclean-generic \ distclean-generic clean-generic maintainer-clean-generic clean \ mostlyclean distclean maintainer-clean # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: httptunnel-3.3/port/netdb_.h0000644000175000017500000000040706676160124013105 0ustar /* port/Netdb.h Copyright (C) 1999 Lars Brinkhoff. See COPYING for terms and conditions. */ #ifndef PORT_NETDB_H #define PORT_NETDB_H #include #include "config.h" #ifndef HAVE_ENDPROTOENT void endprotoent (void); #endif #endif /* PORT_NETDB_H */ httptunnel-3.3/port/Makefile.in0000644000175000017500000002360207246172760013553 0ustar # Makefile.in generated automatically by automake 1.4 from Makefile.am # Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. SHELL = @SHELL@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ prefix = @prefix@ exec_prefix = @exec_prefix@ bindir = @bindir@ sbindir = @sbindir@ libexecdir = @libexecdir@ datadir = @datadir@ sysconfdir = @sysconfdir@ sharedstatedir = @sharedstatedir@ localstatedir = @localstatedir@ libdir = @libdir@ infodir = @infodir@ mandir = @mandir@ includedir = @includedir@ oldincludedir = /usr/include DESTDIR = pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = .. ACLOCAL = @ACLOCAL@ AUTOCONF = @AUTOCONF@ AUTOMAKE = @AUTOMAKE@ AUTOHEADER = @AUTOHEADER@ INSTALL = @INSTALL@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS) INSTALL_DATA = @INSTALL_DATA@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ transform = @program_transform_name@ NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : AWK = @AWK@ CC = @CC@ LN_S = @LN_S@ MAKEINFO = @MAKEINFO@ PACKAGE = @PACKAGE@ RANLIB = @RANLIB@ VERSION = @VERSION@ SUBDIRS = sys noinst_LIBRARIES = libport.a libport_a_SOURCES = poll.c daemon.c unistd_.h vsyslog.c syslog_.h endprotoent.c getopt.c getopt1.c vsnprintf.c getopt.h stdio_.h netdb_.h mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = ../config.h CONFIG_CLEAN_FILES = LIBRARIES = $(noinst_LIBRARIES) DEFS = @DEFS@ -I. -I$(srcdir) -I.. CPPFLAGS = @CPPFLAGS@ LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ libport_a_LIBADD = libport_a_OBJECTS = poll.o daemon.o vsyslog.o endprotoent.o getopt.o \ getopt1.o vsnprintf.o AR = ar CFLAGS = @CFLAGS@ COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ DIST_COMMON = Makefile.am Makefile.in DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) TAR = tar GZIP_ENV = --best SOURCES = $(libport_a_SOURCES) OBJECTS = $(libport_a_OBJECTS) all: all-redirect .SUFFIXES: .SUFFIXES: .S .c .o .s $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps port/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status cd $(top_builddir) \ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status mostlyclean-noinstLIBRARIES: clean-noinstLIBRARIES: -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) distclean-noinstLIBRARIES: maintainer-clean-noinstLIBRARIES: .c.o: $(COMPILE) -c $< .s.o: $(COMPILE) -c $< .S.o: $(COMPILE) -c $< mostlyclean-compile: -rm -f *.o core *.core clean-compile: distclean-compile: -rm -f *.tab.c maintainer-clean-compile: libport.a: $(libport_a_OBJECTS) $(libport_a_DEPENDENCIES) -rm -f libport.a $(AR) cru libport.a $(libport_a_OBJECTS) $(libport_a_LIBADD) $(RANLIB) libport.a # This directory's subdirectories are mostly independent; you can cd # into them and run `make' without going through this Makefile. # To change the values of `make' variables: instead of editing Makefiles, # (1) if the variable is set in `config.status', edit `config.status' # (which will cause the Makefiles to be regenerated when you run `make'); # (2) otherwise, pass the desired values on the `make' command line. @SET_MAKE@ all-recursive install-data-recursive install-exec-recursive \ installdirs-recursive install-recursive uninstall-recursive \ check-recursive installcheck-recursive info-recursive dvi-recursive: @set fnord $(MAKEFLAGS); amf=$$2; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ list='$(SUBDIRS)'; for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" mostlyclean-recursive clean-recursive distclean-recursive \ maintainer-clean-recursive: @set fnord $(MAKEFLAGS); amf=$$2; \ dot_seen=no; \ rev=''; list='$(SUBDIRS)'; for subdir in $$list; do \ rev="$$subdir $$rev"; \ test "$$subdir" = "." && dot_seen=yes; \ done; \ test "$$dot_seen" = "no" && rev=". $$rev"; \ target=`echo $@ | sed s/-recursive//`; \ for subdir in $$rev; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ done && test -z "$$fail" tags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ done tags: TAGS ID: $(HEADERS) $(SOURCES) $(LISP) list='$(SOURCES) $(HEADERS)'; \ unique=`for i in $$list; do echo $$i; done | \ awk ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ here=`pwd` && cd $(srcdir) \ && mkid -f$$here/ID $$unique $(LISP) TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP) tags=; \ here=`pwd`; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \ fi; \ done; \ list='$(SOURCES) $(HEADERS)'; \ unique=`for i in $$list; do echo $$i; done | \ awk ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS) mostlyclean-tags: clean-tags: distclean-tags: -rm -f TAGS ID maintainer-clean-tags: distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) subdir = port distdir: $(DISTFILES) @for file in $(DISTFILES); do \ d=$(srcdir); \ if test -d $$d/$$file; then \ cp -pr $$d/$$file $(distdir)/$$file; \ else \ test -f $(distdir)/$$file \ || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ || cp -p $$d/$$file $(distdir)/$$file || :; \ fi; \ done for subdir in $(SUBDIRS); do \ if test "$$subdir" = .; then :; else \ test -d $(distdir)/$$subdir \ || mkdir $(distdir)/$$subdir \ || exit 1; \ chmod 777 $(distdir)/$$subdir; \ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir=../$(top_distdir) distdir=../$(distdir)/$$subdir distdir) \ || exit 1; \ fi; \ done daemon.o: daemon.c ../config.h endprotoent.o: endprotoent.c netdb_.h ../config.h getopt.o: getopt.c ../config.h stdio_.h getopt1.o: getopt1.c ../config.h getopt.h stdio_.h poll.o: poll.c ../config.h vsnprintf.o: vsnprintf.c ../config.h stdio_.h vsyslog.o: vsyslog.c stdio_.h ../config.h syslog_.h info-am: info: info-recursive dvi-am: dvi: dvi-recursive check-am: all-am check: check-recursive installcheck-am: installcheck: installcheck-recursive install-exec-am: install-exec: install-exec-recursive install-data-am: install-data: install-data-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am install: install-recursive uninstall-am: uninstall: uninstall-recursive all-am: Makefile $(LIBRARIES) all-redirect: all-recursive install-strip: $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install installdirs: installdirs-recursive installdirs-am: mostlyclean-generic: clean-generic: distclean-generic: -rm -f Makefile $(CONFIG_CLEAN_FILES) -rm -f config.cache config.log stamp-h stamp-h[0-9]* maintainer-clean-generic: mostlyclean-am: mostlyclean-noinstLIBRARIES mostlyclean-compile \ mostlyclean-tags mostlyclean-generic mostlyclean: mostlyclean-recursive clean-am: clean-noinstLIBRARIES clean-compile clean-tags clean-generic \ mostlyclean-am clean: clean-recursive distclean-am: distclean-noinstLIBRARIES distclean-compile \ distclean-tags distclean-generic clean-am distclean: distclean-recursive maintainer-clean-am: maintainer-clean-noinstLIBRARIES \ maintainer-clean-compile maintainer-clean-tags \ maintainer-clean-generic distclean-am @echo "This command is intended for maintainers to use;" @echo "it deletes files that may require special tools to rebuild." maintainer-clean: maintainer-clean-recursive .PHONY: mostlyclean-noinstLIBRARIES distclean-noinstLIBRARIES \ clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \ mostlyclean-compile distclean-compile clean-compile \ maintainer-clean-compile install-data-recursive \ uninstall-data-recursive install-exec-recursive \ uninstall-exec-recursive installdirs-recursive uninstalldirs-recursive \ all-recursive check-recursive installcheck-recursive info-recursive \ dvi-recursive mostlyclean-recursive distclean-recursive clean-recursive \ maintainer-clean-recursive tags tags-recursive mostlyclean-tags \ distclean-tags clean-tags maintainer-clean-tags distdir info-am info \ dvi-am dvi check check-am installcheck-am installcheck install-exec-am \ install-exec install-data-am install-data install-am install \ uninstall-am uninstall all-redirect all-am all installdirs-am \ installdirs mostlyclean-generic distclean-generic clean-generic \ maintainer-clean-generic clean mostlyclean distclean maintainer-clean # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: httptunnel-3.3/port/stdio_.h0000644000175000017500000000075306735662263013146 0ustar /* port/stdio_.h Copyright (C) 1999 Lars Brinkhoff. See COPYING for terms and conditions. */ #ifndef PORT_STDIO_H #define PORT_STDIO_H #include #include #include #include "config.h" extern int vsmprintf (char **str, const char *format, va_list ap); #ifndef HAVE_VSNPRINTF extern int vsnprintf (char *str, size_t n, const char *format, va_list ap); extern int snprintf (char *str, size_t n, const char *format, ...); #endif #endif /* PORT_STDIO_H */ httptunnel-3.3/port/vsnprintf.c0000644000175000017500000000212506715256760013703 0ustar /* port/vsnprintf.c Copyright (C) 1999 Lars Brinkhoff. See COPYING for terms and conditions. */ #include "config.h" #include #include #include #include #ifndef HAVE_VPRINTF #error "Must have vfprintf() and vsprintf()." #endif int vsmprintf (char **s, const char *format, va_list ap) { size_t n; FILE *f; f = fopen ("/dev/null", "w"); if (f == NULL) return -1; n = vfprintf (f, format, ap); fclose (f); *s = malloc (n + 1); if (*s == NULL) return -1; return vsprintf (*s, format, ap); } #ifndef HAVE_VSNPRINTF int vsnprintf (char *str, size_t n, const char *format, va_list ap) { char *s; int m, r; m = vsmprintf (&s, format, ap); if (m == -1) return 0; if (m + 1 > n) { m = n - 1; r = -1; } else { r = m; } memcpy (str, s, m); free (s); str[m] = 0; return r; } int snprintf (char *s, size_t n, const char *format, ...) { va_list ap; int m; va_start (ap, format); m = vsnprintf (s, n, format, ap); va_end (ap); return m; } #endif /* HAVE_VSNPRINTF */ httptunnel-3.3/port/getopt1.c0000644000175000017500000001075507126737354013245 0ustar /* getopt_long and getopt_long_only entry points for GNU getopt. Copyright (C) 1987,88,89,90,91,92,93,94,96,97 Free Software Foundation, Inc. the C library, however. The master source lives in /gd/gnu/lib. NOTE: The canonical source of this file is maintained with the GNU C Library. Bugs can be reported to bug-glibc@prep.ai.mit.edu. 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, 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. */ #ifdef HAVE_CONFIG_H #include #endif #include "getopt.h" #if !defined (__STDC__) || !__STDC__ /* This is a separate conditional since some stdc systems reject `defined (const)'. */ #ifndef const #define const #endif #endif #include /* Comment out all this code if we are using the GNU C Library, and are not actually compiling the library itself. This code is part of the GNU C Library, but also included in many other GNU distributions. Compiling and linking in this code is a waste when using the GNU C library (especially if it is a shared library). Rather than having every GNU program understand `configure --with-gnu-libc' and omit the object files, it is simpler to just do this in the source for each such file. */ #define GETOPT_INTERFACE_VERSION 2 #if !defined (_LIBC) && defined (__GLIBC__) && __GLIBC__ >= 2 #include #if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION #define ELIDE_CODE #endif #endif #ifndef ELIDE_CODE /* This needs to come after some library #include to get __GNU_LIBRARY__ defined. */ #ifdef __GNU_LIBRARY__ #include #endif #ifndef NULL #define NULL 0 #endif int getopt_long (argc, argv, options, long_options, opt_index) int argc; char *const *argv; const char *options; const struct option *long_options; int *opt_index; { return _getopt_internal (argc, argv, options, long_options, opt_index, 0); } /* Like getopt_long, but '-' as well as '--' can indicate a long option. If an option that starts with '-' (not '--') doesn't match a long option, but does match a short option, it is parsed as a short option instead. */ int getopt_long_only (argc, argv, options, long_options, opt_index) int argc; char *const *argv; const char *options; const struct option *long_options; int *opt_index; { return _getopt_internal (argc, argv, options, long_options, opt_index, 1); } #endif /* Not ELIDE_CODE. */ #ifdef TEST #include int main (argc, argv) int argc; char **argv; { int c; int digit_optind = 0; while (1) { int this_option_optind = optind ? optind : 1; int option_index = 0; static struct option long_options[] = { {"add", 1, 0, 0}, {"append", 0, 0, 0}, {"delete", 1, 0, 0}, {"verbose", 0, 0, 0}, {"create", 0, 0, 0}, {"file", 1, 0, 0}, {0, 0, 0, 0} }; c = getopt_long (argc, argv, "abc:d:0123456789", long_options, &option_index); if (c == -1) break; switch (c) { case 0: printf ("option %s", long_options[option_index].name); if (optarg) printf (" with arg %s", optarg); printf ("\n"); break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (digit_optind != 0 && digit_optind != this_option_optind) printf ("digits occur in two different argv-elements.\n"); digit_optind = this_option_optind; printf ("option %c\n", c); break; case 'a': printf ("option a\n"); break; case 'b': printf ("option b\n"); break; case 'c': printf ("option c with value `%s'\n", optarg); break; case 'd': printf ("option d with value `%s'\n", optarg); break; case '?': break; default: printf ("?? getopt returned character code 0%o ??\n", c); } } if (optind < argc) { printf ("non-option ARGV-elements: "); while (optind < argc) printf ("%s ", argv[optind++]); printf ("\n"); } exit (0); } #endif /* TEST */ httptunnel-3.3/install-sh0000755000175000017500000001273606657300626012533 0ustar #!/bin/sh # # install - install a program, script, or datafile # This comes from X11R5 (mit/util/scripts/install.sh). # # Copyright 1991 by the Massachusetts Institute of Technology # # Permission to use, copy, modify, distribute, and sell this software and its # documentation for any purpose is hereby granted without fee, provided that # the above copyright notice appear in all copies and that both that # copyright notice and this permission notice appear in supporting # documentation, and that the name of M.I.T. not be used in advertising or # publicity pertaining to distribution of the software without specific, # written prior permission. M.I.T. makes no representations about the # suitability of this software for any purpose. It is provided "as is" # without express or implied warranty. # # Calling this script install-sh is preferred over install.sh, to prevent # `make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. It can only install one file at a time, a restriction # shared with many OS's install programs. # set DOITPROG to echo to test this script # Don't use :- since 4.3BSD and earlier shells don't like it. doit="${DOITPROG-}" # put in absolute paths if you don't have them in your path; or use env. vars. mvprog="${MVPROG-mv}" cpprog="${CPPROG-cp}" chmodprog="${CHMODPROG-chmod}" chownprog="${CHOWNPROG-chown}" chgrpprog="${CHGRPPROG-chgrp}" stripprog="${STRIPPROG-strip}" rmprog="${RMPROG-rm}" mkdirprog="${MKDIRPROG-mkdir}" transformbasename="" transform_arg="" instcmd="$mvprog" chmodcmd="$chmodprog 0755" chowncmd="" chgrpcmd="" stripcmd="" rmcmd="$rmprog -f" mvcmd="$mvprog" src="" dst="" dir_arg="" while [ x"$1" != x ]; do case $1 in -c) instcmd="$cpprog" shift continue;; -d) dir_arg=true shift continue;; -m) chmodcmd="$chmodprog $2" shift shift continue;; -o) chowncmd="$chownprog $2" shift shift continue;; -g) chgrpcmd="$chgrpprog $2" shift shift continue;; -s) stripcmd="$stripprog" shift continue;; -t=*) transformarg=`echo $1 | sed 's/-t=//'` shift continue;; -b=*) transformbasename=`echo $1 | sed 's/-b=//'` shift continue;; *) if [ x"$src" = x ] then src=$1 else # this colon is to work around a 386BSD /bin/sh bug : dst=$1 fi shift continue;; esac done if [ x"$src" = x ] then echo "install: no input file specified" exit 1 else true fi if [ x"$dir_arg" != x ]; then dst=$src src="" if [ -d $dst ]; then instcmd=: chmodcmd="" else instcmd=mkdir fi else # Waiting for this to be detected by the "$instcmd $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if [ -f $src -o -d $src ] then true else echo "install: $src does not exist" exit 1 fi if [ x"$dst" = x ] then echo "install: no destination specified" exit 1 else true fi # If destination is a directory, append the input filename; if your system # does not like double slashes in filenames, you may need to add some logic if [ -d $dst ] then dst="$dst"/`basename $src` else true fi fi ## this sed command emulates the dirname command dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` # Make sure that the destination directory exists. # this part is taken from Noah Friedman's mkinstalldirs script # Skip lots of stat calls in the usual case. if [ ! -d "$dstdir" ]; then defaultIFS=' ' IFS="${IFS-${defaultIFS}}" oIFS="${IFS}" # Some sh's can't handle IFS=/ for some reason. IFS='%' set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` IFS="${oIFS}" pathcomp='' while [ $# -ne 0 ] ; do pathcomp="${pathcomp}${1}" shift if [ ! -d "${pathcomp}" ] ; then $mkdirprog "${pathcomp}" else true fi pathcomp="${pathcomp}/" done fi if [ x"$dir_arg" != x ] then $doit $instcmd $dst && if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi else # If we're going to rename the final executable, determine the name now. if [ x"$transformarg" = x ] then dstfile=`basename $dst` else dstfile=`basename $dst $transformbasename | sed $transformarg`$transformbasename fi # don't allow the sed command to completely eliminate the filename if [ x"$dstfile" = x ] then dstfile=`basename $dst` else true fi # Make a temp file name in the proper directory. dsttmp=$dstdir/#inst.$$# # Move or copy the file name to the temp name $doit $instcmd $src $dsttmp && trap "rm -f ${dsttmp}" 0 && # and set any options; do chmod last to preserve setuid bits # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $instcmd $src $dsttmp" command. if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && # Now rename the file to the real destination. $doit $rmcmd -f $dstdir/$dstfile && $doit $mvcmd $dsttmp $dstdir/$dstfile fi && exit 0 httptunnel-3.3/http.h0000644000175000017500000000411206720335657011647 0ustar /* http.h Copyright (C) 1999 Lars Brinkhoff. See COPYING for terms and conditions. */ #include /* All HTTP methods mankind (i.e. RFC2068) knows. */ /* Actually, Netscape has defined some CONNECT method, but */ /* I don't know much about it. */ typedef enum { HTTP_GET, HTTP_PUT, HTTP_POST, HTTP_OPTIONS, HTTP_HEAD, HTTP_DELETE, HTTP_TRACE } Http_method; typedef struct http_header Http_header; struct http_header { const char *name; const char *value; Http_header *next; /* FIXME: this is ugly; need cons cell. */ }; typedef struct { Http_method method; const char *uri; int major_version; int minor_version; Http_header *header; } Http_request; typedef struct { int major_version; int minor_version; int status_code; const char *status_message; Http_header *header; } Http_response; typedef struct { const char *host_name; int host_port; const char *proxy_name; int proxy_port; const char *proxy_authorization; const char *user_agent; } Http_destination; extern ssize_t http_get (int fd, Http_destination *dest); extern ssize_t http_put (int fd, Http_destination *dest, size_t content_length); extern ssize_t http_post (int fd, Http_destination *dest, size_t content_length); extern int http_error_to_errno (int err); extern Http_response *http_create_response (int major_version, int minor_version, int status_code, const char *status_message); extern ssize_t http_parse_response (int fd, Http_response **response); extern void http_destroy_response (Http_response *response); extern Http_header *http_add_header (Http_header **header, const char *name, const char *value); extern Http_request *http_create_request (Http_method method, const char *uri, int major_version, int minor_version); extern ssize_t http_parse_request (int fd, Http_request **request); extern ssize_t http_write_request (int fd, Http_request *request); extern void http_destroy_request (Http_request *resquest); extern const char *http_header_get (Http_header *header, const char *name); httptunnel-3.3/stamp-h.in0000644000175000017500000000001207246172566012415 0ustar timestamp httptunnel-3.3/hts.c0000644000175000017500000003043107246171365011462 0ustar /* hts.c Copyright (C) 1999, 2000 Lars Brinkhoff. See COPYING for terms and conditions. hts is the server half of httptunnel. httptunnel creates a virtual two-way data path tunneled in HTTP requests. */ #include #include #include #include #include #include #include "common.h" typedef struct { char *me; char *device; const char *host; int port; char *forward_host; int forward_port; size_t content_length; char *pid_filename; int use_std; int use_daemon; int strict_content_length; int keep_alive; int max_connection_age; } Arguments; int debug_level = 0; FILE *debug_file = NULL; static void usage (FILE *f, const char *me) { fprintf (f, "Usage: %s [OPTION]... [PORT]\n" "Listen for incoming httptunnel connections at PORT (default port is %d).\n" "When a connection is made, I/O is redirected to the destination specified\n" "by the --device, --forward-port or --stdin-stdout switch.\n" "\n" " -c, --content-length BYTES use HTTP PUT requests of BYTES size\n" " (k, M, and G postfixes recognized)\n" " -d, --device DEVICE use DEVICE for input and output\n" #ifdef DEBUG_MODE " -D, --debug [LEVEL] enable debug mode\n" #endif " -F, --forward-port HOST:PORT connect to PORT at HOST and use it for \n" " input and output\n" " -h, --help display this help and exit\n" " -k, --keep-alive SECONDS send keepalive bytes every SECONDS seconds\n" " (default is %d)\n" #ifdef DEBUG_MODE " -l, --logfile FILE specify logfile for debug output\n" #endif " -M, --max-connection-age SEC maximum time a connection will stay\n" " open is SEC seconds (default is %d)\n" " -s, --stdin-stdout use stdin/stdout for communication\n" " (implies --no-daemon)\n" " -S, --strict-content-length always write Content-Length bytes in requests\n" " -V, --version output version information and exit\n" " -w, --no-daemon don't fork into the background\n" " -p, --pid-file LOCATION write a PID file to LOCATION\n" "\n" "Report bugs to %s.\n", me, DEFAULT_HOST_PORT, DEFAULT_KEEP_ALIVE, DEFAULT_MAX_CONNECTION_AGE, BUG_REPORT_EMAIL); } static void parse_arguments (int argc, char **argv, Arguments *arg) { int c; /* defaults */ arg->me = argv[0]; arg->host = NULL; arg->port = DEFAULT_HOST_PORT; arg->device = NULL; arg->forward_host = NULL; arg->forward_port = -1; arg->content_length = DEFAULT_CONTENT_LENGTH; arg->pid_filename = NULL; arg->use_std = FALSE; arg->use_daemon = TRUE; arg->strict_content_length = FALSE; arg->keep_alive = DEFAULT_KEEP_ALIVE; arg->max_connection_age = DEFAULT_CONNECTION_MAX_TIME; for (;;) { int option_index = 0; static struct option long_options[] = { { "help", no_argument, 0, 'h' }, { "stdin-stdout", no_argument, 0, 's' }, { "strict-content-length", no_argument, 0, 'S' }, { "version", no_argument, 0, 'V' }, { "no-daemon", no_argument, 0, 'w' }, #ifdef DEBUG_MODE { "debug", optional_argument, 0, 'D' }, { "logfile", required_argument, 0, 'l' }, #endif { "device", required_argument, 0, 'd' }, { "pid-file", required_argument, 0, 'p' }, { "keep-alive", required_argument, 0, 'k' }, { "forward-port", required_argument, 0, 'F' }, { "content-length", required_argument, 0, 'c' }, { "max-connection-age", required_argument, 0, 'M' }, { 0, 0, 0, 0 } }; static const char *short_options = "c:d:F:hk:M:p:sSVw" #ifdef DEBUG_MODE "D:l:" #endif ; c = getopt_long (argc, argv, short_options, long_options, &option_index); if (c == -1) break; switch (c) { case 0: fprintf (stderr, "option %s", long_options[option_index].name); if (optarg) fprintf (stderr, " with arg %s", optarg); fprintf (stderr, "\n"); break; case 'c': arg->content_length = atoi_with_postfix (optarg); break; case 'd': arg->device = optarg; break; #ifdef DEBUG_MODE case 'D': if (optarg) debug_level = atoi (optarg); else debug_level = 1; break; case 'l': debug_file = fopen (optarg, "w"); if (debug_file == NULL) { fprintf (stderr, "%s: couldn't open file %s for writing\n", arg->me, optarg); log_exit (1); } break; #endif /* DEBUG_MODE */ case 'F': name_and_port (optarg, &arg->forward_host, &arg->forward_port); if (arg->forward_port == -1) { fprintf (stderr, "%s: you must specify a port number.\n" "%s: try '%s --help' for help.\n", arg->me, arg->me, arg->me); exit (1); } break; case 'h': usage (stdout, arg->me); exit (0); case 'k': arg->keep_alive = atoi (optarg); break; case 'M': arg->max_connection_age = atoi (optarg); break; case 's': arg->use_std=TRUE; arg->use_daemon=FALSE; break; case 'S': arg->strict_content_length = TRUE; break; case 'V': printf ("hts (%s) %s\n", PACKAGE, VERSION); exit (0); case 'p': arg->pid_filename = optarg; break; case 'w': arg->use_daemon = FALSE; break; case '?': break; default: fprintf (stderr, "?? getopt returned character code 0%o ??\n", c); } } if (argc - 1 == optind) { char *colon = strchr (argv[optind], ':'); if (colon) { *colon = '\0'; arg->host = argv[optind]; arg->port = atoi (colon + 1); } else arg->port = atoi (argv[optind]); } else if (argc - 1 > optind) { usage (stderr, arg->me); exit (1); } if (arg->device == NULL && arg->forward_port == -1 && !arg->use_std) { fprintf (stderr, "%s: one of --device, --forward-port or --stdin-stdout must be used.\n" "%s: try '%s -help' for help.\n", arg->me, arg->me, arg->me); exit (1); } if ((arg->device != NULL && arg->forward_port != -1) || (arg->device != NULL && arg->use_std) || (arg->forward_port != -1 && arg->use_std)) { fprintf (stderr, "%s: only one of --device, --forward-port or --stdin-stdout can be used.\n" "%s: try '%s --help' for help.\n", arg->me, arg->me, arg->me); exit (1); } if (debug_level == 0 && debug_file != NULL) { fprintf (stderr, "%s: --logfile can't be used without debugging\n", arg->me); exit (1); } /* Removed test ((arg->device == NULL) == (arg->forward_port == -1)) * by Sampo Niskanen - those have been tested already! */ if (arg->port == -1 || ((arg->forward_host == NULL) != (arg->forward_port == -1))) { usage (stderr, arg->me); exit (1); } } int main (int argc, char **argv) { int closed; int fd = -1; Arguments arg; Tunnel *tunnel; FILE *pid_file; parse_arguments (argc, argv, &arg); if ((debug_level == 0 || debug_file != NULL) && arg.use_daemon) daemon (0, 1); #ifdef DEBUG_MODE if (debug_level != 0 && debug_file == NULL) debug_file = stderr; #else openlog ("hts", LOG_PID, LOG_DAEMON); #endif log_notice ("hts (%s) %s started with arguments:", PACKAGE, VERSION); log_notice (" me = %s", arg.me); log_notice (" device = %s", arg.device ? arg.device : "(null)"); if (arg.host) log_notice (" port = %s:%d", arg.host, arg.port); else log_notice (" port = %d", arg.port); log_notice (" forward_port = %d", arg.forward_port); log_notice (" forward_host = %s", arg.forward_host ? arg.forward_host : "(null)"); log_notice (" content_length = %d", arg.content_length); log_notice (" strict_content_length = %d", arg.strict_content_length); log_notice (" use_std = %d", arg.use_std); log_notice (" debug_level = %d", debug_level); log_notice (" pid_filename = %s", arg.pid_filename ? arg.pid_filename : "(null)"); tunnel = tunnel_new_server (arg.host, arg.port, arg.content_length); if (tunnel == NULL) { log_error ("couldn't create tunnel", argv[0]); log_exit (1); } if (tunnel_setopt (tunnel, "strict_content_length", &arg.strict_content_length) == -1) log_debug ("tunnel_setopt strict_content_length error: %s", strerror (errno)); if (tunnel_setopt (tunnel, "keep_alive", &arg.keep_alive) == -1) log_debug ("tunnel_setopt keep_alive error: %s", strerror (errno)); if (tunnel_setopt (tunnel, "max_connection_age", &arg.max_connection_age) == -1) log_debug ("tunnel_setopt max_connection_age error: %s", strerror (errno)); #ifdef DEBUG_MODE signal (SIGPIPE, log_sigpipe); #else signal (SIGPIPE, SIG_IGN); #endif if (arg.pid_filename != NULL) { pid_file = fopen (arg.pid_filename, "w+"); if (pid_file == NULL) { fprintf (stderr, "Couldn't open pid file %s: %s\n", arg.pid_filename, strerror (errno)); } else { fprintf (pid_file, "%d\n", (int)getpid ()); if (fclose (pid_file)) { fprintf (stderr, "Error closing pid file: %s\n", strerror (errno)); } } } for (;;) { time_t last_tunnel_write; log_debug ("waiting for tunnel connection"); if (arg.device != NULL) { fd = open_device (arg.device); log_debug ("open_device (\"%s\") = %d", arg.device, fd); if (fd == -1) { log_error ("couldn't open %s: %s", arg.device, strerror (errno)); log_exit (1); } /* Check that fd is not 0 (clash with --stdin-stdout) */ if (fd == 0) { log_notice("changing fd from %d to 3",fd); if (dup2(fd,3) != 3) { log_error ("couldn't dup2(%d,3): %s",fd,strerror(errno)); log_exit (1); } } } else if (arg.use_std) { log_debug ("using stdin as fd"); fd = 0; if (fcntl(fd,F_SETFL,O_NONBLOCK)==-1) { log_error ("couldn't set stdin to non-blocking mode: %s", strerror(errno)); log_exit (1); } /* Usage of stdout (fd = 1) is checked later. */ } if (tunnel_accept (tunnel) == -1) { log_notice ("couldn't accept connection: %s", strerror (errno)); continue; } if (arg.forward_port != -1) { struct sockaddr_in addr; if (set_address (&addr, arg.forward_host, arg.forward_port) == -1) { log_error ("couldn't forward port to %s:%d: %s\n", arg.forward_host, arg.forward_port, strerror (errno)); log_exit (1); } fd = do_connect (&addr); log_debug ("do_connect (\"%s:%d\") = %d", arg.forward_host, arg.forward_port, fd); if (fd == -1) { log_error ("couldn't connect to %s:%d: %s\n", arg.forward_host, arg.forward_port, strerror (errno)); log_exit (1); } /* Check that fd is not 0 (clash with --stdin-stdout) */ if (fd == 0) { log_notice("changing fd from %d to 3",fd); if (dup2(fd,3) != 3) { log_error ("couldn't dup2(%d,3): %s",fd,strerror(errno)); log_exit (1); } } } closed = FALSE; time (&last_tunnel_write); while (!closed) { struct pollfd pollfd[2]; int timeout; time_t t; int n; pollfd[0].fd = fd; pollfd[0].events = POLLIN; pollfd[1].fd = tunnel_pollin_fd (tunnel); pollfd[1].events = POLLIN; time (&t); timeout = 1000 * (arg.keep_alive - (t - last_tunnel_write)); if (timeout < 0) timeout = 0; log_annoying ("poll () ..."); n = poll (pollfd, 2, timeout); log_annoying ("... = %d", n); if (n == -1) { log_error ("poll error: %s\n", strerror (errno)); log_exit (1); } else if (n == 0) { log_verbose ("poll() timed out"); tunnel_padding (tunnel, 1); time (&last_tunnel_write); continue; } log_annoying ("revents[0] = %x, revents[1] = %x, POLLIN = %x", pollfd[0].revents, pollfd[1].revents, POLLIN); handle_input ("device or port", tunnel, fd, pollfd[0].revents, handle_device_input, &closed); handle_input ("tunnel", tunnel, fd, pollfd[1].revents, handle_tunnel_input, &closed); if (pollfd[0].revents & POLLIN) time (&last_tunnel_write); } log_debug ("closing tunnel"); if (fd != 0) { close (fd); } tunnel_close (tunnel); log_notice ("disconnected from FIXME:hostname:port"); } log_debug ("destroying tunnel"); tunnel_destroy (tunnel); log_exit (0); } httptunnel-3.3/TODO0000644000175000017500000001072606756452641011221 0ustar Things to do, in a slightly random order: * Error detection. Maybe HTTP over TCP isn't all that reliable? Especially considering that there's a proxy in the middle. Detect lost connections and reconnect. Checksum data. Retransmit lost data. Etc etc. This is a big project, but it would be nice to have a reliable transport layer (I THINK it's called "transport layer"). >> Actually, it seems reliable enough. * Actually use the #defines in config.h What good is autoconf if you don't use what it generates for you? >> Getting better. * Handling of TUNNEL_OPEN in the server. Come up with something useful to put in the auth_data section of a TUNNEL_OPEN request. * Adhere to Content-Length, even when doing a tunnel_close(). For now, Content-Length is adhered to strictly everywhere except in tunnel_close(). tunnel_close() could, optionally, send padding after the close request. >> Done, but it's not optional. Yet. Should it be? * Auto-detect proxy PUT/POST buffering. Idea: make a second HTTP GET request that will be used to send ACKs to the client when HTTP PUT/POST data arrives. If data is sent in a PUT/POST reqest and the ACK channel is silent, pad the PUT/POST data until ACK arrives. * Remove busy poll loops. I wrote then that way only because I wanted fast results. I didn't intend them to be that way forever. I promise! Instead, use select() or poll() with nice timeouts. >> Done for the server. Remaining: don't use blocking read()s, buffer data until a complete request is received. >> Done for the client. * Make client and server not fork? >> Done for the server. >> Done for the client. * Multiplex data channels in the tunnel. >> Perhaps in external programs. >> See Port forwarding. * Socket-to-device and device-to-socket gateways. >> External programs. >> See Port forwarding. * CGI-to-hts gateway. If the HTTP tunnel is to connect to an already existing HTTP server, there could be a CGI program relaying tunnel traffic to hts. * tunnel_write () always tries to write all the data, regardless of wheter O_NONLBOCK is set or not. Is this a problem? * Use zlib for compression. Note that padding can't be compressed. * Port forwarding. 'htf --port 23 --destination my.site.org:23' waits for a connection on local port 23, and talks to htfmux using a small protocol. htfmux waits for connections and talks to htc trough a pseudo-tty. htfmux reads data from all its connections and multiplexes it over the tunnel. Yet another protocol for this. In the other end, hts talks to htdemux, which handles the other half of port forwarding. Why separate htf and hftmux? Because there is only one instance of hftmux running. To add or remove a new port forwarding, just run a new htf or kill an already running one. This could also be accomplished with hftmux re-reading a configuration file every time it gets a SIGHUP. Either way is possible. Implement one and see if someone hacks up something better. * Use 'Connection: keep-alive'. Keep the connection alive instead of closing it down efter every HTTP request. * Threading. Separate thread for device/port input and tunnel input. * --paranoid switch. Make the data look like HTML code! * protocol abstraction From: Raphael Manfredi Date: Tue, 17 Aug 1999 16:36:43 +0200 Rename httptunnel as "xtptunnel" :-) Why limit yourself to http? Why not also allow ftptunnel? xts -t ftp .... <=> xtc -t ftp .... xtc -t http ... <=> xtc -t http .... If the "tunnel_*" routines are made "generic" in their signature, one could imagine to put them all in a stucture: struct xtp { /* open routine pointer */ /* read routine pointer */ /* write routine pointer */ /* close routine pointer */ } xtp; Then one would get one xtp "driving" structure per protocol type. The code would get much more modular, and extensible, and common code could get factored out, leaving only protocol-specific idiosyncracies in the driving routines. This kind of design looks like a filesystem stack: on top of it, VFS, a virtual file system, and underneath, specific "drivers" for low-level routines for UFS, NFS, CDFS, etc... The FTP proxy must allow PUT requests to go through for this to work on top of FTP, but it might be useful when an HTTP proxy filters http URLs (making it impossible to connect to the remote server at some *.dhis.org site, e.g.), and don't filter FTP ones. httptunnel-3.3/debian/0000755000175000017500000000000007246172756011746 5ustar httptunnel-3.3/debian/changelog0000644000175000017500000000316607153372536013621 0ustar httptunnel (3.2) unstable; urgency=low * New upstream version. -- Teemu Hukkanen Thu, 31 Aug 2000 08:03:42 +0300 httptunnel (3.1-1) unstable; urgency=low * New upstream version. (Closes: #67354) -- Teemu Hukkanen Wed, 26 Jul 2000 10:59:41 +0300 httptunnel (3.0.3-1) unstable; urgency=low * New upstream version. -- Teemu Hukkanen Sun, 23 Jul 2000 03:52:55 +0300 httptunnel (3.0.2) unstable; urgency=low * New upstream version. -- Teemu Hukkanen Wed, 14 Jun 2000 22:49:02 +0300 httptunnel (3.0) unstable; urgency=low * A stable release created from the development branch. Upstream changes from the previous debian packaged version include two patches, fixing TUN driver compatibility and poll() emulation. Essentially this is the same version as 2.11-2. * Cleaned up the build scripts quite a bit. -- Teemu Hukkanen Wed, 12 Jan 2000 20:09:04 +0200 httptunnel (2.11-2) unstable; urgency=low * New upstream version from CVS * FHS transition -- Teemu Hukkanen Wed, 27 Oct 1999 10:52:18 +0300 httptunnel (2.11-1) unstable; urgency=low * New upstream release. -- Teemu Hukkanen Tue, 24 Aug 1999 13:28:54 +0300 httptunnel (2.10-1) unstable; urgency=low * New upstream release. -- Teemu Hukkanen Sat, 14 Aug 1999 00:29:55 +0300 httptunnel (2.8-1) unstable; urgency=low * Initial Release. -- Teemu Hukkanen Thu, 12 Aug 1999 11:56:17 +0300 Local variables: mode: debian-changelog add-log-mailing-address: "tjhukkan@iki.fi" End: httptunnel-3.3/debian/copyright0000644000175000017500000000116107037141421013657 0ustar This package was debianized by Teemu Hukkanen on Wed, 28 Jul 1999 16:00:06 +0300. It was downloaded from Upstream Author(s): Lars Brinkhoff Copyright: httptunnel is licensed under the GNU General Public License. --- httptunnel is free software. See COPYING for terms and conditions. If you like it, I would appreciate if you sent a post card to: Lars Brinkhoff Kopmansgatan 2 411 13 Goteborg Sweden --- A copy of the GNU General Public License is available on Debian GNU/Linux systems as /usr/share/common-license/GPL. httptunnel-3.3/debian/dirs0000644000175000017500000000005107005530026012603 0ustar usr/bin usr/share/man usr/share/man/man1 httptunnel-3.3/debian/postinst0000644000175000017500000000030007037146067013537 0ustar #!/bin/sh if [ "$1" = "configure" ]; then if [ -d /usr/doc -a ! -e /usr/doc/httptunnel -a -d /usr/share/doc/httptunnel ]; then ln -sf ../share/doc/httptunnel /usr/doc/httptunnel fi fi httptunnel-3.3/debian/rules0000755000175000017500000000412207037141421013004 0ustar #!/usr/bin/make -f #-*- makefile -*- install = install -o root -g root install_exec = $(install) -m 755 -s install_dir = $(install) -m 755 -d install_nonex = $(install) -m 644 install_script = $(install) -m 755 install_zipped = gzip -9vc install_symlink = ln -s package = httptunnel rootdir = `pwd`/debian/tmp docdir = $(rootdir)/usr/share/doc/$(package) bindir = $(rootdir)/usr/bin mandir = $(rootdir)/usr/share/man man1dir = $(mandir)/man1 build: debian/build.stamp debian/build.stamp: $(checkdir) CFLAGS="-O2 -g -Wall" CC=gcc ./configure --prefix=/usr \ --mandir=/usr/share/man $(MAKE) touch $@ clean-build: $(RM) debian/build*.stamp -$(MAKE) distclean binary: binary-arch binary-indep binary-indep: debian/binary-indep.stamp debian/binary-indep.stamp: touch $@ binary-arch: debian/binary-arch.stamp debian/binary-arch.stamp: build $(checkdir) $(RM) -r $(rootdir) $(install_dir) $(rootdir) $(install_dir) $(rootdir)/DEBIAN $(install_dir) $(docdir) $(install_dir) $(bindir) $(install_dir) $(man1dir) $(MAKE) install-strip prefix=`pwd`/debian/tmp/usr mandir=`pwd`/debian/tmp/usr/share/man # changelogs $(install_nonex) debian/changelog $(docdir)/changelog.Debian $(install_nonex) ChangeLog $(docdir)/changelog # docs $(install_nonex) FAQ $(docdir) $(install_nonex) INSTALL $(docdir) $(install_nonex) NEWS $(docdir) $(install_nonex) README $(docdir) $(install_nonex) TODO $(docdir) $(install_nonex) DISCLAIMER $(docdir) $(install_nonex) AUTHORS $(docdir) $(install_nonex) HACKING $(docdir) gzip -9vfr $(docdir)/ gzip -9vfr $(man1dir)/ # copyright $(install_nonex) debian/copyright $(docdir) # control $(install_script) debian/prerm $(rootdir)/DEBIAN $(install_script) debian/postinst $(rootdir)/DEBIAN dpkg-shlibdeps $(bindir)/hts $(bindir)/htc dpkg-gencontrol -isp chown -R root.root $(rootdir) chmod -R g-ws $(rootdir) dpkg --build $(rootdir) .. touch $@ define checkdir test -f htc.c -a -f hts.c -a -f debian/rules endef clean-binary: $(RM) debian/binary*.stamp $(RM) *~ $(RM) -r debian/tmp debian/*~ debian/files debian/substvars clean: clean-build clean-binary httptunnel-3.3/debian/control0000644000175000017500000000056707037141421013340 0ustar Source: httptunnel Section: net Priority: optional Maintainer: Teemu Hukkanen Standards-Version: 3.1.0.0 Package: httptunnel Architecture: any Depends: ${shlibs:Depends} Description: Tunnels a data stream in HTTP requests. Creates a bidirectional virtual data stream tunnelled in HTTP requests. The requests can be sent via a HTTP proxy if so desired. httptunnel-3.3/debian/docs0000644000175000017500000000007007005530026012573 0ustar FAQ INSTALL NEWS README TODO DISCLAIMER AUTHORS HACKING httptunnel-3.3/debian/prerm0000755000175000017500000000017207037146067013013 0ustar #!/bin/sh if [ \( "$1" = "upgrade" -o "$1" = "remove" \) -a -L /usr/doc/httptunnel ]; then rm -f /usr/doc/httptunnel fi httptunnel-3.3/Makefile.in0000644000175000017500000003675007246172756012604 0ustar # Makefile.in generated automatically by automake 1.4 from Makefile.am # Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. SHELL = @SHELL@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ prefix = @prefix@ exec_prefix = @exec_prefix@ bindir = @bindir@ sbindir = @sbindir@ libexecdir = @libexecdir@ datadir = @datadir@ sysconfdir = @sysconfdir@ sharedstatedir = @sharedstatedir@ localstatedir = @localstatedir@ libdir = @libdir@ infodir = @infodir@ mandir = @mandir@ includedir = @includedir@ oldincludedir = /usr/include DESTDIR = pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = . ACLOCAL = @ACLOCAL@ AUTOCONF = @AUTOCONF@ AUTOMAKE = @AUTOMAKE@ AUTOHEADER = @AUTOHEADER@ INSTALL = @INSTALL@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS) INSTALL_DATA = @INSTALL_DATA@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ transform = @program_transform_name@ NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : AWK = @AWK@ CC = @CC@ LN_S = @LN_S@ MAKEINFO = @MAKEINFO@ PACKAGE = @PACKAGE@ RANLIB = @RANLIB@ VERSION = @VERSION@ SUBDIRS = port bin_PROGRAMS = htc hts man_MANS = hts.1 htc.1 @SRCDIR_TRUE@CPPFLAGS = -I$(VPATH)/port @SRCDIR_FALSE@CPPFLAGS = -Iport htc_SOURCES = htc.c common.c tunnel.c http.c base64.c htc_LDADD = -Lport -lport hts_SOURCES = hts.c common.c tunnel.c http.c hts_LDADD = -Lport -lport noinst_HEADERS = common.h tunnel.h http.h base64.h EXTRA_DIST = TODO HACKING DISCLAIMER doc/rfc1945.txt doc/rfc2068.txt FAQ doc/rfc2045.txt hts.1 htc.1 debian/changelog debian/control debian/copyright debian/dirs debian/docs debian/rules debian/prerm debian/postinst ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = config.h CONFIG_CLEAN_FILES = PROGRAMS = $(bin_PROGRAMS) DEFS = @DEFS@ -I. -I$(srcdir) -I. LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ htc_OBJECTS = htc.o common.o tunnel.o http.o base64.o htc_DEPENDENCIES = htc_LDFLAGS = hts_OBJECTS = hts.o common.o tunnel.o http.o hts_DEPENDENCIES = hts_LDFLAGS = CFLAGS = @CFLAGS@ COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ man1dir = $(mandir)/man1 MANS = $(man_MANS) NROFF = nroff HEADERS = $(noinst_HEADERS) DIST_COMMON = README ./stamp-h.in AUTHORS COPYING ChangeLog INSTALL \ Makefile.am Makefile.in NEWS TODO acconfig.h acinclude.m4 aclocal.m4 \ config.h.in configure configure.in install-sh missing mkinstalldirs DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) TAR = tar GZIP_ENV = --best SOURCES = $(htc_SOURCES) $(hts_SOURCES) OBJECTS = $(htc_OBJECTS) $(hts_OBJECTS) all: all-redirect .SUFFIXES: .SUFFIXES: .S .c .o .s $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status cd $(top_builddir) \ && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status $(ACLOCAL_M4): configure.in acinclude.m4 cd $(srcdir) && $(ACLOCAL) config.status: $(srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) $(SHELL) ./config.status --recheck $(srcdir)/configure: $(srcdir)/configure.in $(ACLOCAL_M4) $(CONFIGURE_DEPENDENCIES) cd $(srcdir) && $(AUTOCONF) config.h: stamp-h @if test ! -f $@; then \ rm -f stamp-h; \ $(MAKE) stamp-h; \ else :; fi stamp-h: $(srcdir)/config.h.in $(top_builddir)/config.status cd $(top_builddir) \ && CONFIG_FILES= CONFIG_HEADERS=config.h \ $(SHELL) ./config.status @echo timestamp > stamp-h 2> /dev/null $(srcdir)/config.h.in: $(srcdir)/stamp-h.in @if test ! -f $@; then \ rm -f $(srcdir)/stamp-h.in; \ $(MAKE) $(srcdir)/stamp-h.in; \ else :; fi $(srcdir)/stamp-h.in: $(top_srcdir)/configure.in $(ACLOCAL_M4) acconfig.h cd $(top_srcdir) && $(AUTOHEADER) @echo timestamp > $(srcdir)/stamp-h.in 2> /dev/null mostlyclean-hdr: clean-hdr: distclean-hdr: -rm -f config.h maintainer-clean-hdr: mostlyclean-binPROGRAMS: clean-binPROGRAMS: -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) distclean-binPROGRAMS: maintainer-clean-binPROGRAMS: install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) $(mkinstalldirs) $(DESTDIR)$(bindir) @list='$(bin_PROGRAMS)'; for p in $$list; do \ if test -f $$p; then \ echo " $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`"; \ $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \ else :; fi; \ done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) list='$(bin_PROGRAMS)'; for p in $$list; do \ rm -f $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \ done .c.o: $(COMPILE) -c $< .s.o: $(COMPILE) -c $< .S.o: $(COMPILE) -c $< mostlyclean-compile: -rm -f *.o core *.core clean-compile: distclean-compile: -rm -f *.tab.c maintainer-clean-compile: htc: $(htc_OBJECTS) $(htc_DEPENDENCIES) @rm -f htc $(LINK) $(htc_LDFLAGS) $(htc_OBJECTS) $(htc_LDADD) $(LIBS) hts: $(hts_OBJECTS) $(hts_DEPENDENCIES) @rm -f hts $(LINK) $(hts_LDFLAGS) $(hts_OBJECTS) $(hts_LDADD) $(LIBS) install-man1: $(mkinstalldirs) $(DESTDIR)$(man1dir) @list='$(man1_MANS)'; \ l2='$(man_MANS)'; for i in $$l2; do \ case "$$i" in \ *.1*) list="$$list $$i" ;; \ esac; \ done; \ for i in $$list; do \ if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \ else file=$$i; fi; \ ext=`echo $$i | sed -e 's/^.*\\.//'`; \ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ inst=`echo $$inst | sed '$(transform)'`.$$ext; \ echo " $(INSTALL_DATA) $$file $(DESTDIR)$(man1dir)/$$inst"; \ $(INSTALL_DATA) $$file $(DESTDIR)$(man1dir)/$$inst; \ done uninstall-man1: @list='$(man1_MANS)'; \ l2='$(man_MANS)'; for i in $$l2; do \ case "$$i" in \ *.1*) list="$$list $$i" ;; \ esac; \ done; \ for i in $$list; do \ ext=`echo $$i | sed -e 's/^.*\\.//'`; \ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ inst=`echo $$inst | sed '$(transform)'`.$$ext; \ echo " rm -f $(DESTDIR)$(man1dir)/$$inst"; \ rm -f $(DESTDIR)$(man1dir)/$$inst; \ done install-man: $(MANS) @$(NORMAL_INSTALL) $(MAKE) $(AM_MAKEFLAGS) install-man1 uninstall-man: @$(NORMAL_UNINSTALL) $(MAKE) $(AM_MAKEFLAGS) uninstall-man1 # This directory's subdirectories are mostly independent; you can cd # into them and run `make' without going through this Makefile. # To change the values of `make' variables: instead of editing Makefiles, # (1) if the variable is set in `config.status', edit `config.status' # (which will cause the Makefiles to be regenerated when you run `make'); # (2) otherwise, pass the desired values on the `make' command line. @SET_MAKE@ all-recursive install-data-recursive install-exec-recursive \ installdirs-recursive install-recursive uninstall-recursive \ check-recursive installcheck-recursive info-recursive dvi-recursive: @set fnord $(MAKEFLAGS); amf=$$2; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ list='$(SUBDIRS)'; for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" mostlyclean-recursive clean-recursive distclean-recursive \ maintainer-clean-recursive: @set fnord $(MAKEFLAGS); amf=$$2; \ dot_seen=no; \ rev=''; list='$(SUBDIRS)'; for subdir in $$list; do \ rev="$$subdir $$rev"; \ test "$$subdir" = "." && dot_seen=yes; \ done; \ test "$$dot_seen" = "no" && rev=". $$rev"; \ target=`echo $@ | sed s/-recursive//`; \ for subdir in $$rev; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ done && test -z "$$fail" tags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ done tags: TAGS ID: $(HEADERS) $(SOURCES) $(LISP) list='$(SOURCES) $(HEADERS)'; \ unique=`for i in $$list; do echo $$i; done | \ awk ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ here=`pwd` && cd $(srcdir) \ && mkid -f$$here/ID $$unique $(LISP) TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) $(LISP) tags=; \ here=`pwd`; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \ fi; \ done; \ list='$(SOURCES) $(HEADERS)'; \ unique=`for i in $$list; do echo $$i; done | \ awk ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(ETAGS_ARGS)config.h.in$$unique$(LISP)$$tags" \ || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags config.h.in $$unique $(LISP) -o $$here/TAGS) mostlyclean-tags: clean-tags: distclean-tags: -rm -f TAGS ID maintainer-clean-tags: distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) # This target untars the dist file and tries a VPATH configuration. Then # it guarantees that the distribution is self-contained by making another # tarfile. distcheck: dist -rm -rf $(distdir) GZIP=$(GZIP_ENV) $(TAR) zxf $(distdir).tar.gz mkdir $(distdir)/=build mkdir $(distdir)/=inst dc_install_base=`cd $(distdir)/=inst && pwd`; \ cd $(distdir)/=build \ && ../configure --srcdir=.. --prefix=$$dc_install_base \ && $(MAKE) $(AM_MAKEFLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) dvi \ && $(MAKE) $(AM_MAKEFLAGS) check \ && $(MAKE) $(AM_MAKEFLAGS) install \ && $(MAKE) $(AM_MAKEFLAGS) installcheck \ && $(MAKE) $(AM_MAKEFLAGS) dist -rm -rf $(distdir) @banner="$(distdir).tar.gz is ready for distribution"; \ dashes=`echo "$$banner" | sed s/./=/g`; \ echo "$$dashes"; \ echo "$$banner"; \ echo "$$dashes" dist: distdir -chmod -R a+r $(distdir) GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir) -rm -rf $(distdir) dist-all: distdir -chmod -R a+r $(distdir) GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir) -rm -rf $(distdir) distdir: $(DISTFILES) -rm -rf $(distdir) mkdir $(distdir) -chmod 777 $(distdir) $(mkinstalldirs) $(distdir)/debian $(distdir)/doc @for file in $(DISTFILES); do \ d=$(srcdir); \ if test -d $$d/$$file; then \ cp -pr $$d/$$file $(distdir)/$$file; \ else \ test -f $(distdir)/$$file \ || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ || cp -p $$d/$$file $(distdir)/$$file || :; \ fi; \ done for subdir in $(SUBDIRS); do \ if test "$$subdir" = .; then :; else \ test -d $(distdir)/$$subdir \ || mkdir $(distdir)/$$subdir \ || exit 1; \ chmod 777 $(distdir)/$$subdir; \ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir=../$(distdir) distdir=../$(distdir)/$$subdir distdir) \ || exit 1; \ fi; \ done base64.o: base64.c config.h base64.h common.h port/stdio_.h \ port/unistd_.h port/getopt.h port/syslog_.h tunnel.h common.o: common.c port/netdb_.h config.h port/syslog_.h \ port/sys/poll_.h tunnel.h common.h port/stdio_.h port/unistd_.h \ port/getopt.h htc.o: htc.c port/unistd_.h config.h port/getopt.h port/sys/poll_.h \ common.h port/stdio_.h port/syslog_.h tunnel.h base64.h hts.o: hts.c port/unistd_.h config.h port/getopt.h port/sys/poll_.h \ common.h port/stdio_.h port/syslog_.h tunnel.h http.o: http.c http.h common.h config.h port/stdio_.h port/unistd_.h \ port/getopt.h port/syslog_.h tunnel.h rw.o: rw.c common.h config.h tunnel.h tt.o: tt.c common.h config.h tunnel.h tunnel.o: tunnel.c port/netdb_.h config.h port/sys/poll_.h http.h \ tunnel.h common.h port/stdio_.h port/unistd_.h port/getopt.h \ port/syslog_.h info-am: info: info-recursive dvi-am: dvi: dvi-recursive check-am: all-am check: check-recursive installcheck-am: installcheck: installcheck-recursive all-recursive-am: config.h $(MAKE) $(AM_MAKEFLAGS) all-recursive install-exec-am: install-binPROGRAMS install-exec: install-exec-recursive install-data-am: install-man install-data: install-data-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am install: install-recursive uninstall-am: uninstall-binPROGRAMS uninstall-man uninstall: uninstall-recursive all-am: Makefile $(PROGRAMS) $(MANS) $(HEADERS) config.h all-redirect: all-recursive-am install-strip: $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install installdirs: installdirs-recursive installdirs-am: $(mkinstalldirs) $(DESTDIR)$(bindir) $(DESTDIR)$(mandir)/man1 mostlyclean-generic: clean-generic: distclean-generic: -rm -f Makefile $(CONFIG_CLEAN_FILES) -rm -f config.cache config.log stamp-h stamp-h[0-9]* maintainer-clean-generic: mostlyclean-am: mostlyclean-hdr mostlyclean-binPROGRAMS \ mostlyclean-compile mostlyclean-tags \ mostlyclean-generic mostlyclean: mostlyclean-recursive clean-am: clean-hdr clean-binPROGRAMS clean-compile clean-tags \ clean-generic mostlyclean-am clean: clean-recursive distclean-am: distclean-hdr distclean-binPROGRAMS distclean-compile \ distclean-tags distclean-generic clean-am distclean: distclean-recursive -rm -f config.status maintainer-clean-am: maintainer-clean-hdr maintainer-clean-binPROGRAMS \ maintainer-clean-compile maintainer-clean-tags \ maintainer-clean-generic distclean-am @echo "This command is intended for maintainers to use;" @echo "it deletes files that may require special tools to rebuild." maintainer-clean: maintainer-clean-recursive -rm -f config.status .PHONY: mostlyclean-hdr distclean-hdr clean-hdr maintainer-clean-hdr \ mostlyclean-binPROGRAMS distclean-binPROGRAMS clean-binPROGRAMS \ maintainer-clean-binPROGRAMS uninstall-binPROGRAMS install-binPROGRAMS \ mostlyclean-compile distclean-compile clean-compile \ maintainer-clean-compile install-man1 uninstall-man1 install-man \ uninstall-man install-data-recursive uninstall-data-recursive \ install-exec-recursive uninstall-exec-recursive installdirs-recursive \ uninstalldirs-recursive all-recursive check-recursive \ installcheck-recursive info-recursive dvi-recursive \ mostlyclean-recursive distclean-recursive clean-recursive \ maintainer-clean-recursive tags tags-recursive mostlyclean-tags \ distclean-tags clean-tags maintainer-clean-tags distdir info-am info \ dvi-am dvi check check-am installcheck-am installcheck all-recursive-am \ install-exec-am install-exec install-data-am install-data install-am \ install uninstall-am uninstall all-redirect all-am all installdirs-am \ installdirs mostlyclean-generic distclean-generic clean-generic \ maintainer-clean-generic clean mostlyclean distclean maintainer-clean # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: httptunnel-3.3/base64.h0000644000175000017500000000027106701123026011736 0ustar /* base64.h Copyright (C) 1999 Lars Brinkhoff. See COPYING for terms and conditions. */ #include ssize_t encode_base64 (const void *data, size_t length, char **code); httptunnel-3.3/HACKING0000644000175000017500000000556106674722465011524 0ustar General idea. FIXME: client, server. HTTP. All HTTP requests are made by the client, htc, and are served by the server, hts. Data is sent to the server using HTTP PUT requests. These have a Content-Length header line, which is obeyed strictly if the --strict option is used. tunnel.c provides a nice interface to the complexities of HTTP requests. See tunnel.h for information about the programming interface. In the other direction, data is transferred using HTTP GET requests. Proxy buffering. Some proxies buffer data in HTTP PUT or POST requests. FIXME: explain why this is a problem and how it is solved. Debugging. To enable debugging code, use --enable-debug with 'configure'. This will make htc and hts recognize a --debug switch. --debug 0 - no messages whatsoever --debug 1 - log_notice () - important events --debug 2 - log_error () - unexpected errors --debug 3 - log_debug () - sparse debugging --debug 4 - log_verbose () - debugging in innner loops --debug 5 - log_annoying () - system calls and more Without --enable-debug, log_notice() and log_error() will log using syslog() with level LOG_NOTICE and LOG_ERROR, respectively. log_debug(), log_verbose(), and log_annoying() will be disabled. Some notes about the protocol. The data sent in HTTP requests is in itself formatted according to a simple protocol. This is needed becase some HTTP proxy servers buffer data before sending it to its final destination. There are seven different requests in this protocol, and there are two types of requests. Requests with the 0x40 bit set consists of just one byte, with no additional data. Requests with the 0x40 bit clear have a two-byte length field and a variable length data field. TUNNEL_OPEN 01 xx xx yy... xx xx = length of auth data yy... = auth data OPEN is the initial request. For now, auth data is unused, but should be used for authentication. TUNNEL_DATA 02 xx xx yy... xx xx = lenth of data yy... = data DATA is the one and only way to send data. TUNNEL_PADDING 03 xx xx yy... xx xx = lenth of padding yy... = padding (will be discarded) PADDING exists only to allow padding the HTTP data. This is needed for HTTP proxies that buffer data. TUNNEL_ERROR 04 xx xx yy... xx xx = length of error message yy... = error message Report an error to the peer. TUNNEL_PAD1 45 PAD1 can be used for padding when a PADDING request would be too long with regard to Content-Length. PADDING should always be preferred, though, because it's easier for the recipent to parse one large request than many small. TUNNEL_CLOSE 46 CLOSE is used to close the tunnel. No more data can be sent after this request is issued, except for a TUNNEL_DISCONNECT. TUNNEL_DISCONNECT 47 DISCONNECT is used to close the connection temporarily, probably because Content-Length - 1 number of bytes of data has been sent in the HTTP request. httptunnel-3.3/configure.in0000644000175000017500000000275107246172533013033 0ustar dnl Copyright (C) Lars Brinkhoff. dnl Process this file with autoconf to produce a configure script. AC_INIT(tunnel.c) AM_INIT_AUTOMAKE(httptunnel, 3.3) AM_CONFIG_HEADER(config.h) AM_CONDITIONAL(SRCDIR, test "x$srcdir" != x.) AC_ARG_ENABLE(debug, [ --enable-debug enable debugging], AC_DEFINE(DEBUG_MODE, 1)) if test "x$CFLAGS" = x; then if test "x$enable_debug" != x; then CFLAGS="-g -Wall -Wstrict-prototypes -Wmissing-prototypes -Wpointer-arith" else CFLAGS="-O2 -Wall -fomit-frame-pointer" fi fi dnl Checks for programs. AC_PROG_AWK AC_PROG_CC AC_ARG_PROGRAM AC_PROG_INSTALL AC_PROG_LN_S AC_PROG_RANLIB dnl Checks for libraries. AC_CHECK_FUNC(gethostent, , AC_CHECK_LIB(nsl, gethostent)) AC_CHECK_FUNC(setsockopt, , AC_CHECK_LIB(socket, setsockopt)) dnl Checks for header files. AC_HEADER_STDC AC_CHECK_HEADERS(fcntl.h syslog.h unistd.h sys/poll.h) dnl Checks for typedefs, structures, and compiler characteristics. AC_C_CONST AC_C_INLINE AC_TYPE_SIZE_T ##AC_CHECK_TYPE(socklen_t, unsigned) # doesn't search HTTPTUNNEL_TYPE_SOCKLEN_T HTTPTUNNEL_DEFINE_INADDR_NONE AC_CHECK_SIZEOF(char, 1) AC_CHECK_SIZEOF(short, 2) AC_CHECK_SIZEOF(int, 4) AC_CHECK_SIZEOF(long, 4) AC_CHECK_SIZEOF(long long, 8) dnl Checks for library functions. AC_FUNC_MEMCMP AC_TYPE_SIGNAL AC_FUNC_VPRINTF AC_CHECK_FUNCS(socket strdup strerror daemon vsyslog) AC_CHECK_FUNCS(poll select endprotoent vsnprintf syslog) AC_OUTPUT(Makefile port/Makefile port/sys/Makefile) httptunnel-3.3/mkinstalldirs0000755000175000017500000000132606657300626013326 0ustar #! /bin/sh # mkinstalldirs --- make directory hierarchy # Author: Noah Friedman # Created: 1993-05-16 # Public domain # $Id: mkinstalldirs,v 1.1.1.1 1999/02/07 12:05:42 lars Exp $ errstatus=0 for file do set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` shift pathcomp= for d do pathcomp="$pathcomp$d" case "$pathcomp" in -* ) pathcomp=./$pathcomp ;; esac if test ! -d "$pathcomp"; then echo "mkdir $pathcomp" mkdir "$pathcomp" || lasterr=$? if test ! -d "$pathcomp"; then errstatus=$lasterr fi fi pathcomp="$pathcomp/" done done exit $errstatus # mkinstalldirs ends here httptunnel-3.3/README0000644000175000017500000000413106754505310011370 0ustar httptunnel creates a bidirectional virtual data path tunnelled in HTTP requests. The requests can be sent via an HTTP proxy if so desired. This can be useful for users behind restrictive firewalls. If WWW access is allowed through an HTTP proxy, it's possible to use httptunnel and, say, telnet or PPP to connect to a computer outside the firewall. If you still don't understand what this is all about, maybe you can find some useful information in the FAQ file. This program is mostly intended for technically oriented users. They should know what to do. httptunnel is free software. See COPYING for terms and conditions. If you like it, I would appreciate if you sent a post card to: Lars Brinkhoff Kopmansgatan 2 411 13 Goteborg Sweden Information and/or latest release should be available from these places: http://www.nocrew.org/software/httptunnel.html http://www.gnu.org/software/httptunnel/httptunnel.html ftp://ftp.nocrew.org/pub/nocrew/unix ftp://ftp.gnu.org/pub/httptunnel I take no responsibility for what you do with this software. It has the potential to do dangerous things, like disabling the protection you system administrator has set up for the local network. Read the DISCLAIMER file. There are two programs: hts and htc. hts is the httptunnel server and htc is the client. hts should be installed on a computer outside the HTTP proxy, and htc should be installed on your local computer. Documentation about how to use the programs should be searched in this order: source code --help output FAQ README Having said that, here's a (probably outdated) example: At host REMOTE, start hts like this: hts -F localhost:23 8888 At host LOCAL, start htc like this: htc -F 2323 -P PROXY:8000 REMOTE:8888 or, if using a buffering HTTP proxy: htc -F 2323 -P PROXY:8000 -B 48K REMOTE:8888 Now you can do this at host LOCAL: telnet localhost 2323 and you will hopefully get a login prompt from host REMOTE. See also http://metalab.unc.edu/LDP/HOWTO/mini/Firewall-Piercing.html which is a good introduction to firewall piercing. It also has describes one way to use httptunnel. httptunnel-3.3/AUTHORS0000644000175000017500000000230007246171610011553 0ustar Programming: Lars Brinkhoff Research: Stefan Berndtsson Magnus Lundström Disclaimer: Barak Pearlmutter Documentation: Teemu Hukkanen getopt_long usage: Taken from the manual page. getopt_long code: Taken from GNU fileutils-4.0. Patches: Tomas Berndtsson (Solaris) Andrew Gray (Solaris, AIX) Larry Gensch (Digital UNIX) John Bley Andrew Mobbs Krishna Swaroop Philip Craig (Windows) Jeffrey S Laing Ludovic Rousseau Shimayoshi Takao Chris Lesiak Albert Chin-A-Young Raphael Manfredi Fumitoshi UKAI Brian Somers Sampo Niskanen Testing: Philip Craig FAQ: Lars Brinkhoff Christian Brideau ... and many novice users. httptunnel-3.3/common.c0000644000175000017500000001716007246170145012153 0ustar /* common.c Copyright (C) 1999, 2000 Lars Brinkhoff. See COPYING for terms and conditions. Code common to both htc and hts. */ #include #include #include #include #include #include #include #include #include #include "tunnel.h" #include "common.h" #ifndef TRUE #define TRUE 1 #define FALSE 0 #endif #ifdef DEBUG_MODE static void log_level (int level, char *fmt0, va_list ap) { if (debug_level >= level) { struct tm *t2; char s[40]; time_t t; int i; time (&t); t2 = localtime (&t); strftime (s, sizeof s, "%Y%m%d %H%M%S ", t2); fprintf (debug_file, "%s", s); for (i = 1; i < level; i++) fprintf (debug_file, " "); vfprintf (debug_file, fmt0, ap); fprintf (debug_file, "\n"); fflush (debug_file); } } #endif void log_exit (int status) { log_notice ("exit with status = %d", status); exit (status); } void log_notice (char *fmt0, ...) { va_list ap; va_start(ap, fmt0); #ifdef DEBUG_MODE log_level (1, fmt0, ap); #else vsyslog (LOG_NOTICE, fmt0, ap); #endif va_end(ap); } void log_error (char *fmt0, ...) { va_list ap; va_start(ap, fmt0); #ifdef DEBUG_MODE log_level (2, fmt0, ap); #else vsyslog (LOG_ERROR, fmt0, ap); #endif va_end(ap); } #ifdef DEBUG_MODE void log_debug (char *fmt0, ...) { va_list ap; va_start(ap, fmt0); log_level (3, fmt0, ap); va_end(ap); } #endif #ifdef DEBUG_MODE void log_verbose (char *fmt0, ...) { va_list ap; va_start(ap, fmt0); log_level (4, fmt0, ap); va_end(ap); } #endif #ifdef DEBUG_MODE void log_annoying (char *fmt0, ...) { va_list ap; va_start (ap, fmt0); log_level (5, fmt0, ap); va_end(ap); } #endif int server_socket (struct in_addr addr, int port, int backlog) { struct sockaddr_in address; int i, s; s = socket (PF_INET, SOCK_STREAM, 0); if (s == -1) return -1; i = 1; if (setsockopt (s, SOL_SOCKET, SO_REUSEADDR, (void *)&i, sizeof i) == -1) { log_error ("server_socket: setsockopt SO_REUSEADDR: %s", strerror (errno)); } memset (&address, '\0', sizeof address); #if defined(__FreeBSD__) || defined(__OpenBSD__) address.sin_len = sizeof address; #endif address.sin_family = PF_INET; address.sin_port = htons ((short)port); address.sin_addr = addr; if (bind (s, (struct sockaddr *)&address, sizeof (address)) == -1) { close (s); return -1; } if (listen (s, (unsigned)backlog) == -1) { close (s); return -1; } return s; } int set_address (struct sockaddr_in *address, const char *host, int port) { memset (address, '\0', sizeof *address); #if defined(__FreeBSD__) || defined(__OpenBSD__) address->sin_len = sizeof *address; #endif address->sin_family = PF_INET; address->sin_port = htons ((u_short)port); address->sin_addr.s_addr = inet_addr (host); if (address->sin_addr.s_addr == INADDR_NONE) { struct hostent *ent; unsigned int ip; log_annoying ("set_address: gethostbyname (\"%s\")", host); ent = gethostbyname (host); log_annoying ("set_address: ent = %p", ent); if (ent == 0) return -1; memcpy(&address->sin_addr.s_addr, ent->h_addr, (unsigned)ent->h_length); ip = ntohl (address->sin_addr.s_addr); log_annoying ("set_address: host = %d.%d.%d.%d", ntohl (ip) >> 24, (ntohl (ip) >> 16) & 0xff, (ntohl (ip) >> 8) & 0xff, ntohl (ip) & 0xff); } return 0; } int open_device (char *device) { struct termios t; int fd; fd = open (device, O_RDWR | O_NONBLOCK); if (fd == -1) return -1; if (tcgetattr (fd, &t) == -1) { if (errno == ENOTTY || errno == EINVAL) return fd; else return -1; } t.c_iflag = 0; t.c_oflag = 0; t.c_lflag = 0; if (tcsetattr (fd, TCSANOW, &t) == -1) return -1; return fd; } #ifdef DEBUG_MODE void dump_buf (FILE *f, unsigned char *buf, size_t len) { const int N = 20; int i, j; for (i = 0; i < len;) { fputc ('[', f); for (j = 0; j < N && i + j < len; j++) fprintf (f, "%02x", buf[i + j]); for (; j < N; j++) fprintf (f, " "); fputc (']', f); fputc ('[', f); for (j = 0; j < N && i + j < len; j++) { int c = buf[i + j]; if (c < ' ' || c > 126) fputc ('.', f); else fputc (c, f); } fputc (']', f); fputc ('\n', f); i += j; } } #endif int handle_device_input (Tunnel *tunnel, int fd, int events) { unsigned char buf[10240]; ssize_t n, m; if (events & POLLIN) { n = read (fd, buf, sizeof buf); if (n == 0 || n == -1) { if (n == -1 && errno != EAGAIN) log_error ("handle_device_input: read() error: %s", strerror (errno)); return n; } #ifdef DEBUG_MODE log_annoying ("read %d bytes from device:", n); if (debug_level >= 5) dump_buf (debug_file, buf, (size_t)n); #endif m = tunnel_write (tunnel, buf, (size_t)n); log_annoying ("tunnel_write (%p, %p, %d) = %d", tunnel, buf, n, m); return m; } else if (events & POLLHUP) { log_error ("handle_device_input: POLLHUP"); sleep (5); } else if (events & POLLERR) log_error ("handle_device_input: POLLERR"); else if (events & POLLNVAL) log_error ("handle_device_input: POLLINVAL"); else log_error ("handle_device_input: none of the above"); errno = EIO; return -1; } int handle_tunnel_input (Tunnel *tunnel, int fd, int events) { unsigned char buf[10240]; ssize_t n, m; if (events & POLLIN) { n = tunnel_read (tunnel, buf, sizeof buf); if (n <= 0) { log_annoying ("handle_tunnel_input: tunnel_read() = %d\n", n); if (n == -1 && errno != EAGAIN) log_error ("handle_tunnel_input: tunnel_read() error: %s", strerror (errno)); return n; } #ifdef DEBUG_MODE log_annoying ("read %d bytes from tunnel:", n); if (debug_level >= 5) dump_buf (debug_file, buf, (size_t)n); #endif /* If fd == 0, then we are using --stdin-stdout so write to stdout, * not fd. */ m = write_all (fd ? fd : 0, buf, (size_t)n); log_annoying ("write_all (%d, %p, %d) = %d", fd ? fd : 1, buf, n, m); return m; } else if (events & POLLHUP) log_error ("handle_device_input: POLLHUP"); else if (events & POLLERR) log_error ("handle_device_input: PULLERR"); else if (events & POLLNVAL) log_error ("handle_device_input: PULLINVAL"); else log_error ("handle_device_input: none of the above"); errno = EIO; return -1; } void name_and_port (const char *nameport, char **name, int *port) { char *p; *name = strdup (nameport); if (*name == NULL) { fprintf (stderr, "Out of memory\n"); exit (1); } p = strchr (*name, ':'); if (p != NULL) { *port = atoi (p + 1); *p = '\0'; } } int atoi_with_postfix (const char *s_) { char *s = strdup (s_); int n = strlen (s); int factor = 1; int x; if (s == NULL) { fprintf (stderr, "Out of memory\n"); exit (1); } switch (s[n - 1]) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': break; case 'k': case 'K': factor = 1024; break; case 'M': factor = 1024 * 1024; break; case 'G': factor = 1024 * 1024 * 1024; break; default: fprintf (stderr, "Unknown postfix: %c\n", s[n - 1]); exit (1); } if (factor != 1) s[n - 1] = '\0'; x = factor * atoi (s); free (s); return x; } #ifdef DEBUG_MODE RETSIGTYPE log_sigpipe (int sig) { log_debug ("caught SIGPIPE"); signal (SIGPIPE, log_sigpipe); } #endif httptunnel-3.3/common.h0000644000175000017500000000675407137262577012201 0ustar /* common.h Copyright (C) 1999 Lars Brinkhoff. See COPYING for terms and conditions. */ #ifndef COMMON_H #define COMMON_H #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include "tunnel.h" #define DEFAULT_HOST_PORT 8888 #define DEFAULT_CONTENT_LENGTH (100 * 1024) /* bytes */ #define DEFAULT_KEEP_ALIVE 5 /* seconds */ #define DEFAULT_MAX_CONNECTION_AGE 300 /* seconds */ #define BUG_REPORT_EMAIL "bug-httptunnel@gnu.org" #ifndef TRUE #define TRUE 1 #define FALSE 0 #endif #if defined (LOG_ERR) && !defined (LOG_ERROR) #define LOG_ERROR LOG_ERR #endif extern int debug_level; extern FILE *debug_file; extern void log_exit (int status); extern void log_notice (char *fmt0, ...); extern void log_error (char *fmt0, ...); #ifdef DEBUG_MODE extern void log_debug (char *fmt0, ...); extern void log_verbose (char *fmt0, ...); extern void log_annoying (char *fmt0, ...); #else static inline void log_debug () {} static inline void log_verbose () {} static inline void log_annoying () {} #endif extern int server_socket (struct in_addr addr, int port, int backlog); extern int set_address (struct sockaddr_in *address, const char *host, int port); extern int open_device (char *device); extern int handle_device_input (Tunnel *tunnel, int fd, int events); extern int handle_tunnel_input (Tunnel *tunnel, int fd, int events); extern void name_and_port (const char *nameport, char **name, int *port); extern int atoi_with_postfix (const char *s_); extern RETSIGTYPE log_sigpipe (int); void dump_buf (FILE *f, unsigned char *buf, size_t len); static inline ssize_t read_all (int fd, void *buf, size_t len) { ssize_t n, m, r; long flags; char *rbuf = buf; flags = fcntl (fd, F_GETFL); fcntl (fd, F_SETFL, flags & ~O_NONBLOCK); r = len; for (n = 0; n < len; n += m) { log_annoying ("read (%d, %p, %d) ...", fd, rbuf + n, len - n); m = read (fd, rbuf + n, len - n); log_annoying ("... = %d", m); if (m == 0) { r = 0; break; } else if (m == -1) { if (errno != EAGAIN) { r = -1; break; } else m = 0; } } fcntl (fd, F_SETFL, flags); return r; } static inline ssize_t write_all (int fd, void *data, size_t len) { ssize_t n, m; char *wdata = data; for (n = 0; n < len; n += m) { log_annoying ("write (%d, %p, %d) ...", fd, wdata + n, len - n); m = write (fd, wdata + n, len - n); log_annoying ("... = %d", m); if (m == 0) return 0; else if (m == -1) { if (errno != EAGAIN) return -1; else m = 0; } } return len; } static inline int do_connect (struct sockaddr_in *address) { int fd; fd = socket (AF_INET, SOCK_STREAM, 0); if (fd == -1) return -1; if (connect (fd, (struct sockaddr *)address, sizeof (struct sockaddr_in)) == -1) { close (fd); return -1; } return fd; } static inline void handle_input (const char *type, Tunnel *tunnel, int fd, int events, int (*handler)(Tunnel *tunnel, int fd, int events), int *closed) { if (events) { ssize_t n; n = handler (tunnel, fd, events); if (n == 0 || (n == -1 && errno != EAGAIN)) { if (n == 0) log_debug ("%s closed", type); else log_error ("%s read error: %s", type, strerror (errno)); *closed = TRUE; } } } #endif /* COMMON_H */ httptunnel-3.3/http.c0000644000175000017500000004236307132603414011637 0ustar /* http.c Copyright (C) 1999 Lars Brinkhoff. See COPYING for terms and conditions. bug alert: parse_header() doesn't handle header fields that are extended over multiple lines. */ #include #include #include #include #include "http.h" #include "common.h" static inline ssize_t http_method (int fd, Http_destination *dest, Http_method method, ssize_t length) { char str[1024]; /* FIXME: possible buffer overflow */ Http_request *request; ssize_t n; if (fd == -1) { log_error ("http_method: fd == -1"); return -1; } n = 0; if (dest->proxy_name != NULL) n = sprintf (str, "http://%s:%d", dest->host_name, dest->host_port); sprintf (str + n, "/index.html?crap=%ld", time (NULL)); request = http_create_request (method, str, 1, 1); if (request == NULL) return -1; sprintf (str, "%s:%d", dest->host_name, dest->host_port); http_add_header (&request->header, "Host", str); if (length >= 0) { sprintf (str, "%d", length); http_add_header (&request->header, "Content-Length", str); } http_add_header (&request->header, "Connection", "close"); if (dest->proxy_authorization) { http_add_header (&request->header, "Proxy-Authorization", dest->proxy_authorization); } if (dest->user_agent) { http_add_header (&request->header, "User-Agent", dest->user_agent); } n = http_write_request (fd, request); http_destroy_request (request); return n; } ssize_t http_get (int fd, Http_destination *dest) { return http_method (fd, dest, HTTP_GET, -1); } ssize_t http_put (int fd, Http_destination *dest, size_t length) { return http_method (fd, dest, HTTP_PUT, (ssize_t)length); } ssize_t http_post (int fd, Http_destination *dest, size_t length) { return http_method (fd, dest, HTTP_POST, (ssize_t)length); } int http_error_to_errno (int err) { /* Error codes taken from RFC2068. */ switch (err) { case -1: /* system error */ return errno; case -200: /* OK */ case -201: /* Created */ case -202: /* Accepted */ case -203: /* Non-Authoritative Information */ case -204: /* No Content */ case -205: /* Reset Content */ case -206: /* Partial Content */ return 0; case -400: /* Bad Request */ log_error ("http_error_to_errno: 400 bad request"); return EIO; case -401: /* Unauthorized */ log_error ("http_error_to_errno: 401 unauthorized"); return EACCES; case -403: /* Forbidden */ log_error ("http_error_to_errno: 403 forbidden"); return EACCES; case -404: /* Not Found */ log_error ("http_error_to_errno: 404 not found"); return ENOENT; case -411: /* Length Required */ log_error ("http_error_to_errno: 411 length required"); return EIO; case -413: /* Request Entity Too Large */ log_error ("http_error_to_errno: 413 request entity too large"); return EIO; case -505: /* HTTP Version Not Supported */ log_error ("http_error_to_errno: 413 HTTP version not supported"); return EIO; case -100: /* Continue */ case -101: /* Switching Protocols */ case -300: /* Multiple Choices */ case -301: /* Moved Permanently */ case -302: /* Moved Temporarily */ case -303: /* See Other */ case -304: /* Not Modified */ case -305: /* Use Proxy */ case -402: /* Payment Required */ case -405: /* Method Not Allowed */ case -406: /* Not Acceptable */ case -407: /* Proxy Autentication Required */ case -408: /* Request Timeout */ case -409: /* Conflict */ case -410: /* Gone */ case -412: /* Precondition Failed */ case -414: /* Request-URI Too Long */ case -415: /* Unsupported Media Type */ case -500: /* Internal Server Error */ case -501: /* Not Implemented */ case -502: /* Bad Gateway */ case -503: /* Service Unavailable */ case -504: /* Gateway Timeout */ log_error ("http_error_to_errno: HTTP error %d", err); return EIO; default: log_error ("http_error_to_errno: unknown error %d", err); return EIO; } } static Http_method http_string_to_method (const char *method, size_t n) { if (strncmp (method, "GET", n) == 0) return HTTP_GET; if (strncmp (method, "PUT", n) == 0) return HTTP_PUT; if (strncmp (method, "POST", n) == 0) return HTTP_POST; if (strncmp (method, "OPTIONS", n) == 0) return HTTP_OPTIONS; if (strncmp (method, "HEAD", n) == 0) return HTTP_HEAD; if (strncmp (method, "DELETE", n) == 0) return HTTP_DELETE; if (strncmp (method, "TRACE", n) == 0) return HTTP_TRACE; return -1; } static const char * http_method_to_string (Http_method method) { switch (method) { case HTTP_GET: return "GET"; case HTTP_PUT: return "PUT"; case HTTP_POST: return "POST"; case HTTP_OPTIONS: return "OPTIONS"; case HTTP_HEAD: return "HEAD"; case HTTP_DELETE: return "DELETE"; case HTTP_TRACE: return "TRACE"; } return "(uknown)"; } static ssize_t read_until (int fd, int ch, unsigned char **data) { unsigned char *buf, *buf2; ssize_t n, len, buf_size; *data = NULL; buf_size = 100; buf = malloc (buf_size); if (buf == NULL) { log_error ("read_until: out of memory"); return -1; } len = 0; while ((n = read_all (fd, buf + len, 1)) == 1) { if (buf[len++] == ch) break; if (len + 1 == buf_size) { buf_size *= 2; buf2 = realloc (buf, buf_size); if (buf2 == NULL) { log_error ("read_until: realloc failed"); free (buf); return -1; } buf = buf2; } } if (n <= 0) { free (buf); if (n == 0) log_error ("read_until: closed"); else log_error ("read_until: read error: %s", strerror (errno)); return n; } /* Shrink to minimum size + 1 in case someone wants to add a NUL. */ buf2 = realloc (buf, len + 1); if (buf2 == NULL) log_error ("read_until: realloc: shrink failed"); /* not fatal */ else buf = buf2; *data = buf; return len; } static inline Http_header * http_alloc_header (const char *name, const char *value) { Http_header *header; header = malloc (sizeof (Http_header)); if (header == NULL) return NULL; header->name = header->value = NULL; header->name = strdup (name); header->value = strdup (value); if (name == NULL || value == NULL) { if (name == NULL) free ((char *)name); if (value == NULL) free ((char *)value); free (header); return NULL; } return header; } Http_header * http_add_header (Http_header **header, const char *name, const char *value) { Http_header *new_header; new_header = http_alloc_header (name, value); if (new_header == NULL) return NULL; new_header->next = NULL; while (*header) header = &(*header)->next; *header = new_header; return new_header; } static ssize_t parse_header (int fd, Http_header **header) { unsigned char buf[2]; unsigned char *data; Http_header *h; size_t len; ssize_t n; *header = NULL; n = read_all (fd, buf, 2); if (n <= 0) return n; if (buf[0] == '\r' && buf[1] == '\n') return n; h = malloc (sizeof (Http_header)); if (h == NULL) { log_error ("parse_header: malloc failed"); return -1; } *header = h; h->name = NULL; h->value = NULL; n = read_until (fd, ':', &data); if (n <= 0) return n; data = realloc (data, n + 2); if (data == NULL) { log_error ("parse_header: realloc failed"); return -1; } memmove (data + 2, data, n); memcpy (data, buf, 2); n += 2; data[n - 1] = 0; h->name = data; len = n; n = read_until (fd, '\r', &data); if (n <= 0) return n; data[n - 1] = 0; h->value = data; len += n; n = read_until (fd, '\n', &data); if (n <= 0) return n; free (data); if (n != 1) { log_error ("parse_header: invalid line ending"); return -1; } len += n; log_verbose ("parse_header: %s:%s", h->name, h->value); n = parse_header (fd, &h->next); if (n <= 0) return n; len += n; return len; } static ssize_t http_write_header (int fd, Http_header *header) { ssize_t n = 0, m; if (header == NULL) return write_all (fd, "\r\n", 2); m = write_all (fd, (void *)header->name, strlen (header->name)); if (m == -1) { return -1; } n += m; m = write_all (fd, ": ", 2); if (m == -1) { return -1; } n += m; m = write_all (fd, (void *)header->value, strlen (header->value)); if (m == -1) { return -1; } n += m; m = write_all (fd, "\r\n", 2); if (m == -1) { return -1; } n += m; m = http_write_header (fd, header->next); if (m == -1) { return -1; } n += m; return n; } static void http_destroy_header (Http_header *header) { if (header == NULL) return; http_destroy_header (header->next); if (header->name) free ((char *)header->name); if (header->value) free ((char *)header->value); free (header); } static inline Http_response * http_allocate_response (const char *status_message) { Http_response *response; response = malloc (sizeof (Http_response)); if (response == NULL) return NULL; response->status_message = strdup (status_message); if (response->status_message == NULL) { free (response); return NULL; } return response; } Http_response * http_create_response (int major_version, int minor_version, int status_code, const char *status_message) { Http_response *response; response = http_allocate_response (status_message); if (response == NULL) return NULL; response->major_version = major_version; response->minor_version = minor_version; response->status_code = status_code; response->header = NULL; return response; } ssize_t http_parse_response (int fd, Http_response **response_) { Http_response *response; unsigned char *data; size_t len; ssize_t n; *response_ = NULL; response = malloc (sizeof (Http_response)); if (response == NULL) { log_error ("http_parse_response: out of memory"); return -1; } response->major_version = -1; response->minor_version = -1; response->status_code = -1; response->status_message = NULL; response->header = NULL; n = read_until (fd, '/', &data); if (n <= 0) { free (response); return n; } else if (n != 5 || memcmp (data, "HTTP", 4) != 0) { log_error ("http_parse_response: expected \"HTTP\""); free (data); free (response); return -1; } free (data); len = n; n = read_until (fd, '.', &data); if (n <= 0) { free (response); return n; } data[n - 1] = 0; response->major_version = atoi (data); log_verbose ("http_parse_response: major version = %d", response->major_version); free (data); len += n; n = read_until (fd, ' ', &data); if (n <= 0) { free (response); return n; } data[n - 1] = 0; response->minor_version = atoi (data); log_verbose ("http_parse_response: minor version = %d", response->minor_version); free (data); len += n; n = read_until (fd, ' ', &data); if (n <= 0) { free (response); return n; } data[n - 1] = 0; response->status_code = atoi (data); log_verbose ("http_parse_response: status code = %d", response->status_code); free (data); len += n; n = read_until (fd, '\r', &data); if (n <= 0) { free (response); return n; } data[n - 1] = 0; response->status_message = data; log_verbose ("http_parse_response: status message = \"%s\"", response->status_message); len += n; n = read_until (fd, '\n', &data); if (n <= 0) { http_destroy_response (response); return n; } free (data); if (n != 1) { log_error ("http_parse_request: invalid line ending"); http_destroy_response (response); return -1; } len += n; n = parse_header (fd, &response->header); if (n <= 0) { http_destroy_response (response); return n; } len += n; *response_ = response; return len; } void http_destroy_response (Http_response *response) { if (response->status_message) free ((char *)response->status_message); http_destroy_header (response->header); free (response); } static inline Http_request * http_allocate_request (const char *uri) { Http_request *request; request = malloc (sizeof (Http_request)); if (request == NULL) return NULL; request->uri = strdup (uri); if (request->uri == NULL) { free (request); return NULL; } return request; } Http_request * http_create_request (Http_method method, const char *uri, int major_version, int minor_version) { Http_request *request; request = http_allocate_request (uri); if (request == NULL) return NULL; request->method = method; request->major_version = major_version; request->minor_version = minor_version; request->header = NULL; return request; } ssize_t http_parse_request (int fd, Http_request **request_) { Http_request *request; unsigned char *data; size_t len; ssize_t n; *request_ = NULL; request = malloc (sizeof (Http_request)); if (request == NULL) { log_error ("http_parse_request: out of memory"); return -1; } request->method = -1; request->uri = NULL; request->major_version = -1; request->minor_version = -1; request->header = NULL; n = read_until (fd, ' ', &data); if (n <= 0) { free (request); return n; } request->method = http_string_to_method (data, n - 1); if (request->method == -1) { log_error ("http_parse_request: expected an HTTP method"); free (data); free (request); return -1; } data[n - 1] = 0; log_verbose ("http_parse_request: method = \"%s\"", data); free (data); len = n; n = read_until (fd, ' ', &data); if (n <= 0) { free (request); return n; } data[n - 1] = 0; request->uri = data; len += n; log_verbose ("http_parse_request: uri = \"%s\"", request->uri); n = read_until (fd, '/', &data); if (n <= 0) { http_destroy_request (request); return n; } else if (n != 5 || memcmp (data, "HTTP", 4) != 0) { log_error ("http_parse_request: expected \"HTTP\""); free (data); http_destroy_request (request); return -1; } free (data); len = n; n = read_until (fd, '.', &data); if (n <= 0) { http_destroy_request (request); return n; } data[n - 1] = 0; request->major_version = atoi (data); log_verbose ("http_parse_request: major version = %d", request->major_version); free (data); len += n; n = read_until (fd, '\r', &data); if (n <= 0) { http_destroy_request (request); return n; } data[n - 1] = 0; request->minor_version = atoi (data); log_verbose ("http_parse_request: minor version = %d", request->minor_version); free (data); len += n; n = read_until (fd, '\n', &data); if (n <= 0) { http_destroy_request (request); return n; } free (data); if (n != 1) { log_error ("http_parse_request: invalid line ending"); http_destroy_request (request); return -1; } len += n; n = parse_header (fd, &request->header); if (n <= 0) { http_destroy_request (request); return n; } len += n; *request_ = request; return len; } ssize_t http_write_request (int fd, Http_request *request) { char str[1024]; /* FIXME: buffer overflow */ ssize_t n = 0; size_t m; m = sprintf (str, "%s %s HTTP/%d.%d\r\n", http_method_to_string (request->method), request->uri, request->major_version, request->minor_version); m = write_all (fd, str, m); log_verbose ("http_write_request: %s", str); if (m == -1) { log_error ("http_write_request: write error: %s", strerror (errno)); return -1; } n += m; m = http_write_header (fd, request->header); if (m == -1) { return -1; } n += m; return n; } void http_destroy_request (Http_request *request) { if (request->uri) free ((char *)request->uri); http_destroy_header (request->header); free (request); } static Http_header * http_header_find (Http_header *header, const char *name) { if (header == NULL) return NULL; if (strcmp (header->name, name) == 0) return header; return http_header_find (header->next, name); } const char * http_header_get (Http_header *header, const char *name) { Http_header *h; h = http_header_find (header, name); if (h == NULL) return NULL; return h->value; } #if 0 void http_header_set (Http_header **header, const char *name, const char *value) { Http_header *h; size_t n; char *v; n = strlen (value); v = malloc (n + 1); if (v == NULL) fail; memcpy (v, value, n + 1); h = http_header_find (*header, name); if (h == NULL) { Http_header *h2; h2 = malloc (sizeof (Http_header)); if (h2 == NULL) fail; n = strlen (name); h2->name = malloc (strlen (name) + 1); if (h2->name == NULL) fail; memcpy (h2->name, name, n + 1); h2->value = v; h2->next = *header; *header = h2; return NULL; } else { free (h->value); h->value = v; } } #endif httptunnel-3.3/hts.10000644000175000017500000000256006752256162011402 0ustar .TH HTS 1 .SH NAME hts \- httptunnel server .SH SYNOPSIS .B hts .I "[options] [port]" .SH "DESCRIPTION" This manual page briefly documents the .BR hts command. .PP .B hts listens for incoming httptunnel connections at PORT (default port is 8888). When a connection is made, I/O is redirected to the destination specified by the --device or --forward-port switch. .SH OPTIONS The program follows the usual GNU command line syntax, with long options starting with two dashes (`-'). A summary of options are included below. .TP .B \-h, \-\-help Show summary of options. .TP .B \-c, \-\-content-length BYTES use HTTP PUT requests of BYTES size (k, M, and G postfixes recognized) .TP .B \-d, \-\-device DEVICE use DEVICE for input and output .TP .B \-F, \-\-forward\-port HOST:PORT connect to PORT at HOST and use it for input and output .TP .B \-k, \-\-keep\-alive SECONDS send keepalive bytes every SECONDS seconds (default is 5) .TP .B \-M, \-\-max\-connection\-age SEC maximum time a connection will stay open is SEC seconds (default is 300) .TP .B \-S, \-\-strict\-content\-length always write Content-Length bytes in requests .TP .B \-V, \-\-version output version information and exit .TP .B \-p, \-\-pid\-file LOCATION write a PID file to LOCATION .SH AUTHOR This manual page was contributed by Teemu Hukkanen , and was originally written for the Debian GNU/Linux system. httptunnel-3.3/acconfig.h0000644000175000017500000000032406674677702012452 0ustar /* Enable debugging mode. */ #undef DEBUG_MODE @BOTTOM@ /* Define to 'int' if doesn't define. */ #undef socklen_t /* Define to 0xffffffff if doesn't define. */ #undef INADDR_NONE httptunnel-3.3/COPYING0000644000175000017500000004311006657300626011550 0ustar GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 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 Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. httptunnel-3.3/tunnel.c0000644000175000017500000007627507153666322012210 0ustar /* tunnel.c Copyright (C) 1999, 2000 Lars Brinkhoff. See COPYING for terms and conditions. See tunnel.h for some documentation about the programming interface. */ #include #include #include #include #include #include #include #include #include #include "http.h" #include "tunnel.h" #include "common.h" /* #define IO_COUNT_HTTP_HEADER */ /* #define USE_SHUTDOWN */ #define READ_TRAIL_TIMEOUT (1 * 1000) /* milliseconds */ #define ACCEPT_TIMEOUT 10 /* seconds */ #define min(a, b) ((a) < (b) ? (a) : (b)) #define TUNNEL_IN 1 #define TUNNEL_OUT 2 #if SIZEOF_CHAR == 1 typedef unsigned char Request; #else #error "FIXME: Can't handle SIZEOF_CHAR != 1" #endif #if SIZEOF_SHORT == 2 typedef unsigned short Length; #else #error "FIXME: Can't handle SIZEOF_SHORT != 2" #endif enum tunnel_request { TUNNEL_SIMPLE = 0x40, TUNNEL_OPEN = 0x01, TUNNEL_DATA = 0x02, TUNNEL_PADDING = 0x03, TUNNEL_ERROR = 0x04, TUNNEL_PAD1 = TUNNEL_SIMPLE | 0x05, TUNNEL_CLOSE = TUNNEL_SIMPLE | 0x06, TUNNEL_DISCONNECT = TUNNEL_SIMPLE | 0x07 }; static inline const char * REQ_TO_STRING (Request request) { switch (request) { case TUNNEL_OPEN: return "TUNNEL_OPEN"; case TUNNEL_DATA: return "TUNNEL_DATA"; case TUNNEL_PADDING: return "TUNNEL_PADDING"; case TUNNEL_ERROR: return "TUNNEL_ERROR"; case TUNNEL_PAD1: return "TUNNEL_PAD1"; case TUNNEL_CLOSE: return "TUNNEL_CLOSE"; case TUNNEL_DISCONNECT: return "TUNNEL_DISCONNECT"; default: return "(unknown)"; } } struct tunnel { int in_fd, out_fd; int server_socket; Http_destination dest; struct sockaddr_in address; size_t bytes; size_t content_length; char buf[65536]; char *buf_ptr; size_t buf_len; int padding_only; size_t in_total_raw; size_t in_total_data; size_t out_total_raw; size_t out_total_data; time_t out_connect_time; int strict_content_length; int keep_alive; int max_connection_age; }; static const size_t sizeof_header = sizeof (Request) + sizeof (Length); static inline int tunnel_is_disconnected (Tunnel *tunnel) { return tunnel->out_fd == -1; } static inline int tunnel_is_connected (Tunnel *tunnel) { return !tunnel_is_disconnected (tunnel); } static inline int tunnel_is_server (Tunnel *tunnel) { return tunnel->server_socket != -1; } static inline int tunnel_is_client (Tunnel *tunnel) { return !tunnel_is_server (tunnel); } #if 1 static int get_proto_number (const char *name) { struct protoent *p; int number; p = getprotobyname (name); if (p == NULL) number = -1; else number = p->p_proto; endprotoent (); return number; } #endif static int tunnel_in_setsockopts (int fd) { #ifdef SO_RCVLOWAT int tcp = get_proto_number ("tcp"); if (tcp != -1) { int i, n; i = 1; if (setsockopt (fd, tcp, SO_RCVLOWAT, (void *)&i, sizeof i) == -1) { log_debug ("tunnel_in_setsockopts: non-fatal SO_RCVLOWAT error: %s", strerror (errno)); } n = sizeof i; getsockopt (fd, tcp, SO_RCVLOWAT, (void *)&i, &n); log_debug ("tunnel_out_setsockopts: SO_RCVLOWAT: %d", i); } #endif /* SO_RCVLOWAT */ return 0; } static int tunnel_out_setsockopts (int fd) { #ifdef SO_SNDLOWAT { int tcp = get_proto_number ("tcp"); int i, n; if (tcp != -1) { i = 1; if (setsockopt (fd, tcp, SO_SNDLOWAT, (void *)&i, sizeof i) == -1) { log_debug ("tunnel_out_setsockopts: " "non-fatal SO_SNDLOWAT error: %s", strerror (errno)); } n = sizeof i; getsockopt (fd, tcp, SO_SNDLOWAT, (void *)&i, &n); log_debug ("tunnel_out_setsockopts: non-fatal SO_SNDLOWAT: %d", i); } } #endif /* SO_SNDLOWAT */ #ifdef SO_LINGER { struct linger l; int n; l.l_onoff = 1; l.l_linger = 20 * 100; /* linger for 20 seconds */ if (setsockopt (fd, SOL_SOCKET, SO_LINGER, (void *)&l, sizeof l) == -1) { log_debug ("tunnel_out_setsockopts: non-fatal SO_LINGER error: %s", strerror (errno)); } n = sizeof l; getsockopt (fd, SOL_SOCKET, SO_LINGER, (void *)&l, &n); log_debug ("tunnel_out_setsockopts: SO_LINGER: onoff=%d linger=%d", l.l_onoff, l.l_linger); } #endif /* SO_LINGER */ #ifdef TCP_NODELAY { int tcp = get_proto_number ("tcp"); int i, n; if (tcp != -1) { i = 1; if (setsockopt (fd, tcp, TCP_NODELAY, (void *)&i, sizeof i) == -1) { log_debug ("tunnel_out_setsockopts: " "non-fatal TCP_NODELAY error: %s", strerror (errno)); } n = sizeof i; getsockopt (fd, tcp, TCP_NODELAY, (void *)&i, &n); log_debug ("tunnel_out_setsockopts: non-fatal TCP_NODELAY: %d", i); } } #else #ifdef SO_SNDBUF { int i, n; i = 0; if (setsockopt (fd, SOL_SOCKET, SO_SNDBUF, (void *)&i, sizeof i) == -1) { log_debug ("tunnel_out_setsockopts: non-fatal SO_SNDBUF error: %s", strerror (errno)); } n = sizeof i; getsockopt (fd, SOL_SOCKET, SO_SNDBUF, (void *)&i, &n); log_debug ("tunnel_out_setsockopts: SO_SNDBUF: %d", i); } #endif /* SO_SNDBUF */ #endif /* TCP_NODELAY */ #ifdef SO_KEEPALIVE { int i, n; i = 1; if (setsockopt (fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&i, sizeof i) == -1) { log_debug ("tunnel_out_setsockopts: non-fatal SO_KEEPALIVE error: %s", strerror (errno)); } n = sizeof i; getsockopt (fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&i, &n); log_debug ("tunnel_out_setsockopts: SO_KEEPALIVE: %d", i); } #endif /* SO_KEEPALIVE */ return 0; } static void tunnel_out_disconnect (Tunnel *tunnel) { if (tunnel_is_disconnected (tunnel)) return; #ifdef DEBUG_MODE if (tunnel_is_client (tunnel) && tunnel->bytes != tunnel->content_length + 1) log_error ("tunnel_out_disconnect: warning: " "bytes=%d != content_length=%d", tunnel->bytes, tunnel->content_length + 1); #endif close (tunnel->out_fd); tunnel->out_fd = -1; tunnel->bytes = 0; tunnel->buf_ptr = tunnel->buf; tunnel->buf_len = 0; log_debug ("tunnel_out_disconnect: output disconnected"); } static void tunnel_in_disconnect (Tunnel *tunnel) { if (tunnel->in_fd == -1) return; close (tunnel->in_fd); tunnel->in_fd = -1; log_debug ("tunnel_in_disconnect: input disconnected"); } static int tunnel_out_connect (Tunnel *tunnel) { ssize_t n; if (tunnel_is_connected (tunnel)) { log_debug ("tunnel_out_connect: already connected"); tunnel_out_disconnect (tunnel); } tunnel->out_fd = do_connect (&tunnel->address); if (tunnel->out_fd == -1) { log_error ("tunnel_out_connect: do_connect (%d.%d.%d.%d:%u) error: %s", ntohl (tunnel->address.sin_addr.s_addr) >> 24, (ntohl (tunnel->address.sin_addr.s_addr) >> 16) & 0xff, (ntohl (tunnel->address.sin_addr.s_addr) >> 8) & 0xff, ntohl (tunnel->address.sin_addr.s_addr) & 0xff, ntohs (tunnel->address.sin_port), strerror (errno)); return -1; } tunnel_out_setsockopts (tunnel->out_fd); #ifdef USE_SHUTDOWN shutdown (tunnel->out_fd, 0); #endif /* + 1 to allow for TUNNEL_DISCONNECT */ n = http_post (tunnel->out_fd, &tunnel->dest, tunnel->content_length + 1); if (n == -1) return -1; #ifdef IO_COUNT_HTTP_HEADER tunnel->out_total_raw += n; log_annoying ("tunnel_out_connect: out_total_raw = %u", tunnel->out_total_raw); #endif tunnel->bytes = 0; tunnel->buf_ptr = tunnel->buf; tunnel->buf_len = 0; tunnel->padding_only = TRUE; time (&tunnel->out_connect_time); log_debug ("tunnel_out_connect: output connected"); return 0; } static int tunnel_in_connect (Tunnel *tunnel) { Http_response *response; ssize_t n; log_verbose ("tunnel_in_connect()"); if (tunnel->in_fd != -1) { log_error ("tunnel_in_connect: already connected"); return -1; } tunnel->in_fd = do_connect (&tunnel->address); if (tunnel->in_fd == -1) { log_error ("tunnel_in_connect: do_connect() error: %s", strerror (errno)); return -1; } tunnel_in_setsockopts (tunnel->in_fd); if (http_get (tunnel->in_fd, &tunnel->dest) == -1) return -1; #ifdef USE_SHUTDOWN if (shutdown (tunnel->in_fd, 1) == -1) { log_error ("tunnel_in_connect: shutdown() error: %s", strerror (errno)); return -1; } #endif n = http_parse_response (tunnel->in_fd, &response); if (n <= 0) { if (n == 0) log_error ("tunnel_in_connect: no response; peer " "closed connection"); else log_error ("tunnel_in_connect: no response; error: %s", strerror (errno)); } else if (response->major_version != 1 || (response->minor_version != 1 && response->minor_version != 0)) { log_error ("tunnel_in_connect: unknown HTTP version: %d.%d", response->major_version, response->minor_version); n = -1; } else if (response->status_code != 200) { log_error ("tunnel_in_connect: HTTP error %d", response->status_code); errno = http_error_to_errno (-response->status_code); n = -1; } if (response) http_destroy_response (response); if (n > 0) { #ifdef IO_COUNT_HTTP_HEADER tunnel->in_total_raw += n; log_annoying ("tunnel_in_connect: in_total_raw = %u", tunnel->in_total_raw); #endif } else { return n; } log_debug ("tunnel_in_connect: input connected"); return 1; } static inline ssize_t tunnel_write_data (Tunnel *tunnel, void *data, size_t length) { if (write_all (tunnel->out_fd, data, length) == -1) { log_error ("tunnel_write_data: write error: %s", strerror (errno)); return -1; } tunnel->bytes += length; return length; } static int tunnel_write_request (Tunnel *tunnel, Request request, void *data, Length length) { if (tunnel->bytes + sizeof request + (data ? sizeof length + length : 0) > tunnel->content_length) tunnel_padding (tunnel, tunnel->content_length - tunnel->bytes); #if 1 /* FIXME: this is a kludge */ { time_t t; time (&t); if (tunnel_is_client (tunnel) && tunnel_is_connected (tunnel) && t - tunnel->out_connect_time > tunnel->max_connection_age) { char c = TUNNEL_DISCONNECT; log_debug ("tunnel_write_request: connection > %d seconds old", tunnel->max_connection_age); if (tunnel->strict_content_length) { int l = tunnel->content_length - tunnel->bytes - 1; log_debug ("tunnel_write_request: write padding (%d bytes)", tunnel->content_length - tunnel->bytes - 1); if (l > 3) { char c; short s; int i; c = TUNNEL_PADDING; tunnel_write_data (tunnel, &c, sizeof c); s = htons(l-2); tunnel_write_data (tunnel, &s, sizeof s); l -= 2; c = 0; for (i=0; ipadding_only = FALSE; if (tunnel_write_data (tunnel, &request, sizeof request) == -1) { if (errno != EPIPE) return -1; tunnel_out_disconnect (tunnel); if (tunnel_is_client (tunnel)) tunnel_out_connect (tunnel); else { log_error ("tunnel_write_request: couldn't write request: " "output is disconnected"); errno = EIO; return -1; } /* return tunnel_write_request (tunnel, request, data, length); */ if (tunnel_write_data (tunnel, &request, sizeof request) == -1) return -1; } if (data) { Length network_length = htons ((short)length); if (tunnel_write_data (tunnel, &network_length, sizeof network_length) == -1) return -1; #ifdef DEBUG_MODE if (request == TUNNEL_DATA && debug_level >= 5) { log_annoying ("tunnel_write_request: TUNNEL_DATA:"); dump_buf (debug_file, data, (size_t)length); } #endif if (tunnel_write_data (tunnel, data, (size_t)length) == -1) return -1; } if (data) { tunnel->out_total_raw += 3 + length; if (request == TUNNEL_DATA) log_verbose ("tunnel_write_request: %s (%d)", REQ_TO_STRING (request), length); else log_debug ("tunnel_write_request: %s (%d)", REQ_TO_STRING (request), length); } else { tunnel->out_total_raw += 1; log_debug ("tunnel_write_request: %s", REQ_TO_STRING (request)); } log_annoying ("tunnel_write_data: out_total_raw = %u", tunnel->out_total_raw); #ifdef DEBUG_MODE if (tunnel->bytes > tunnel->content_length) log_debug ("tunnel_write_request: tunnel->bytes > tunnel->content_length"); #endif if (tunnel->bytes >= tunnel->content_length) { char c = TUNNEL_DISCONNECT; tunnel_write_data (tunnel, &c, sizeof c); tunnel_out_disconnect (tunnel); #if 0 if (tunnel_is_server (tunnel)) tunnel_accept (tunnel); #endif } return 0; } int tunnel_connect (Tunnel *tunnel) { char auth_data[1] = { 42 }; /* dummy data, not used by server */ log_verbose ("tunnel_connect()"); if (tunnel_is_connected (tunnel)) { log_error ("tunnel_connect: already connected"); errno = EINVAL; return -1; } if (tunnel_write_request (tunnel, TUNNEL_OPEN, auth_data, sizeof auth_data) == -1) return -1; if (tunnel_in_connect (tunnel) <= 0) return -1; return 0; } static inline int tunnel_write_or_padding (Tunnel *tunnel, Request request, void *data, size_t length) { static char padding[65536]; size_t n, remaining; char *wdata = data; for (remaining = length; remaining > 0; remaining -= n, wdata += n) { if (tunnel->bytes + remaining > tunnel->content_length - sizeof_header && tunnel->content_length - tunnel->bytes > sizeof_header) n = tunnel->content_length - sizeof_header - tunnel->bytes; else if (remaining > tunnel->content_length - sizeof_header) n = tunnel->content_length - sizeof_header; else n = remaining; if (n > 65535) n = 65535; if (request == TUNNEL_PADDING) { if (n + sizeof_header > remaining) n = remaining - sizeof_header; if (tunnel_write_request (tunnel, request, padding, n) == -1) break; n += sizeof_header; } else { if (tunnel_write_request (tunnel, request, wdata, n) == -1) break; } } return length - remaining; } ssize_t tunnel_write (Tunnel *tunnel, void *data, size_t length) { ssize_t n; n = tunnel_write_or_padding (tunnel, TUNNEL_DATA, data, length); tunnel->out_total_data += length; log_verbose ("tunnel_write: out_total_data = %u", tunnel->out_total_data); return n; } ssize_t tunnel_padding (Tunnel *tunnel, size_t length) { if (length < sizeof_header + 1) { int i; for (i = 0; i < length; i++) tunnel_write_request (tunnel, TUNNEL_PAD1, NULL, 0); return length; } return tunnel_write_or_padding (tunnel, TUNNEL_PADDING, NULL, length); } int tunnel_close (Tunnel *tunnel) { struct pollfd p; char buf[10240]; ssize_t n; if (tunnel->strict_content_length) { log_debug ("tunnel_close: write padding (%d bytes)", tunnel->content_length - tunnel->bytes - 1); tunnel_padding (tunnel, tunnel->content_length - tunnel->bytes - 1); } log_debug ("tunnel_close: write TUNNEL_CLOSE request"); tunnel_write_request (tunnel, TUNNEL_CLOSE, NULL, 0); tunnel_out_disconnect (tunnel); log_debug ("tunnel_close: reading trailing data from input ..."); p.fd = tunnel->in_fd; p.events = POLLIN; while (poll (&p, 1, READ_TRAIL_TIMEOUT) > 0) { if (p.revents & POLLIN) { n = read (tunnel->in_fd, buf, sizeof buf); if (n > 0) { log_annoying ("read (%d, %p, %d) = %d", tunnel->in_fd, buf, sizeof buf, n); continue; } else if (n == -1 && errno == EAGAIN) continue; else if (n == -1) log_debug ("tunnel_close: ... error: %s", strerror (errno)); else log_debug ("tunnel_close: ... done (tunnel closed)"); } if (p.revents & POLLHUP) log_debug ("POLLHUP"); if (p.revents & POLLERR) log_debug ("POLLERR"); if (p.revents & POLLNVAL) log_debug ("POLLNVAL"); break; } tunnel_in_disconnect (tunnel); tunnel->buf_len = 0; tunnel->in_total_raw = 0; tunnel->in_total_data = 0; tunnel->out_total_raw = 0; tunnel->out_total_data = 0; return 0; } static int tunnel_read_request (Tunnel *tunnel, enum tunnel_request *request, unsigned char *buf, size_t *length) { Request req; Length len; ssize_t n; log_annoying ("read (%d, %p, %d) ...", tunnel->in_fd, &req, 1); n = read (tunnel->in_fd, &req, 1); log_annoying ("... = %d", n); if (n == -1) { if (errno != EAGAIN) log_error ("tunnel_read_request: error reading request: %s", strerror (errno)); return n; } else if (n == 0) { log_debug ("tunnel_read_request: connection closed by peer"); tunnel_in_disconnect (tunnel); if (tunnel_is_client (tunnel) && tunnel_in_connect (tunnel) == -1) return -1; errno = EAGAIN; return -1; } *request = req; tunnel->in_total_raw += n; log_annoying ("request = 0x%x (%s)", req, REQ_TO_STRING (req)); if (req & TUNNEL_SIMPLE) { log_annoying ("tunnel_read_request: in_total_raw = %u", tunnel->in_total_raw); log_debug ("tunnel_read_request: %s", REQ_TO_STRING (req)); *length = 0; return 1; } n = read_all (tunnel->in_fd, &len, 2); if (n <= 0) { log_error ("tunnel_read_request: error reading request length: %s", strerror (errno)); if (n == 0) errno = EIO; return -1; } len = ntohs (len); *length = len; tunnel->in_total_raw += n; log_annoying ("length = %d", len); if (len > 0) { n = read_all (tunnel->in_fd, buf, (size_t)len); if (n <= 0) { log_error ("tunnel_read_request: error reading request data: %s", strerror (errno)); if (n == 0) errno = EIO; return -1; } tunnel->in_total_raw += n; log_annoying ("tunnel_read_request: in_total_raw = %u", tunnel->in_total_raw); } if (req == TUNNEL_DATA) log_verbose ("tunnel_read_request: %s (%d)", REQ_TO_STRING (req), len); else log_debug ("tunnel_read_request: %s (%d)", REQ_TO_STRING (req), len); return 1; } ssize_t tunnel_read (Tunnel *tunnel, void *data, size_t length) { enum tunnel_request req; size_t len; ssize_t n; if (tunnel->buf_len > 0) { n = min (tunnel->buf_len, length); memcpy (data, tunnel->buf_ptr, n); tunnel->buf_ptr += n; tunnel->buf_len -= n; return n; } if (tunnel->in_fd == -1) { if (tunnel_is_client (tunnel)) { if (tunnel_in_connect (tunnel) == -1) return -1; } else { #if 1 if (tunnel_accept (tunnel) == -1) return -1; #else errno = EAGAIN; return -1; #endif } errno = EAGAIN; return -1; } if (tunnel->out_fd == -1 && tunnel_is_server (tunnel)) { tunnel_accept (tunnel); errno = EAGAIN; return -1; } if (tunnel_read_request (tunnel, &req, tunnel->buf, &len) <= 0) { log_annoying ("tunnel_read_request returned <= 0, returning -1"); return -1; } switch (req) { case TUNNEL_OPEN: /* do something with tunnel->buf */ break; case TUNNEL_DATA: tunnel->buf_ptr = tunnel->buf; tunnel->buf_len = len; tunnel->in_total_data += len; log_verbose ("tunnel_read: in_total_data = %u", tunnel->in_total_data); return tunnel_read (tunnel, data, length); case TUNNEL_PADDING: /* discard data */ break; case TUNNEL_PAD1: /* do nothing */ break; case TUNNEL_ERROR: tunnel->buf[len] = 0; log_error ("tunnel_read: received error: %s", tunnel->buf); errno = EIO; return -1; case TUNNEL_CLOSE: return 0; case TUNNEL_DISCONNECT: tunnel_in_disconnect (tunnel); if (tunnel_is_client (tunnel) && tunnel_in_connect (tunnel) == -1) return -1; errno = EAGAIN; return -1; default: log_error ("tunnel_read: protocol error: unknown request 0x%02x", req); errno = EINVAL; return -1; } errno = EAGAIN; return -1; } int tunnel_pollin_fd (Tunnel *tunnel) { if (tunnel_is_server (tunnel) && (tunnel->in_fd == -1 || tunnel->out_fd == -1)) { if (tunnel->in_fd == -1) log_verbose ("tunnel_pollin_fd: in_fd = -1; returning server_socket = %d", tunnel->server_socket); else log_verbose ("tunnel_pollin_fd: out_fd = -1; returning server_socket = %d", tunnel->server_socket); return tunnel->server_socket; } else if (tunnel->in_fd != -1) return tunnel->in_fd; else { log_error ("tunnel_pollin_fd: returning -1"); return -1; } } /* If the write connection is up and needs padding to the block length specified in the second argument, send some padding. */ int tunnel_maybe_pad (Tunnel *tunnel, size_t length) { size_t padding; if (tunnel_is_disconnected (tunnel) || tunnel->bytes % length == 0 || tunnel->padding_only) return 0; padding = length - tunnel->bytes % length; if (padding > tunnel->content_length - tunnel->bytes) padding = tunnel->content_length - tunnel->bytes; return tunnel_padding (tunnel, padding); } #if 0 ssize_t old_parse_header (int s, int *type) { static const char *end_of_header = "\r\n\r\n"; ssize_t n, len = 0; char c; int i; *type = -1; n = read_all (s, &c, 1); if (n != 1) return -1; len += n; if (c == 'P') *type = TUNNEL_IN; else if (c == 'G') *type = TUNNEL_OUT; else { log_error ("parse_header: unknown HTTP request starting with '%c'", c); errno = EINVAL; return -1; } i = 0; while (i < 4) { n = read_all (s, &c, 1); if (n != 1 && errno != EAGAIN) return n; len += n; if (c == end_of_header[i]) i++; else i = 0; } return len; } #endif int tunnel_accept (Tunnel *tunnel) { if (tunnel->in_fd != -1 && tunnel->out_fd != -1) { log_debug ("tunnel_accept: tunnel already established"); return 0; } while (tunnel->in_fd == -1 || tunnel->out_fd == -1) { struct sockaddr_in addr; Http_request *request; struct pollfd p; ssize_t m; int len; int n; int s; p.fd = tunnel->server_socket; p.events = POLLIN; n = poll (&p, 1, (tunnel->in_fd != -1 || tunnel->out_fd != -1 ? ACCEPT_TIMEOUT * 1000 : -1)); if (n == -1) { log_error ("tunnel_accept: poll error: %s", strerror (errno)); return -1; } else if (n == 0) { log_error ("tunnel_accept: poll timed out"); break; } len = sizeof addr; s = accept (tunnel->server_socket, (struct sockaddr *)&addr, &len); if (s == -1) { log_error ("tunnel_accept: accept error: %s", strerror (errno)); return -1; } log_notice ("connection from %d.%d.%d.%d:%u", ntohl (addr.sin_addr.s_addr) >> 24, (ntohl (addr.sin_addr.s_addr) >> 16) & 0xff, (ntohl (addr.sin_addr.s_addr) >> 8) & 0xff, ntohl (addr.sin_addr.s_addr) & 0xff, ntohs (addr.sin_port)); m = http_parse_request (s, &request); if (m <= 0) return m; if (request->method == -1) { log_error ("tunnel_accept: error parsing header: %s", strerror (errno)); close (s); } else if (request->method == HTTP_POST || request->method == HTTP_PUT) { if (tunnel->in_fd == -1) { tunnel->in_fd = s; #ifdef IO_COUNT_HTTP_HEADER tunnel->in_total_raw += m; /* from parse_header() */ log_annoying ("tunnel_accept: in_total_raw = %u", tunnel->in_total_raw); #endif fcntl (tunnel->in_fd, F_SETFL, fcntl (tunnel->in_fd, F_GETFL) | O_NONBLOCK); tunnel_in_setsockopts (tunnel->in_fd); log_debug ("tunnel_accept: input connected"); } else { log_error ("rejected tunnel_in: already got a connection"); close (s); } } else if (request->method == HTTP_GET) { if (tunnel->out_fd == -1) { char str[1024]; tunnel->out_fd = s; tunnel_out_setsockopts (tunnel->out_fd); sprintf (str, "HTTP/1.1 200 OK\r\n" /* "Date: %s\r\n" */ /* "Server: %s\r\n" */ /* "Last-Modified: %s\r\n" */ /* "ETag: %s\r\n" */ /* "Accept-Ranges: %s\r\n" */ "Content-Length: %d\r\n" "Connection: close\r\n" "Pragma: no-cache\r\n" "Cache-Control: no-cache, no-store, must-revalidate\r\n" "Expires: 0\r\n" /* FIXME: "0" is not a legitimate HTTP date. */ "Content-Type: text/html\r\n" "\r\n", /* +1 to allow for TUNNEL_DISCONNECT */ tunnel->content_length + 1); if (write_all (tunnel->out_fd, str, strlen (str)) <= 0) { log_error ("tunnel_accept: couldn't write GET header: %s", strerror (errno)); close (tunnel->out_fd); tunnel->out_fd = -1; } else { tunnel->bytes = 0; tunnel->buf_len = 0; tunnel->buf_ptr = tunnel->buf; #ifdef IO_COUNT_HTTP_HEADER tunnel->out_total_raw += strlen (str); log_annoying ("tunnel_accept: out_total_raw = %u", tunnel->out_total_raw); #endif log_debug ("tunnel_accept: output connected"); } } else { log_error ("tunnel_accept: rejected tunnel_out: " "already got a connection"); close (s); } } else { log_error ("tunnel_accept: unknown header type"); log_debug ("tunnel_accept: closing connection"); close (s); } http_destroy_request (request); } if (tunnel->in_fd == -1 || tunnel->out_fd == -1) { log_error ("tunnel_accept: in_fd = %d, out_fd = %d", tunnel->in_fd, tunnel->out_fd); if (tunnel->in_fd != -1) close (tunnel->in_fd); tunnel->in_fd = -1; log_debug ("tunnel_accept: input disconnected"); tunnel_out_disconnect (tunnel); return -1; } return 0; } Tunnel * tunnel_new_server (const char *host, int port, size_t content_length) { Tunnel *tunnel; struct in_addr addr; struct hostent *hp; if (host == NULL) addr.s_addr = INADDR_ANY; else if ((addr.s_addr = inet_addr (host)) == INADDR_NONE) { hp = gethostbyname (host); if (hp == NULL || hp->h_addrtype != AF_INET) return NULL; memcpy (&addr, hp->h_addr, hp->h_length); } tunnel = malloc (sizeof (Tunnel)); if (tunnel == NULL) return NULL; /* If content_length is 0, a value must be determined automatically. */ /* For now, a default value will do. */ if (content_length == 0) content_length = DEFAULT_CONTENT_LENGTH; tunnel->in_fd = -1; tunnel->out_fd = -1; tunnel->server_socket = -1; tunnel->dest.host_name = host; tunnel->dest.host_port = port; tunnel->buf_ptr = tunnel->buf; tunnel->buf_len = 0; /* -1 to allow for TUNNEL_DISCONNECT */ tunnel->content_length = content_length - 1; tunnel->in_total_raw = 0; tunnel->in_total_data = 0; tunnel->out_total_raw = 0; tunnel->out_total_data = 0; tunnel->strict_content_length = FALSE; tunnel->bytes = 0; tunnel->server_socket = server_socket (addr, tunnel->dest.host_port, 1); if (tunnel->server_socket == -1) { log_error ("tunnel_new_server: server_socket (%d) = -1", tunnel->dest.host_port); tunnel_destroy (tunnel); return NULL; } return tunnel; } Tunnel * tunnel_new_client (const char *host, int host_port, const char *proxy, int proxy_port, size_t content_length) { const char *remote; int remote_port; Tunnel *tunnel; log_verbose ("tunnel_new_client (\"%s\", %d, \"%s\", %d, %d)", host, host_port, proxy ? proxy : "(null)", proxy_port, content_length); tunnel = malloc (sizeof (Tunnel)); if (tunnel == NULL) { log_error ("tunnel_new_client: out of memory"); return NULL; } tunnel->in_fd = -1; tunnel->out_fd = -1; tunnel->server_socket = -1; tunnel->dest.host_name = host; tunnel->dest.host_port = host_port; tunnel->dest.proxy_name = proxy; tunnel->dest.proxy_port = proxy_port; tunnel->dest.proxy_authorization = NULL; tunnel->dest.user_agent = NULL; /* -1 to allow for TUNNEL_DISCONNECT */ tunnel->content_length = content_length - 1; tunnel->buf_ptr = tunnel->buf; tunnel->buf_len = 0; tunnel->in_total_raw = 0; tunnel->in_total_data = 0; tunnel->out_total_raw = 0; tunnel->out_total_data = 0; tunnel->strict_content_length = FALSE; tunnel->bytes = 0; if (tunnel->dest.proxy_name == NULL) { remote = tunnel->dest.host_name; remote_port = tunnel->dest.host_port; } else { remote = tunnel->dest.proxy_name; remote_port = tunnel->dest.proxy_port; } if (set_address (&tunnel->address, remote, remote_port) == -1) { log_error ("tunnel_new_client: set_address: %s", strerror (errno)); free (tunnel); return NULL; } return tunnel; } void tunnel_destroy (Tunnel *tunnel) { if (tunnel_is_connected (tunnel) || tunnel->in_fd != -1) tunnel_close (tunnel); if (tunnel->server_socket != -1) close (tunnel->server_socket); free (tunnel); } static int tunnel_opt (Tunnel *tunnel, const char *opt, void *data, int get_flag) { if (strcmp (opt, "strict_content_length") == 0) { if (get_flag) *(int *)data = tunnel->strict_content_length; else tunnel->strict_content_length = *(int *)data; } else if (strcmp (opt, "keep_alive") == 0) { if (get_flag) *(int *)data = tunnel->keep_alive; else tunnel->keep_alive = *(int *)data; } else if (strcmp (opt, "max_connection_age") == 0) { if (get_flag) *(int *)data = tunnel->max_connection_age; else tunnel->max_connection_age = *(int *)data; } else if (strcmp (opt, "proxy_authorization") == 0) { if (get_flag) { if (tunnel->dest.proxy_authorization == NULL) *(char **)data = NULL; else *(char **)data = strdup (tunnel->dest.proxy_authorization); } else { if (tunnel->dest.proxy_authorization != NULL) free ((char *)tunnel->dest.proxy_authorization); tunnel->dest.proxy_authorization = strdup ((char *)data); if (tunnel->dest.proxy_authorization == NULL) return -1; } } else if (strcmp (opt, "user_agent") == 0) { if (get_flag) { if (tunnel->dest.user_agent == NULL) *(char **)data = NULL; else *(char **)data = strdup (tunnel->dest.user_agent); } else { if (tunnel->dest.user_agent != NULL) free ((char *)tunnel->dest.user_agent); tunnel->dest.user_agent = strdup ((char *)data); if (tunnel->dest.user_agent == NULL) return -1; } } else { errno = EINVAL; return -1; } return 0; } int tunnel_setopt (Tunnel *tunnel, const char *opt, void *data) { return tunnel_opt (tunnel, opt, data, FALSE); } int tunnel_getopt (Tunnel *tunnel, const char *opt, void *data) { return tunnel_opt (tunnel, opt, data, TRUE); } httptunnel-3.3/doc/0000755000175000017500000000000010657370556011267 5ustar httptunnel-3.3/DISCLAIMER0000644000175000017500000000063206657373202012056 0ustar I hereby disclaim all responsibility for this hack. If it backfires on you in any way whatsoever, that's the breaks. Not my fault. If you don't understand the risks inherent in doing this, don't do it. If you use this hack and it allows vicious vandals to break into your company's computers and costs you your job and your company millions of dollars, well that's just tough nuggies. Don't come crying to me. httptunnel-3.3/ChangeLog0000644000175000017500000007315307246171562012301 0ustar 2001-02-25 lars brinkhoff From Sampo Niskanen : * common.c (handle_tunnel_input): write to stdout if fd = 0. * htc.c (struct Arguments): add use_std and use_daemon. (usage): add short option -z for --proxy-authorization-file. add -s, --stdin-stdout option. add -w, --no-daemon option. (parse_arguments): recognize new options. (parse_arguments): write diagnostics to stderr instead of stdout. (main): likewise. * hts.c (struct Arguments): add use_std and use_daemon. (usage): add -s, --stdin-stdout option. add -w, --no-daemon option. (parse_arguments): recognize new options. (main): write diagnostics to stderr instead of stdout. 2000-09-01 lars brinkhoff From Brian Somers : * htc.c (main): correct typo in log message. * tunnel.c (tunnel_out_connect): use ntohl() to convert IP address. (tunnel_accept): likewise. * common.c (set_address): likewise. 2000-08-31 lars brinkhoff * configure.in: version 3.2 * debian/changelog: sync with new version. From Brian Somers : * tunnel.c (tunnel_new_server): change inet_aton() to the more generally available inet_addr(). 2000-07-25 lars brinkhoff * configure.in: version 3.1 * debian/changelog: sync with new version. From Brian Somers : * tunnel.h: update tunnel_new_server prototype. * tunnel.c (tunnel_is_server): tunnel is server when server_socket != -1. (tunnel_out_connect): log the port number. (tunnel_in_connect): don't call http_destroy_response with NULL argument. (tunnel_accept): log client IP number and port. (tunnel_new_server): accept char *host argument, which is used to bind the server to a specific network interface. initialize tunnel->bytes to 0. pass struct in_addr to server_socket. (tunnel_new_client): initialize tunnel->bytes to 0. * hts.c (parse_arguments): host defaults to NULL. recognize [HOST:]PORT syntax. (main): log host:port, if host was specified. pass host to tunnel_new_server. * common.c (server_socket): take a sockaddr_in * argument; improve sockaddr_in initialization. (set_address): improve sockaddr_in initialization. * common.h: update server_socks prototype. * htc.c (main): pass a struct in_addr to server_socket. 2000-07-24 lars brinkhoff From Fumitoshi UKAI : * common.c (handle_device_input): set errno to EIO on error. (handle_tunnel_input): likewise. 2000-07-12 lars brinkhoff From Jonathan Buschmann : * tunnel.c: include to get definition of TCP_NODELAY. 2000-07-11 lars brinkhoff * configure.in: version 3.0.3. 2000-07-10 lars brinkhoff * http.c (http_method): add random string to HTTP requests, in order to work with proxies that doesn't recognize "no-cache" etc. Thanks to Rogier R. Mulhuijzen for the suggestion. 2000-07-04 lars brinkhoff * htc.c (parse_arguments): fix spelling of "authorization". 2000-06-30 lars brinkhoff * port/Makefile.am (libport_a_SOURCES): change getopt_.h to getopt.h. 2000-06-29 lars brinkhoff From Albert Chin-A-Young : * port/getopt_.h: rename to port/getopt.h * port/getopt.c: include getopt.h instead of getopt_.h. * port/getopt1.c: likewise. * common.h: likewise. Myself: * configure.in: remove checks for getopt.h, getopt(), and getopt_long(). * common.h: remove HAVE_GETOPT check. 2000-06-22 lars brinkhoff * htc.c (parse_arguments): correct typo of "proxy-authorization-file". (parse_arguments): remove terminating CRLF or LF from auth file. Thanks to Raphael Manfredi for this patch. * configure.in: version 3.0.2. * debian/changelog: sync with new version. 2000-06-14 lars brinkhoff * configure.in: version 3.0.1. 2000-01-13 lars brinkhoff * configure.in: from Albert Chin-A-Young : A better way to check if -lnsl and -lsocket should be used. Even though some systems have -lnsl and -lsocket, it doesn't imply they should be used (i.e. IRIX). 2000-01-12 lars brinkhoff * configure.in: version 3.0. * NEWS: updated with user-visible changes since 2.0. 1999-12-22 lars brinkhoff * cvs tag release_2_90 * configure.in: version 2.90. 1999-12-15 lars brinkhoff * common.c (open_device): from Chris Lesiak : The following patch allows httptunnel to work with devices that aren't ttys. Specifically, the Universal TUN device driver version 0.3 by Maxim Krasnyansky patch to linux-2.2.12 seems to work fine. 1999-12-07 lars brinkhoff * port/poll.c (poll): patch from Shimayoshi Takao fixed bug in poll() emulation. 1999-10-25 lars brinkhoff * htc.c (parse_arguments): * tunnel.c (tunnel_write_request): patch from Ludovic Rousseau to make --strict-content-length work. 1999-08-24 lars brinkhoff * cvs tag release_2_11 * configure.in: version 2.11. * tunnel.c (tunnel_read): return -1 if tunnel_read_request returns 0. (tunnel_read_request): return 1 on success. (tunnel_read_request): set errno when returning 0. 1999-08-21 lars brinkhoff * tunnel.c (tunnel_read_request): added logging of request header. 1999-08-18 lars brinkhoff * tunnel.c (tunnel_in_connect): improve error logging. (tunnel_connect): return -1 if tunnel_in_connect() returns 0. * TODO: added new idea from Raphael Manfredi. * htc.c (usage, parse_arguments): recognize --proxy-authorization-file. Thanks to Raphael Manfredi for suggesting this feature. 1999-08-16 lars brinkhoff * configure.in: version 2.10.cvs. * cvs tag release_2_10 * configure.in: version 2.10. (apparently 2.9 got lost) * tunnel.c (tunnel_out_connect): * tunnel.c (tunnel_in_connect): don't use shutdown() (unless USE_SHUTDOWN is defined). * tunnel.c (tunnel_out_setsockopts): prefer using TCP_NODELAY to SO_SNDBUF. Thanks to Raphael Manfredi for pointing out the problems with using shutdown() and SO_SNDBUF. 1999-08-13 lars brinkhoff * htc.c (main): don't null-terminate the base64 string, since encode_base64() does it. use strcopy and strcat instead of snprintf. * base64.c (encode_base64): null-terminate the encoded string. * htc.c (main): use the length value returned by encode_base64() and null-terminate the base64-encoded string before using it with snprintf. Thanks to James Fidell for reporting this bug. * base64.c (encode_base64): allocate one more byte for the result string, in case someone wants to null-terminate it. 1999-08-12 lars brinkhoff * configure.in: version 2.8.cvs. * cvs tag release_2_8 * configure.in: version 2.8. * Makefile.am (EXTRA_DIST): forgot to include the debian files. 1999-08-10 lars brinkhoff * cvs tag release_2_7 1999-08-06 lars brinkhoff * configure.in: version 2.7. 1999-08-05 lars brinkhoff * hts.1, htc.1: moved debian/hts.1 to top level and added htc.1. Both manuals contributed by Teemu Hukkanen . * debian/changelog, debian/copyright, debian/dirs, debian/docs, debian/hts.1, debian/rules, debian/control: Debian files contributed by Teemu Hukkanen . 1999-06-28 lars brinkhoff * port/stdio_.h: #include and "config.h" to make sure size_t is defined before it is used. Thanks to Barry Hunter Priest for reporting this bug. 1999-06-09 lars brinkhoff * tunnel.c (tunnel_opt): bug fix from Jeffrey S Laing . Wed May 26 08:15:54 1999 lars brinkhoff * tunnel.c (tunnel_read_request): don't try to read any data field if the length field of the request is 0. Tue May 18 21:18:28 1999 lars brinkhoff * cvs tag release_2_6 * http.c (http_parse_response): allocates a Http_response (http_parse_request): allocates a Http_request. * configure.in: version 2.6. Sun May 9 12:10:45 1999 lars brinkhoff * cvs tag release_2_5 * htc.c (main): added forgotten arguments to initial "started with arguments" log message. Thanks to Philip Craig for this patch: * port/syslog_.h: corrected vsyslog() prototype. * hts.c (parse_arguments): added forgotten -k option. * htc.c (usage): fixed spelling. (parse_arguments): added forgotten -k option. * renamed all port/Foo.h files into port/foo_.h. 1999-05-08 lars brinkhoff * configure.in: version 2.5. * cvs tag release_2_4 * htc.c (usage, parse_arguments): new -U, --user-agent option. (main): call tunnel_setopt to set "user_agent" option. * tunnel.c (tunnel_opt): recognize "user_agent" option. * http.c (http_method): add User-Agent header if specified. * http.c (http_method_to_string): new function. (http_alloc_header): new function. (http_add_header): new function. (http_write_header): new function. (http_allocate_response): new function. (http_create_response): new function. (http_allocate_request): new function. (http_create_request): new function. (http_write_request): new function. (http_method): call http_create_request, http_add_header, and http_write_request. 1999-04-24 lars brinkhoff * hts.c (main): not specifying a pid file resulted in a crash on some operating systems. Thanks to Krishna Swaroop . * configure.in: version 2.4. Tue Apr 13 22:15:24 1999 lars brinkhoff * cvs tag release_2_3 * hts.c (main, parse_arguments): add --pid-file option. Thanks to Andrew Mobbs . 1999-04-04 lars brinkhoff * configure.in: check for syslog(). * port/vsyslog.c (syslog): new function. If config.h defines neither HAVE_SYSLOG nor HAVE_VSYSLOG, logging will be disabled. 1999-04-02 lars brinkhoff * htc.c (main): --proxy-authorization fix. * configure.in: version 2.3. * cvs tag release_2_2 * configure.in: version 2.2 * port/vsnprintf.c (snprintf): new function. * htc.c (main): set proxy_authorization option on tunnel. (Arguments): new proxy_authorization variable. (usage, parse_arguments): new --proxy-authorization option. * http.c (http_method): add Proxy-Authorization to header. * http.h (Http_destination): new proxy_authorization variable. * tunnel.c (tunnel_opt): recognizes the "proxy_authorization" option. * tunnel.c (tunnel_getopt): removed len argument. * Makefile.am (EXTRA_DIST): add doc/rfc2045.txt. (htc_SOURCES): add base64.c. (noinst_SOURCES): add base64.h. * base64.c (encode_base64): new function. Fri Mar 26 10:22:07 1999 lars brinkhoff * README: added reference to MANUAL. * MANUAL: added reference to Firewall Piercing mini-HOTWO. Thu Mar 25 09:14:04 1999 lars brinkhoff * http.c (parse_header): missed one allocation check. Thanks to John Bley for this patch. Wed Mar 24 16:36:26 1999 lars brinkhoff * cvs tag release_2_1 * FAQ: added HP-UX question. Mon Mar 22 18:51:10 1999 lars brinkhoff * tunnel.c (tunnel_opt): new function. (tunnel_getopt, tunnel_setopt): use tunnel_opt. (tunnel_opt): new options keep_alive and max_connection_age. (struct tunnel): new variables keep_alive and max_connection_age. (tunnel_write_request): close connection if it's older than max_connection_age seconds. * htc.c, hts.c (main): send keepalive byte after arg.keep_alive seconds of inactivity. * htc.c, hts.c (usage, parse_arguments, main): new options --keep-alive and --max-connection-age. Sat Mar 20 06:51:35 1999 lars brinkhoff * tunnel.c (tunnel_write_request): write padding before closing old connection if strict_content_length is set. (tunnel_close): don't write padding unless strict_content_length is set. (struct tunnel): new strict_content_length variable. (tunnel_setopt, tunnel_getopt): new functions. * htc.c, hts.c (Arguments, parse_arguments): new --strict option. * common.c (log_level): time stamps in debug messages. * port/vsnprintf.c (vsnprintf, vsmprintf): new functions. * configure.in: check for vsnprintf. * port/vsyslog.c: use vsnprintf instead of vsprintf. * configure.in: changed name from DEBUG to DEBUG_MODE. changed all other files accordingly. * common.c (log_exit): new function. * htc.c, hts.c: use log_exit instead of exit. * rw.c, tt.c: removed. * Makefile.am: removed references to rw and tt. * port/getopt.c, port/getopt1.c, port/getopt.h: copied from GNU fileutils-4.0. * port/endprotoent.c, port/Netdb.h, port/poll.c, port/sys/Poll.h, port/vsyslog.c, port/Syslog.h, port/endprotoent.h, port/Netdb.h, port/vsnprintf.c, port/Stdio.h, port/daemon.c, port/Unistd.h: new files. * common.c, common.h, tunnel.c: removed poll(), vsyslog(), endprotoent(), daemon(). * modified all old files to use the new files. * configure.in: version 2.1. * cvs tag release_2_0 * Makefile.am (EXTRA_DIST): added FAQ. * FAQ: new file. * NEWS: updated for version 2.0. * configure.in: version 2.0. Fri Mar 19 12:32:44 1999 lars brinkhoff * NEWS: updated for version 1.103. * acinclude.m4 (HTTPTUNNEL_DEFINE_INADDR_NONE): #include in test to make it work on OpenBSD. * TODO: some new stuff. Wed Mar 17 07:08:53 1999 lars brinkhoff * hts.c (main): forgot return type int! * htc.c, hts.c (main): improve a command line error message. * common.h (BUG_REPORT_EMAIL): email bugs to bug-httptunnel@gnu.org. * configure.in: version 1.103. * cvs tag release_1_102 * NEWS: updated for version 1.102. * configure.in: stricter warnings when --enable-debug. common.c, common.h, hts.c, http.c, tunnel.c: changes to remove compiler warnings. * tunnel.c (tunnel_out_setsockopts, tunnel_in_setsockopts): don't return an error when the first setsockopt() fails. also changed from log_error to log_debug, because errors can be ignored. Tue Mar 16 15:28:07 1999 lars brinkhoff * AUTHORS: changed email addresses to the preferred ones. * configure.in: add check for endprotoent(). * tunnel.c (endprotoent) [!HAVE_ENDPROTOENT]: define dummy emulation function (Cygwin B20 didn't have it). * AUTHORS: Added Philip Craig to Testing section. * configure.in: version 1.102. * cvs tag release_1_101 * NEWS: updated for version 1.101. * htc.c (main): removed problem which caused a busy loop. * common.c (log_level): removed one level of indentation. * hts.c, htc.c (main): log_notice PACKAGE, VERSION, and debug_level. * tunnel.h (DEFAULT_CONNECTION_MAX_TIME): 5 minutes seems good enough. * common.h (DEFAULT_KEEP_ALIVE): 5 seconds seems to satisfy a very very picky proxy. * Makefile.am: disabled compilation of tt and rw, as they are hardly needed anymore. * configure.in: version 1.101. * cvs tag release_1_100. * NEWS: updated for version 1.100. * Makefile.am (EXTRA_DIST): added MANUAL (but it's not). * tunnel.h (DEFAULT_CONNECTION_MAX_TIME): default maximum time a HTTP POST connection will stay open. * common.h (DEFAULT_KEEP_ALIVE): default period for sending keep-alive bytes. * configure.in: version 1.100. * tunnel.c (tunnel_out_setsockopts): set SO_SNDLOWAT at TCP level instead of SOL_SOCKET level. (tunnel_in_setsockopts): set SO_RCVLOWAT at TCP level instead of SOL_SOCKET level. (get_proto_number): new function. Tue Mar 16 14:25:01 1999 Tomas Berndtsson * tunnel.c (tunnel_new_client): fixed string printing when the proxy string is NULL, so it doesn't segfault on Solaris. Mon Mar 15 18:24:11 1999 lars brinkhoff * cvs tag release_1_99 * NEWS: updated for 1.99. * MANUAL: added, but isn't. Sun Mar 14 05:04:44 1999 lars brinkhoff * TODO: added idea for --paranoid switch. * README: added plea for post cards. improved the example. * common.c (log_notice, log_error, log_debug, log_verbose, log_annoying): adjusted the debug level so that 0 means no debug messages at all. 5 is now the highest level. * hts.c, htc.c (main): not specifying a debug level when --enable-debug caused a crash. * configure.in: version 1.99. * cvs tag release_1_98 * NEWS: updated for version 1.98. Sat Mar 13 09:31:00 1999 lars brinkhoff * http.c: changed read_until to return malloced string and changed other functions accordingly. * configure.in: version 1.98. * tunnel.c (tunnel_write_request, tunnel_write): moved the code that closes old connections from tunnel_write to tunnel_write_request. * htc.c (usage, parse_arguments): changed -f to -F. * hts.c (usage, parse_arguments): changed -f to -F. * httptunnel is now GNU software. * common.c (server_socket): setsockopt SO_REUSEADDR on server sockets. Idea from Magnus Lundström's mailtunnel. Fri Mar 12 19:05:22 1999 lars brinkhoff * tunnel.c (tunnel_out_connect): note time when connection was made. (tunnel_write): close connection if it's old. * tunnel.c (tunnel_in_setsockopts, tunnel_out_setsockopts): new functions. (tunnel_accept): call tunnel_{in,out}_setsockopts. (tunnel_in_connect): call tunnel_in_setsockopts. (tunnel_out_connect): call tunnel_out_setsockopts. Thu Mar 11 12:12:14 1999 lars brinkhoff * cvs tag release_1_97 * NEWS: updated for 1.97. * tunnel.c (tunnel_accept): set the send buffer size of the outgoing socket to 0. set SO_KEEPALIVE option too. (tunnel_close): reset I/O counters. * HACKING: removed unneccesary reference no non-free software. * common.c (poll): slight improvement after having looked at the poll emulation code by Sean Reifschneider . Wed Mar 10 22:16:40 1999 lars brinkhoff * tunnel.c (tunnel_accept): call http_destroy_request. (tunnel_in_connect): call http_destroy_response. * http.c (http_destroy_response, http_destroy_request): new functions. Tue Mar 9 11:40:16 1999 lars brinkhoff * tunnel.c (tunnel_accept): use http_parse_request(). * http.c (parse_header, http_parse_response, http_header_value, http_parse_request): don't use dynamic memory allocation #ifdef DONT_MALLOC. * configure.in: removed "[=verbose]" from --enable-debug help output. added -Wpointer-arith to CFLAGS when not --enable-debug. * tunnel.c (tunnel_write_request): maybe fixed bug that caused lost HTTP POST connections to corrupt data. (Nope, didn't work.) * hts.c (parse_arguments): forgot to add "c:" to short_options to make --content-length work. Thanks to Philip Craig for this one. Mon Mar 8 18:42:01 1999 lars brinkhoff * http.c (parse_header, http_parse_request, http_header_value): new functions. (parse_response): improved to parse header. * http.h (Http_method, Http_header, Http_request, Http_response): added new types to describe the HTTP protocol. Improved Http_response. * common.c (poll): block indefinitely when using a negative timeout value. * configure.in: version 1.97. * cvs tag release_1_96 * NEWS: updated for 1.96. * configure.in: add -Wno-unused and -Wpointer-arith to CFLAGS if --enable-debug. * AUTHORS: added Andrew Gray and Larry Gensch. Thanks to Larry Gensch at Digital for this patch: * tunnel.c (tunnel_write_or_padding): fixed void * arithmetic. * common.h (write_all, read_all): fixed void * arithetic. * tunnel.h (tunnel_padding): fixed prototype/definition mismatch. Sun Mar 7 11:17:48 1999 lars brinkhoff * common.c (poll): emulate poll() using select(). * configure.in: check for poll() and . * Makefile.am (EXTRA_DIST): add doc/rfc*.txt. * configure.in: version 1.96 * cvs tag release_1_95 * NEWS: updated for 1.95. * tunnel.c (tunnel_accept): add "Expires: 0" and "Cache-Control: no-store, must-revalidate" to HTTP GET response. * htc.c, hts.c (main): ignore SIGPIPE unless --enable-debug. * common.c (log_sigpipe): new function replacing sigpipe() in htc.c and hts.c. * tunnel.c: don't include HTTP header stuff in the I/O counters unless #define IO_COUNT_HTTP_HEADER. * tunnel.c (tunnel_accept): add Content-Length to HTTP GET response. (parse_header): return number of bytes read. * hts.c (usage, parse_arguments, main): accept new switch --content-length. * common.c (atoi_with_postfix): moved here from htc.c. * http.c (http_method, http_get, http_put, http_post): return number of bytes written. (http_parse_response): return number of bytes read. * tunnel.c (struct tunnel): add counters for total number of bytes read and written for both data and raw I/O. (tunnel_out_connect): increase out_total_raw. (tunnel_in_connect): increase in_total_raw. (tunnel_write_data): increase out_total_raw. (tunnel_write): increase out_total_data. (tunnel_read_request): increase in_total_raw. (tunnel_read): increase in_total_data. (tunnel_accept): increase in_total_raw and out_total_raw. (tunnel_new_server, tunnel_new_client): reset counters. Sat Mar 6 10:57:54 1999 lars brinkhoff * configure.in: version 1.95. * cvs tag release_1_94 * NEWS: update for version 1.94. * configure.in: version 1.94. * cvs tag release_1_93 * NEWS: update for version 1.93. * tunnel.c (tunnel_in_connect): check HTTP version and HTTP status code. * http.c (http_parse_response, read_until): new functions. * tunnel.c (tunnel_in_connect): use http_parse_response(). * configure.in: version 1.93. * cvs tag release_1_92 * configure.in: version 1.92. * http.c, http.h (http_method, http_put, http_post, http_get): Broke out HTTP-specific functions. * tunnel.c: changed Tunnel to use Http_destination and modified all affected code accordingly. * cvs tag release_1_91 * configure.in: version 1.91. * NEWS: update news for 1.5, 1.90, and 1.91. * cvs tag release_1_90 * tunnel.c, htc.c, hts.c: clean up debugging messages. Thu Mar 4 06:44:27 1999 lars brinkhoff * common.h: #define LOG_ERROR LOG_ERR if necessary. (tip from Andrew Gray). Wed Mar 3 17:49:52 1999 lars brinkhoff * htc.c, hts.c (main): send a pad byte every now and then to keep the connection alive. * htc.c, hts.c (main): check for NULL before sending strings to notice(). * common.c, common.h: made notice, debug, and verbose into functions instead of macros (patch from Andrew Gray). * tunnel.c: improved error logging. Tue Mar 2 17:48:23 1999 lars brinkhoff * tunnel.c (tunnel_maybe_pad): don't send padding if only padding has been sent over the connection. (tunnel_write_request): make a note if something other than padding was sent over the connection. Sun Feb 28 00:34:13 1999 lars brinkhoff * tunnel.c (tunnel_write): use the protocol for server writes. (tunnel_write_request): try to make server accept/disconnect connections like the client does connect/disconnect. * tunnel.c (tunnel_read_request): new function. (tunnel_read): removed function. (tunnel_server_read): renamed to tunnel_read. (tunnel_read): call tunnel_read_request(). * configure.in: changed to version 1.90 in anticipation of the big change to using the tunnel protocol on HTTP GET requests also. * tunnel.c (tunnel_write_request): if writing to the connection returns error EPIPE, the connection to the proxy has timed out, and must be re-established. I'm not drunk. Sat Feb 27 00:29:22 1999 lars brinkhoff * htc.c (sigpipe): new function. (main): catch SIGPIPE. * cvs tag release_1_5 * configure.in: version 1.5. * tunnel.c (tunnel_close): write padding before TUNNEL_CLOSE. Fri Feb 26 17:37:02 1999 lars brinkhoff * tunnel.c (tunnel_write_request): send a TUNNEL_DISCONNECT just before disconnecting. (tunnel_server_read): recognize TUNNEL_DISCONNECT as a command to close the connection. (tunnel_new_client): set tunnel->content_length to content_length - 1 to allow for one extra TUNNEL_DISCONNECT at the end of the data. (tunnel_out_connect): use tunnel->content_length + 1 to allow for one extra TUNNEL_DISCONNECT at the end of the data. * tunnel.c (tunnel_accept): Solaris expects a char * for argument 4 to setsockopt(), so casting to void * should not produce any warnings anywhere. * common.c, common.h (daemon): new function #ifndef HAVE_DAEMON. * hts.c, htc.c: use daemon(). * configure.in: check for daemon(). Thu Feb 25 20:43:49 1999 lars brinkhoff * hts.c (parse_arguments): added --logfile switch. * htc.c (parse_arguments): added --logfile switch. * common.h (log): new macro that calls syslog(). * tunnel.c (tunnel_accept): time out if out and in connections doesn't occur within ACCEPT_TIMEOUT seconds of each other. Wed Feb 24 19:50:28 1999 lars brinkhoff * cvs tag release_1_4 * configure.in: version 1.4 * tunnel.c (tunnel_close): use a timeout to avoild waiting forever for trailing pad data after a TUNNEL_CLOSE. * tunnel.c (tunnel_accept): Write a HTTP/1.1 header in response to HTTP GET requests. (tunnel_in_connect): Expect a header in a HTTP GET response. * acinclude.m4 (HTTPTUNNEL_DEFINE_INADDR_NONE): spelling fix. * htc.c, hts.c: hid the check for HAVE_GETOPT_H in common.h. Wed Feb 24 18:40:29 1999 Tomas Berndtsson * configure.in: added check for libnsl, which is needed on some Solaris systems for networking functions. * htc.c, hts.c: use #ifdef HAVE_GETOPT_LONG and #ifdef HAVE_GETOPT_H to exclude certain parts so that it will compile if getopt_long is not presesnt on the system. * configure.in: use HTTPTUNNEL_DEFINE_INADDR_NONE to check if INADDR_NONE is defined. * acconfig.h: added @BOTTOM@ statement to get autoheader to include own defines into config.h.in. * acinclude.m4: define HTTPTUNNEL_DEFINE_INADDR_NONE, which checks whether defines INADDR_NONE. #define as 0xffffffff otherwise. INADDR_NONE is not defined on Solaris. Tue Feb 23 22:15:23 1999 lars brinkhoff * cvs tag release_1_3 * configure.in: version 1.3. * common.h: #include and before . Hopefully, this will avoid compilation errors on solaris 2.5.1. If getopt_long() isn't available, provide broken emulation through getopt(). Sun Feb 21 08:05:59 1999 lars brinkhoff * cvs tag release_1_2 * configure.in: version 1.2. * htc.c (parse_arguments): not specifying a proxy was incorrectly reported as a usare error. fixed. * configure.in: use HTTPTUNNEL_TYPE_SOCKLEN_T to check for socklen_t. * acinclude.m4: new file. Define HTTPTUNNEL_TYPE_SOCKLEN_T, which checks whether declares socklen_t. #define as int otherwise. * common.h (do_connect): cast second argument from sockaddr_in * to sockaddr * to avoid warning. Sat Feb 20 09:23:11 1999 lars brinkhoff * cvs tag release_1_1 * README: removed the note about the bug. * tunnel.c (tunnel_server_read): fixed the annoying buffer bug. * common.c (dump_buf): new function used to dump data read from a device, socket, or tunnel. * hts.c (main), htc.c (main), common.h: broke out common code into handle_input(). * configure.in: version set to 1.1, but no release planned yet. * HACKING: added a paragraph about the debugging code. * htc.c, hts.c: made --debug take optional argument instead of previous repeating scheme. * rw.c: set debug = 0. no debugging here. * htc.c, hts.c, common.h: repeating --debug gives more verbose debugging messages. * tt.c: set debug = 1 so that debugging is always on if --enable-debug is. * tunnel.c: add debugging output. * htc.c (usage): improved --help output. (parse_arguments): allow default values for host port and proxy port. (parse_arguments): add --debug switch. * htc.c: add debugging output. don't fork if --debug. * hts.c (usage): improved --help output. (parse_arguments): allow a default setting for PORT. (parse_arguments): complain if forwarding port isn't specified. (parse_arguments): add --debug switch. * hts.c: added debugging output. don't fork if --debug. * configure.in: add --enable-debug switch. Fri Feb 19 00:09:00 1999 lars brinkhoff * cvs tag release_1_0 * htc.c (main): made it loop, waiting for new connections. added a close_tunnel(). * tunnel.c (tunnel_close): don't free tunnel object. (tunnel_destroy): new function. (tunnel_is_connected): new function. Thu Feb 18 07:28:18 1999 lars brinkhoff * hts.c (main): loops waiting for new connections, daemon-like forking. * configure.in: bumped version to 0.10. * hts.c (usage): new function. (parse_arguments): new function. (main): call parse_arguments(). if --forward-port was specified, connect a socket, and use it for I/O. * htc.c (parse_arguments): added new --forward-port option. (main): if --forward-port was specified, listen for a connection on a socket, and use it for I/O. * common.c, common.h (server_socket): moved here from tunnel.h. * common.c (set_address): new function. (name_and_port): moved here from htc.c. * common.h: moved contents of do.h here. * do.h: deleted file. * htc.c (wait_for_connection_on_port): new function. * acconfig.h: New file defining PACKAGE and VERSION. httptunnel-3.3/htc.c0000644000175000017500000004236307246170251011442 0ustar /* htc.c Copyright (C) 1999, 2000 Lars Brinkhoff. See COPYING for terms and conditions. htc is the client half of httptunnel. httptunnel creates a virtual two-way data path tunneled in HTTP requests. */ #include #include #include #include #include #include #include #include "common.h" #include "base64.h" #define DEFAULT_PROXY_PORT 8080 #define DEFAULT_PROXY_BUFFER_TIMEOUT 500 /* milliseconds */ typedef struct { char *me; char *device; char *host_name; int host_port; char *proxy_name; int proxy_port; size_t proxy_buffer_size; int proxy_buffer_timeout; size_t content_length; int forward_port; int use_std; int use_daemon; int strict_content_length; int keep_alive; int max_connection_age; char *proxy_authorization; char *user_agent; } Arguments; #define NO_PROXY_BUFFER 0 #define NO_PROXY (NULL) int debug_level = 0; FILE *debug_file = NULL; static void usage (FILE *f, const char *me) { fprintf (f, "Usage: %s [OPTION]... HOST[:PORT]\n" "Set up a httptunnel connection to PORT at HOST (default port is %d).\n" "When a connection is made, I/O is redirected from the source specified\n" "by the --device, --forward-port or --stdin-stdout switch to the tunnel.\n" "\n" " -A, --proxy-authorization USER:PASSWORD proxy authorization\n" " -z, --proxy-authorization-file FILE proxy authorization file\n" " -B, --proxy-buffer-size BYTES assume a proxy buffer size of BYTES bytes\n" " (k, M, and G postfixes recognized)\n" " -c, --content-length BYTES use HTTP PUT requests of BYTES size\n" " (k, M, and G postfixes recognized)\n" " -d, --device DEVICE use DEVICE for input and output\n" #ifdef DEBUG_MODE " -D, --debug [LEVEL] enable debugging mode\n" #endif " -F, --forward-port PORT use TCP port PORT for input and output\n" " -h, --help display this help and exit\n" " -k, --keep-alive SECONDS send keepalive bytes every SECONDS seconds\n" " (default is %d)\n" #ifdef DEBUG_MODE " -l, --logfile FILE specify file for debugging output\n" #endif " -M, --max-connection-age SEC maximum time a connection will stay\n" " open is SEC seconds (default is %d)\n" " -P, --proxy HOSTNAME[:PORT] use a HTTP proxy (default port is %d)\n" " -s, --stdin-stdout use stdin/stdout for communication\n" " (implies --no-daemon)\n" " -S, --strict-content-length always write Content-Length bytes in requests\n" " -T, --timeout TIME timeout, in milliseconds, before sending\n" " padding to a buffering proxy\n" " -U, --user-agent STRING specify User-Agent value in HTTP requests\n" " -V, --version output version information and exit\n" " -w, --no-daemon don't fork into the background\n" "\n" "Report bugs to %s.\n", me, DEFAULT_HOST_PORT, DEFAULT_KEEP_ALIVE, DEFAULT_MAX_CONNECTION_AGE, DEFAULT_PROXY_PORT, BUG_REPORT_EMAIL); } static int wait_for_connection_on_socket (int s) { struct sockaddr addr; socklen_t len; int t; len = sizeof addr; t = accept (s, &addr, &len); if (t == -1) return -1; return t; } static void parse_arguments (int argc, char **argv, Arguments *arg) { int c; /* defaults */ arg->me = argv[0]; arg->device = NULL; arg->forward_port = -1; arg->host_name = NULL; arg->host_port = DEFAULT_HOST_PORT; arg->proxy_name = NO_PROXY; arg->proxy_port = DEFAULT_PROXY_PORT; arg->proxy_buffer_size = NO_PROXY_BUFFER; arg->proxy_buffer_timeout = -1; arg->content_length = DEFAULT_CONTENT_LENGTH; arg->use_std = FALSE; arg->use_daemon = TRUE; arg->strict_content_length = FALSE; arg->keep_alive = DEFAULT_KEEP_ALIVE; arg->max_connection_age = DEFAULT_CONNECTION_MAX_TIME; arg->proxy_authorization = NULL; arg->user_agent = NULL; for (;;) { int option_index = 0; static struct option long_options[] = { { "help", no_argument, 0, 'h' }, { "version", no_argument, 0, 'V' }, { "no-daemon", no_argument, 0, 'w' }, { "stdin-stdout", no_argument, 0, 's' }, #ifdef DEBUG_MODE { "debug", required_argument, 0, 'D' }, { "logfile", required_argument, 0, 'l' }, #endif { "proxy", required_argument, 0, 'P' }, { "device", required_argument, 0, 'd' }, { "timeout", required_argument, 0, 'T' }, { "keep-alive", required_argument, 0, 'k' }, { "user-agent", required_argument, 0, 'U' }, { "forward-port", required_argument, 0, 'F' }, { "content-length", required_argument, 0, 'c' }, { "strict-content-length", no_argument, 0, 'S' }, { "proxy-buffer-size", required_argument, 0, 'B' }, { "proxy-authorization", required_argument, 0, 'A' }, { "max-connection-age", required_argument, 0, 'M' }, { "proxy-authorization-file", required_argument, 0, 'z' }, { 0, 0, 0, 0 } }; static const char *short_options = "A:B:c:d:F:hk:M:P:sST:U:Vwz:" #ifdef DEBUG_MODE "D:l:" #endif ; c = getopt_long (argc, argv, short_options, long_options, &option_index); if (c == -1) break; switch (c) { case 0: fprintf (stderr, "option %s", long_options[option_index].name); if (optarg) fprintf (stderr, " with arg %s", optarg); fprintf (stderr, "\n"); break; case 'A': arg->proxy_authorization = optarg; break; case 'B': arg->proxy_buffer_size = atoi_with_postfix (optarg); break; case 'c': arg->content_length = atoi_with_postfix (optarg); break; case 'd': arg->device = optarg; break; #ifdef DEBUG_MODE case 'D': if (optarg) debug_level = atoi (optarg); else debug_level = 1; break; case 'l': debug_file = fopen (optarg, "w"); if (debug_file == NULL) { fprintf (stderr, "%s: couldn't open file %s for writing\n", arg->me, optarg); exit (1); } break; #endif case 'F': arg->forward_port = atoi (optarg); break; case 'k': arg->keep_alive = atoi (optarg); break; case 'M': arg->max_connection_age = atoi (optarg); break; case 'h': usage (stdout, arg->me); exit (0); case 'P': name_and_port (optarg, &arg->proxy_name, &arg->proxy_port); if (arg->proxy_port == -1) arg->proxy_port = DEFAULT_PROXY_PORT; if (arg->proxy_buffer_timeout == -1) arg->proxy_buffer_timeout = DEFAULT_PROXY_BUFFER_TIMEOUT; break; case 's': arg->use_std=TRUE; arg->use_daemon=FALSE; break; case 'S': arg->strict_content_length = TRUE; break; case 'T': arg->proxy_buffer_timeout = atoi (optarg); break; case 'U': arg->user_agent = optarg; break; case 'V': printf ("htc (%s) %s\n", PACKAGE, VERSION); exit (0); case 'w': arg->use_daemon=FALSE; break; case 'z': { struct stat s; char *auth; int f; f = open (optarg, O_RDONLY); if (f == -1) { fprintf (stderr, "couldn't open %s: %s\n", optarg, strerror (errno)); exit (1); } if (fstat (f, &s) == -1) { fprintf (stderr, "error fstating %s: %s\n", optarg, strerror (errno)); exit (1); } auth = malloc (s.st_size + 1); if (auth == NULL) { fprintf (stderr, "out of memory whilst allocating " "authentication string\n"); exit (1); } if (read_all (f, auth, s.st_size) == -1) { fprintf (stderr, "error reading %s: %s\n", optarg, strerror (errno)); exit (1); } /* * If file ends with a "\r\n" or "\n", chop them off. */ if (s.st_size >= 1 && auth[s.st_size - 1] == '\n') { s.st_size -= (s.st_size >= 2 && auth[s.st_size - 2] == '\r') ? 2 : 1; } auth[s.st_size] = 0; arg->proxy_authorization = auth; } break; case '?': break; default: fprintf (stderr, "?? getopt returned character code 0%o ??\n", c); } } if (optind == argc - 1) { name_and_port (argv[optind], &arg->host_name, &arg->host_port); if (arg->host_port == -1) arg->host_port = DEFAULT_HOST_PORT; } else { fprintf (stderr, "%s: the destination of the tunnel must be specified.\n" "%s: try '%s --help' for help.\n", arg->me, arg->me, arg->me); exit (1); } if (arg->device == NULL && arg->forward_port == -1 && !arg->use_std) { fprintf (stderr, "%s: one of --device, --forward-port or --stdin-stdout must be used.\n" "%s: try '%s -help' for help.\n", arg->me, arg->me, arg->me); exit (1); } if ((arg->device != NULL && arg->forward_port != -1) || (arg->device != NULL && arg->use_std) || (arg->forward_port != -1 && arg->use_std)) { fprintf (stderr, "%s: only one of --device, --forward-port or --stdin-stdout can be used.\n" "%s: try '%s --help' for help.\n", arg->me, arg->me, arg->me); exit (1); } /* Removed test ((arg->device == NULL) == (arg->forward_port == -1)) * by Sampo Niskanen - those have been tested already! */ if (arg->host_name == NULL || arg->host_port == -1 || (arg->proxy_name != NO_PROXY && arg->proxy_port == -1)) { usage (stderr, arg->me); exit (1); } if (debug_level == 0 && debug_file != NULL) { fprintf (stderr, "%s: --logfile can't be used without debugging\n", arg->me); exit (1); } if (arg->proxy_name == NO_PROXY) { if (arg->proxy_buffer_size != NO_PROXY_BUFFER) { fprintf (stderr, "%s: warning: --proxy-buffer-size can't be " "used without --proxy\n", arg->me); arg->proxy_buffer_size = NO_PROXY_BUFFER; } if (arg->proxy_buffer_timeout != -1) { fprintf (stderr, "%s: warning: --proxy-buffer-timeout can't be " "used without --proxy\n", arg->me); arg->proxy_buffer_timeout = -1; } if (arg->proxy_authorization != NULL) { fprintf (stderr, "%s: warning: --proxy-authorization can't be " "used without --proxy\n", arg->me); arg->proxy_authorization = NULL; } } else if (arg->proxy_buffer_size == NO_PROXY_BUFFER) arg->proxy_buffer_timeout = -1; } int main (int argc, char **argv) { int s = -1; int fd = -1; Arguments arg; Tunnel *tunnel; int closed; parse_arguments (argc, argv, &arg); if ((debug_level == 0 || debug_file != NULL) && arg.use_daemon) daemon (0, 1); #ifdef DEBUG_MODE if (debug_level != 0 && debug_file == NULL) debug_file = stderr; #else openlog ("htc", LOG_PID, LOG_DAEMON); #endif log_notice ("htc (%s) %s started with arguments:", PACKAGE, VERSION); log_notice (" me = %s", arg.me); log_notice (" device = %s", arg.device ? arg.device : "(null)"); log_notice (" host_name = %s", arg.host_name ? arg.host_name : "(null)"); log_notice (" host_port = %d", arg.host_port); log_notice (" proxy_name = %s", arg.proxy_name ? arg.proxy_name : "(null)"); log_notice (" proxy_port = %d", arg.proxy_port); log_notice (" proxy_buffer_size = %d", arg.proxy_buffer_size); log_notice (" proxy_buffer_timeout = %d", arg.proxy_buffer_timeout); log_notice (" content_length = %d", arg.content_length); log_notice (" forward_port = %d", arg.forward_port); log_notice (" max_connection_age = %d", arg.max_connection_age); log_notice (" use_std = %d", arg.use_std); log_notice (" strict_content_length = %d", arg.strict_content_length); log_notice (" keep_alive = %d", arg.keep_alive); log_notice (" proxy_authorization = %s", arg.proxy_authorization ? arg.proxy_authorization : "(null)"); log_notice (" user_agent = %s", arg.user_agent ? arg.user_agent : "(null)"); log_notice (" debug_level = %d", debug_level); if (arg.forward_port != -1) { struct in_addr addr; addr.s_addr = INADDR_ANY; s = server_socket (addr, arg.forward_port, 0); log_debug ("server_socket (%d) = %d", arg.forward_port, s); if (s == -1) { log_error ("couldn't create server socket: %s", strerror (errno)); log_exit (1); } } #ifdef DEBUG_MODE signal (SIGPIPE, log_sigpipe); #else signal (SIGPIPE, SIG_IGN); #endif for (;;) { time_t last_tunnel_write; if (arg.device) { fd = open_device (arg.device); log_debug ("open_device (\"%s\") = %d", arg.device, fd); if (fd == -1) { log_error ("couldn't open %s: %s", arg.device, strerror (errno)); log_exit (1); } /* Check that fd is not 0 (clash with --stdin-stdout) */ if (fd == 0) { log_notice("changing fd from %d to 3",fd); if (dup2(fd,3) != 3) { log_error ("couldn't dup2(%d,3): %s",fd,strerror(errno)); log_exit (1); } } } else if (arg.forward_port != -1) { log_debug ("waiting for connection on port %d", arg.forward_port); fd = wait_for_connection_on_socket (s); log_debug ("wait_for_connection_on_socket (%d) = %d", s, fd); if (fd == -1) { log_error ("couldn't forward port %d: %s", arg.forward_port, strerror (errno)); log_exit (1); } /* Check that fd is not 0 (clash with --stdin-stdout) */ if (fd == 0) { log_notice("changing fd from %d to 3",fd); if (dup2(fd,3) != 3) { log_error ("couldn't dup2(%d,3): %s",fd,strerror(errno)); log_exit (1); } } } else if (arg.use_std) { log_debug ("using stdin as fd"); fd = 0; if (fcntl(fd,F_SETFL,O_NONBLOCK)==-1) { log_error ("couldn't set stdin to non-blocking mode: %s", strerror(errno)); log_exit (1); } /* Usage of stdout (fd = 1) is checked later. */ } log_debug ("creating a new tunnel"); tunnel = tunnel_new_client (arg.host_name, arg.host_port, arg.proxy_name, arg.proxy_port, arg.content_length); if (tunnel == NULL) { log_error ("couldn't create tunnel"); log_exit (1); } if (tunnel_setopt (tunnel, "strict_content_length", &arg.strict_content_length) == -1) log_debug ("tunnel_setopt strict_content_length error: %s", strerror (errno)); if (tunnel_setopt (tunnel, "keep_alive", &arg.keep_alive) == -1) log_debug ("tunnel_setopt keep_alive error: %s", strerror (errno)); if (tunnel_setopt (tunnel, "max_connection_age", &arg.max_connection_age) == -1) log_debug ("tunnel_setopt max_connection_age error: %s", strerror (errno)); if (arg.proxy_authorization != NULL) { ssize_t len; char *auth; len = encode_base64 (arg.proxy_authorization, strlen (arg.proxy_authorization), &auth); if (len == -1) { log_error ("encode_base64 error: %s", strerror (errno)); } else { char *str = malloc (len + 7); if (str == NULL) { log_error ("out of memory when encoding " "authorization string"); log_exit (1); } strcpy (str, "Basic "); strcat (str, auth); free (auth); if (tunnel_setopt (tunnel, "proxy_authorization", str) == -1) log_error ("tunnel_setopt proxy_authorization error: %s", strerror (errno)); free (str); } } if (arg.user_agent != NULL) { if (tunnel_setopt (tunnel, "user_agent", arg.user_agent) == -1) log_error ("tunnel_setopt user_agent error: %s", strerror (errno)); } if (tunnel_connect (tunnel) == -1) { log_error ("couldn't open tunnel: %s", strerror (errno)); log_exit (1); } if (arg.proxy_name) log_notice ("connected to %s:%d via %s:%d", arg.host_name, arg.host_port, arg.proxy_name, arg.proxy_port); else log_notice ("connected to %s:%d", arg.host_name, arg.host_port); closed = FALSE; time (&last_tunnel_write); while (!closed) { struct pollfd pollfd[2]; int keep_alive_timeout; int timeout; time_t t; int n; pollfd[0].fd = fd; pollfd[0].events = POLLIN; pollfd[1].fd = tunnel_pollin_fd (tunnel); pollfd[1].events = POLLIN; time (&t); timeout = 1000 * (arg.keep_alive - (t - last_tunnel_write)); keep_alive_timeout = TRUE; if (timeout < 0) timeout = 0; if (arg.proxy_buffer_timeout != -1 && arg.proxy_buffer_timeout < timeout) { timeout = arg.proxy_buffer_timeout; keep_alive_timeout = FALSE; } log_annoying ("poll () ..."); n = poll (pollfd, 2, timeout); log_annoying ("... = %d", n); if (n == -1) { log_error ("poll error: %s", strerror (errno)); log_exit (1); } else if (n == 0) { log_verbose ("poll() timed out"); if (keep_alive_timeout) { tunnel_padding (tunnel, 1); time (&last_tunnel_write); } else { if (tunnel_maybe_pad (tunnel, arg.proxy_buffer_size) > 0) time (&last_tunnel_write); } continue; } handle_input ("device or port", tunnel, fd, pollfd[0].revents, handle_device_input, &closed); handle_input ("tunnel", tunnel, fd, pollfd[1].revents, handle_tunnel_input, &closed); if (pollfd[0].revents & POLLIN) time (&last_tunnel_write); } log_debug ("destroying tunnel"); if (fd != 0) { close (fd); } tunnel_destroy (tunnel); if (arg.proxy_name) log_notice ("disconnected from %s:%d via %s:%d", arg.host_name, arg.host_port, arg.proxy_name, arg.proxy_port); else log_notice ("disconnected from %s%d", arg.host_name, arg.host_port); } log_debug ("closing server socket"); close (s); log_exit (0); }