Example #1
0
/**
 * @brief
 *	Open a connection with a pbs server.
 *	Do not allow TCP to block us if Server host is down
 *	At this point, this does not attempt to find a fail_over Server
 *
 * @param[in]   server - specifies the server to which to connect
 * @param[in]   tout - timeout value for select
 *
 * @return int
 * @retval >= 0	index to the internal connection table representing the
 *		connection made.
 * @retval -1	error encountered in getting index
 */
int
pbs_connect_noblk(char *server, int tout)
{
	int out;
	int i;
	pbs_socklen_t l;
	int n;
	struct timeval tv;
	fd_set fdset;
	struct batch_reply *reply;
	char server_name[PBS_MAXSERVERNAME+1];
	unsigned int server_port;
	struct addrinfo *aip, *pai;
	struct addrinfo hints;
	struct sockaddr_in *inp;
	short int connect_err = 0;

	struct sockaddr_in sockname;
	pbs_socklen_t	 socknamelen;

#ifdef WIN32
	int     non_block = 1;
	struct sockaddr_in to_sock;
	struct sockaddr_in from_sock;
#endif

#ifndef WIN32
	int nflg;
	int oflg;
#endif

	/* initialize the thread context data, if not already initialized */
	if (pbs_client_thread_init_thread_context() != 0)
		return -1;

	if (pbs_loadconf(0) == 0)
		return -1;

	/* get server host and port	*/

	server = PBS_get_server(server, server_name, &server_port);
	if (server == NULL) {
		pbs_errno = PBSE_NOSERVER;
		return -1;
	}

	/* Reserve a connection state record */
	if (pbs_client_thread_lock_conntable() != 0)
		return -1;

	out = -1;
	for (i=1;i<NCONNECTS;i++) {
		if (connection[i].ch_inuse) continue;
		out = i;
		connection[out].ch_inuse = 1;
		connection[out].ch_errno = 0;
		connection[out].ch_socket= -1;
		connection[out].ch_errtxt = NULL;
		break;
	}

	if (pbs_client_thread_unlock_conntable() != 0)
		return -1; /* pbs_errno set by the function */

	if (out < 0) {
		pbs_errno = PBSE_NOCONNECTS;
		return -1;
	}


	/* get socket	*/

#ifdef WIN32
	/* the following lousy hack is needed since the socket call needs */
	/* SYSTEMROOT env variable properly set! */
	if (getenv("SYSTEMROOT") == NULL) {
		setenv("SYSTEMROOT", "C:\\WINNT", 1);
		setenv("SystemRoot", "C:\\WINNT", 1);
	}
	connection[out].ch_socket = socket(AF_INET, SOCK_STREAM, 0);
	if (connection[out].ch_socket < 0) {
		setenv("SYSTEMROOT", "C:\\WINDOWS", 1);
		setenv("SystemRoot", "C:\\WINDOWS", 1);
		connection[out].ch_socket = socket(AF_INET, SOCK_STREAM, 0);
	}
#else
	connection[out].ch_socket = socket(AF_INET, SOCK_STREAM, 0);
#endif
	if (connection[out].ch_socket < 0) {
		connection[out].ch_inuse = 0;
		pbs_errno = ERRORNO;
		return -1;
	}

	/* set socket non-blocking */

#ifdef WIN32
	if (ioctlsocket(connection[out].ch_socket, FIONBIO, &non_block) == SOCKET_ERROR)
#else
	oflg = fcntl(connection[out].ch_socket, F_GETFL) & ~O_ACCMODE;
	nflg = oflg | O_NONBLOCK;
	if (fcntl(connection[out].ch_socket, F_SETFL, nflg) == -1)
#endif
		goto err;

	/* and connect... */

	strcpy(pbs_server, server);    /* set for error messages from commands */
	memset(&hints, 0, sizeof(struct addrinfo));
	/*
	 *      Why do we use AF_UNSPEC rather than AF_INET?  Some
	 *      implementations of getaddrinfo() will take an IPv6
	 *      address and map it to an IPv4 one if we ask for AF_INET
	 *      only.  We don't want that - we want only the addresses
	 *      that are genuinely, natively, IPv4 so we start with
	 *      AF_UNSPEC and filter ai_family below.
	 */
	hints.ai_family = AF_UNSPEC;
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_protocol = IPPROTO_TCP;

	if (getaddrinfo(server, NULL, &hints, &pai) != 0) {
		CLOSESOCKET(connection[out].ch_socket);
		connection[out].ch_inuse = 0;
		pbs_errno = PBSE_BADHOST;
		return -1;
	}
	for (aip = pai; aip != NULL; aip = aip->ai_next) {
		/* skip non-IPv4 addresses */
		if (aip->ai_family == AF_INET) {
			inp = (struct sockaddr_in *) aip->ai_addr;
			break;
		}
	}
	if (aip == NULL) {
		/* treat no IPv4 addresses as getaddrinfo() failure */
		CLOSESOCKET(connection[out].ch_socket);
		connection[out].ch_inuse = 0;
		pbs_errno = PBSE_BADHOST;
		freeaddrinfo(pai);
		return -1;
	} else
		inp->sin_port = htons(server_port);
	if (connect(connection[out].ch_socket,
		aip->ai_addr,
		aip->ai_addrlen) < 0) {
		connect_err = 1;
	}
	if (connect_err == 1)
	{
		/* connect attempt failed */
		pbs_errno = ERRORNO;
		switch (pbs_errno) {
#ifdef WIN32
			case WSAEWOULDBLOCK:
#else
			case EINPROGRESS:
			case EWOULDBLOCK:
#endif
				while (1) {
					FD_ZERO(&fdset);
					FD_SET(connection[out].ch_socket, &fdset);
					tv.tv_sec = tout;
					tv.tv_usec = 0;
					n = select(connection[out].ch_socket+1, NULL, &fdset, NULL, &tv);
					if (n > 0) {
						pbs_errno = 0;
						l = sizeof(pbs_errno);
						(void)getsockopt(connection[out].ch_socket,
							SOL_SOCKET, SO_ERROR,
							&pbs_errno, &l);
						if (pbs_errno == 0)
							break;
						else
							goto err;
					} if ((n < 0) &&
#ifdef WIN32
						(ERRORNO == WSAEINTR)
#else
						(ERRORNO == EINTR)
#endif
						) {
						continue;
					} else {
						goto err;
					}
				}
				break;

			default:
err:
				CLOSESOCKET(connection[out].ch_socket);
				connection[out].ch_inuse = 0;
				freeaddrinfo(pai);
				return -1;	/* cannot connect */

		}
	}
	freeaddrinfo(pai);

	/* reset socket blocking */
#ifdef WIN32
	non_block = 0;
	if (ioctlsocket(connection[out].ch_socket, FIONBIO, &non_block) == SOCKET_ERROR)
#else
	if (fcntl(connection[out].ch_socket, F_SETFL, oflg) < 0)
#endif
		goto err;

	/*
	 * multiple threads cant get the same connection id above,
	 * so no need to lock this piece of code
	 */
	/* setup connection level thread context */
	if (pbs_client_thread_init_connect_context(out) != 0) {
		CLOSESOCKET(connection[out].ch_socket);
		connection[out].ch_inuse = 0;
		/* pbs_errno set by the pbs_connect_init_context routine */
		return -1;
	}
	/*
	 * even though the following is communication with server on
	 * a connection handle, it does not need to be lock since
	 * this connection handle has not be returned back yet to the client
	 * so others threads cannot use it
	 */

	/* send "dummy" connect message */
	DIS_tcp_setup(connection[out].ch_socket);
	if ((i = encode_DIS_ReqHdr(connection[out].ch_socket,
		PBS_BATCH_Connect, pbs_current_user)) ||
		(i = encode_DIS_ReqExtend(connection[out].ch_socket,
		NULL))) {
		pbs_errno = PBSE_SYSTEM;
		return -1;
	}
	if (DIS_tcp_wflush(connection[out].ch_socket)) {
		pbs_errno = PBSE_SYSTEM;
		return -1;
	}
	reply = PBSD_rdrpy(out);
	PBSD_FreeReply(reply);

	/*do configured authentication (kerberos, pbs_iff, whatever)*/

	/*Get the socket port for engage_authentication()*/
	socknamelen = sizeof(sockname);
	if (getsockname(connection[out].ch_socket, (struct sockaddr *)&sockname, &socknamelen))
		return -1;
	if (engage_authentication(connection[out].ch_socket,
		server,
		server_port,
		&sockname) == -1) {
		CLOSESOCKET(connection[out].ch_socket);
		connection[out].ch_inuse = 0;
		pbs_errno = PBSE_PERM;
		return -1;
	}

	/* setup DIS support routines for following pbs_* calls */
	DIS_tcp_setup(connection[out].ch_socket);
	pbs_tcp_timeout = PBS_DIS_TCP_TIMEOUT_VLONG;	/* set for 3 hours */

	return out;
}
Example #2
0
int
client_to_svr_extend(pbs_net_t hostaddr, unsigned int port, int authport_flags, char *localaddr)
{
	struct sockaddr_in	remote;
	int	sock;
	int	local_port;
	int	errn;
	int	rc;
#ifdef WIN32
	int	ret;
	int	non_block = 1;
	struct	linger      li;
	struct	sockaddr_in from;
	struct	timeval     tv;
	fd_set	            writeset;
#else
	struct pollfd	fds[1];
	pbs_socklen_t	len = sizeof(rc);
	int		oflag;
#endif


	/*	If local privilege port requested, bind to one	*/
	/*	Must be root privileged to do this		*/
	local_port = authport_flags & B_RESERVED;

	if (local_port) {
#ifdef	IP_PORTRANGE_LOW
		int			lport = IPPORT_RESERVED - 1;

		sock = rresvport(&lport);
		if (sock < 0) {
			if (errno == EAGAIN)
				return PBS_NET_RC_RETRY;
			else
				return PBS_NET_RC_FATAL;
		}
#else	/* IP_PORTRANGE_LOW */
		struct sockaddr_in	local;
		unsigned short		tryport;
		static unsigned short	start_port = 0;

		sock = socket(AF_INET, SOCK_STREAM, 0);
		if (sock < 0) {
			return PBS_NET_RC_FATAL;
		}

		if (start_port == 0) {	/* arbitrary start point */
			start_port = (getpid() %(IPPORT_RESERVED/2)) +
				IPPORT_RESERVED/2;
		}
		else if (--start_port < IPPORT_RESERVED/2)
			start_port = IPPORT_RESERVED - 1;
		tryport = start_port;

		memset(&local, 0, sizeof(local));
		local.sin_family = AF_INET;
		if (localaddr != NULL) {
			local.sin_addr.s_addr = inet_addr(localaddr);
			if (local.sin_addr.s_addr == INADDR_NONE) {
				perror("inet_addr failed");
				return (PBS_NET_RC_FATAL);
			}
		} else if (pbs_conf.pbs_public_host_name) {
			pbs_net_t public_addr;
			public_addr = get_hostaddr(pbs_conf.pbs_public_host_name);
			if (public_addr == (pbs_net_t)0) {
				return (PBS_NET_RC_FATAL);
			}
			local.sin_addr.s_addr = htonl(public_addr);
		}
		for (;;) {

			local.sin_port = htons(tryport);
			if (bind(sock, (struct sockaddr *)&local,
				sizeof(local)) == 0)
				break;

#ifdef WIN32
			errno = WSAGetLastError();
			if (errno != EADDRINUSE && errno != EADDRNOTAVAIL && errno != WSAEACCES) {
				closesocket(sock);
#else
			if (errno != EADDRINUSE && errno != EADDRNOTAVAIL) {
				close(sock);
#endif
				return PBS_NET_RC_FATAL;
			}
			else if (--tryport < (IPPORT_RESERVED/2)) {
				tryport = IPPORT_RESERVED - 1;
			}
			if (tryport == start_port) {
#ifdef WIN32
				closesocket(sock);
#else
				close(sock);
#endif
				return PBS_NET_RC_RETRY;
			}
		}
		/*
		 ** Ensure last tryport becomes start port on next call.
		 */
		start_port = tryport;
#endif	/* IP_PORTRANGE_LOW */
	}
	else {
		sock = socket(AF_INET, SOCK_STREAM, 0);
		if (sock < 0) {
			return PBS_NET_RC_FATAL;
		}
	}

	remote.sin_addr.s_addr = htonl(hostaddr);

	remote.sin_port = htons((unsigned short)port);
	remote.sin_family = AF_INET;
#ifdef WIN32
	li.l_onoff = 1;
	li.l_linger = 5;

	setsockopt(sock, SOL_SOCKET, SO_LINGER, (char *)&li, sizeof(li));

	if (ioctlsocket(sock, FIONBIO, &non_block) == SOCKET_ERROR) {
		errno = WSAGetLastError();
		closesocket(sock);
		return (PBS_NET_RC_FATAL);
	}
#else
	oflag = fcntl(sock, F_GETFL);
	if (fcntl(sock, F_SETFL, (oflag | O_NONBLOCK)) == -1) {
		close(sock);
		return (PBS_NET_RC_FATAL);
	}
#endif

	if (connect(sock, (struct sockaddr *)&remote, sizeof(remote)) < 0) {

#ifdef WIN32
		errno = WSAGetLastError();
#endif
		/*
		 * Bacause of  threading, pbs_errno is actually a macro
		 * pointing to a variable within a tread context.  On certain
		 * platforms, the threading library resulted in errno being
		 * cleared after pbs_errno was set set from it, so save
		 * errno into a local variable first, then test it.
		 */
		errn = errno;
		pbs_errno = errn;
		switch (errn) {
#ifdef WIN32
			case WSAEINTR:
#else
			case EINTR:
#endif
			case EADDRINUSE:
			case ETIMEDOUT:
			case ECONNREFUSED:
#ifdef WIN32
				closesocket(sock);
#else
				close(sock);
#endif
				return (PBS_NET_RC_RETRY);

#ifdef WIN32
			case WSAEWOULDBLOCK:
				FD_ZERO(&writeset);
				FD_SET((unsigned int)sock, &writeset);
				tv.tv_sec = conn_timeout;	/* connect timeout */
				tv.tv_usec = 0;
				ret = select(1, NULL, &writeset, NULL, &tv);
				if (ret == SOCKET_ERROR) {
					errno = WSAGetLastError(); 
					errn = errno;
					pbs_errno = errn;
					closesocket(sock);
					return PBS_NET_RC_FATAL;
				} else if (ret == 0) {
					closesocket(sock);
					return PBS_NET_RC_RETRY;
				}
				break;
#else	/* UNIX */
			case EWOULDBLOCK:
			case EINPROGRESS:
				while (1) {
					fds[0].fd = sock;
					fds[0].events  = POLLOUT;
					fds[0].revents = 0;

					rc = poll(fds, (nfds_t)1, conn_timeout * 1000);
					if (rc == -1) {
						errn = errno;
						if ((errn != EAGAIN) && (errn != EINTR))
							break;
					} else
						break;	/* no error */
				}

				if (rc == 1) {
					/* socket may be connected and ready to write */
					rc = 0;
					if ((getsockopt(sock, SOL_SOCKET, SO_ERROR, &rc, &len) == -1) || (rc != 0)) {
						close(sock);
						return PBS_NET_RC_FATAL;
					}
					break;

				} else if (rc == 0) {
					/* socket not ready - not connected in time */
					close(sock);
					return PBS_NET_RC_RETRY;
				} else {
					/* socket not ready - error */
					close(sock);
					return PBS_NET_RC_FATAL;
				}
#endif	/* end UNIX */

			default:
#ifdef WIN32
				closesocket(sock);
#else
				close(sock);
#endif
				return (PBS_NET_RC_FATAL);
		}
	}

	/* reset socket to blocking */
#ifdef WIN32
	non_block = 0;
	if (ioctlsocket(sock, FIONBIO, &non_block) == SOCKET_ERROR) {
		errno = WSAGetLastError();
		closesocket(sock);
		return PBS_NET_RC_FATAL;
	}
#else	/* UNIX */
	if (fcntl(sock, F_SETFL, oflag) == -1) {
		close(sock);
		return (PBS_NET_RC_FATAL);
	}
#endif

	if (engage_authentication(sock,
		remote.sin_addr, port, authport_flags) != -1)
		return sock;

	/*authentication unsuccessful*/

#ifdef WIN32
	closesocket(sock);
#else
	close(sock);
#endif
	return (PBS_NET_RC_FATAL);
}
Example #3
0
/**
 * @brief
 *	Makes a PBS_BATCH_Connect request to 'server'.
 *
 * @param[in]   server - the hostname of the pbs server to connect to.
 * @param[in]   extend_data - a string to send as "extend" data.
 *
 * @return int
 * @retval >= 0	index to the internal connection table representing the
 *		connection made.
 * @retval -1	error encountered setting up the connection.
 */
int
__pbs_connect_extend(char *server, char *extend_data)
{
	struct sockaddr_in server_addr;
	struct sockaddr_in my_sockaddr;
	int out;
	int i;
	int f;
	char  *altservers[2];
	int    have_alt = 0;
	struct batch_reply	*reply;
	char server_name[PBS_MAXSERVERNAME+1];
	unsigned int server_port;
	struct sockaddr_in sockname;
	pbs_socklen_t	 socknamelen;
#ifdef WIN32
	struct sockaddr_in to_sock;
	struct sockaddr_in from_sock;
#endif

#ifndef WIN32
	char   pbsrc[_POSIX_PATH_MAX];
	struct stat sb;
	int    using_secondary = 0;
#endif  /* not WIN32 */

	/* initialize the thread context data, if not already initialized */
	if (pbs_client_thread_init_thread_context() != 0)
		return -1;

	if (pbs_loadconf(0) == 0)
		return -1;

	/* get server host and port	*/

	server = PBS_get_server(server, server_name, &server_port);
	if (server == NULL) {
		pbs_errno = PBSE_NOSERVER;
		return -1;
	}

	if (pbs_conf.pbs_primary && pbs_conf.pbs_secondary) {
		/* failover configuered ...   */
		if (hostnmcmp(server, pbs_conf.pbs_primary) == 0) {
			have_alt = 1;
			/* We want to try the one last seen as "up" first to not   */
			/* have connection delays.   If the primary was up, there  */
			/* is no .pbsrc.NAME file.  If the last command connected  */
			/* to the Secondary, then it created the .pbsrc.USER file. */

			/* see if already seen Primary down */
#ifdef WIN32
			/* due to windows quirks, all try both in same order */
			altservers[0] = pbs_conf.pbs_primary;
			altservers[1] = pbs_conf.pbs_secondary;
#else
			(void)snprintf(pbsrc, _POSIX_PATH_MAX, "%s/.pbsrc.%s", pbs_conf.pbs_tmpdir, pbs_current_user);
			if (stat(pbsrc, &sb) == -1) {
				/* try primary first */
				altservers[0] = pbs_conf.pbs_primary;
				altservers[1] = pbs_conf.pbs_secondary;
				using_secondary = 0;
			} else {
				/* try secondary first */
				altservers[0] = pbs_conf.pbs_secondary;
				altservers[1] = pbs_conf.pbs_primary;
				using_secondary = 1;
			}
#endif
		}
	}

	/* if specific host name declared for the host on which */
	/* this client is running,  get its address */
	if (pbs_conf.pbs_public_host_name) {
		if (get_hostsockaddr(pbs_conf.pbs_public_host_name, &my_sockaddr) != 0)
			return -1; /* pbs_errno was set */
	}

	/* Reserve a connection state record */
	if (pbs_client_thread_lock_conntable() != 0)
		return -1;

	out = -1;
	for (i=1;i<NCONNECTS;i++) {
		if (connection[i].ch_inuse) continue;
		out = i;
		connection[out].ch_errno = 0;
		connection[out].ch_socket= -1;
		connection[out].ch_errtxt = NULL;
		connection[out].ch_inuse = 1; /* reserve the socket */
		break;
	}

	if (pbs_client_thread_unlock_conntable() != 0)
		return -1; /* pbs_errno set by the function */

	if (out < 0) {
		pbs_errno = PBSE_NOCONNECTS;
		return -1;
	}

	/*
	 * connect to server ...
	 * If attempt to connect fails and if Failover configured and
	 *   if attempting to connect to Primary,  try the Secondary
	 *   if attempting to connect to Secondary, try the Primary
	 */
	for (i=0; i<(have_alt+1); ++i) {

		/* get socket	*/

#ifdef WIN32
		/* the following lousy hack is needed since the socket call needs */
		/* SYSTEMROOT env variable properly set! */
		if (getenv("SYSTEMROOT") == NULL) {
			setenv("SYSTEMROOT", "C:\\WINNT", 1);
			setenv("SystemRoot", "C:\\WINNT", 1);
		}
		connection[out].ch_socket = socket(AF_INET, SOCK_STREAM, 0);
		if (connection[out].ch_socket < 0) {
			setenv("SYSTEMROOT", "C:\\WINDOWS", 1);
			setenv("SystemRoot", "C:\\WINDOWS", 1);
			connection[out].ch_socket = socket(AF_INET, SOCK_STREAM, 0);

		}
#else
		connection[out].ch_socket = socket(AF_INET, SOCK_STREAM, 0);
#endif
		if (connection[out].ch_socket < 0) {
			connection[out].ch_inuse = 0;
			pbs_errno = errno;
			return -1;
		}

		/* and connect... */

		if (have_alt) {
			server = altservers[i];
		}
		strcpy(pbs_server, server); /* set for error messages from commands */

		/* If a specific host name is defined which the client should use */

		if (pbs_conf.pbs_public_host_name) {
			/* my address will be in my_sockaddr,  bind the socket to it */
			my_sockaddr.sin_port = 0;
			if (bind(connection[out].ch_socket, (struct sockaddr *)&my_sockaddr, sizeof(my_sockaddr)) != 0) {
				return -1;
			}
		}

		if (get_hostsockaddr(server, &server_addr) != 0)
			return -1;

		server_addr.sin_port = htons(server_port);
		if (connect(connection[out].ch_socket,
			(struct sockaddr *)&server_addr,
			sizeof(struct sockaddr)) == 0) {

				break;
		} else {
			/* connect attempt failed */
			CLOSESOCKET(connection[out].ch_socket);
			pbs_errno = errno;
		}
	}
	if (i >= (have_alt+1)) {
		connection[out].ch_inuse = 0;
		return -1; 		/* cannot connect */
	}

#ifndef WIN32
	if (have_alt && (i == 1)) {
		/* had to use the second listed server ... */
		if (using_secondary == 1) {
			/* remove file that causes trying the Secondary first */
			unlink(pbsrc);
		} else {
			/* create file that causes trying the Primary first   */
			f = open(pbsrc, O_WRONLY|O_CREAT, 0200);
			if (f != -1)
				(void)close(f);
		}
	}
#endif

	/* setup connection level thread context */
	if (pbs_client_thread_init_connect_context(out) != 0) {
		CLOSESOCKET(connection[out].ch_socket);
		connection[out].ch_inuse = 0;
		/* pbs_errno set by the pbs_connect_init_context routine */
		return -1;
	}

	/*
	 * No need for global lock now on, since rest of the code
	 * is only communication on a connection handle.
	 * But we dont need to lock the connection handle, since this
	 * connection handle is not yet been returned to the client
	 */

	/* The following code was originally  put in for HPUX systems to deal
	 * with the issue where returning from the connect() call doesn't
	 * mean the connection is complete.  However, this has also been
	 * experienced in some Linux ppc64 systems like js-2. Decision was
	 * made to enable this harmless code for all architectures.
	 * FIX: Need to use the socket to send
	 * a message to complete the process.  For IFF authentication there is
	 * no leading authentication message needing to be sent on the client
	 * socket, so will send a "dummy" message and discard the replyback.
	 */

#if !defined(PBS_SECURITY ) || (PBS_SECURITY == STD )

	DIS_tcp_setup(connection[out].ch_socket);
	if ((i = encode_DIS_ReqHdr(connection[out].ch_socket,
		PBS_BATCH_Connect, pbs_current_user)) ||
		(i = encode_DIS_ReqExtend(connection[out].ch_socket,
		extend_data))) {
		pbs_errno = PBSE_SYSTEM;
		return -1;
	}
	if (DIS_tcp_wflush(connection[out].ch_socket)) {
		pbs_errno = PBSE_SYSTEM;
		return -1;
	}

	reply = PBSD_rdrpy(out);
	PBSD_FreeReply(reply);

#endif	/* PBS_SECURITY ... */

	/*do configured authentication (kerberos, pbs_iff, whatever)*/

	/*Get the socket port for engage_authentication() */
	socknamelen = sizeof(sockname);
	if (getsockname(connection[out].ch_socket, (struct sockaddr *)&sockname, &socknamelen))
		return -1;

	if (engage_authentication(connection[out].ch_socket,
		server,
		server_port,
		&sockname) == -1) {
		CLOSESOCKET(connection[out].ch_socket);
		connection[out].ch_inuse = 0;
		pbs_errno = PBSE_PERM;
		return -1;
	}

	/* setup DIS support routines for following pbs_* calls */

	DIS_tcp_setup(connection[out].ch_socket);
	pbs_tcp_timeout = PBS_DIS_TCP_TIMEOUT_VLONG;	/* set for 3 hours */

	/*
	 * Disable Nagle's algorithm on the TCP connection to server.
	 * Nagle's algorithm is hurting cmd-server communication.
	 */
	if (pbs_connection_set_nodelay(out) == -1) {
		CLOSESOCKET(connection[out].ch_socket);
		connection[out].ch_inuse = 0;
		pbs_errno = PBSE_SYSTEM;
		return -1;
	}

	return out;
}