diff -u -r stunnel-3.14.bak/common.h stunnel-3.14.new/common.h --- stunnel-3.14.bak/common.h Fri Apr 13 15:48:54 2001 +++ stunnel-3.14.new/common.h Fri Apr 13 23:26:04 2001 @@ -182,6 +182,7 @@ int clients; int option; int foreground; /* force messages to stderr */ + char remotetarget[STRLEN]; unsigned short localport, remoteport; u32 *localnames, *remotenames; char *execname, **execargs; /* program name and arguments for local mode */@@ -202,6 +203,7 @@ int random_bytes; /* how many random bytes to read */ char *pid_dir; int cert_defaults; + int delay_host_lookup; } server_options; /* Prototypes for stunnel.c */ diff -u -r stunnel-3.14.bak/stunnel.c stunnel-3.14.new/stunnel.c --- stunnel-3.14.bak/stunnel.c Fri Apr 13 15:48:54 2001 +++ stunnel-3.14.new/stunnel.c Fri Apr 13 23:34:41 2001 @@ -113,9 +113,9 @@ #ifndef USE_WIN32 static int make_sockets(int [2]); #endif -static void name2nums(char *, u32 **, u_short *); +static int name2nums(char *, u32 **, u_short *); static u_short port2num(char *); -static void host2num(u32 **, char *); +static int host2num(u32 **, char *); /* Error/exceptions handling functions */ static void ioerror(char *); @@ -215,6 +215,11 @@ return 0; /* success */ } +static struct option longopts[] = { + {"delay-host-lookup", no_argument, + &options.delay_host_lookup, 1}, + {NULL, 0, NULL, 0}}; + static void get_options(int argc, char *argv[]) { /* get options and set global variables */ int c; @@ -242,8 +247,12 @@ options.rand_file=NULL; options.rand_write=1; options.random_bytes=RANDOM_BYTES; + options.delay_host_lookup=0; + options.remotenames=NULL; opterr=0; - while ((c = getopt(argc, argv, "A:a:cp:v:d:fTl:L:r:s:g:t:u:n:N:hC:D:E:R:WB:VP:S:")) != EOF) + while ((c = getopt_long(argc, argv, + "A:a:cp:v:d:fTl:L:r:s:g:t:u:n:N:hC:D:E:R:WB:VP:S:", + longopts, NULL)) != EOF) switch (c) { case 'A': safecopy(options.cert_file,optarg); @@ -289,7 +298,11 @@ } options.option|=OPT_DAEMON; options.localnames=NULL; - name2nums(optarg, &options.localnames, &options.localport); + if (!name2nums(optarg, + &options.localnames, &options.localport)) { + sockerror("gethostbyname"); + exit(1); + } if(!options.localnames) { alloc(&options.localnames, 1); options.localnames[0]=htonl(INADDR_ANY); @@ -337,12 +350,7 @@ safecopy(options.servname, optarg); safestring(options.servname); } - options.remotenames=NULL; - name2nums(optarg, &options.remotenames, &options.remoteport); - if (!options.remotenames) { - alloc(&options.remotenames, 1); - options.remotenames[0] = htonl(INADDR_LOOPBACK); - } + safecopy(options.remotetarget, optarg); break; case 's': options.setuid_user=optarg; @@ -381,6 +389,8 @@ case 'P': options.pid_dir=optarg; break; + case 0: + break; case '?': log(LOG_ERR, "Illegal option: '%c'", optopt); case 'h': @@ -433,6 +443,19 @@ if ( servname_selected ) { safecopy(options.servname, servname_selected); } + if (! options.delay_host_lookup) { + if (options.option & OPT_REMOTE) { + if (!name2nums(options.remotetarget, + &options.remotenames, &options.remoteport)) { + sockerror("gethostbyname"); + exit(1); + } + if (!options.remotenames) { + alloc(&options.remotenames, 1); + options.remotenames[0] = htonl(INADDR_LOOPBACK); + } + } + } } static void daemon_loop() @@ -740,6 +763,22 @@ } } + if (options.delay_host_lookup) { + if (!options.remotenames) { + free(options.remotenames); + options.remotenames=NULL; + } + if (!name2nums(options.remotetarget, + &options.remotenames, &options.remoteport)) { + sockerror("gethostbyname"); + return -1; + } + if (!options.remotenames) { + alloc(&options.remotenames, 1); + options.remotenames[0] = htonl(INADDR_LOOPBACK); + } + } + addr.sin_port=options.remoteport; /* connect each host from the list*/ @@ -867,17 +906,18 @@ } #endif -static void name2nums(char *name, u32 **names, u_short *port) +static int name2nums(char *name, u32 **names, u_short *port) { char hostname[STRLEN], *portname; safecopy(hostname, name); if((portname=strrchr(hostname, ':'))) { *portname++='\0'; - host2num(names, hostname); *port=port2num(portname); + return host2num(names, hostname); } else { *port=port2num(hostname); /* no ':' - use default host IP */ + return 1; } } @@ -897,7 +937,7 @@ return port; } -static void host2num(u32 **hostlist, char *hostname) +static int host2num(u32 **hostlist, char *hostname) { /* get list of host addresses */ struct hostent *h; u32 ip; @@ -908,12 +948,11 @@ if(ip!=-1) { /* dotted decimal */ alloc(hostlist, 1); (*hostlist)[0]=ip; - return; + return 1; } /* not dotted decimal - we have to call resolver */ if(!(h=gethostbyname(hostname))) { /* get list of addresses */ - sockerror("gethostbyname"); - exit(1); + return 0; } i=0; tab=h->h_addr_list; @@ -922,6 +961,7 @@ alloc(hostlist, i); /* allocate memory */ while(--i>=0) (*hostlist)[i]=*(u32 *)(h->h_addr_list[i]); + return 1; } static void ioerror(char *txt) /* Input/Output error handler */ @@ -1092,6 +1132,8 @@ #ifndef USE_WIN32 "[-P { dir/ | filename | none } ] " + "\n\t" + "[--delay-host-lookup] " "\n\t[-d [host:]port [-f] ] " "\n\t[-r [host:]port | { -l | -L } program [-- args] ] " #else @@ -1110,6 +1152,8 @@ "\n -l program\t execute local inetd-type program" "\n -L program\t open local pty and execute program" #endif + "\n --delay-host-lookup" + "\n\t\t doesn't performs hostname lookups until a connection is made" "\n" "\n -c\t\tclient mode (remote service uses SSL)" #ifndef USE_WIN32 diff -u -r stunnel-3.14.bak/stunnel.sdf stunnel-3.14.new/stunnel.sdf --- stunnel-3.14.bak/stunnel.sdf Fri Apr 13 15:48:54 2001 +++ stunnel-3.14.new/stunnel.sdf Fri Apr 13 23:21:09 2001 @@ -21,6 +21,7 @@ S<[-g setgid_group]> S<[-n protocol]> S<[-P { dir/ | filename | none } ]> + S<[--delay-host-lookup]> S<[-B bytes]> S<[-R randfile]> S<[-W]> @@ -266,6 +267,25 @@ connect to remote service If no host specified, defaults to localhost. + +=item B<--delay-host-lookup> + +Without this option, the remote service hostname is resolved into an +IP address immediately upon startup, and a failed hostname lookup is a +fatal error. Specifying this option, which only makes sense with +B<-r>, causes stunnel to delay the hostname lookup until it actually +has a connection to tunnel. Futhermore, it will repeat the hostname +lookup for every connection attempt, rather than caching the result. +A failed host lookup triggers only a dropped connection; however, +connections may appear to hang while waiting for a slow lookup. + +This option is useful for laptops and other intermittently connected +systems that might not be able to successfully complete a DNS lookup +when stunnel is started. It's also useful if the lifetime of the +program is significantly longer than the TTL of the DNS records (i.e, +if dynamic DNS is in use), so the host lookup should be repeated for +each new connection. + =back