=================================================================== RCS file: /src/master/socks/Makefile,v retrieving revision 1.1.1.3 diff -u -r1.1.1.3 Makefile --- 1.1.1.3 1995/05/19 00:37:38 +++ Makefile 1995/05/19 01:51:56 @@ -3,19 +3,19 @@ SHELL=/bin/sh -#SOCKS=-DSOCKS +SOCKS=-DSOCKS # or -SOCKS=-Dconnect=Rconnect -Dgetsockname=Rgetsockname -Dlisten=Rlisten -Daccept=Raccept -Drcmd=Rrcmd -Dbind=Rbind -Dselect=Rselect +#SOCKS=-Dconnect=Rconnect -Dgetsockname=Rgetsockname -Dlisten=Rlisten -Daccept=Raccept -Drcmd=Rrcmd -Dbind=Rbind -Dselect=Rselect # If the second definition of SOCKS is used, you MUST also # define SHORTENED_RBIND # Define SHORTENED_RBIND to make Rbind() take exactly the same # argument list as the regular bind(), i.e., without the additional # 'remhost' argument. -SHORTENED_RBIND=-DSHORTENED_RBIND +#SHORTENED_RBIND=-DSHORTENED_RBIND # If your system doesn't have PWD defined, define it here: -#PWD=/projects/insg/socks.cstc.4.2beta +PWD=/home/seth/src/proj/SOF/clients/socks.cvs # It should be this current directory. # If your system has getcwd() but no getwd(), uncomment the next line: @@ -26,22 +26,22 @@ # Define RCMD and SUPPORT_RCMD if you want to support Rrcmd, which is required # for SOCKSified rlogin, rsh, and rcp. -#RCMD=Rrcmd.o -#SUPPORT_RCMD=-DSUPPORT_RCMD +RCMD=Rrcmd.o +SUPPORT_RCMD=-DSUPPORT_RCMD # Define FOR_PS if your system is not SYSV and you want to have the # command 'ps' show some details of sockd's activity. -#FOR_PS=-DFOR_PS +FOR_PS=-DFOR_PS # optimization flag for cc -OPTIMIZE=-g +OPTIMIZE=-g -O #OPTIMIZE=-O # Be careful with the OPTIMIZE flag. SunPro's SC2.0.1, for example, is # knwon to produce incorrect code when -O is used. # Define NO_CLIENT_LOG if you don't want SOCKS clients to produce # log entries of its activities. -#NO_CLIENT_LOG= -Dopenlog=socks_0openlog -Dsyslog=socks_0syslog -Dcloselog=socks_0closelog +NO_CLIENT_LOG= -Dopenlog=socks_0openlog -Dsyslog=socks_0syslog -Dcloselog=socks_0closelog # Define DNS_THROUGH_NIS if your SOCKS client hosts let their NIS # servers do the DNS loopkup for them. You are in this category if @@ -53,28 +53,29 @@ # or 'h_errno redefined' error message, # this is the macro to change. Define it or undefine it, whichever # works. The reasons are too messy to explain. -#BIND_RESOLVER=-DBIND_RESOLVER +BIND_RESOLVER=-DBIND_RESOLVER # Directory into which to install the man pages MAN_DEST_DIR = /usr/local/man # Directory into which the SOCKS server should be installed -SERVER_BIN_DIR = /usr/etc +SERVER_BIN_DIR = /tmp # Directory into the client programs should be installed CLIENTS_BIN_DIR = /usr/local/bin +# Common options to use with CFLAGS +COMMON_FLAGS=-DUSE_REQUESTED_PORT -DUSE_PASV -DSOME_NODELAY + # SunOS 4.1.x should use -CC=cc -#CC=gcc -OTHER_CFLAGS= $(GETCWD) $(FASCIST) $(SHORTENED_RBIND) -DCOMPAT $(DEBUG) +#CC=cc +CC=gcc +OTHER_CFLAGS= -static $(GETCWD) $(FASCIST) $(SHORTENED_RBIND) -DCOMPAT $(DEBUG) RANLIB=ranlib OS=sun4.1 INSTALL=install GETPASS=getpass.o -RESOLV_LIB=-lresolv -# ... or -#RESOLV_LIB= +RESOLV_LIB=-lresolv -l44bsd # IRIX 4 should use #CC=cc @@ -139,11 +140,11 @@ #GETPASS= # SOLARIS should use -#CC=cc -#RESOLV_LIB=-lresolv -lnsl -lsocket -#OTHER_CFLAGS=-DSOLARIS -Dindex=strchr -Drindex=strrchr $(SHORTENED_RBIND) -DUSE_DIRENT $(GETCWD) $(FASCIST) -DCOMPAT +#CC=gcc +#RESOLV_LIB=-L/usr/local/lib -lnsl -lsocket -lresolv -l44bsd +#OTHER_CFLAGS=-DSOLARIS -Dindex=strchr -Drindex=strrchr $(SHORTENED_RBIND) -DCOMPAT -DHAVE_STRERROR -DUSE_DIRENT $(GETCWD) $(FASCIST) -DUSE_REQUESTED_PORT -DUSE_PASV -DSOME_NODELAY -DBIND_RESOLVER -I/usr/local/include #RANLIB=/bin/true -#OS=solaris2.2 +#OS=solaris2.3 #INSTALL=install #GETPASS=getpass.o @@ -322,7 +323,7 @@ OPTIMIZE="$(OPTIMIZE)" \ SOCKS_LIB="$(SOCKS_LIB)" SUPPORT_RCMD="$(SUPPORT_RCMD)" \ IDENT_LIB="$(IDENT_LIB)" \ - OTHER_CFLAGS="$(OTHER_CFLAGS) $(FOR_PS)") + OTHER_CFLAGS="$(COMMON_FLAGS) $(OTHER_CFLAGS) $(FOR_PS)") clients: RFINGER RFTP RTELNET @@ -331,11 +332,11 @@ OPTIMIZE="$(OPTIMIZE)" \ RCMD="$(RCMD)" SUPPORT_RCMD="$(SUPPORT_RCMD)" \ DNS_THROUGH_NIS="$(DNS_THROUGH_NIS)" \ - OTHER_CFLAGS="$(OTHER_CFLAGS) $(NO_CLIENT_LOG) $(BIND_RESOLVER)" \ + OTHER_CFLAGS="$(COMMON_FLAGS) $(OTHER_CFLAGS) $(NO_CLIENT_LOG) $(BIND_RESOLVER)" \ RANLIB="$(RANLIB)") LIBIDENT: - (cd libident; $(MAKE) CC="$(CC)" OTHER_CFLAGS="$(OTHER_CFLAGS)" \ + (cd libident; $(MAKE) CC="$(CC)" OTHER_CFLAGS="$(COMMON_FLAGS) $(OTHER_CFLAGS)" \ OPTIMIZE="$(OPTIMIZE)" RANLIB="$(RANLIB)") # This also build rwhois @@ -343,19 +344,19 @@ (cd rfinger; $(MAKE) CC="$(CC)" $(WHOIS_SERVER) \ OPTIMIZE="$(OPTIMIZE)" SOCKS="$(SOCKS)" \ RESOLV_LIB="$(RESOLV_LIB)" SOCKS_LIB="$(SOCKS_LIB)" \ - OTHER_CFLAGS="$(OTHER_CFLAGS) $(NO_CLIENT_LOG)") + OTHER_CFLAGS="$(COMMON_FLAGS) $(OTHER_CFLAGS) $(NO_CLIENT_LOG)") RTELNET: LIB (cd rtelnet; $(MAKE) CC="$(CC)" OS="$(OS)" SOCKS_LIB="$(SOCKS_LIB)" \ OPTIMIZE="$(OPTIMIZE)" SOCKS="$(SOCKS)" \ RESOLV_LIB="$(RESOLV_LIB)" \ - OTHER_CFLAGS="$(OTHER_CFLAGS) $(NO_CLIENT_LOG)") + OTHER_CFLAGS="$(COMMON_FLAGS) $(OTHER_CFLAGS) $(NO_CLIENT_LOG)") RFTP: LIB (cd rftp; $(MAKE) CC="$(CC)" SOCKS_LIB="$(SOCKS_LIB)" \ OPTIMIZE="$(OPTIMIZE)" SOCKS="$(SOCKS)" \ RESOLV_LIB="$(RESOLV_LIB)" \ - OTHER_CFLAGS="$(OTHER_CFLAGS) $(NO_CLIENT_LOG) $(BIND_RESOLVER)") + OTHER_CFLAGS="$(COMMON_FLAGS) $(OTHER_CFLAGS) $(NO_CLIENT_LOG) $(BIND_RESOLVER)") install.server: (cd sockd; $(MAKE) INSTALL="$(INSTALL)" MAN_DEST_DIR="$(MAN_DEST_DIR)" \ @@ -363,7 +364,7 @@ OPTIMIZE="$(OPTIMIZE)" \ SOCKS_LIB="$(SOCKS_LIB)" SUPPORT_RCMD="$(SUPPORT_RCMD)" \ IDENT_LIB="$(IDENT_LIB)" \ - OTHER_CFLAGS="$(OTHER_CFLAGS) $(FOR_PS)" \ + OTHER_CFLAGS="$(COMMON_FLAGS) $(OTHER_CFLAGS) $(FOR_PS)" \ SERVER_BIN_DIR="$(SERVER_BIN_DIR)" install install.man) install.clients: install.man @@ -374,7 +375,7 @@ RCMD="$(RCMD)" SUPPORT_RCMD="$(SUPPORT_RCMD)" \ DNS_THROUGH_NIS="$(DNS_THROUGH_NIS)" \ RESOLV_LIB="$(RESOLV_LIB)" \ - OTHER_CFLAGS="$(OTHER_CFLAGS) $(NO_CLIENT_LOG)" \ + OTHER_CFLAGS="$(COMMON_FLAGS) $(OTHER_CFLAGS) $(NO_CLIENT_LOG)" \ CLIENTS_BIN_DIR="$(CLIENTS_BIN_DIR)" \ install) done install.man: =================================================================== RCS file: /src/master/socks/include/socks.h,v retrieving revision 1.1.1.3 diff -u -r1.1.1.3 socks.h --- 1.1.1.3 1995/05/19 00:37:55 +++ socks.h 1995/05/19 01:06:21 @@ -6,7 +6,7 @@ * This is overridden at run time by the contents of environment * variable SOCKS_SERVER if it exists. */ -#define SOCKS_DEFAULT_SERVER "SOCKS.server.for.your.site" +#define SOCKS_DEFAULT_SERVER "localhost" /* * Default Domain Nameserver for the SOCKS clients. @@ -73,7 +73,7 @@ /* ** How long (in seconds) to keep a connection around while it is idle */ -#define SOCKS_TIMEOUT 2*60*60 /* 2hr in seconds */ +#define SOCKS_TIMEOUT 3*24*60*60 /* 3day in seconds */ /* How long before connection attempts timed out */ #define CLIENT_CONN_TIMEOUT 60*2 /* 2 minutes */ @@ -106,7 +106,7 @@ /* Current SOCKS protocol version */ #define SOCKS_VERSION 4 -#define CSTC_RELEASE "4.2" +#define CSTC_RELEASE "4.2 (sos)" /* ** Response commands/codes =================================================================== RCS file: /src/master/socks/lib/Rconnect.c,v retrieving revision 1.1.1.3 diff -u -r1.1.1.3 Rconnect.c --- 1.1.1.3 1995/05/19 00:37:58 +++ Rconnect.c 1995/05/19 01:06:23 @@ -651,14 +651,22 @@ remhost = dsthost; socks_saddrtoname(&remhost, socks_dst_name, sizeof(socks_dst_name)); #endif /* #ifdef SHORTENED_RBIND */ +#ifdef USE_REQUESTED_PORT + socks_porttoserv(lport, socks_dst_serv, sizeof(socks_dst_serv)); +#else /*USE_REQUESTED_PORT*/ socks_porttoserv(socks_last_conn_port, socks_dst_serv, sizeof(socks_dst_serv)); +#endif /*USE_REQUESTED_PORT*/ #ifdef DEBUG fprintf(stderr, "Rbind 100, lport=%u, socks_dst_name=>%s<, socks_dst_serv=>%s<\n", lport, socks_dst_name, socks_dst_serv); fprintf(stderr, "Rbind(%d, %s, %s)\n", sock, socks_dst_name, socks_dst_serv); #endif /* #ifdef DEBUG */ psin.sin_addr.s_addr = remhost; +#ifdef USE_REQUESTED_PORT + psin.sin_port = htons(lport); +#else /*USE_REQUESTED_PORT*/ psin.sin_port = socks_last_conn_port; +#endif #ifdef VERSATILE_CLIENTS direct = socks_check_cconf(&me, &psin); #ifdef DEBUG @@ -735,7 +743,11 @@ dst.version = SOCKS_VERSION; dst.cmd = SOCKS_BIND; +#ifdef USE_REQUESTED_PORT + dst.port = htons(lport); +#else /*USE_REQUESTED_PORT*/ dst.port = socks_last_conn_port; +#endif /*USE_REQUESTED_PORT*/ dst.host = remhost; if (socksC_proto(sock, &dst) < 0) return(-1); =================================================================== RCS file: /src/master/socks/lib/check_user.c,v retrieving revision 1.1.1.3 diff -u -r1.1.1.3 check_user.c --- 1.1.1.3 1995/05/19 00:38:07 +++ check_user.c 1995/05/19 01:06:24 @@ -1,5 +1,3 @@ -#include "socks.h" - #include /* >>> K. Shackelford */ #if defined(hpux) || defined(AIX) || defined(DGUX) @@ -14,6 +12,10 @@ #else #include #endif +#include +#include + +#include "socks.h" #ifdef SOLARIS #include "bstring.h" @@ -144,8 +146,6 @@ return 0; } -#include -#include static int check_userfile(userfile, src_user) char *userfile, *src_user; =================================================================== RCS file: /src/master/socks/lib/getpass.c,v retrieving revision 1.1.1.1 diff -u -r1.1.1.1 getpass.c --- 1.1.1.1 1994/11/14 20:43:06 +++ getpass.c 1995/04/10 20:07:33 @@ -37,6 +37,9 @@ #ifdef SVR3 #include #else +#ifdef __bsdi__ +#include +#endif #include #endif #include =================================================================== RCS file: /src/master/socks/rftp/ftp.c,v retrieving revision 1.1.1.3 diff -u -r1.1.1.3 ftp.c --- 1.1.1.3 1995/05/19 00:38:24 +++ ftp.c 1995/05/19 01:06:26 @@ -35,24 +35,6 @@ static char sccsid[] = "@(#)ftp.c 5.38 (Berkeley) 4/22/91"; #endif /* not lint */ -#if defined(SOCKS) -#define connect Rconnect -#define getsockname Rgetsockname -#define listen Rlisten -#define accept Raccept -#define rcmd Rrcmd -# if defined(SHORTENED_RBIND) -#define bind Rbind -# else /* SHORTENED_RBIND not defined */ -/* - * Be sure to put in socks_bind_remoteAddr (32-bit integer) the IP - * address (in network byte order) of the host it is aiming for, - * which is typically the destination host of the previous connect(). - */ -#define bind(a,b,c) Rbind(a,b,c,socks_bind_remoteAddr) -# endif /* # if defined(SHORTENED_RBIND) */ -#endif /* #if defined(SOCKS) */ - #include #include #include @@ -94,6 +76,25 @@ #define bcmp(b1,b2,len) memcmp(b1, b2, (size_t)(len)) #endif +#if defined(SOCKS) +#define connect Rconnect +#define getsockname Rgetsockname +#define listen Rlisten +#define accept Raccept +#define rcmd Rrcmd +# if defined(SHORTENED_RBIND) +#define bind Rbind +# else /* SHORTENED_RBIND not defined */ +/* + * Be sure to put in socks_bind_remoteAddr (32-bit integer) the IP + * address (in network byte order) of the host it is aiming for, + * which is typically the destination host of the previous connect(). + */ +#define bind(a,b,c) Rbind(a,b,c,socks_bind_remoteAddr) +# endif /* # if defined(SHORTENED_RBIND) */ +#endif /* #if defined(SOCKS) */ + + struct sockaddr_in hisctladdr; struct sockaddr_in data_addr; int data = -1; @@ -1136,10 +1137,58 @@ */ initconn() { +#ifdef USE_PASV + struct sockaddr_in from; + int a1,a2,a3,a4,p1,p2; +#endif register char *p, *a; int result, len, tmpno = 0; int on = 1; +#ifdef USE_PASV + data = socket(AF_INET, SOCK_STREAM, 0); + if (data < 0) { + perror("ftp: socket"); + return(1); + } + if (options & SO_DEBUG && + setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof (on)) < 0) + perror("ftp: setsockopt (ignored)"); + if (command("PASV") != COMPLETE) { + printf("Passive mode refused.\n"); + return(1); + } + +/* + * What we've got at this point is a string of comma separated + * one-byte unsigned integer values, separated by commas. + * The first four are the an IP address. The fifth is the MSB + * of the port number, the sixth is the LSB. From that we'll + * prepare a sockaddr_in. + */ + + if (sscanf(pasv,"%d,%d,%d,%d,%d,%d",&a1,&a2,&a3,&a4,&p1,&p2) != 6) { + printf("Passive mode address scan failure. Shouldn't happen!\n"); + return(1); + }; + + data_addr.sin_family = AF_INET; + data_addr.sin_addr.s_addr = htonl((a1<<24)|(a2<<16)|(a3<<8)|a4); + data_addr.sin_port = htons((p1<<8)|p2); + + if(Rconnect(data, (struct sockaddr *) &data_addr, sizeof(data_addr))<0){ + perror("ftp: connect"); + return(1); + } +#ifdef IP_TOS + on = IPTOS_THROUGHPUT; + if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0) + perror("ftp: setsockopt TOS (ignored)"); +#endif + return(0); + +/* End of PASV initconn() */ +#else noport: data_addr = myctladdr; if (sendport) @@ -1200,6 +1249,8 @@ if (tmpno) sendport = 1; return (1); +/* End of if not PASV */ +#endif } FILE * @@ -1209,6 +1260,9 @@ struct sockaddr_in from; int s, fromlen = sizeof (from), tos; +#ifdef USE_PASV + return (fdopen(data,lmode)); +#else s = accept(data, (struct sockaddr *) &from, &fromlen); if (s < 0) { perror("ftp: accept"); @@ -1223,6 +1277,7 @@ perror("ftp: setsockopt TOS (ignored)"); #endif return (fdopen(data, lmode)); +#endif /*PASV*/ } ptransfer(direction, bytes, t0, t1) =================================================================== RCS file: /src/master/socks/rftp/ftp_var.h,v retrieving revision 1.1.1.2 diff -u -r1.1.1.2 ftp_var.h --- 1.1.1.2 1995/05/19 00:38:26 +++ ftp_var.h 1995/05/19 01:06:28 @@ -146,6 +146,7 @@ #if defined (COMPAT) || defined (ultrix) || defined(SCO) typedef void (*sig_t)(); +#if !defined (HAVE_STRERROR) static char *strerror(errnum) { extern int sys_nerr; extern char *sys_errlist[]; @@ -153,4 +154,5 @@ return (errnum < sys_nerr && errnum >= 0 ? sys_errlist[errno] : "UNDEFINED"); } +#endif #endif =================================================================== RCS file: /src/master/socks/rftp/glob.c,v retrieving revision 1.1.1.2 diff -u -r1.1.1.2 glob.c --- 1.1.1.2 1995/05/19 00:38:27 +++ glob.c 1995/05/19 01:06:29 @@ -235,7 +235,7 @@ register struct dirent *dp; DIR *dirp; -#if defined(sgi) || defined(hpux) || defined(__osf__) +#if defined(sgi) || defined(hpux) || defined(__osf__) || defined(SOLARIS) /* IRIX opendir() does not accept a null directory string to mean the current directory. Must use ".". But leave =================================================================== RCS file: /src/master/socks/sockd/sockd.c,v retrieving revision 1.1.1.3 diff -u -r1.1.1.3 sockd.c --- 1.1.1.3 1995/05/19 00:39:37 +++ sockd.c 1995/05/19 01:06:32 @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -303,8 +304,28 @@ #endif /* LOG_DAEMON */ #else in = dup(0); + #endif /* NOT_THROUGH_INETD */ +#ifdef ALWAYS_NODELAY + /* TCP NO_DELAY--prevent buffered I/O */ + { + struct protoent *p; + int one=1; + + if (!(p = getprotobyname("tcp"))) + { + perror("getproto"); + exit(2); + } + if(setsockopt(in, p->p_proto, TCP_NODELAY, (char *)&one, sizeof(one)) < 0) + { + perror("setsockopt"); + exit(2); + } + } +#endif /* NO_NODELAY */ + if (getpeername(in, (struct sockaddr *)&from, &fromlen) < 0) { syslog(LOG_HIGH, "error -- unable to get client address."); exit(1); @@ -472,10 +493,54 @@ socks_fail("socket()", in, &ndst); #endif /* #if defined(SUPPORT_RCMD) */ +#ifdef ALWAYS_NODELAY + /* TCP NO_DELAY--prevent buffered I/O */ + { + struct protoent *p; + int one=1; + + if (!(p = getprotobyname("tcp"))) + { + perror("getproto"); + exit(2); + } + if(setsockopt(out, p->p_proto, TCP_NODELAY, (char *)&one, sizeof(one)) < 0) + { + perror("setsockopt"); + exit(2); + } + } +#endif /*NONODELAY*/ + sin.sin_family = AF_INET; sin.sin_port = dst->port; sin.sin_addr.s_addr = dst->host; +#ifdef SOME_NODELAY /* NODELAY only on telnet */ + /* TCP NO_DELAY--prevent buffered I/O */ + if (dst->port == 23) + { + struct protoent *p; + int one=1; + + if (!(p = getprotobyname("tcp"))) + { + perror("getproto"); + exit(2); + } + if(setsockopt(in, p->p_proto, TCP_NODELAY, (char *)&one, sizeof(one)) < 0) + { + perror("setsockopt"); + exit(2); + } + if(setsockopt(out, p->p_proto, TCP_NODELAY, (char *)&one, sizeof(one)) < 0) + { + perror("setsockopt"); + exit(2); + } + } +#endif /*SOME_NODELAY*/ + ndst.version = Version; ndst.cmd = SOCKS_RESULT; @@ -519,7 +584,11 @@ sin.sin_family = AF_INET; ndst.version = Version; ndst.cmd = SOCKS_RESULT; +#ifdef USE_REQUESTED_PORT + sin.sin_port = htons(dst->port); +#else /*USE_REQUESTED_PORT*/ sin.sin_port = htons(0); +#endif /*USE_REQUESTED_PORT*/ #ifdef MULTIHOMED_SERVER sin.sin_addr = sockd_route(dst->host); #else @@ -553,6 +622,25 @@ if ((out = socket(AF_INET, SOCK_STREAM, 0)) < 0) socks_fail("socket()", in, &ndst); +#ifdef ALWAYS_NODELAY + /* TCP NO_DELAY--prevent buffered I/O */ + { + struct protoent *p; + int one=1; + + if (!(p = getprotobyname("tcp"))) + { + perror("getproto"); + exit(2); + } + if(setsockopt(lsock, p->p_proto, TCP_NODELAY, (char *)&one, sizeof(one)) < 0) + { + perror("setsockopt"); + exit(2); + } + } +#endif /*NO_NODELAY*/ + if (bind(out, (struct sockaddr *)&sin, sizeof(sin)) < 0) socks_fail("bind()", in, &ndst); if (getsockname(out, (struct sockaddr *)&sin, &len) < 0) @@ -623,6 +711,8 @@ /* >>> Andy McFadden fadden@uts.amdahl.com */ struct linger ling; /* for linger */ int length; /* for linger */ + int in_shutdown = 0; + int out_shutdown = 0; alarm(0); @@ -644,12 +734,16 @@ else fdsbits = out +1; - while (1) { + while (!in_shutdown || !out_shutdown) { tout.tv_sec = SOCKS_TIMEOUT; tout.tv_usec = 0; - FD_SET(in, &fds); - FD_SET(out, &fds); - if ((s = select(fdsbits, &fds, NULL,NULL, &tout)) > 0) { + FD_ZERO(&fds); + if (!in_shutdown) + FD_SET(in, &fds); + if (!out_shutdown) + FD_SET(out, &fds); + + if ((n = select(fdsbits, &fds, NULL,NULL, &tout)) > 0) { if (FD_ISSET(in, &fds)) { if ((n = read(in, buf, sizeof buf)) > 0) { from_in += n; @@ -657,7 +751,14 @@ goto bad; } } else { - goto bad; + /* + * EOF on read from in. + * shutdown outgoing out + * shutdown incoming in + */ + shutdown(out,1); + shutdown(in,0); + in_shutdown++; } } if (FD_ISSET(out, &fds)) { @@ -667,7 +768,14 @@ goto bad; } } else { - goto bad; + /* + * EOF on read from out. + * shutdown incoming out + * shutdown outgoing in + */ + shutdown(in,1); + shutdown(out,0); + out_shutdown++; } } } else if ((s == 0) || ((s < 0) && (errno == EINTR))) {